renatofilho@484: #!/usr/bin/python renatofilho@484: renatofilho@484: import os renatofilho@484: import lib renatofilho@484: import sys morphbr@511: import imp renatofilho@484: import ConfigParser morphbr@511: import logging as log morphbr@511: morphbr@511: log.basicConfig(level=log.DEBUG, morphbr@511: format="%(asctime)s %(levelname)-8s %(message)s", morphbr@511: datefmt='%Y-%m-%d %H:%M:%S') renatofilho@484: renatofilho@484: config = ConfigParser.ConfigParser() renatofilho@484: config.read("stream.conf") renatofilho@484: morphbr@511: def load_module(pathlist, name): morphbr@511: fp, path, desc = imp.find_module(name, pathlist) morphbr@511: try: morphbr@511: module = imp.load_module(name, fp, path, desc) morphbr@511: return module morphbr@511: finally: morphbr@511: if fp: morphbr@511: fp.close() morphbr@511: morphbr@511: renatofilho@484: media_plugin = config.get("Media", "engine") morphbr@511: media_plugin_module = load_module(["./plugins/media"], media_plugin) morphbr@511: media = media_plugin_module.Media(config) renatofilho@484: renatofilho@484: comm_plugin = config.get("Comm", "engine") morphbr@511: comm_plugin_module = load_module(["./plugins/comm"], comm_plugin) morphbr@511: server = comm_plugin_module.Server(config) renatofilho@484: morphbr@511: log.info("Starting GMyth-Stream server") renatofilho@484: morphbr@504: morphbr@504: ''' morphbr@504: PROTOCOL DESCRIPTION morphbr@504: ===================== morphbr@504: morphbr@504: COMMAND OPTIONS morphbr@504: morphbr@504: -> SETUP DESCRIPTION morphbr@504: |-> used to setup transcoding and streaming parameters morphbr@504: |-> must be used before any "PLAY" command morphbr@504: |-> e.g: morphbr@504: morphbr@504: file://file_name mux vcodec vbitrate fps acodec abitrate width height options morphbr@504: dvd://title_number mux vcodec vbitrate fps acodec abitrate width height options morphbr@504: morphbr@504: -> PLAY DESCRIPTION morphbr@504: |-> used to start transcoding and streaming of file morphbr@504: |-> must be used just if SETUP was used before morphbr@504: |-> after it, _must_ send STOP morphbr@504: morphbr@504: -> STOP DESCRIPTION morphbr@504: |-> used to stop transcoding and streaming process morphbr@504: |-> must be used just if PLAY was used before morphbr@504: |-> must be used after PLAY morphbr@504: morphbr@504: -> QUIT DESCRIPTION morphbr@504: |-> used to quit the main loop (quit program) morphbr@504: morphbr@504: ''' morphbr@504: nextport = 0 morphbr@533: setup = (False, "STOPPED") morphbr@504: morphbr@511: def do_setup(server, filename, mux, vcodec, vbitrate, fps, acodec, abitrate, morphbr@511: width, height, *options): morphbr@511: global nextport morphbr@533: global setup morphbr@533: morphbr@533: if setup[1] != "PLAYING": morphbr@533: nextport += 1 morphbr@533: ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec, morphbr@533: abitrate, width, height, nextport, options) morphbr@533: if ret[0]: morphbr@533: server.sendOk() morphbr@533: else: morphbr@533: server.sendNotOk(ret[1]) morphbr@533: morphbr@533: setup = (True, setup[1]) morphbr@533: morphbr@533: else: server.sendNotOk("You must STOP before SETingUP again") morphbr@516: morphbr@511: return True morphbr@511: morphbr@511: def do_play(server): morphbr@533: global setup morphbr@533: morphbr@533: if setup[0] and setup[1] == "STOPPED": morphbr@533: setup = (setup[0], "PLAYING") morphbr@533: ret = media.play() morphbr@533: if ret[0]: morphbr@533: server.sendOk("%d" % nextport) morphbr@533: else: morphbr@533: server.sendNotOk(ret[1]) morphbr@533: morphbr@516: else: morphbr@533: if setup[1] == "STOPPED": morphbr@533: server.sendNotOk("You must SETUP before PLAYing") morphbr@533: else: morphbr@533: server.sendNotOk("You must STOP before PLAYing again") morphbr@516: morphbr@511: return True morphbr@511: morphbr@511: def do_stop(server): morphbr@533: global setup morphbr@533: morphbr@511: media.stop() morphbr@533: setup = (False, "STOPPED") morphbr@511: server.sendOk() morphbr@511: return True morphbr@511: morphbr@516: def do_list(server, *directory): morphbr@516: file_list = [] morphbr@516: for j in directory: morphbr@533: lib.list_media_files(j, file_list) morphbr@516: morphbr@533: server.sendOk(file_list) morphbr@516: return True morphbr@516: morphbr@511: def do_quit(server): morphbr@511: server.finish = 1 morphbr@511: media.stop() morphbr@511: server.sendOk() morphbr@511: return True morphbr@511: morphbr@511: morphbr@511: mapping = { morphbr@511: "SETUP": do_setup, morphbr@511: "PLAY": do_play, morphbr@511: "STOP": do_stop, morphbr@516: "LIST": do_list, morphbr@511: "QUIT": do_quit, morphbr@511: } morphbr@511: morphbr@533: morphbr@511: def dispatch(server, msg): morphbr@511: pieces = msg.split() morphbr@511: if len(pieces) < 1: morphbr@511: log.error("Invalid client command format: %r" % msg) morphbr@511: server.sendNotOk("Invalid Format") morphbr@511: return False morphbr@511: morphbr@511: cmd = pieces[0] morphbr@511: f = mapping.get(cmd, None) morphbr@511: if not f: morphbr@511: log.error("Unknow command: %r" % msg) morphbr@511: server.sendNotOk("Unknow Command") morphbr@511: return False morphbr@511: morphbr@511: try: morphbr@511: return f(server, *pieces[1:]) morphbr@511: except Exception, e: morphbr@511: log.error("Could not execute %r: %s" % (msg, e)) morphbr@511: server.sendNotOk(str(e)) morphbr@511: return False morphbr@511: morphbr@511: morphbr@511: morphbr@511: while not server.finish: morphbr@504: conn, client, port = server.getRequest() morphbr@504: if nextport == 0: morphbr@504: nextport = port renatofilho@484: morphbr@511: while not server.finish: morphbr@511: msg = server.getMsg() morphbr@511: if not msg: renatofilho@484: break renatofilho@484: morphbr@511: log.info("Client %s sent command: %r" % (client, msg)) morphbr@511: dispatch(server, msg) morphbr@511: morphbr@511: log.info("Closing connection with %s" % (client,)) morphbr@504: server.disconnect_client(conn) morphbr@533: try: morphbr@533: os.wait() morphbr@533: except Exception, e: morphbr@533: log.error(e) renatofilho@484: renatofilho@484: server.stop() morphbr@511: log.info("Server stopped. Closing...") renatofilho@484: