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