gmyth-stream/server/0.3/lib/request_handler.py
author morphbr
Thu May 31 17:12:51 2007 +0100 (2007-05-31)
branchtrunk
changeset 727 72f9152d4e2a
parent 724 64b061775d06
child 729 8ef808220720
permissions -rw-r--r--
[svn r733] * GMyth-Streamer
- Bug fix for listing transcoded files
     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             tl = self.server.get_transcoders()
   207             if not tl and not self.query.get("tid", None):
   208                 running = "<p>No running transcoder.</p>\n"
   209                 stopall = ""
   210                 stopone = ""
   211 
   212             elif self.query.get("tid", None) and not tl:
   213                 tids = self.query.get("tid")
   214                 for tid in tids:
   215                     stat = self.transcoders_log.get_status(int(tid))
   216                     self.wfile.write("Running: %s<br>" % stat)
   217 
   218             elif self.query.get("tid", None):
   219                 req_tid = self.query.get("tid")
   220                 for transcoder, request in tl:
   221                     if str(transcoder.tid) in req_tid:
   222                         self.wfile.write("%s:Status: %s %%" % (\
   223                             transcoder.tid, transcoder.status))
   224                 return True
   225 
   226             else:
   227                 running = "<p>Running transcoders:</p>\n"
   228                 stopall = utils._create_html_item("<a href='%s?request=all'>"
   229                                                  "[STOP ALL]</a>" %
   230                                                  self.menu["Stop"])
   231 
   232                 for transcoder, request in tl:
   233                     stopone += utils._create_html_item("%s;"
   234                                                        "<a href='%s?tid=%s'>"
   235                                                        " [STOP] </a>") % (
   236                         transcoder, self.menu["Stop"], transcoder.tid)
   237 
   238             self.wfile.write(utils.getHTML("status",
   239                                            {"menu": self._nav_items(),
   240                                             "running": running,
   241                                             "stopall": stopall,
   242                                             "stopone": stopone}))
   243     # serve_status()
   244 
   245 
   246     def _get_transcoder(self):
   247         # get transcoder option: mencoder is the default
   248         request_transcoders = self.query.get("transcoder", ["mencoder"])
   249 
   250         for t in request_transcoders:
   251             transcoder = self.transcoders.get(t)
   252             if transcoder:
   253                 return transcoder
   254 
   255         if not transcoder:
   256             return self.transcoders[self.def_transcoder]
   257     # _get_transcoder()
   258 
   259 
   260     def _get_new_id(self, tid):
   261         self.server.last_tid = utils.create_tid(tid)
   262         self.tid_queue.append(self.server.last_tid)
   263         return self.server.last_tid
   264     # _get_new_id()
   265 
   266 
   267     def serve_new_id(self, body):
   268         self.send_response(200)
   269         self.send_header("Content-Type", "text/html")
   270         self.send_header('Connection', 'close')
   271         self.end_headers()
   272 
   273         if body:
   274             self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
   275     # serve_new_id()
   276 
   277     def serve_get_log(self, body):
   278         self.send_response(200)
   279         self.send_header("Content-Type", "text/html")
   280         self.send_header('Connection', 'close')
   281         self.end_headers()
   282 
   283         if body:
   284             if self.query.get("tid", None):
   285                 tid = int(self.query.get("tid")[0])
   286                 stat = self.transcoders_log.get_status(tid)
   287                 self.wfile.write("Status: %s" % stat)
   288             else:
   289                 stat = self.transcoders_log.get_status()
   290                 for rtid, status in stat.iteritems():
   291                     self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
   292     # serve_get_log()
   293 
   294     def serve_get_all_log(self, body):
   295         self.send_response(200)
   296         self.send_header("Content-Type", "text/html")
   297         self.send_header('Connection', 'close')
   298         self.end_headers()
   299 
   300         if body:
   301             if self.query.get("tid", None):
   302                 tid = int(self.query.get("tid")[0])
   303                 stat = self.transcoders_log.get_status(tid, True)
   304                 for status in stat:
   305                     self.wfile.write("%s<br><br>" % status)
   306             else:
   307                 stat = self.transcoders_log.get_status(None, True)
   308                 for rtid, history in stat.iteritems():
   309                     for status in history:
   310                         self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
   311                     self.wfile.write("<br><br>")
   312     # serve_get_all_log()
   313 
   314     def serve_stream(self, body):
   315         transcoder = self._get_transcoder()
   316         try:
   317             obj = transcoder(self.query)
   318         except Exception, e:
   319             self.send_error(500, str(e))
   320             return
   321 
   322         self.send_response(200)
   323         self.send_header("Content-Type", obj.get_mimetype())
   324         self.send_header('Connection', 'close')
   325         self.end_headers()
   326 
   327         if body:
   328             if self.query.get("transcoder", None):
   329                 test_tid = int(self.query.get("tid", "0")[0])
   330                 if test_tid == 0 or test_tid not in self.tid_queue:
   331                     test_tid = self._get_new_id(self.server.last_tid)
   332 
   333                 self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
   334                 obj.tid = test_tid
   335                 obj.log = self.transcoders_log
   336 
   337                 self.server.add_transcoders(self, obj)
   338                 obj.start(self.wfile)
   339                 self.server.del_transcoders(self, obj)
   340                 files.TranscodedFile("", self.query)
   341 
   342             elif self.query.get("type", "")[0] == "file" and \
   343                      self.query.get("uri", None):
   344                 media = open(self.query.get("uri", None)[0])
   345                 self.wfile.write(media.read())
   346     # serve_stream()
   347 
   348 
   349     def log_request(self, code='-', size='-'):
   350         self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
   351     # log_request()
   352 
   353 
   354     def log_error(self, format, *args):
   355         self.log.error("%s: %s" % (self.address_string(), format % args))
   356     # log_error()
   357 
   358 
   359     def log_message(self, format, *args):
   360         self.log.info("%s: %s" % (self.address_string(), format % args))
   361     # log_message()
   362 
   363 # RequestHandler