[svn r475] Regarding GMyth-Stream: trunk
authormorphbr
Fri Mar 30 04:12:52 2007 +0100 (2007-03-30)
branchtrunk
changeset 47057833200a415
parent 469 28879368706b
child 471 2eef40885322
[svn r475] Regarding GMyth-Stream:

- Bug fixes
- Better error handling
- Return messages to client
- Created a lib.py with common functions
- Improved API of comm plugins
gmyth-stream/lib.py
gmyth-stream/main.py
gmyth-stream/plugins/comm/tcp.py
gmyth-stream/plugins/comm/xmlrpc.py
gmyth-stream/plugins/media/ffmpeg.py
gmyth-stream/tests/client_ffmpeg.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gmyth-stream/lib.py	Fri Mar 30 04:12:52 2007 +0100
     1.3 @@ -0,0 +1,7 @@
     1.4 +import time
     1.5 +
     1.6 +def now():
     1.7 +    return time.strftime("%Y-%m-%d %H:%M:%S");
     1.8 +
     1.9 +def log(msg):
    1.10 +    print "[%s] %s" % (now(), msg)
     2.1 --- a/gmyth-stream/main.py	Thu Mar 29 23:14:32 2007 +0100
     2.2 +++ b/gmyth-stream/main.py	Fri Mar 30 04:12:52 2007 +0100
     2.3 @@ -1,13 +1,10 @@
     2.4  #!/usr/bin/python
     2.5  
     2.6 +import os
     2.7 +import lib
     2.8  import sys
     2.9 -import os
    2.10  import ConfigParser
    2.11  
    2.12 -def now():
    2.13 -    return time.strftime("%Y-%m-%d %H:%M:%S");
    2.14 -
    2.15 -
    2.16  config = ConfigParser.ConfigParser()
    2.17  config.read("stream.conf")
    2.18  
    2.19 @@ -22,7 +19,7 @@
    2.20  # Start Our Server:
    2.21  server = Server(config)
    2.22  
    2.23 -print "--> Starting the server..."
    2.24 +lib.log("Starting GMyth-Stream server")
    2.25  
    2.26  while (server.finish == 0):
    2.27      con, client = server.getRequest()
    2.28 @@ -32,29 +29,39 @@
    2.29  
    2.30          if not msg: break
    2.31  
    2.32 -        elif (msg == "SETUP"):
    2.33 +        lib.log("Received %s from: %s" % (msg, client) )
    2.34 +
    2.35 +        if (msg == "SETUP"):
    2.36              setup = server.getMsg(1024).strip().split(" ")
    2.37 -            media.setup(setup[0], setup[1], setup[2], \
    2.38 -                        setup[3], setup[4], setup[5],
    2.39 -                        setup[6], setup[7], setup[8],
    2.40 -                        setup[9])
    2.41 +            if ( len(setup) == 10 ):
    2.42 +                media.setup(setup[0], setup[1], setup[2], \
    2.43 +                            setup[3], setup[4], setup[5],
    2.44 +                            setup[6], setup[7], setup[8],
    2.45 +                            setup[9])
    2.46 +
    2.47 +                server.Ack("SETUP")
    2.48 +
    2.49 +            else:
    2.50 +                lib.log("Wrong SETUP command from: %s" % client)
    2.51  
    2.52          elif (msg == "PLAY"):
    2.53              media.play()
    2.54 +            server.Ack("PLAY")
    2.55  
    2.56          elif (msg == "STOP"):
    2.57              media.stop()
    2.58 +            server.Ack("STOP")
    2.59  
    2.60          elif (msg == "CLOSE"):
    2.61              server.finish = 1
    2.62              media.stop()
    2.63 +            server.Ack("CLOSE")
    2.64              break
    2.65  
    2.66 -        print "[%s] %s: %s" % (now(), client, msg)
    2.67 -
    2.68 -    print "[%s] Closing connection with %s" % (now(), client)
    2.69 +    lib.log("Closing connection with %s" % client[0])
    2.70      server.disconnect_client(con)
    2.71  
    2.72  server.stop()
    2.73  del(server)
    2.74 -print "--> Server stopped..."
    2.75 +lib.log("Server stopped. Closing...")
    2.76 +
     3.1 --- a/gmyth-stream/plugins/comm/tcp.py	Thu Mar 29 23:14:32 2007 +0100
     3.2 +++ b/gmyth-stream/plugins/comm/tcp.py	Fri Mar 30 04:12:52 2007 +0100
     3.3 @@ -1,3 +1,4 @@
     3.4 +import lib
     3.5  import time
     3.6  import socket
     3.7  
     3.8 @@ -12,17 +13,20 @@
     3.9          self.tcp.bind( (self.host, self.port) )
    3.10          self.tcp.listen(1)
    3.11  
    3.12 -    def now(self):
    3.13 -        return time.strftime("%Y-%m-%d %H:%M:%S");
    3.14 +    def getMsg(self, size):
    3.15 +        return self.con.recv(size)
    3.16  
    3.17 -    def getMsg(self, size):
    3.18 -        con = self.data[0]
    3.19 -        return con.recv(size)
    3.20 +    def sendMsg(self, msg):
    3.21 +        self.con.send(msg)
    3.22 +
    3.23 +    def Ack(self, command):
    3.24 +        msg = "[%s] Command %s received" % (lib.now(), command)
    3.25 +        self.sendMsg(msg + "\n")
    3.26  
    3.27      def getRequest(self):
    3.28 -        self.data = self.tcp.accept()
    3.29 -        print "[%s] Received request from ip=%s" % (self.now(), self.data[1] )
    3.30 -        return self.data
    3.31 +        self.con, self.client = self.tcp.accept()
    3.32 +        print "[%s] Received request from ip=%s" % (lib.now(), self.client )
    3.33 +        return (self.con, self.client)
    3.34  
    3.35      def disconnect_client(self, connection):
    3.36          connection.close()
     4.1 --- a/gmyth-stream/plugins/comm/xmlrpc.py	Thu Mar 29 23:14:32 2007 +0100
     4.2 +++ b/gmyth-stream/plugins/comm/xmlrpc.py	Fri Mar 30 04:12:52 2007 +0100
     4.3 @@ -1,74 +1,58 @@
     4.4 - '''
     4.5 - # GMyth-Stream
     4.6 - #
     4.7 - # @file plugins/comm/xmlrpc.py
     4.8 - #
     4.9 - # @brief <p> Plugin for GMyth-Stream
    4.10 - #
    4.11 - # Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
    4.12 - # @author Artur Duque de Souza <artur.souza@indt.org.br>
    4.13 - #
    4.14 - #
    4.15 - # This program is free software; you can redistribute it and/or modify
    4.16 - # it under the terms of the GNU Lesser General Public License as published by
    4.17 - # the Free Software Foundation; either version 2 of the License, or
    4.18 - # (at your option) any later version.
    4.19 - #
    4.20 - # This program is distributed in the hope that it will be useful,
    4.21 - # but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.22 - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.23 - # GNU General Public License for more details.
    4.24 - #
    4.25 - # You should have received a copy of the GNU Lesser General Public License
    4.26 - # along with this program; if not, write to the Free Software
    4.27 - # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.28 - #
    4.29 - '''
    4.30 -
    4.31 +import lib
    4.32  import SimpleXMLRPCServer
    4.33  
    4.34  
    4.35  class Handler:
    4.36  
    4.37 -    def __init__(self, pool):
    4.38 -        self.pool = pool
    4.39 +    def __init__(self, recv_pool, send_pool):
    4.40 +        self.recv_pool = recv_pool
    4.41 +        self.send_pool = send_pool
    4.42 +        self.getMsg = self.sendMsg
    4.43  
    4.44      def _listMethods(self):
    4.45 -        return ['Setup', 'Play', 'Stop', 'Close']
    4.46 +        return ['setup', 'play', 'stop', 'close', 'getMsg']
    4.47  
    4.48      def _methodHelp(self, method):
    4.49  
    4.50 -        if method == 'Setup':
    4.51 -            return "Setup the Media: Setup(filename,codec,bitrate,widht,height,port)"
    4.52 -        elif method == 'Play':
    4.53 -            return "Play the Media: Play()"
    4.54 -        elif method == 'Stop':
    4.55 -            return "Stop the Media: Stop()"
    4.56 -        elif method == 'Close':
    4.57 -            return "Close the connection: Close()"
    4.58 +        if method == 'setup':
    4.59 +            return "Setup the Media: setup( filename, mux, vcodec, vbitrate, fps, acodec, abitrate, width, height, port"
    4.60 +        elif method == 'play':
    4.61 +            return "Play the Media: play()"
    4.62 +        elif method == 'stop':
    4.63 +            return "Stop the Media: stop()"
    4.64 +        elif method == 'close':
    4.65 +            return "Close the connection: close()"
    4.66 +        elif method == 'getMsg':
    4.67 +            return "Return the first message in the pool: getMsg()"
    4.68          else:
    4.69              # By convention, return empty
    4.70              # string if no help is available
    4.71              return ""
    4.72  
    4.73 +    def setup(self, filename, mux, vcodec, vbitrate,\
    4.74 +            fps, acodec, abitrate, width, height, port):
    4.75 +        self.recv_pool.append("SETUP")
    4.76 +        self.recv_pool.append("%s %s %s %s %s %s %s" % (filename, mux, vcodec, vbitrate,\
    4.77 +                                                        fps, acodec, abitrate, width, height, port)
    4.78 +        return self.sendMsg()
    4.79  
    4.80 -    def Setup(self, filename, codec, bitrate, width, height, port):
    4.81 -        self.pool.append("SETUP")
    4.82 -        self.pool.append("%s %s %s %s %s %s" % (filename, codec, bitrate,\
    4.83 -                                             width, height, port))
    4.84 -        return 0
    4.85 +    def play(self):
    4.86 +        self.recv_pool.append("PLAY")
    4.87 +        return self.sendMsg()
    4.88  
    4.89 -    def Play(self):
    4.90 -        self.pool.append("PLAY")
    4.91 -        return 0
    4.92 +    def stop(self):
    4.93 +        self.recv_pool.append("STOP")
    4.94 +        return self.sendMsg()
    4.95  
    4.96 -    def Stop(self):
    4.97 -        self.pool.append("STOP")
    4.98 -        return 0
    4.99 +    def close(self):
   4.100 +        self.recv_pool.append("CLOSE")
   4.101 +        return self.sendMsg()
   4.102  
   4.103 -    def Close(self):
   4.104 -        self.pool.append("CLOSE")
   4.105 -        return 0
   4.106 +    def sendMsg(self):
   4.107 +        if self.send_pool != []:
   4.108 +            return self.send_pool.pop(0)
   4.109 +        else:
   4.110 +            return ""
   4.111  
   4.112  
   4.113  class Server:
   4.114 @@ -77,20 +61,28 @@
   4.115          self.host = 'localhost'
   4.116          self.port = int(config.get("Comm", "port"))
   4.117          self.finish = 0
   4.118 -        self.pool = []
   4.119 +        self.recv_pool = []
   4.120 +        self.send_pool = []
   4.121  
   4.122 -        self.handler = Handler(self.pool)
   4.123 +        self.handler = Handler(self.recv_pool, self.send_pool)
   4.124  
   4.125          self.xmlrpc = SimpleXMLRPCServer.SimpleXMLRPCServer((self.host, self.port))
   4.126          self.xmlrpc.register_instance(self.handler)
   4.127  
   4.128  
   4.129      def getMsg(self, size):
   4.130 -        try:
   4.131 -            return self.pool.pop(0)
   4.132 -        except IndexError:
   4.133 +        if self.recv_pool != []:
   4.134 +            return self.recv_pool.pop(0)
   4.135 +        else:
   4.136              return ""
   4.137  
   4.138 +    def sendMsg(self, msg):
   4.139 +        self.send_pool.append(msg)
   4.140 +
   4.141 +    def Ack(self, command):
   4.142 +        msg = "[%s] Command %s received" % (lib.now(), command)
   4.143 +        self.sendMsg(msg + "\n")
   4.144 +
   4.145      def getRequest(self):
   4.146          self.xmlrpc.handle_request()
   4.147          return (0, "RPC Client")
     5.1 --- a/gmyth-stream/plugins/media/ffmpeg.py	Thu Mar 29 23:14:32 2007 +0100
     5.2 +++ b/gmyth-stream/plugins/media/ffmpeg.py	Fri Mar 30 04:12:52 2007 +0100
     5.3 @@ -1,5 +1,6 @@
     5.4  import os
     5.5  import sys
     5.6 +import lib
     5.7  import time
     5.8  import socket
     5.9  import ConfigParser
    5.10 @@ -9,6 +10,8 @@
    5.11      def __init__(self, config):
    5.12  
    5.13          self.config = config
    5.14 +        self.socket = None
    5.15 +        self.child_pid = None
    5.16  
    5.17      def setup(self, filename, mux, vcodec, vbitrate,\
    5.18                fps, acodec, abitrate, width, height, port):
    5.19 @@ -27,18 +30,22 @@
    5.20  
    5.21          # good one: /tmp/mpg/cpm.mpg mpeg mpeg1video 400 25 mp2 192 320 240 5000
    5.22          self.path = self.config.get("FFmpeg", "path")
    5.23 -        self.path += " -i %s -f %s -vcodec %s -b %d -r %d -acodec %s -ab %d -s %dx%d -" % (
    5.24 +        self.path += " -i %s -bufsize 4096 -f %s -vcodec %s -b %d -r %d -acodec %s -ab %d -s %dx%d -" % (
    5.25              self.filename, self.mux, self.vcodec, self.vbitrate,\
    5.26              self.fps, self.acodec, self.abitrate, self.width, self.height)
    5.27  
    5.28 +        if (self.socket != None):
    5.29 +            del(self.socket)
    5.30 +
    5.31          self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    5.32          self.socket.bind( ('', self.port) )
    5.33 +        self.socket.settimeout(10)
    5.34  
    5.35      def play(self):
    5.36  
    5.37          self.socket.listen(1)
    5.38  
    5.39 -        print "Starting FFmpeg: %s" % self.path
    5.40 +        lib.log("Starting FFmpeg: %s" % self.path)
    5.41  
    5.42          # exec FFmpeg and get stdout
    5.43          child_stdin, child_stdout = os.popen2(self.path)
    5.44 @@ -49,24 +56,35 @@
    5.45              #child
    5.46  
    5.47              conn,addr= self.socket.accept()
    5.48 -            print "--> Sending Data..."
    5.49 -            data = child_stdout.read(1024)
    5.50 +            lib.log("Sending Data to client: %s" % addr[0])
    5.51 +            data = child_stdout.read(4096)
    5.52 +            conn.settimeout(5)
    5.53 +            retry = 0
    5.54  
    5.55 -            while( data != ""):
    5.56 +            while( data != "" and retry < 5):
    5.57                  try:
    5.58                      conn.send(data)
    5.59                  except socket.error:
    5.60 -                    break
    5.61 +                    lib.log("Socket error (maybe timeout ?)")
    5.62 +                    retry = retry + 1
    5.63 +
    5.64                  data = child_stdout.read(1024)
    5.65  
    5.66 -            print "--> Finished sending data..."
    5.67 -            conn.close()
    5.68 +            if (retry < 5):
    5.69 +                lib.log("Finished sending Data to client: %s" % addr[0])
    5.70 +            else:
    5.71 +                lib.log("Client timed out")
    5.72 +
    5.73 +            child_stdout.close()
    5.74 +            #conn.close()
    5.75 +            #sys.exit()
    5.76  
    5.77  
    5.78      def stop(self):
    5.79  
    5.80 -        print "--> Trying to stop FFmpeg process..."
    5.81 +        lib.log("Closing socket")
    5.82          self.socket.close()
    5.83 -        os.kill(self.child_pid, 9)
    5.84  
    5.85 -
    5.86 +        lib.log("Trying to stop FFmpeg process")
    5.87 +        if (self.child_pid != None):
    5.88 +            os.kill(self.child_pid, 9)
     6.1 --- a/gmyth-stream/tests/client_ffmpeg.py	Thu Mar 29 23:14:32 2007 +0100
     6.2 +++ b/gmyth-stream/tests/client_ffmpeg.py	Fri Mar 30 04:12:52 2007 +0100
     6.3 @@ -1,24 +1,43 @@
     6.4  import os
     6.5 +import sys
     6.6  import time
     6.7  import socket
     6.8  
     6.9 -HOST='localhost'
    6.10 -PORT=5000
    6.11  
    6.12 -s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    6.13 -s.settimeout(10)
    6.14 +if len(sys.argv) < 2:
    6.15 +    HOST = 'localhost'
    6.16 +    PORT = 5000
    6.17 +elif len(sys.argv) == 2:
    6.18 +    HOST = sys.argv[1]
    6.19 +    PORT = 5000
    6.20 +else:
    6.21 +    HOST = sys.argv[1]
    6.22 +    PORT = int(sys.argv[2])
    6.23  
    6.24 -arq = open('/tmp/dvb.mpg','r')
    6.25 +socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    6.26 +socket.settimeout(10)
    6.27 +
    6.28 +try:
    6.29 +    socket.connect( (HOST,PORT) )
    6.30 +except:
    6.31 +    print "\n--> Could not connect to ('%s':'%d')\n" % (HOST,PORT)
    6.32 +    sys.exit(-1)
    6.33 +
    6.34  
    6.35  mplayer = os.popen("which mplayer").read().strip()
    6.36 -mplayer += " -noidx -"
    6.37 +mplayer += " - 1> /dev/null"
    6.38  pin, pout = os.popen2(mplayer)
    6.39  
    6.40 -s.connect((HOST,PORT))
    6.41 -i = 0
    6.42 -
    6.43 -data = s.recv(1024)
    6.44 +data = socket.recv(1024)
    6.45  while (data != ""):
    6.46      pin.write(data)
    6.47 -    data = s.recv(1024)
    6.48 +    data = socket.recv(1024)
    6.49  
    6.50 +pin.close()
    6.51 +pout.close()
    6.52 +
    6.53 +
    6.54 +# from select import select
    6.55 +# r, w, x = select([pout], []. [], 0)
    6.56 +# if pout in r:
    6.57 +#     pout.read(32)