#!/usr/bin/python

import os
import lib
import sys
import imp
import ConfigParser
import logging as log

log.basicConfig(level=log.DEBUG,
                format="%(asctime)s %(levelname)-8s %(message)s",
                datefmt='%Y-%m-%d %H:%M:%S')

config = ConfigParser.ConfigParser()
config.read("stream.conf")

def load_module(pathlist, name):
    fp, path, desc = imp.find_module(name, pathlist)
    try:
        module = imp.load_module(name, fp, path, desc)
        return module
    finally:
        if fp:
            fp.close()


media_plugin = config.get("Media", "engine")
media_plugin_module = load_module(["./plugins/media"], media_plugin)
media = media_plugin_module.Media(config)

comm_plugin = config.get("Comm", "engine")
comm_plugin_module = load_module(["./plugins/comm"], comm_plugin)
server = comm_plugin_module.Server(config)

log.info("Starting GMyth-Stream server")


'''
PROTOCOL DESCRIPTION
=====================

COMMAND OPTIONS

-> SETUP DESCRIPTION
|-> used to setup transcoding and streaming parameters
|-> must be used before any "PLAY" command
|-> e.g:

file://file_name mux vcodec vbitrate fps acodec abitrate width height options
dvd://title_number mux vcodec vbitrate fps acodec abitrate width height options

-> PLAY DESCRIPTION
 |-> used to start transcoding and streaming of file
 |-> must be used just if SETUP was used before
 |-> after it, _must_ send STOP

-> STOP DESCRIPTION
 |-> used to stop transcoding and streaming process
 |-> must be used just if PLAY was used before
 |-> must be used after PLAY

-> QUIT DESCRIPTION
 |-> used to quit the main loop (quit program)

'''
nextport = 0
setup = (False, "STOPPED")

def do_setup(server, filename, mux, vcodec, vbitrate, fps, acodec, abitrate,
             width, height, *options):
    global nextport
    global setup

    if setup[1] != "PLAYING":
        nextport += 1
        ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec,
                          abitrate, width, height, nextport, options)
        if ret[0]:
            server.sendOk()
        else:
            server.sendNotOk(ret[1])

        setup = (True, setup[1])

    else: server.sendNotOk("You must STOP before SETingUP again")

    return True

def do_play(server):
    global setup

    if setup[0] and setup[1] == "STOPPED":
        setup = (setup[0], "PLAYING")
        ret = media.play()
        if ret[0]:
            server.sendOk("%d" % nextport)
        else:
            server.sendNotOk(ret[1])

    else:
        if setup[1] == "STOPPED":
            server.sendNotOk("You must SETUP before PLAYing")
        else:
            server.sendNotOk("You must STOP before PLAYing again")

    return True

def do_stop(server):
    global setup

    media.stop()
    setup = (False, "STOPPED")
    server.sendOk()
    return True

def do_list(server, *directory):
    file_list = []
    for j in directory:
        lib.list_media_files(j, file_list)

    server.sendOk(file_list)
    return True

def do_quit(server):
    server.finish = 1
    media.stop()
    server.sendOk()
    return True


mapping = {
    "SETUP": do_setup,
    "PLAY": do_play,
    "STOP": do_stop,
    "LIST": do_list,
    "QUIT": do_quit,
    }


def dispatch(server, msg):
    pieces = msg.split()
    if len(pieces) < 1:
        log.error("Invalid client command format: %r" % msg)
        server.sendNotOk("Invalid Format")
        return False

    cmd = pieces[0]
    f = mapping.get(cmd, None)
    if not f:
        log.error("Unknow command: %r" % msg)
        server.sendNotOk("Unknow Command")
        return False

    try:
        return f(server, *pieces[1:])
    except Exception, e:
        log.error("Could not execute %r: %s" % (msg, e))
        server.sendNotOk(str(e))
        return False



while not server.finish:
    conn, client, port = server.getRequest()
    if nextport == 0:
        nextport = port

    while not server.finish:
        msg = server.getMsg()
        if not msg:
            break

        log.info("Client %s sent command: %r" % (client, msg))
        dispatch(server, msg)

    log.info("Closing connection with %s" % (client,))
    server.disconnect_client(conn)
    try:
        os.wait()
    except Exception, e:
        log.error(e)

server.stop()
log.info("Server stopped. Closing...")

