1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/server/0.3/gms.py Tue May 29 21:24:48 2007 +0100
1.3 @@ -0,0 +1,26 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +__author__ = "Artur Duque de Souza"
1.7 +__author_email__ = "artur.souza@indt.org.br"
1.8 +__license__ = "GPL"
1.9 +__version__ = "0.3"
1.10 +__thanks__ = "Gustavo Sverzut Barbieri"
1.11 +
1.12 +import sys
1.13 +import os
1.14 +import logging as log
1.15 +from lib.server import serve_forever, load_plugins_transcoders
1.16 +
1.17 +log_level = log.INFO
1.18 +for p in sys.argv[1:]:
1.19 + if p == "-v" or p == "--verbose":
1.20 + log_level -= 10
1.21 +
1.22 +log.basicConfig(level=log_level,
1.23 + format=("### %(asctime)s %(name)-18s \t%(levelname)-8s "
1.24 + "\t%(message)s"),
1.25 + datefmt="%Y-%m-%d %H:%M:%S")
1.26 +
1.27 +pd = os.path.join("plugins", "transcoders")
1.28 +load_plugins_transcoders(pd)
1.29 +serve_forever()
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/gmyth-stream/server/0.3/html/index.html Tue May 29 21:24:48 2007 +0100
2.3 @@ -0,0 +1,9 @@
2.4 +<html>
2.5 + <head><title>GMyth-Streamer Server</title></head>
2.6 + <body>
2.7 +<h1>Welcome to GMyth-Streamer Server</h1>
2.8 +<ul>
2.9 +%(menu)s
2.10 +</ul>
2.11 + </body>
2.12 +</html>
2.13 \ No newline at end of file
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/gmyth-stream/server/0.3/html/menu.html Tue May 29 21:24:48 2007 +0100
3.3 @@ -0,0 +1,1 @@
3.4 +<li><a href="%(url)s">%(name)s</a></li>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/gmyth-stream/server/0.3/html/shutdown.html Tue May 29 21:24:48 2007 +0100
4.3 @@ -0,0 +1,6 @@
4.4 +<html>
4.5 + <head><title>GMyth-Streamer Server Exited</title></head>
4.6 + <body>
4.7 + <h1>GMyth-Streamer is not running anymore</h1>
4.8 + </body>
4.9 +</html>
4.10 \ No newline at end of file
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/gmyth-stream/server/0.3/html/status.html Tue May 29 21:24:48 2007 +0100
5.3 @@ -0,0 +1,14 @@
5.4 +<html>
5.5 + <head><title>GMyth-Streamer Server Status</title></head>
5.6 + <body>
5.7 + <h1>GMyth-Streamer Status</h1>
5.8 + <ul>
5.9 + %(running)s
5.10 + %(stopall)s
5.11 + %(stopone)s
5.12 + </ul>
5.13 + <ul>
5.14 + %(menu)s
5.15 + </ul>
5.16 + </body>
5.17 +</html>
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/gmyth-stream/server/0.3/html/stop_all.html Tue May 29 21:24:48 2007 +0100
6.3 @@ -0,0 +1,9 @@
6.4 +<html>
6.5 + <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
6.6 + <body>
6.7 + <h1>GMyth-Streamer stopped running transcoders</h1>
6.8 + <ul>
6.9 + %(menu)s
6.10 + </ul>
6.11 + </body>
6.12 +</html>
6.13 \ No newline at end of file
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/gmyth-stream/server/0.3/html/stop_selected.html Tue May 29 21:24:48 2007 +0100
7.3 @@ -0,0 +1,12 @@
7.4 +<html>
7.5 + <head><title>GMyth-Streamer Server Stopped Transcoders</title></head>
7.6 + <body>
7.7 + <h1>GMyth-Streamer stopped running transcoders:</h1>
7.8 + <ul>
7.9 + %(opts)s
7.10 + </ul>
7.11 + <ul>
7.12 + %(menu)s
7.13 + </ul>
7.14 + </body>
7.15 +</html>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/gmyth-stream/server/0.3/lib/log.py Tue May 29 21:24:48 2007 +0100
8.3 @@ -0,0 +1,109 @@
8.4 +#!/usr/bin/env python
8.5 +
8.6 +__author__ = "Artur Duque de Souza"
8.7 +__author_email__ = "artur.souza@indt.org.br"
8.8 +__license__ = "GPL"
8.9 +__version__ = "0.1"
8.10 +
8.11 +import os
8.12 +import logging
8.13 +
8.14 +__all__ = ("Log", "log_structure")
8.15 +
8.16 +class log_structure(object):
8.17 + """Structure to hold log info."""
8.18 +
8.19 + def __init__(self, log=None):
8.20 + self.log = log
8.21 + self.history = []
8.22 + # __init__()
8.23 +
8.24 +# log_structure()
8.25 +
8.26 +class Log(object):
8.27 + """This class implements a log where we can store status of
8.28 + all transcoders (even from those that are not running any more)."""
8.29 +
8.30 + ## key = tid
8.31 + ## item = ls
8.32 + logs = {}
8.33 +
8.34 + def insert(self, tid, name):
8.35 + """Insert a given tid on the log structure"""
8.36 + if not self.logs.has_key(tid):
8.37 + self.logs[tid] = log_structure(logging.getLogger(name))
8.38 + return True
8.39 + else:
8.40 + return False
8.41 + # insert()
8.42 +
8.43 + def remove(self, tid=None):
8.44 + """Cleans up all log stored for a
8.45 + given tid or for all transcodes."""
8.46 + if not tid:
8.47 + self.logs = {}
8.48 + else:
8.49 + del(self.logs[tid])
8.50 +
8.51 + return True
8.52 + # clean()
8.53 +
8.54 + def get_status(self, tid=None, all=False):
8.55 + """Get the status of all transcoders or
8.56 + of just one of them if it's given an tid."""
8.57 + if not tid:
8.58 + ret = {}
8.59 + for tids, logs in self.logs.items():
8.60 + if len(logs.history) > 0:
8.61 + if not all:
8.62 + ret[tids] = logs.history[-1]
8.63 + else:
8.64 + ret[tids] = logs.history
8.65 + return ret
8.66 + elif self.logs.has_key(tid) and len(self.logs[tid].history) > 0:
8.67 + if not all:
8.68 + return self.logs[tid].history[-1]
8.69 + else:
8.70 + return self.logs[tid].history
8.71 +
8.72 + return False
8.73 + # get_status()
8.74 +
8.75 + def _update_status(self, tid=None, msg=""):
8.76 + """Update the status of a given tid. Private method that
8.77 + is only called inside error/info/debug wrappers"""
8.78 + if msg != "":
8.79 + self.logs[tid].history.append(msg)
8.80 + return True
8.81 + else:
8.82 + return False
8.83 + # update_status()
8.84 +
8.85 + def error(self, tid, msg):
8.86 + """Python's Log.error wrapper"""
8.87 + if self.logs.has_key(tid):
8.88 + self.logs[tid].log.error("%s" % msg)
8.89 + return self._update_status(tid, msg)
8.90 + else:
8.91 + return False
8.92 + # error()
8.93 +
8.94 + def info(self, tid, msg):
8.95 + """Python's Log.info wrapper"""
8.96 + if self.logs.has_key(tid):
8.97 + self.logs[tid].log.info("%s" % msg)
8.98 + self._update_status(tid, msg)
8.99 + return True
8.100 + else:
8.101 + return False
8.102 + # info()
8.103 +
8.104 + def debug(self, tid, msg):
8.105 + """Python's Log.debug wrapper"""
8.106 + if self.logs.has_key(tid):
8.107 + self.logs[tid].log.debug("%s" % msg)
8.108 + self._update_status(tid, msg)
8.109 + return True
8.110 + else:
8.111 + return False
8.112 + # debug()
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/gmyth-stream/server/0.3/lib/request_handler.py Tue May 29 21:24:48 2007 +0100
9.3 @@ -0,0 +1,332 @@
9.4 +#!/usr/bin/env python
9.5 +
9.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
9.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
9.8 +__license__ = "GPL"
9.9 +__version__ = "0.4"
9.10 +
9.11 +import os
9.12 +import threading
9.13 +import SocketServer
9.14 +import BaseHTTPServer
9.15 +import socket
9.16 +import urlparse
9.17 +import cgi
9.18 +import lib.utils as utils
9.19 +import logging
9.20 +
9.21 +from log import Log
9.22 +import lib.transcoder as transcoder
9.23 +
9.24 +__all__ = ("RequestHandler")
9.25 +
9.26 +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
9.27 + """Class that implements an HTTP request handler for our server."""
9.28 + log = logging.getLogger("gms.request")
9.29 + def_transcoder = None
9.30 + transcoders = utils.PluginSet(transcoder.Transcoder)
9.31 + transcoders_log = Log()
9.32 + tid_queue = []
9.33 +
9.34 + menu = {
9.35 + "Log": "/get_log.do",
9.36 + "Stop": "/stop-transcoder.do",
9.37 + "Status": "/status.do",
9.38 + "All Log": "/get_all_log.do",
9.39 + "Version": "/version.do",
9.40 + "Shutdown": "/shutdown.do"
9.41 + }
9.42 +
9.43 + @classmethod
9.44 + def load_plugins_transcoders(cls, directory):
9.45 + cls.transcoders.load_from_directory(directory)
9.46 +
9.47 + if cls.def_transcoder is None and cls.transcoders:
9.48 + cls.def_transcoder = cls.transcoders[0].name
9.49 + # load_plugins_transcoders()
9.50 +
9.51 +
9.52 + def do_dispatch(self, body):
9.53 + self.url = self.path
9.54 +
9.55 + pieces = urlparse.urlparse(self.path)
9.56 + self.path = pieces[2]
9.57 + self.query = cgi.parse_qs(pieces[4])
9.58 +
9.59 + if self.path == "/":
9.60 + self.serve_main(body)
9.61 + elif self.path == "/shutdown.do":
9.62 + self.serve_shutdown(body)
9.63 + elif self.path == "/stop-transcoder.do":
9.64 + self.serve_stop_transcoder(body)
9.65 + elif self.path == "/status.do":
9.66 + self.serve_status(body)
9.67 + elif self.path == "/version.do":
9.68 + self.serve_version(body)
9.69 + elif self.path == "/new_id.do":
9.70 + self.serve_new_id(body)
9.71 + elif self.path == "/get_log.do":
9.72 + self.serve_get_log(body)
9.73 + elif self.path == "/get_all_log.do":
9.74 + self.serve_get_all_log(body)
9.75 + elif self.path == "/stream.do":
9.76 + self.serve_stream(body)
9.77 + else:
9.78 + action = self.query.get("action", None)
9.79 + if action and "stream.do" in action:
9.80 + self.serve_stream(body)
9.81 + else:
9.82 + self.send_error(404, "File not found")
9.83 + # do_dispatch()
9.84 +
9.85 +
9.86 + def do_GET(self):
9.87 + self.do_dispatch(True)
9.88 + # do_GET()
9.89 +
9.90 +
9.91 + def do_HEAD(self):
9.92 + self.do_dispatch(False)
9.93 + # do_HEAD()
9.94 +
9.95 +
9.96 + def _nav_items(self):
9.97 + ret = ""
9.98 + for name, url in self.menu.items():
9.99 + ret += utils.getHTML("menu", {"name": name, "url": url})
9.100 +
9.101 + return ret
9.102 + # _nav_items()
9.103 +
9.104 + def serve_main(self, body):
9.105 + self.send_response(200)
9.106 + self.send_header("Content-Type", "text/html")
9.107 + self.send_header('Connection', 'close')
9.108 + self.end_headers()
9.109 + if body:
9.110 + self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
9.111 + # serve_main()
9.112 +
9.113 + def serve_version(self, body):
9.114 + self.send_response(200)
9.115 + self.send_header("Content-Type", "text/html")
9.116 + self.send_header('Connection', 'close')
9.117 + self.end_headers()
9.118 + if body:
9.119 + self.wfile.write("Version: %s" % __version__)
9.120 +
9.121 +
9.122 + def serve_shutdown(self, body):
9.123 + self.send_response(200)
9.124 + self.send_header("Content-Type", "text/html")
9.125 + self.send_header('Connection', 'close')
9.126 + self.end_headers()
9.127 + if body:
9.128 + self.wfile.write(utils.getHTML("shutdown"))
9.129 + self.server.server_close()
9.130 + # serve_shutdown()
9.131 +
9.132 +
9.133 + def serve_stop_all_transcoders(self, body):
9.134 + self.send_response(200)
9.135 + self.send_header("Content-Type", "text/html")
9.136 + self.send_header('Connection', 'close')
9.137 + self.end_headers()
9.138 + if body:
9.139 + self.server.stop_transcoders()
9.140 + self.wfile.write(utils.getHTML("stop_all", {"menu": self._nav_items()}))
9.141 + # serve_stop_all_transcoders()
9.142 +
9.143 +
9.144 + def serve_stop_selected_transcoders(self, body, tids=[]):
9.145 + self.send_response(200)
9.146 + self.send_header("Content-Type", "text/html")
9.147 + self.send_header('Connection', 'close')
9.148 + self.end_headers()
9.149 + opts = ""
9.150 + if body:
9.151 + transcoders = self.server.get_transcoders()
9.152 +
9.153 + for tid in tids:
9.154 + for t, r in transcoders:
9.155 + if t.tid == int(tid):
9.156 + try:
9.157 + t.stop()
9.158 + except Exception, e:
9.159 + self.log.info("Plugin already stopped")
9.160 +
9.161 + opts += utils._create_html_item("%s" % t)
9.162 +
9.163 + break
9.164 +
9.165 + self.wfile.write(utils.getHTML("stop_selected",
9.166 + {"menu": self._nav_items(),
9.167 + "opts": opts}))
9.168 + # serve_stop_selected_transcoders()
9.169 +
9.170 +
9.171 + def serve_stop_transcoder(self, body):
9.172 + req = self.query.get("request", None)
9.173 + tid = self.query.get("tid", None)
9.174 + if req and "all" in req:
9.175 + self.serve_stop_all_transcoders(body)
9.176 + elif tid:
9.177 + self.serve_stop_selected_transcoders(body, tid[0].split(";"))
9.178 + else:
9.179 + self.serve_status(body)
9.180 + # serve_stop_transcoder()
9.181 +
9.182 +
9.183 + def serve_status(self, body):
9.184 + self.send_response(200)
9.185 + self.send_header("Content-Type", "text/html")
9.186 + self.send_header('Connection', 'close')
9.187 + self.end_headers()
9.188 + stopone = ""
9.189 +
9.190 + if body:
9.191 + tl = self.server.get_transcoders()
9.192 + if not tl:
9.193 + running = "<p>No running transcoder.</p>\n"
9.194 + stopall = ""
9.195 + stopone = ""
9.196 +
9.197 + elif self.query.get("tid", None):
9.198 + req_tid = int(self.query.get("tid")[0])
9.199 + for transcoder, request in tl:
9.200 + if transcoder.tid == req_tid:
9.201 + self.wfile.write("Status: %s %%" % transcoder.status)
9.202 + return True
9.203 +
9.204 + return False
9.205 +
9.206 + else:
9.207 + running = "<p>Running transcoders:</p>\n"
9.208 + stopall = utils._create_html_item("<a href='%s?request=all'>"
9.209 + "[STOP ALL]</a>" %
9.210 + self.menu["Stop"])
9.211 +
9.212 + for transcoder, request in tl:
9.213 + stopone += utils._create_html_item("%s;"
9.214 + "<a href='%s?tid=%s'>"
9.215 + " [STOP] </a>") % (
9.216 + transcoder, self.menu["Stop"], transcoder.tid)
9.217 +
9.218 + self.wfile.write(utils.getHTML("status",
9.219 + {"menu": self._nav_items(),
9.220 + "running": running,
9.221 + "stopall": stopall,
9.222 + "stopone": stopone}))
9.223 + # serve_status()
9.224 +
9.225 +
9.226 + def _get_transcoder(self):
9.227 + # get transcoder option: mencoder is the default
9.228 + request_transcoders = self.query.get("transcoder", ["mencoder"])
9.229 +
9.230 + for t in request_transcoders:
9.231 + transcoder = self.transcoders.get(t)
9.232 + if transcoder:
9.233 + return transcoder
9.234 +
9.235 + if not transcoder:
9.236 + return self.transcoders[self.def_transcoder]
9.237 + # _get_transcoder()
9.238 +
9.239 +
9.240 + def _get_new_id(self, tid):
9.241 + self.server.last_tid = utils.create_tid(tid)
9.242 + self.tid_queue.append(self.server.last_tid)
9.243 + return self.server.last_tid
9.244 + # _get_new_id()
9.245 +
9.246 +
9.247 + def serve_new_id(self, body):
9.248 + self.send_response(200)
9.249 + self.send_header("Content-Type", "text/html")
9.250 + self.send_header('Connection', 'close')
9.251 + self.end_headers()
9.252 +
9.253 + if body:
9.254 + self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
9.255 + # serve_new_id()
9.256 +
9.257 + def serve_get_log(self, body):
9.258 + self.send_response(200)
9.259 + self.send_header("Content-Type", "text/html")
9.260 + self.send_header('Connection', 'close')
9.261 + self.end_headers()
9.262 +
9.263 + if body:
9.264 + if self.query.get("tid", None):
9.265 + tid = int(self.query.get("tid")[0])
9.266 + stat = self.transcoders_log.get_status(tid)
9.267 + self.wfile.write("%s" % stat)
9.268 + else:
9.269 + stat = self.transcoders_log.get_status()
9.270 + for rtid, status in stat.iteritems():
9.271 + self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
9.272 + # serve_get_log()
9.273 +
9.274 + def serve_get_all_log(self, body):
9.275 + self.send_response(200)
9.276 + self.send_header("Content-Type", "text/html")
9.277 + self.send_header('Connection', 'close')
9.278 + self.end_headers()
9.279 +
9.280 + if body:
9.281 + if self.query.get("tid", None):
9.282 + tid = int(self.query.get("tid")[0])
9.283 + stat = self.transcoders_log.get_status(tid, True)
9.284 + for status in stat:
9.285 + self.wfile.write("%s<br><br>" % status)
9.286 + else:
9.287 + stat = self.transcoders_log.get_status(None, True)
9.288 + for rtid, history in stat.iteritems():
9.289 + for status in history:
9.290 + self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
9.291 + self.wfile.write("<br><br>")
9.292 + # serve_get_all_log()
9.293 +
9.294 + def serve_stream(self, body):
9.295 + transcoder = self._get_transcoder()
9.296 + try:
9.297 + obj = transcoder(self.query)
9.298 + except Exception, e:
9.299 + self.send_error(500, str(e))
9.300 + return
9.301 +
9.302 + self.send_response(200)
9.303 + self.send_header("Content-Type", obj.get_mimetype())
9.304 + self.send_header('Connection', 'close')
9.305 + self.end_headers()
9.306 +
9.307 + if body:
9.308 + test_tid = int(self.query.get("tid", "0")[0])
9.309 + if test_tid == 0 or test_tid not in self.tid_queue:
9.310 + test_tid = self._get_new_id(self.server.last_tid)
9.311 +
9.312 + self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
9.313 + obj.tid = test_tid
9.314 + obj.log = self.transcoders_log
9.315 +
9.316 + self.server.add_transcoders(self, obj)
9.317 + obj.start(self.wfile)
9.318 + self.server.del_transcoders(self, obj)
9.319 + # serve_stream()
9.320 +
9.321 +
9.322 + def log_request(self, code='-', size='-'):
9.323 + self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
9.324 + # log_request()
9.325 +
9.326 +
9.327 + def log_error(self, format, *args):
9.328 + self.log.error("%s: %s" % (self.address_string(), format % args))
9.329 + # log_error()
9.330 +
9.331 +
9.332 + def log_message(self, format, *args):
9.333 + self.log.info("%s: %s" % (self.address_string(), format % args))
9.334 + # log_message()
9.335 +# RequestHandler
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/gmyth-stream/server/0.3/lib/server.py Tue May 29 21:24:48 2007 +0100
10.3 @@ -0,0 +1,117 @@
10.4 +#!/usr/bin/env python
10.5 +
10.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
10.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
10.8 +__license__ = "GPL"
10.9 +__version__ = "0.4"
10.10 +
10.11 +import os
10.12 +import threading
10.13 +import SocketServer
10.14 +import BaseHTTPServer
10.15 +import socket
10.16 +import urlparse
10.17 +import cgi
10.18 +import lib.utils as utils
10.19 +import logging
10.20 +
10.21 +from log import Log
10.22 +from request_handler import RequestHandler
10.23 +
10.24 +__all__ = ("Server", "serve_forever", "load_plugins_transcoders")
10.25 +
10.26 +class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
10.27 + log = logging.getLogger("gms.server")
10.28 + last_tid = 0
10.29 + run = True
10.30 + _transcoders = {}
10.31 + _lock = threading.RLock()
10.32 +
10.33 + def serve_forever(self):
10.34 + self.log.info("GMyth-Streamer serving HTTP on %s:%s" %
10.35 + self.socket.getsockname())
10.36 + try:
10.37 + while self.run:
10.38 + self.handle_request()
10.39 + except KeyboardInterrupt, e:
10.40 + pass
10.41 +
10.42 + self.log.debug("Stopping all remaining transcoders...")
10.43 + self.stop_transcoders()
10.44 + self.log.debug("Transcoders stopped!")
10.45 + # serve_forever()
10.46 +
10.47 +
10.48 + def get_request(self):
10.49 + skt = self.socket
10.50 + old = skt.gettimeout()
10.51 + skt.settimeout(0.5)
10.52 + while self.run:
10.53 + try:
10.54 + r = skt.accept()
10.55 + skt.settimeout(old)
10.56 + return r
10.57 + except socket.timeout, e:
10.58 + pass
10.59 + raise socket.error("Not running")
10.60 + # get_request()
10.61 +
10.62 +
10.63 + def server_close(self):
10.64 + self.run = False
10.65 + self.stop_transcoders()
10.66 +
10.67 + BaseHTTPServer.HTTPServer.server_close(self)
10.68 + # server_close()
10.69 +
10.70 +
10.71 + def stop_transcoders(self):
10.72 + self._lock.acquire()
10.73 + for transcoder, request in self._transcoders.iteritems():
10.74 + self.log.info("Stop transcoder: %s, client=%s" %
10.75 + (transcoder, request.client_address))
10.76 + transcoder.stop()
10.77 + self._lock.release()
10.78 + # stop_transcoders()
10.79 +
10.80 +
10.81 + def get_transcoders(self):
10.82 + self._lock.acquire()
10.83 + try:
10.84 + return self._transcoders.items()
10.85 + finally:
10.86 + self._lock.release()
10.87 + # get_transcoders()
10.88 +
10.89 +
10.90 + def add_transcoders(self, request, transcoder):
10.91 + self._lock.acquire()
10.92 + try:
10.93 + self._transcoders[transcoder] = request
10.94 + finally:
10.95 + self._lock.release()
10.96 + # add_transcoders()
10.97 +
10.98 +
10.99 + def del_transcoders(self, request, transcoder):
10.100 + self._lock.acquire()
10.101 + try:
10.102 + del self._transcoders[transcoder]
10.103 + finally:
10.104 + self._lock.release()
10.105 + # del_transcoders()
10.106 +# Server
10.107 +
10.108 +
10.109 +
10.110 +def serve_forever(host="0.0.0.0", port=40000):
10.111 + addr = (host, port)
10.112 + RequestHandler.protocol_version = "HTTP/1.0"
10.113 + httpd = Server(addr, RequestHandler)
10.114 + httpd.serve_forever()
10.115 +# serve_forever()
10.116 +
10.117 +
10.118 +def load_plugins_transcoders(directory):
10.119 + RequestHandler.load_plugins_transcoders(directory)
10.120 +# load_plugins_transcoders()
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/gmyth-stream/server/0.3/lib/transcoder.py Tue May 29 21:24:48 2007 +0100
11.3 @@ -0,0 +1,60 @@
11.4 +#!/usr/bin/env python
11.5 +
11.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
11.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
11.8 +__license__ = "GPL"
11.9 +__version__ = "0.4"
11.10 +
11.11 +__all__ = ("Transcoder")
11.12 +
11.13 +class Transcoder(object):
11.14 + """Transcoder's Class: parent class to implement
11.15 + a plugin for transcoding data."""
11.16 + priority = 0 # negative values have higher priorities
11.17 + name = None # to be used in requests
11.18 + status = None
11.19 + log = None
11.20 + tid = -1
11.21 +
11.22 + def __init__(self, params):
11.23 + self.params = params
11.24 + # __init__()
11.25 +
11.26 +
11.27 + def params_first(self, key, default=None):
11.28 + if default is None:
11.29 + return self.params[key][0]
11.30 + else:
11.31 + try:
11.32 + return self.params[key][0]
11.33 + except:
11.34 + return default
11.35 + # params_first()
11.36 +
11.37 +
11.38 + def get_mimetype(self):
11.39 + mux = self.params_first("mux", "mpg")
11.40 +
11.41 + if mux == "mpeg":
11.42 + return "video/mpeg"
11.43 + elif mux == "avi":
11.44 + return "video/x-msvideo"
11.45 + else:
11.46 + return "application/octet-stream"
11.47 + # get_mimetype()
11.48 +
11.49 + def start(self, outfile):
11.50 + return True
11.51 + # start()
11.52 +
11.53 +
11.54 + def stop(self):
11.55 + return True
11.56 + # stop()
11.57 +
11.58 + def __str__(self):
11.59 + return '%s: %s( params=%s ) - Status: %s%%' % \
11.60 + (self.__class__.__name__, self.tid,
11.61 + self.params, self.status)
11.62 + # __str__()
11.63 +# Transcoder
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/gmyth-stream/server/0.3/lib/utils.py Tue May 29 21:24:48 2007 +0100
12.3 @@ -0,0 +1,188 @@
12.4 +#!/usr/bin/env
12.5 +
12.6 +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
12.7 +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
12.8 +__license__ = "GPL"
12.9 +__version__ = "0.3"
12.10 +
12.11 +import os
12.12 +import stat
12.13 +import sys
12.14 +import logging
12.15 +import urllib
12.16 +import gobject
12.17 +import imp
12.18 +
12.19 +log = logging.getLogger("gms.utils")
12.20 +
12.21 +__all__ = ("which", "load_plugins", "PluginSet", "getHTML")
12.22 +
12.23 +def which(app):
12.24 + """Function to implement which(1) unix command"""
12.25 + pl = os.environ["PATH"].split(os.pathsep)
12.26 + for p in pl:
12.27 + path = os.path.join(p, app)
12.28 + if os.path.isfile(path):
12.29 + st = os.stat(path)
12.30 + if st[stat.ST_MODE] & 0111:
12.31 + return path
12.32 + return ""
12.33 +# which()
12.34 +
12.35 +
12.36 +def _load_module(pathlist, name):
12.37 + fp, path, desc = imp.find_module(name, pathlist)
12.38 + try:
12.39 + module = imp.load_module(name, fp, path, desc)
12.40 + return module
12.41 + finally:
12.42 + if fp:
12.43 + fp.close()
12.44 +# _load_module()
12.45 +
12.46 +
12.47 +class PluginSet(object):
12.48 + def __init__(self, basetype, *items):
12.49 + self.basetype = basetype
12.50 + self.map = {}
12.51 + self.list = []
12.52 +
12.53 + for i in items:
12.54 + self._add(i)
12.55 + self._sort()
12.56 + # __init__()
12.57 +
12.58 +
12.59 + def _add(self, item):
12.60 + self.map[item.name] = item
12.61 + self.list.append(item)
12.62 + # _add()
12.63 +
12.64 +
12.65 + def add(self, item):
12.66 + self._add()
12.67 + self._sort()
12.68 + # add()
12.69 +
12.70 +
12.71 + def __getitem__(self, spec):
12.72 + if isinstance(spec, basestring):
12.73 + return self.map[spec]
12.74 + else:
12.75 + return self.list[spec]
12.76 + # __getitem__()
12.77 +
12.78 +
12.79 + def get(self, name, default=None):
12.80 + return self.map.get(name, default)
12.81 + # get()
12.82 +
12.83 +
12.84 + def __iter__(self):
12.85 + return self.list.__iter__()
12.86 + # __iter__()
12.87 +
12.88 +
12.89 + def __len__(self):
12.90 + return len(self.list)
12.91 + # __len__()
12.92 +
12.93 +
12.94 + def _sort(self):
12.95 + self.list.sort(lambda a, b: cmp(a.priority, b.priority))
12.96 + # _sort()
12.97 +
12.98 +
12.99 + def update(self, pluginset):
12.100 + self.map.update(pluginset.map)
12.101 + self.list.extend(pluginset.list)
12.102 + self._sort()
12.103 + # update()
12.104 +
12.105 +
12.106 + def load_from_directory(self, directory):
12.107 + for i in load_plugins(directory, self.basetype):
12.108 + self._add(i)
12.109 + self._sort()
12.110 + # load_from_directory()
12.111 +
12.112 +
12.113 + def __str__(self):
12.114 + lst = []
12.115 + for o in self.list:
12.116 + lst.append('"%s" (%s)' % (o.name, o.__name__))
12.117 +
12.118 + return "%s(basetype=%s, items=[%s])" % \
12.119 + (self.__class__.__name__,
12.120 + self.basetype.__name__,
12.121 + ", ".join(lst))
12.122 + # __str__()
12.123 +# PluginSet
12.124 +
12.125 +
12.126 +def load_plugins(directory, basetype):
12.127 + """Function to load plugins from a given directory"""
12.128 + tn = basetype.__name__
12.129 + log.debug("Loading plugins from %s, type=%s" % (directory, tn))
12.130 +
12.131 +
12.132 + plugins = []
12.133 + for d in os.listdir(directory):
12.134 + if not d.endswith(".py"):
12.135 + continue
12.136 +
12.137 + name = d[0: -3]
12.138 + if name == "__init__":
12.139 + continue
12.140 +
12.141 + directory.replace(os.path.sep, ".")
12.142 + mod = _load_module([directory], name)
12.143 + for sym in dir(mod):
12.144 + cls = getattr(mod, sym)
12.145 + if isinstance(cls, type) and issubclass(cls, basetype) and \
12.146 + cls != basetype:
12.147 + plugins.append(cls)
12.148 + log.info("Loaded %s (%s) from %s" % \
12.149 + (cls.__name__, tn, os.path.join(directory, d)))
12.150 +
12.151 + return plugins
12.152 +# load_plugins()
12.153 +
12.154 +def getHTML(html_file, params={}):
12.155 + """This function parses an html file with the given
12.156 + parameters and returns a formated web-page"""
12.157 + try:
12.158 + filename = os.path.join(sys.path[0], "html", html_file + ".html")
12.159 + html = open(filename).read() % params
12.160 + return html
12.161 + except Exception, e:
12.162 + return "HTML format error. Wrong keys: %s" % e
12.163 +
12.164 +# getHTML
12.165 +
12.166 +def _create_html_item(opt):
12.167 + """Create an <li> item using HTML."""
12.168 + return "<li>%s</li>\n" % opt
12.169 +# _create_html_item
12.170 +
12.171 +def progress_bar(log, value, max, barsize):
12.172 + """Creates and displays a progressbar. By OSantana"""
12.173 + chars = int(value * barsize / float(max))
12.174 + percent = int((value / float(max)) * 100)
12.175 + sys.stdout.write("#" * chars)
12.176 + sys.stdout.write(" " * (barsize - chars + 2))
12.177 + if value >= max:
12.178 + sys.stdout.write("done.\n\n")
12.179 + else:
12.180 + sys.stdout.write("[%3i%%]\r" % (percent))
12.181 + sys.stdout.flush()
12.182 + return percent
12.183 +# progress_bar() by osantana
12.184 +
12.185 +def create_tid(last_tid):
12.186 + """Function to generate TIDs (ids for transcoders).
12.187 + At first it just do +1 on last_tid but can be implemented
12.188 + to generate more sparse TIDs"""
12.189 + tid = last_tid + 1
12.190 + return tid
12.191 +# create_id()
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/gmyth-stream/server/0.3/plugins/transcoders/gmencoder.py Tue May 29 21:24:48 2007 +0100
13.3 @@ -0,0 +1,99 @@
13.4 +#!/usr/bin/env python
13.5 +
13.6 +__author__ = "Renato Filho"
13.7 +__author_email__ = "renato.filho@indt.org.br"
13.8 +__license__ = "GPL"
13.9 +__version__ = "0.1"
13.10 +
13.11 +import os
13.12 +import shlex
13.13 +import signal
13.14 +import subprocess
13.15 +import time
13.16 +
13.17 +import select
13.18 +
13.19 +import lib.utils as utils
13.20 +import lib.server as server
13.21 +import lib.transcoder as transcoder
13.22 +
13.23 +__all__ = ("TranscoderGMencoder",)
13.24 +
13.25 +class TranscoderGMencoder(transcoder.Transcoder):
13.26 + gmencoder_path = utils.which("gmencoder")
13.27 + name = "gmencoder"
13.28 + priority = -1
13.29 + proc = None
13.30 +
13.31 + def __init__(self, params):
13.32 + transcoder.Transcoder.__init__(self, params)
13.33 + self.opts = []
13.34 + # __init__()
13.35 +
13.36 + def _insert_param (self, name, value):
13.37 + if (value != ""):
13.38 + self.opts.append(name)
13.39 + self.opts.append(value)
13.40 +
13.41 + def _parser_params (self):
13.42 + self._insert_param("-i", \
13.43 + "%s://%s" % (self.params_first("type", "file"), self.params_first("uri", "")))
13.44 + self._insert_param("--video-encode", self.params_first("ve", ""))
13.45 + self._insert_param("--video-opts", "bitrate=200,pass=2,quantizer=5")
13.46 + self._insert_param("--video-fps", self.params_first("fps", ""))
13.47 + self._insert_param("--video-width", self.params_first("width", ""))
13.48 + self._insert_param("--video-height", self.params_first("height", ""))
13.49 + self._insert_param("--audio-rate", "32000")
13.50 + self._insert_param("--audio-encode", self.params_first("ae", ""))
13.51 + # _parse_params
13.52 +
13.53 + def start(self, outfd):
13.54 + self.opts.append (self.gmencoder_path)
13.55 + self._parser_params ()
13.56 + self._insert_param ("-o", "fd://%d" % outfd.fileno())
13.57 +
13.58 + cmd = " ".join(self.opts)
13.59 + self.log.info ("GMencoder: %s", cmd)
13.60 +
13.61 + try:
13.62 + self.proc = subprocess.Popen(self.opts, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
13.63 + except Exception, e:
13.64 + self.log.error(self.tid, "Error executing GMencoder: %s" % e)
13.65 + return False
13.66 +
13.67 + try:
13.68 + while (self.proc and self.proc.poll() == None):
13.69 + r, w, x = select.select([self.proc.stdout], [], [], 0)
13.70 + if self.proc.stdout in r:
13.71 + progress = self.proc.stdout.readline()
13.72 + self.log.info ("stdout %s" % progress)
13.73 + if (progress.find ("PROGRESS") >= 0):
13.74 + self.status = progress.split (":")[1]
13.75 + #if (progress.find ("DONE") >= 0):
13.76 + # break
13.77 + self.log.info ("Process exit")
13.78 + except Exception, e:
13.79 + self.log.error(self.tid, "Problems handling data: %s" % e)
13.80 + return False
13.81 +
13.82 + return True
13.83 + # start()
13.84 +
13.85 +
13.86 + def stop(self):
13.87 + if self.proc:
13.88 + self.log.info ("STOPED GMencoder plugin")
13.89 + try:
13.90 + self.proc.stdin.write ("QUIT\n")
13.91 + except Exception, e:
13.92 + pass
13.93 +
13.94 + try:
13.95 + self.proc.wait()
13.96 + except Exception, e:
13.97 + pass
13.98 +
13.99 + self.proc = None
13.100 + # stop()
13.101 +
13.102 +# TranscoderGMencoder
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/gmyth-stream/server/0.3/plugins/transcoders/mencoder.py Tue May 29 21:24:48 2007 +0100
14.3 @@ -0,0 +1,305 @@
14.4 +#!/usr/bin/env python
14.5 +
14.6 +__author__ = "Artur Duque de Souza"
14.7 +__author_email__ = "artur.souza@indt.org.br"
14.8 +__license__ = "GPL"
14.9 +__version__ = "0.1"
14.10 +
14.11 +import os
14.12 +import shlex
14.13 +import signal
14.14 +import subprocess
14.15 +import time
14.16 +import fcntl
14.17 +
14.18 +import lib.utils as utils
14.19 +import lib.server as server
14.20 +import plugins.transcoders.mencoder_lib.mythtv as mythtv
14.21 +
14.22 +from select import select
14.23 +import lib.transcoder as transcoder
14.24 +
14.25 +__all__ = ("TranscoderMencoder",)
14.26 +
14.27 +class TranscoderMencoder(transcoder.Transcoder):
14.28 + """Transcoder class that implements a transcoder using Mencoder"""
14.29 + mencoder_path = utils.which("mencoder")
14.30 + name = "mencoder"
14.31 + priority = -1
14.32 + args = {}
14.33 + proc = None
14.34 + gmyth = None
14.35 +
14.36 + # only works with avi container
14.37 + status = 0
14.38 +
14.39 + def _setup_params(self):
14.40 + params_first = self.params_first
14.41 +
14.42 + # general_opts
14.43 + self.args["local"] = params_first("local", False)
14.44 + self.args["language"] = params_first("language", False)
14.45 + self.args["subtitle"] = params_first("subtitle", False)
14.46 + self.args["format"] = params_first("format", "mpeg1")
14.47 + self.args["outfile"] = params_first("outfile", "-")
14.48 +
14.49 + # input_opt
14.50 + self.args["type"] = params_first("type", "file")
14.51 + self.args["input"] = params_first("uri", "-")
14.52 +
14.53 + # audio_opts
14.54 + self.args["acodec"] = params_first("acodec", "mp2")
14.55 + self.args["abitrate"] = params_first("abitrate", 192)
14.56 + self.args["volume"] = params_first("volume", 5)
14.57 +
14.58 + # video_opts
14.59 + self.args["mux"] = params_first("mux", "mpeg")
14.60 + self.args["fps"] = params_first("fps", 25)
14.61 + self.args["vcodec"] = params_first("vcodec", "mpeg1video")
14.62 + self.args["vbitrate"] = params_first("vbitrate", 400)
14.63 + self.args["width"] = params_first("width", 320)
14.64 + self.args["height"] = params_first("height", 240)
14.65 + # _setup_params()
14.66 +
14.67 +
14.68 + def _setup_audio(self):
14.69 + if self.args["acodec"] == "mp3lame":
14.70 + audio = "-oac mp3lame -lameopts cbr:br=%s vol=%s" % (
14.71 + self.args["abitrate"], self.args["volume"])
14.72 + else:
14.73 + audio = "-oac lavc -lavcopts acodec=%s:abitrate=%s" % (
14.74 + self.args["acodec"], self.args["abitrate"])
14.75 +
14.76 + return audio
14.77 + # _setup_audio()
14.78 +
14.79 +
14.80 + def _setup_video(self):
14.81 + video = " -of %s" % self.args["mux"]
14.82 + video += " -ofps %s" % self.args["fps"]
14.83 +
14.84 + vcodec = self.args["vcodec"]
14.85 + if vcodec == "nuv" or vcodec == "xvid"\
14.86 + or vcodec == "qtvideo" or vcodec == "copy":
14.87 + video += " -ovc %s" % vcodec
14.88 + else:
14.89 + video += " -ovc lavc -lavcopts vcodec=%s:vbitrate=%s" % (
14.90 + vcodec, self.args["vbitrate"])
14.91 +
14.92 + if self.args["mux"] == "mpeg":
14.93 + video += " -mpegopts format=%s" % self.args["format"]
14.94 + video += " -vf scale=%s:%s" % (self.args["width"], self.args["height"])
14.95 +
14.96 + return video
14.97 + # _setup_video()
14.98 +
14.99 +
14.100 + def _arg_append(self, args, options):
14.101 + for arg in shlex.split(options):
14.102 + args.append(arg)
14.103 + # arg_append()
14.104 +
14.105 + def _setup_mencoder_opts(self, args):
14.106 + args.append(self.mencoder_path)
14.107 +
14.108 + if self.args["outfile"] == "-" and self.args["type"]:
14.109 + args.append(self.args["input"])
14.110 + else:
14.111 + args.append("-")
14.112 +
14.113 + if self.args["language"]:
14.114 + self._arg_append(args, "-alang %s" % self.args["language"])
14.115 +
14.116 + if self.args["subtitle"]:
14.117 + self._arg_append(args, "-slang %s" % self.args["subtitle"])
14.118 + self._arg_append(args, "-subfps %s" % self.args["fps"])
14.119 +
14.120 + self._arg_append(args, "-idx")
14.121 + self._arg_append(args, "-cache 1024")
14.122 + self._arg_append(args, self._setup_audio())
14.123 + self._arg_append(args, self._setup_video())
14.124 +
14.125 + self._arg_append(args, "-really-quiet")
14.126 + self._arg_append(args, "-o %s" % self.args["outfile"])
14.127 + self._arg_append(args, "2>%s" % os.devnull)
14.128 + # _setup_args()
14.129 +
14.130 + def _setup_filename(self):
14.131 + """This function setups the file to encode parsing the uri.
14.132 + So, type can be:
14.133 + * file
14.134 + * dvd
14.135 + * myth
14.136 +
14.137 + If the last one is detected we have to parse the uri to find args.
14.138 + Then we store all the args inside a dictionary: self.args['gmyth-cat']
14.139 + """
14.140 + _type = self.args["type"]
14.141 +
14.142 + if _type == "file":
14.143 + if not os.path.exists(self.args["input"]):
14.144 + raise IOError,\
14.145 + "File requested does not exist: %s." % self.args["input"]
14.146 + else:
14.147 + self.args["input"] = "file://%s" % self.args["input"]
14.148 +
14.149 + elif _type == "dvd":
14.150 + self.args["input"] = "dvd://".join(self.args["input"])
14.151 +
14.152 + elif _type == "myth":
14.153 + self.args["gmyth-cat"] = mythtv._setup_mythfilename(self)
14.154 + # _setup_filename()
14.155 +
14.156 +
14.157 + def __init__(self, params):
14.158 + transcoder.Transcoder.__init__(self, params)
14.159 + self.mencoder_opts = []
14.160 +
14.161 + try:
14.162 + self._setup_params()
14.163 + self._setup_filename()
14.164 + self._setup_mencoder_opts(self.mencoder_opts)
14.165 + except Exception, e:
14.166 + self.log.error(self.tid, e)
14.167 + # __init__()
14.168 +
14.169 +
14.170 + def _check_opened_file(self, stdw, _stdin):
14.171 + loop = True
14.172 + while loop:
14.173 + try:
14.174 + return open(self.args["outfile"])
14.175 + except:
14.176 + os.write(stdw, _stdin.read(1024))
14.177 + # _check_opened_file
14.178 +
14.179 +
14.180 + def _start_outfile(self, outfd):
14.181 + finished = False
14.182 +
14.183 + # fix this (not necessary)
14.184 + outfd.write("OK")
14.185 +
14.186 + # Configuring stdin
14.187 + try:
14.188 + _stdin = open(self.args["input"])
14.189 + size = int(os.path.getsize(self.args["input"]))
14.190 + except Exception, e:
14.191 + self.log.error(self.tid, "Mencoder stdin setup error: %s" % e)
14.192 + return False
14.193 +
14.194 + self.status = 0
14.195 + total_read = 0
14.196 +
14.197 + # Configuring pipes
14.198 + stdr, stdw = os.pipe()
14.199 +
14.200 + if not self._run_mencoder(input=stdr):
14.201 + return False
14.202 +
14.203 + stdout = self._check_opened_file(stdw, _stdin)
14.204 +
14.205 + try:
14.206 + while self.proc and self.proc.poll() == None:
14.207 + if not finished:
14.208 + data_in = _stdin.read(4096)
14.209 + if data_in != "":
14.210 + os.write(stdw, data_in)
14.211 + total_read += 4096
14.212 + d = stdout.read(4096)
14.213 + self.status = utils.progress_bar(self.log,
14.214 + int(total_read),
14.215 + int(size), 50)
14.216 + else:
14.217 + finished = True
14.218 + os.close(stdw)
14.219 +
14.220 + else:
14.221 + d = stdout.read(4096)
14.222 +
14.223 + except Exception, e:
14.224 + self.log.error(self.tid, "Problems handling data: %s" % e)
14.225 + self.stop()
14.226 + return False
14.227 +
14.228 + self.log.info(self.tid, "%s: Finished sending data to client" % repr(self))
14.229 + return True
14.230 + # _start_outfile()
14.231 +
14.232 + def _start(self, outfd):
14.233 + # Play a file on disk or DVD
14.234 + if not self._run_mencoder(output=subprocess.PIPE):
14.235 + return False
14.236 +
14.237 + try:
14.238 + while self.proc and self.proc.poll() == None:
14.239 + d = self.proc.stdout.read(1024)
14.240 + outfd.write(d)
14.241 + except Exception, e:
14.242 + self.log.error(self.tid, "Problems handling data: %s" % e)
14.243 + return False
14.244 +
14.245 + self.log.info(self.tid, "%s: Finished sending data to client" % repr(self))
14.246 + return True
14.247 + # _start()
14.248 +
14.249 + def _run_mencoder(self, input=None, output=None):
14.250 + try:
14.251 + self.proc = subprocess.Popen(self.mencoder_opts, stdin=input,
14.252 + stdout=output, close_fds=True)
14.253 + except Exception, e:
14.254 + self.log.error(self.tid, "Error executing mencoder: %s" % e)
14.255 + return False
14.256 +
14.257 + return True
14.258 + # _run_mencoder()
14.259 +
14.260 + def start(self, outfd):
14.261 + cmd = " ".join(self.mencoder_opts)
14.262 + self.log.debug(self.tid, "Plugin's tid: %s" % self.tid)
14.263 + self.log.debug(self.tid, "Mencoder: %s" % cmd)
14.264 + #fixme
14.265 +
14.266 + ret = False
14.267 +
14.268 + if self.args["outfile"] == "-" and \
14.269 + self.args["type"] in ["file", "dvd"]:
14.270 + ret = self._start(outfd)
14.271 +
14.272 + elif self.args["type"] == "myth":
14.273 + ret = mythtv.start_myth(self, outfd)
14.274 +
14.275 + else:
14.276 + ret = self._start_outfile(outfd)
14.277 +
14.278 + self.stop()
14.279 +
14.280 + if not ret:
14.281 + self.log.error(self.tid, "Problems while starting streaming.")
14.282 +
14.283 + return ret
14.284 + # start()
14.285 +
14.286 + def _aux_stop(self, obj, next=False):
14.287 + if obj:
14.288 + try:
14.289 + os.kill(obj.pid, signal.SIGKILL)
14.290 + if next:
14.291 + os.kill(obj.pid+1, signal.SIGKILL)
14.292 + except OSError, e:
14.293 + pass
14.294 +
14.295 + try:
14.296 + obj.wait()
14.297 + except Exception, e:
14.298 + pass
14.299 +
14.300 + obj = None
14.301 + # _aux_stop
14.302 +
14.303 + def stop(self):
14.304 + self._aux_stop(self.proc, True)
14.305 + self._aux_stop(self.gmyth)
14.306 + # stop()
14.307 +
14.308 +# TranscoderMencoder
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/gmyth-stream/server/0.3/plugins/transcoders/mencoder_lib/mythtv.py Tue May 29 21:24:48 2007 +0100
15.3 @@ -0,0 +1,106 @@
15.4 +import os
15.5 +import subprocess
15.6 +import fcntl
15.7 +
15.8 +import lib.utils as utils
15.9 +import lib.server as server
15.10 +
15.11 +from select import select
15.12 +
15.13 +def _setup_mythfilename(self):
15.14 + # mythtv:mythtv@192.168.3.110:6543/1002_20070426230000.nuv
15.15 + try:
15.16 + _mysql = self.args["input"].split("@")[0].split(":")
15.17 + except IndexError, e:
15.18 + _mysql = ["mythtv", "mythtv"]
15.19 +
15.20 + try:
15.21 + _args = self.args["input"].split("@")[1].split(":")
15.22 + except IndexError, e:
15.23 + _args = self.args["input"].split(":")
15.24 +
15.25 + gmyth_dict = {}
15.26 + gmyth_dict["mysql"] = _mysql
15.27 + gmyth_dict["backend"] = _args[0]
15.28 + gmyth_dict["port"] = _args[1].split("/", 1)[0]
15.29 +
15.30 + _tmp_file = _args[1].split("/", 1)[1]
15.31 +
15.32 + if _tmp_file.find("channel") >= 0:
15.33 + gmyth_dict["kind"] = "c"
15.34 + gmyth_dict["cfile"] = _tmp_file.split("=")[1]
15.35 + else:
15.36 + gmyth_dict["kind"] = "f"
15.37 + gmyth_dict["cfile"] = _tmp_file
15.38 +
15.39 + self.args["input"] = "-"
15.40 + return gmyth_dict
15.41 +# _setup_mythfilename
15.42 +
15.43 +def _setup_mythfile(err):
15.44 + size = err.readline().split("Size:")[1]
15.45 + flags = fcntl.fcntl (err, fcntl.F_GETFL, 0) | os.O_NONBLOCK
15.46 + fcntl.fcntl(err, fcntl.F_SETFL, flags)
15.47 + return size
15.48 +# _setup_mythfile
15.49 +
15.50 +def _setup_gmythcat(self):
15.51 + gmyth_cat = utils.which("gmyth-cat")
15.52 + if self.args.has_key("gmyth-cat"):
15.53 + return [ utils.which("gmyth-cat"),
15.54 + "-h", self.args["gmyth-cat"]["backend"],
15.55 + "-p", self.args["gmyth-cat"]["port"],
15.56 + "-" + self.args["gmyth-cat"]["kind"],
15.57 + self.args["gmyth-cat"]["cfile"]
15.58 + ]
15.59 + else:
15.60 + self.log.error(self.tid, "URI error")
15.61 + return []
15.62 +# _setup_gmythcat
15.63 +
15.64 +def start_myth(self, outfd):
15.65 + opts = _setup_gmythcat(self)
15.66 + try:
15.67 + self.gmyth = subprocess.Popen(opts, stdout=subprocess.PIPE,
15.68 + stderr=subprocess.PIPE,
15.69 + close_fds=True)
15.70 + except Exception, e:
15.71 + self.log.error(self.tid, "Error executing gmyth-cat: %s" % e)
15.72 + return False
15.73 +
15.74 + if not self._run_mencoder(input=self.gmyth.stdout,
15.75 + output=subprocess.PIPE):
15.76 + return False
15.77 +
15.78 + if self.args["gmyth-cat"]["kind"] == "f":
15.79 + try:
15.80 + size = _setup_mythfile(self.gmyth.stderr)
15.81 + self.log.debug(self.tid, "Size of file: %s" % size)
15.82 + except Exception, e:
15.83 + self.log.error(self.tid, "Problems getting size of file: %s" % e)
15.84 + return False
15.85 +
15.86 + try:
15.87 + while self.proc and self.proc.poll() == None:
15.88 + r, w, x = select([self.gmyth.stderr, self.proc.stdout],
15.89 + [], [], 0)
15.90 + if self.proc.stdout in r:
15.91 + d = self.proc.stdout.read(4096)
15.92 + outfd.write(d)
15.93 +
15.94 + if self.gmyth.stderr in r:
15.95 + partial = self.gmyth.stderr.read(50).split("\n")[-2]
15.96 + if partial != "":
15.97 + self.status = utils.progress_bar(self.log,
15.98 + int(partial),
15.99 + int(size), 50)
15.100 +
15.101 + except IndexError, e:
15.102 + pass
15.103 + except Exception, e:
15.104 + self.log.error(self.tid, "Problems handling data: %s" % e)
15.105 + return False
15.106 +
15.107 + self.log.info(self.tid, "Finished sending data")
15.108 + return True
15.109 +# _start_myth()