gmyth-stream/server/0.3/lib/request_handler.py
author morphbr
Thu May 31 19:56:52 2007 +0100 (2007-05-31)
branchtrunk
changeset 730 f91c31df4992
parent 729 8ef808220720
child 732 c172f3576790
permissions -rw-r--r--
[svn r736] * GMyth-Streamer
- Silly bug fix
     1 #!/usr/bin/env python
     2 
     3 __author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
     4 __author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
     5 __license__ = "GPL"
     6 __version__ = "0.3"
     7 
     8 import os
     9 import cgi
    10 import socket
    11 import logging
    12 import urlparse
    13 import threading
    14 import SocketServer
    15 import BaseHTTPServer
    16 
    17 import lib.utils as utils
    18 import lib.file_handler as files
    19 import lib.transcoder as transcoder
    20 
    21 from log import Log
    22 
    23 __all__ = ("RequestHandler")
    24 
    25 class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    26     """Class that implements an HTTP request handler for our server."""
    27     log = logging.getLogger("gms.request")
    28     def_transcoder = None
    29     transcoders = utils.PluginSet(transcoder.Transcoder)
    30     transcoders_log = Log()
    31     tid_queue = []
    32 
    33     menu = {
    34         "Log": "/get_log.do",
    35         "Stop": "/stop-transcoder.do",
    36         "Status": "/status.do",
    37         "All Log": "/get_all_log.do",
    38         "Version": "/version.do",
    39         "Shutdown": "/shutdown.do"
    40         }
    41 
    42     @classmethod
    43     def load_plugins_transcoders(cls, directory):
    44         cls.transcoders.load_from_directory(directory)
    45 
    46         if cls.def_transcoder is None and cls.transcoders:
    47             cls.def_transcoder = cls.transcoders[0].name
    48     # load_plugins_transcoders()
    49 
    50 
    51     def do_dispatch(self, body):
    52         self.url = self.path
    53         pieces = urlparse.urlparse(self.path)
    54         self.path = pieces[2]
    55         self.query = cgi.parse_qs(pieces[4])
    56 
    57         url = {
    58             "/": self.serve_main,
    59             "/shutdown.do": self.serve_shutdown,
    60             "/stop-transcoder.do": self.serve_stop_transcoder,
    61             "/status.do": self.serve_status,
    62             "/version.do": self.serve_version,
    63             "/new_id.do": self.serve_new_id,
    64             "/get_log.do": self.serve_get_log,
    65             "/get_all_log.do": self.serve_get_all_log,
    66             "/stream.do": self.serve_stream,
    67             "/list.do": self.serve_list,
    68             }
    69 
    70         try:
    71             url[self.path](body)
    72         except KeyError, e:
    73             action = self.query.get("action", None)
    74             if action and "stream.do" in action:
    75                 self.serve_stream(body)
    76             else:
    77                 self.send_error(404, "File not found")
    78 
    79     # do_dispatch()
    80 
    81 
    82     def do_GET(self):
    83         self.do_dispatch(True)
    84     # do_GET()
    85 
    86 
    87     def do_HEAD(self):
    88         self.do_dispatch(False)
    89     # do_HEAD()
    90 
    91 
    92     def _nav_items(self):
    93         ret = ""
    94         for name, url in self.menu.items():
    95             ret += utils.getHTML("menu", {"name": name, "url": url})
    96         return ret
    97     # _nav_items()
    98 
    99 
   100     def serve_main(self, body):
   101         self.send_response(200)
   102         self.send_header("Content-Type", "text/html")
   103         self.send_header('Connection', 'close')
   104         self.end_headers()
   105         if body:
   106             self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
   107     # serve_main()
   108 
   109 
   110     def serve_version(self, body):
   111         self.send_response(200)
   112         self.send_header("Content-Type", "text/html")
   113         self.send_header('Connection', 'close')
   114         self.end_headers()
   115         if body:
   116             self.wfile.write("Version: %s" %  __version__)
   117     # serve_version
   118 
   119 
   120     def serve_shutdown(self, body):
   121         self.send_response(200)
   122         self.send_header("Content-Type", "text/html")
   123         self.send_header('Connection', 'close')
   124         self.end_headers()
   125         if body:
   126             self.wfile.write(utils.getHTML("shutdown"))
   127         self.server.server_close()
   128     # serve_shutdown()
   129 
   130 
   131     def serve_list(self, body):
   132         self.send_response(200)
   133         self.send_header("Content-Type", "text/html")
   134         self.send_header('Connection', 'close')
   135         self.end_headers()
   136 
   137         if body:
   138             file_list = []
   139             files.list_media_files(".transcoded", file_list)
   140             output = files.FileList(map(lambda x, y: x+y, file_list,
   141                                         ["<br>"]*len(file_list)))
   142             self.wfile.write(output)
   143 
   144     # serve_list()
   145 
   146 
   147     def serve_stop_all_transcoders(self, body):
   148         self.send_response(200)
   149         self.send_header("Content-Type", "text/html")
   150         self.send_header('Connection', 'close')
   151         self.end_headers()
   152         if body:
   153             self.server.stop_transcoders()
   154             self.wfile.write(utils.getHTML("stop_all",
   155                                            {"menu": self._nav_items()}))
   156     # serve_stop_all_transcoders()
   157 
   158 
   159     def serve_stop_selected_transcoders(self, body, tids=[]):
   160         self.send_response(200)
   161         self.send_header("Content-Type", "text/html")
   162         self.send_header('Connection', 'close')
   163         self.end_headers()
   164         opts = ""
   165         if body:
   166             transcoders = self.server.get_transcoders()
   167 
   168             for tid in tids:
   169                 for t, r in transcoders:
   170                     if t.tid == int(tid):
   171                         try:
   172                             t.stop()
   173                         except Exception, e:
   174                             self.log.info("Plugin already stopped")
   175 
   176                         opts += utils._create_html_item("%s" % t)
   177 
   178                         break
   179 
   180                 self.wfile.write(utils.getHTML("stop_selected",
   181                                                {"menu": self._nav_items(),
   182                                                 "opts": opts}))
   183     # serve_stop_selected_transcoders()
   184 
   185 
   186     def serve_stop_transcoder(self, body):
   187         req = self.query.get("request", None)
   188         tid = self.query.get("tid", None)
   189         if req and "all" in req:
   190             self.serve_stop_all_transcoders(body)
   191         elif tid:
   192             self.serve_stop_selected_transcoders(body, tid[0].split(";"))
   193         else:
   194             self.serve_status(body)
   195     # serve_stop_transcoder()
   196 
   197 
   198     def serve_status(self, body):
   199         self.send_response(200)
   200         self.send_header("Content-Type", "text/html")
   201         self.send_header('Connection', 'close')
   202         self.end_headers()
   203         stopone = ""
   204 
   205         if body:
   206             running = ""
   207             tl = self.server.get_transcoders()
   208             if not tl and not self.query.get("tid", None):
   209                 running = "<p>No running transcoder.</p>\n"
   210                 stopall = ""
   211                 stopone = ""
   212 
   213             elif self.query.get("tid", None) and not tl:
   214                 tids = self.query.get("tid")
   215                 for tid in tids:
   216                     stat = self.transcoders_log.get_status(int(tid))
   217                     self.wfile.write("%s<br>" % stat)
   218 
   219             elif self.query.get("tid", None):
   220                 req_tid = self.query.get("tid")
   221                 for transcoder, request in tl:
   222                     if str(transcoder.tid) in req_tid:
   223                         self.wfile.write("%s:Status: %s %%" % (\
   224                             transcoder.tid, transcoder.status))
   225                 return True
   226 
   227             else:
   228                 running = "<p>Running transcoders:</p>\n"
   229                 stopall = utils._create_html_item("<a href='%s?request=all'>"
   230                                                  "[STOP ALL]</a>" %
   231                                                  self.menu["Stop"])
   232 
   233                 for transcoder, request in tl:
   234                     stopone += utils._create_html_item("%s;"
   235                                                        "<a href='%s?tid=%s'>"
   236                                                        " [STOP] </a>") % (
   237                         transcoder, self.menu["Stop"], transcoder.tid)
   238 
   239             self.wfile.write(utils.getHTML("status",
   240                                            {"menu": self._nav_items(),
   241                                             "running": running,
   242                                             "stopall": stopall,
   243                                             "stopone": stopone}))
   244     # serve_status()
   245 
   246 
   247     def _get_transcoder(self):
   248         # get transcoder option: mencoder is the default
   249         request_transcoders = self.query.get("transcoder", ["mencoder"])
   250 
   251         for t in request_transcoders:
   252             transcoder = self.transcoders.get(t)
   253             if transcoder:
   254                 return transcoder
   255 
   256         if not transcoder:
   257             return self.transcoders[self.def_transcoder]
   258     # _get_transcoder()
   259 
   260 
   261     def _get_new_id(self, tid):
   262         self.server.last_tid = utils.create_tid(tid)
   263         self.tid_queue.append(self.server.last_tid)
   264         return self.server.last_tid
   265     # _get_new_id()
   266 
   267 
   268     def serve_new_id(self, body):
   269         self.send_response(200)
   270         self.send_header("Content-Type", "text/html")
   271         self.send_header('Connection', 'close')
   272         self.end_headers()
   273 
   274         if body:
   275             self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
   276     # serve_new_id()
   277 
   278     def serve_get_log(self, body):
   279         self.send_response(200)
   280         self.send_header("Content-Type", "text/html")
   281         self.send_header('Connection', 'close')
   282         self.end_headers()
   283 
   284         if body:
   285             if self.query.get("tid", None):
   286                 tid = int(self.query.get("tid")[0])
   287                 stat = self.transcoders_log.get_status(tid)
   288                 self.wfile.write("Status: %s" % stat)
   289             else:
   290                 stat = self.transcoders_log.get_status()
   291                 for rtid, status in stat.iteritems():
   292                     self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
   293     # serve_get_log()
   294 
   295     def serve_get_all_log(self, body):
   296         self.send_response(200)
   297         self.send_header("Content-Type", "text/html")
   298         self.send_header('Connection', 'close')
   299         self.end_headers()
   300 
   301         if body:
   302             if self.query.get("tid", None):
   303                 tid = int(self.query.get("tid")[0])
   304                 stat = self.transcoders_log.get_status(tid, True)
   305                 for status in stat:
   306                     self.wfile.write("%s<br><br>" % status)
   307             else:
   308                 stat = self.transcoders_log.get_status(None, True)
   309                 for rtid, history in stat.iteritems():
   310                     for status in history:
   311                         self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
   312                     self.wfile.write("<br><br>")
   313     # serve_get_all_log()
   314 
   315     def serve_stream(self, body):
   316         transcoder = self._get_transcoder()
   317         try:
   318             obj = transcoder(self.query)
   319         except Exception, e:
   320             self.send_error(500, str(e))
   321             return
   322 
   323         self.send_response(200)
   324         self.send_header("Content-Type", obj.get_mimetype())
   325         self.send_header('Connection', 'close')
   326         self.end_headers()
   327 
   328         if body:
   329             if self.query.get("transcoder", None):
   330                 test_tid = int(self.query.get("tid", "0")[0])
   331                 if test_tid == 0 or test_tid not in self.tid_queue:
   332                     test_tid = self._get_new_id(self.server.last_tid)
   333 
   334                 self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
   335                 obj.tid = test_tid
   336                 obj.log = self.transcoders_log
   337 
   338                 self.server.add_transcoders(self, obj)
   339                 obj.start(self.wfile)
   340                 self.server.del_transcoders(self, obj)
   341                 files.TranscodedFile("", self.query)
   342 
   343             elif self.query.get("type", "")[0] == "file" and \
   344                      self.query.get("uri", None):
   345                 media = open(self.query.get("uri", None)[0])
   346                 self.wfile.write(media.read())
   347     # serve_stream()
   348 
   349 
   350     def log_request(self, code='-', size='-'):
   351         self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
   352     # log_request()
   353 
   354 
   355     def log_error(self, format, *args):
   356         self.log.error("%s: %s" % (self.address_string(), format % args))
   357     # log_error()
   358 
   359 
   360     def log_message(self, format, *args):
   361         self.log.info("%s: %s" % (self.address_string(), format % args))
   362     # log_message()
   363 
   364 # RequestHandler