[svn r516] GMyth-Streamer: Barbieri's patches trunk
authormorphbr
Fri Apr 06 22:58:06 2007 +0100 (2007-04-06)
branchtrunk
changeset 51116312d0021cb
parent 510 4abc2d465d80
child 512 5f15d749c024
[svn r516] GMyth-Streamer: Barbieri's patches
gmyth-stream/server/lib.py
gmyth-stream/server/main.py
gmyth-stream/server/plugins/comm/tcp.py
gmyth-stream/server/plugins/media/mencoder.py
     1.1 --- a/gmyth-stream/server/lib.py	Thu Apr 05 19:58:40 2007 +0100
     1.2 +++ b/gmyth-stream/server/lib.py	Fri Apr 06 22:58:06 2007 +0100
     1.3 @@ -1,9 +1,25 @@
     1.4  import time
     1.5 +import logging
     1.6 +import os
     1.7 +import stat
     1.8  
     1.9  def now():
    1.10      return time.strftime("%Y-%m-%d %H:%M:%S");
    1.11  
    1.12  def log(msg):
    1.13 +    logging.log(logging.DEBUG, msg)
    1.14      new_msg = "[%s] %s" % (now(), msg)
    1.15 -    print new_msg
    1.16      return new_msg
    1.17 +
    1.18 +
    1.19 +bin_path_list = os.environ["PATH"].split(os.pathsep)
    1.20 +def which(prg):
    1.21 +    for d in bin_path_list:
    1.22 +        path = os.path.join(d, prg)
    1.23 +        if os.path.exits(path):
    1.24 +            st = os.stat(path)
    1.25 +            if st[stat.ST_MODE] & 0111:
    1.26 +                return path
    1.27 +    return ""
    1.28 +
    1.29 +
     2.1 --- a/gmyth-stream/server/main.py	Thu Apr 05 19:58:40 2007 +0100
     2.2 +++ b/gmyth-stream/server/main.py	Fri Apr 06 22:58:06 2007 +0100
     2.3 @@ -3,23 +3,36 @@
     2.4  import os
     2.5  import lib
     2.6  import sys
     2.7 +import imp
     2.8  import ConfigParser
     2.9 +import logging as log
    2.10 +
    2.11 +log.basicConfig(level=log.DEBUG,
    2.12 +                format="%(asctime)s %(levelname)-8s %(message)s",
    2.13 +                datefmt='%Y-%m-%d %H:%M:%S')
    2.14  
    2.15  config = ConfigParser.ConfigParser()
    2.16  config.read("stream.conf")
    2.17  
    2.18 +def load_module(pathlist, name):
    2.19 +    fp, path, desc = imp.find_module(name, pathlist)
    2.20 +    try:
    2.21 +        module = imp.load_module(name, fp, path, desc)
    2.22 +        return module
    2.23 +    finally:
    2.24 +        if fp:
    2.25 +            fp.close()
    2.26 +
    2.27 +
    2.28  media_plugin = config.get("Media", "engine")
    2.29 -exec("from plugins.media.%s import *" % media_plugin)
    2.30 -
    2.31 -media = Media(config)
    2.32 +media_plugin_module = load_module(["./plugins/media"], media_plugin)
    2.33 +media = media_plugin_module.Media(config)
    2.34  
    2.35  comm_plugin = config.get("Comm", "engine")
    2.36 -exec("from plugins.comm.%s import *" % comm_plugin)
    2.37 +comm_plugin_module = load_module(["./plugins/comm"], comm_plugin)
    2.38 +server = comm_plugin_module.Server(config)
    2.39  
    2.40 -# Start Our Server:
    2.41 -server = Server(config)
    2.42 -
    2.43 -lib.log("Starting GMyth-Stream server")
    2.44 +log.info("Starting GMyth-Stream server")
    2.45  
    2.46  
    2.47  '''
    2.48 @@ -52,66 +65,83 @@
    2.49  '''
    2.50  nextport = 0
    2.51  
    2.52 -while (server.finish == 0):
    2.53 +def do_setup(server, filename, mux, vcodec, vbitrate, fps, acodec, abitrate,
    2.54 +             width, height, *options):
    2.55 +    global nextport
    2.56 +    nextport += 1
    2.57 +    ret = media.setup(filename, mux, vcodec, vbitrate, fps, acodec,
    2.58 +                      abitrate, width, height, nextport, options)
    2.59 +    if ret == 0:
    2.60 +        server.sendOk()
    2.61 +    else:
    2.62 +        server.sendNotOk(ret)
    2.63 +    return True
    2.64 +
    2.65 +def do_play(server):
    2.66 +    media.play()
    2.67 +    server.sendOk("%d" % nextport)
    2.68 +    return True
    2.69 +
    2.70 +
    2.71 +def do_stop(server):
    2.72 +    media.stop()
    2.73 +    server.sendOk()
    2.74 +    return True
    2.75 +
    2.76 +def do_quit(server):
    2.77 +    server.finish = 1
    2.78 +    media.stop()
    2.79 +    server.sendOk()
    2.80 +    return True
    2.81 +
    2.82 +
    2.83 +mapping = {
    2.84 +    "SETUP": do_setup,
    2.85 +    "PLAY": do_play,
    2.86 +    "STOP": do_stop,
    2.87 +    "QUIT": do_quit,
    2.88 +    }
    2.89 +
    2.90 +def dispatch(server, msg):
    2.91 +    pieces = msg.split()
    2.92 +    if len(pieces) < 1:
    2.93 +        log.error("Invalid client command format: %r" % msg)
    2.94 +        server.sendNotOk("Invalid Format")
    2.95 +        return False
    2.96 +
    2.97 +    cmd = pieces[0]
    2.98 +    f = mapping.get(cmd, None)
    2.99 +    if not f:
   2.100 +        log.error("Unknow command: %r" % msg)
   2.101 +        server.sendNotOk("Unknow Command")
   2.102 +        return False
   2.103 +
   2.104 +    try:
   2.105 +        return f(server, *pieces[1:])
   2.106 +    except Exception, e:
   2.107 +        log.error("Could not execute %r: %s" % (msg, e))
   2.108 +        server.sendNotOk(str(e))
   2.109 +        return False
   2.110 +
   2.111 +
   2.112 +
   2.113 +while not server.finish:
   2.114      conn, client, port = server.getRequest()
   2.115 -    server.sendMsg("Welcome to GMyth-Streamer Master")
   2.116      if nextport == 0:
   2.117          nextport = port
   2.118  
   2.119 -    while True:
   2.120 -        msg = server.getMsg(1024).strip()
   2.121 -
   2.122 -        if not msg: break
   2.123 -
   2.124 -        lib.log("Received %s from: %s" % (msg, client) )
   2.125 -
   2.126 -        if msg == "SETUP":
   2.127 -            setup = server.getMsg(1024).strip().split(" ")
   2.128 -            size = len(setup)
   2.129 -            options = []
   2.130 -
   2.131 -            if size < 10:
   2.132 -                server.sendMsg(lib.log("Wrong SETUP command from: %s" % client[0]))
   2.133 -
   2.134 -            else:
   2.135 -
   2.136 -                if size > 10:
   2.137 -                    i = 10
   2.138 -                    while (i < size):
   2.139 -                        options.append(setup[i])
   2.140 -                        i += 1
   2.141 -
   2.142 -                nextport += 1
   2.143 -                ret = media.setup(setup[0], setup[1], setup[2], \
   2.144 -                                  setup[3], setup[4], setup[5],
   2.145 -                                  setup[6], setup[7], setup[8],
   2.146 -                                  nextport, options)
   2.147 -
   2.148 -                if ret == 0:
   2.149 -                    server.Ack("SETUP")
   2.150 -                else:
   2.151 -                    server.sendMsg(lib.log(ret))
   2.152 -
   2.153 -
   2.154 -        elif msg == "PLAY":
   2.155 -            media.play()
   2.156 -            server.Ack("PLAY")
   2.157 -            server.sendMsg("STREAM PORT=%d" % nextport)
   2.158 -
   2.159 -        elif msg == "STOP":
   2.160 -            media.stop()
   2.161 -            server.Ack("STOP")
   2.162 -
   2.163 -        elif msg == "QUIT":
   2.164 -            server.finish = 1
   2.165 -            media.stop()
   2.166 -            server.Ack("QUIT")
   2.167 +    while not server.finish:
   2.168 +        msg = server.getMsg()
   2.169 +        if not msg:
   2.170              break
   2.171  
   2.172 -    lib.log("Closing connection with %s" % client[0])
   2.173 +        log.info("Client %s sent command: %r" % (client, msg))
   2.174 +        dispatch(server, msg)
   2.175 +
   2.176 +
   2.177 +    log.info("Closing connection with %s" % (client,))
   2.178      server.disconnect_client(conn)
   2.179  
   2.180  server.stop()
   2.181 -del(server)
   2.182 -lib.log("Server stopped. Closing...")
   2.183 +log.info("Server stopped. Closing...")
   2.184  
     3.1 --- a/gmyth-stream/server/plugins/comm/tcp.py	Thu Apr 05 19:58:40 2007 +0100
     3.2 +++ b/gmyth-stream/server/plugins/comm/tcp.py	Fri Apr 06 22:58:06 2007 +0100
     3.3 @@ -1,36 +1,79 @@
     3.4  import lib
     3.5  import time
     3.6  import socket
     3.7 +import logging as log
     3.8  
     3.9  class Server(object):
    3.10  
    3.11      def __init__(self, config):
    3.12 -        self.host = ''
    3.13 +        self.host = '0.0.0.0'
    3.14          self.port = int(config.get("Comm", "port"))
    3.15          self.finish = 0
    3.16  
    3.17 +        addr = (self.host, self.port)
    3.18 +        log.debug("Setup TCP server at %s:%s" % addr)
    3.19          self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    3.20          self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    3.21 -        self.tcp.bind( (self.host, self.port) )
    3.22 +        self.tcp.bind(addr)
    3.23          self.tcp.listen(1)
    3.24 +        log.info("TCP server listening at %s:%s (sock=%d)" %
    3.25 +                 (self.host, self.port, self.tcp.fileno()))
    3.26  
    3.27 -    def getMsg(self, size):
    3.28 -        return self.con.recv(size)
    3.29 +    def getMsg(self):
    3.30 +        bytes = []
    3.31 +        try:
    3.32 +            while 1:
    3.33 +                c = self.con.recv(1)
    3.34 +                bytes.append(c)
    3.35 +                if not c or c == "\n":
    3.36 +                    break
    3.37 +        except Exception, e:
    3.38 +            log.error("Error reading message from client: %s" % e)
    3.39 +            return None
    3.40 +
    3.41 +        if not bytes or bytes[-1] != "\n":
    3.42 +            msg = "".join(bytes)
    3.43 +            log.error("Invalid message from client: %r" % msg)
    3.44 +            return None
    3.45 +
    3.46 +        # remove \n and \r
    3.47 +        bytes.pop()
    3.48 +        if bytes[-1] == "\r":
    3.49 +            bytes.pop()
    3.50 +
    3.51 +        msg = "".join(bytes)
    3.52 +        log.debug("RECV: %r" % msg)
    3.53 +        return msg
    3.54  
    3.55      def sendMsg(self, msg):
    3.56 +        log.debug("SEND: %r" % msg)
    3.57          self.con.send(msg + "\n")
    3.58  
    3.59 -    def Ack(self, command):
    3.60 -        msg = "[%s] Command %s received" % (lib.now(), command)
    3.61 -        self.sendMsg(msg)
    3.62 +    def sendOk(self, payload=None):
    3.63 +        self.sendMsg("OK %d" % bool(payload is not None))
    3.64 +        if payload is not None:
    3.65 +            if not isinstance(payload, (tuple, list)):
    3.66 +                payload = (payload,)
    3.67 +            for e in payload:
    3.68 +                self.sendMsg("+%s" % e)
    3.69 +            self.sendMsg(".")
    3.70 +
    3.71 +    def sendNotOk(self, reason=""):
    3.72 +        self.sendMsg("NOTOK %r" % reason)
    3.73  
    3.74      def getRequest(self):
    3.75 +        log.debug("Wait for client request at %s:%s (sock=%d)" %
    3.76 +                  (self.host, self.port, self.tcp.fileno()))
    3.77          self.con, self.client = self.tcp.accept()
    3.78 -        print "[%s] Received request from ip=%s" % (lib.now(), self.client )
    3.79 +        log.info("Incoming request from %s (con=%s)" %
    3.80 +                 (self.client, self.con.fileno()))
    3.81          return (self.con, self.client, self.port)
    3.82  
    3.83      def disconnect_client(self, connection):
    3.84 +        log.info("Closed request from %s (con=%s)" %
    3.85 +                 (self.client, self.con.fileno()))
    3.86          connection.close()
    3.87  
    3.88      def stop(self):
    3.89 +        log.debug("Stop")
    3.90          self.tcp.close()
     4.1 --- a/gmyth-stream/server/plugins/media/mencoder.py	Thu Apr 05 19:58:40 2007 +0100
     4.2 +++ b/gmyth-stream/server/plugins/media/mencoder.py	Fri Apr 06 22:58:06 2007 +0100
     4.3 @@ -35,7 +35,7 @@
     4.4          for opt in options:
     4.5  
     4.6              if opt == "local":
     4.7 -                self.mplayer = os.popen("which mplayer").read().strip()
     4.8 +                self.mplayer = lib.which("mplayer")
     4.9  
    4.10              elif opt.find("language=") >= 0:
    4.11                  try:
    4.12 @@ -57,7 +57,7 @@
    4.13              msg = "dvd://" + msg
    4.14  
    4.15          self.mplayer += " " + msg
    4.16 -        self.mplayer_pid = Popen(self.mplayer, shell=True)
    4.17 +        self.mplayer_pid = Popen(self.mplayer, shell=True, close_fds=True)
    4.18  
    4.19      def setup_mencoder(self):
    4.20          self.path = self.config.get("Mencoder", "path")
    4.21 @@ -169,7 +169,8 @@
    4.22          lib.log("Starting Mencoder: %s %s" % (self.path, self.args) )
    4.23          # exec Mencoder
    4.24          if self.mencoder_old:
    4.25 -            self.mencoder_pid = Popen(self.path + self.args, shell=True)
    4.26 +            self.mencoder_pid = Popen(self.path + self.args, shell=True,
    4.27 +                                      close_fds=True)
    4.28              self.pout = open(self.fifo)
    4.29          else:
    4.30              self.path += self.args