morphbr@718: #!/usr/bin/env python
morphbr@718:
morphbr@718: __author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
morphbr@718: __author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
morphbr@718: __license__ = "GPL"
morphbr@723: __version__ = "0.3"
morphbr@718:
morphbr@718: import os
morphbr@723: import cgi
morphbr@723: import socket
morphbr@723: import logging
morphbr@723: import urlparse
morphbr@718: import threading
morphbr@718: import SocketServer
morphbr@718: import BaseHTTPServer
morphbr@723:
morphbr@718: import lib.utils as utils
morphbr@723: import lib.file_handler as files
morphbr@723: import lib.transcoder as transcoder
morphbr@718:
morphbr@718: from log import Log
morphbr@718:
morphbr@718: __all__ = ("RequestHandler")
morphbr@718:
morphbr@718: class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
morphbr@718: """Class that implements an HTTP request handler for our server."""
morphbr@718: log = logging.getLogger("gms.request")
morphbr@718: def_transcoder = None
morphbr@718: transcoders = utils.PluginSet(transcoder.Transcoder)
morphbr@718: transcoders_log = Log()
morphbr@718: tid_queue = []
morphbr@718:
morphbr@718: menu = {
morphbr@718: "Log": "/get_log.do",
morphbr@718: "Stop": "/stop-transcoder.do",
morphbr@718: "Status": "/status.do",
morphbr@718: "All Log": "/get_all_log.do",
morphbr@718: "Version": "/version.do",
morphbr@718: "Shutdown": "/shutdown.do"
morphbr@718: }
morphbr@718:
morphbr@718: @classmethod
morphbr@718: def load_plugins_transcoders(cls, directory):
morphbr@718: cls.transcoders.load_from_directory(directory)
morphbr@718:
morphbr@718: if cls.def_transcoder is None and cls.transcoders:
morphbr@718: cls.def_transcoder = cls.transcoders[0].name
morphbr@718: # load_plugins_transcoders()
morphbr@718:
morphbr@718:
morphbr@718: def do_dispatch(self, body):
morphbr@718: self.url = self.path
morphbr@718: pieces = urlparse.urlparse(self.path)
morphbr@718: self.path = pieces[2]
morphbr@718: self.query = cgi.parse_qs(pieces[4])
morphbr@718:
morphbr@723: url = {
morphbr@723: "/": self.serve_main,
morphbr@723: "/shutdown.do": self.serve_shutdown,
morphbr@723: "/stop-transcoder.do": self.serve_stop_transcoder,
morphbr@723: "/status.do": self.serve_status,
morphbr@723: "/version.do": self.serve_version,
morphbr@723: "/new_id.do": self.serve_new_id,
morphbr@723: "/get_log.do": self.serve_get_log,
morphbr@723: "/get_all_log.do": self.serve_get_all_log,
morphbr@723: "/stream.do": self.serve_stream,
morphbr@723: "/list.do": self.serve_list,
morphbr@723: }
morphbr@723:
morphbr@723: try:
morphbr@723: url[self.path](body)
morphbr@723: except KeyError, e:
morphbr@744: try:
morphbr@744: action = self.query.get("action", None)
morphbr@744: if action and "stream.do" in action:
morphbr@744: self.serve_stream(body)
morphbr@744: elif os.path.exists("html/%s" % self.path):
morphbr@744: data = open("html/%s" % self.path)
morphbr@744: self.wfile.write(data.read())
morphbr@744: else:
morphbr@744: self.send_error(404, "File not found")
morphbr@744: except Exception, e:
morphbr@744: self.log.error(e)
morphbr@723:
morphbr@718: # do_dispatch()
morphbr@718:
morphbr@718:
morphbr@718: def do_GET(self):
morphbr@718: self.do_dispatch(True)
morphbr@718: # do_GET()
morphbr@718:
morphbr@718:
morphbr@718: def do_HEAD(self):
morphbr@718: self.do_dispatch(False)
morphbr@718: # do_HEAD()
morphbr@718:
morphbr@718:
morphbr@718: def _nav_items(self):
morphbr@718: ret = ""
morphbr@718: for name, url in self.menu.items():
morphbr@718: ret += utils.getHTML("menu", {"name": name, "url": url})
morphbr@718: return ret
morphbr@718: # _nav_items()
morphbr@718:
morphbr@723:
morphbr@718: def serve_main(self, body):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: if body:
morphbr@718: self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
morphbr@718: # serve_main()
morphbr@718:
morphbr@723:
morphbr@718: def serve_version(self, body):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: if body:
morphbr@718: self.wfile.write("Version: %s" % __version__)
morphbr@723: # serve_version
morphbr@718:
morphbr@718:
morphbr@718: def serve_shutdown(self, body):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: if body:
morphbr@718: self.wfile.write(utils.getHTML("shutdown"))
morphbr@718: self.server.server_close()
morphbr@718: # serve_shutdown()
morphbr@718:
morphbr@718:
morphbr@723: def serve_list(self, body):
morphbr@723: self.send_response(200)
morphbr@723: self.send_header("Content-Type", "text/html")
morphbr@723: self.send_header('Connection', 'close')
morphbr@723: self.end_headers()
morphbr@724:
morphbr@724: if body:
morphbr@723: file_list = []
morphbr@724: files.list_media_files(".transcoded", file_list)
morphbr@723: output = files.FileList(map(lambda x, y: x+y, file_list,
morphbr@723: ["
"]*len(file_list)))
morphbr@724: self.wfile.write(output)
morphbr@723:
morphbr@723: # serve_list()
morphbr@723:
morphbr@723:
morphbr@718: def serve_stop_all_transcoders(self, body):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: if body:
morphbr@718: self.server.stop_transcoders()
morphbr@723: self.wfile.write(utils.getHTML("stop_all",
morphbr@723: {"menu": self._nav_items()}))
morphbr@718: # serve_stop_all_transcoders()
morphbr@718:
morphbr@718:
morphbr@718: def serve_stop_selected_transcoders(self, body, tids=[]):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: opts = ""
morphbr@718: if body:
morphbr@718: transcoders = self.server.get_transcoders()
morphbr@718:
morphbr@718: for tid in tids:
morphbr@718: for t, r in transcoders:
morphbr@718: if t.tid == int(tid):
morphbr@718: try:
morphbr@718: t.stop()
morphbr@718: except Exception, e:
morphbr@718: self.log.info("Plugin already stopped")
morphbr@718:
morphbr@718: opts += utils._create_html_item("%s" % t)
morphbr@718:
morphbr@718: break
morphbr@718:
morphbr@718: self.wfile.write(utils.getHTML("stop_selected",
morphbr@718: {"menu": self._nav_items(),
morphbr@718: "opts": opts}))
morphbr@718: # serve_stop_selected_transcoders()
morphbr@718:
morphbr@718:
morphbr@718: def serve_stop_transcoder(self, body):
morphbr@718: req = self.query.get("request", None)
morphbr@718: tid = self.query.get("tid", None)
morphbr@718: if req and "all" in req:
morphbr@718: self.serve_stop_all_transcoders(body)
morphbr@718: elif tid:
morphbr@718: self.serve_stop_selected_transcoders(body, tid[0].split(";"))
morphbr@718: else:
morphbr@718: self.serve_status(body)
morphbr@718: # serve_stop_transcoder()
morphbr@718:
morphbr@718:
morphbr@718: def serve_status(self, body):
morphbr@718: self.send_response(200)
morphbr@718: self.send_header("Content-Type", "text/html")
morphbr@718: self.send_header('Connection', 'close')
morphbr@718: self.end_headers()
morphbr@718: stopone = ""
morphbr@732: running = ""
morphbr@732: stopall = ""
morphbr@718:
morphbr@718: if body:
morphbr@718: tl = self.server.get_transcoders()
morphbr@741: if not tl and not self.query.get("tid", None) and \
morphbr@741: not self.query.get("running", None):
morphbr@718: running = "
No running transcoder.
\n" morphbr@718: morphbr@741: elif not tl and self.query.get("tid", None): morphbr@724: tids = self.query.get("tid") morphbr@724: for tid in tids: morphbr@724: stat = self.transcoders_log.get_status(int(tid)) morphbr@729: self.wfile.write("%sRunning transcoders:
\n" morphbr@718: stopall = utils._create_html_item("" morphbr@718: "[STOP ALL]" % morphbr@718: self.menu["Stop"]) morphbr@718: morphbr@718: for transcoder, request in tl: morphbr@718: stopone += utils._create_html_item("%s;" morphbr@718: "" morphbr@718: " [STOP] ") % ( morphbr@718: transcoder, self.menu["Stop"], transcoder.tid) morphbr@718: morphbr@718: self.wfile.write(utils.getHTML("status", morphbr@718: {"menu": self._nav_items(), morphbr@718: "running": running, morphbr@718: "stopall": stopall, morphbr@718: "stopone": stopone})) morphbr@718: # serve_status() morphbr@718: morphbr@718: morphbr@718: def _get_transcoder(self): morphbr@718: # get transcoder option: mencoder is the default morphbr@718: request_transcoders = self.query.get("transcoder", ["mencoder"]) morphbr@718: morphbr@718: for t in request_transcoders: morphbr@718: transcoder = self.transcoders.get(t) morphbr@718: if transcoder: morphbr@718: return transcoder morphbr@718: morphbr@718: if not transcoder: morphbr@718: return self.transcoders[self.def_transcoder] morphbr@718: # _get_transcoder() morphbr@718: morphbr@718: morphbr@718: def _get_new_id(self, tid): morphbr@718: self.server.last_tid = utils.create_tid(tid) morphbr@718: self.tid_queue.append(self.server.last_tid) morphbr@718: return self.server.last_tid morphbr@718: # _get_new_id() morphbr@718: morphbr@718: morphbr@718: def serve_new_id(self, body): morphbr@718: self.send_response(200) morphbr@718: self.send_header("Content-Type", "text/html") morphbr@718: self.send_header('Connection', 'close') morphbr@718: self.end_headers() morphbr@718: morphbr@718: if body: morphbr@718: self.wfile.write("%s" % self._get_new_id(self.server.last_tid)) morphbr@718: # serve_new_id() morphbr@718: morphbr@718: def serve_get_log(self, body): morphbr@718: self.send_response(200) morphbr@718: self.send_header("Content-Type", "text/html") morphbr@718: self.send_header('Connection', 'close') morphbr@718: self.end_headers() morphbr@718: morphbr@718: if body: morphbr@718: if self.query.get("tid", None): morphbr@718: tid = int(self.query.get("tid")[0]) morphbr@718: stat = self.transcoders_log.get_status(tid) morphbr@723: self.wfile.write("Status: %s" % stat) morphbr@718: else: morphbr@718: stat = self.transcoders_log.get_status() morphbr@718: for rtid, status in stat.iteritems(): morphbr@718: self.wfile.write("%s: %s