gmyth-stream/server/0.3/lib/request_handler.py
author morphbr
Mon Jun 04 19:05:36 2007 +0100 (2007-06-04)
branchtrunk
changeset 743 f92cd43fea7d
parent 742 fe8ddffd7f5c
child 744 ef4fb30176dd
permissions -rw-r--r--
[svn r749] * GMyth-Streamer
- Bug fixes
     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             elif os.path.exists("html/%s" % self.path):
    77                 data = open("html/%s" % self.path)
    78                 self.wfile.write(data.read())
    79             else:
    80                 self.send_error(404, "File not found")
    81 
    82     # do_dispatch()
    83 
    84 
    85     def do_GET(self):
    86         self.do_dispatch(True)
    87     # do_GET()
    88 
    89 
    90     def do_HEAD(self):
    91         self.do_dispatch(False)
    92     # do_HEAD()
    93 
    94 
    95     def _nav_items(self):
    96         ret = ""
    97         for name, url in self.menu.items():
    98             ret += utils.getHTML("menu", {"name": name, "url": url})
    99         return ret
   100     # _nav_items()
   101 
   102 
   103     def serve_main(self, body):
   104         self.send_response(200)
   105         self.send_header("Content-Type", "text/html")
   106         self.send_header('Connection', 'close')
   107         self.end_headers()
   108         if body:
   109             self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
   110     # serve_main()
   111 
   112 
   113     def serve_version(self, body):
   114         self.send_response(200)
   115         self.send_header("Content-Type", "text/html")
   116         self.send_header('Connection', 'close')
   117         self.end_headers()
   118         if body:
   119             self.wfile.write("Version: %s" %  __version__)
   120     # serve_version
   121 
   122 
   123     def serve_shutdown(self, body):
   124         self.send_response(200)
   125         self.send_header("Content-Type", "text/html")
   126         self.send_header('Connection', 'close')
   127         self.end_headers()
   128         if body:
   129             self.wfile.write(utils.getHTML("shutdown"))
   130         self.server.server_close()
   131     # serve_shutdown()
   132 
   133 
   134     def serve_list(self, body):
   135         self.send_response(200)
   136         self.send_header("Content-Type", "text/html")
   137         self.send_header('Connection', 'close')
   138         self.end_headers()
   139 
   140         if body:
   141             file_list = []
   142             files.list_media_files(".transcoded", file_list)
   143             output = files.FileList(map(lambda x, y: x+y, file_list,
   144                                         ["<br>"]*len(file_list)))
   145             self.wfile.write(output)
   146 
   147     # serve_list()
   148 
   149 
   150     def serve_stop_all_transcoders(self, body):
   151         self.send_response(200)
   152         self.send_header("Content-Type", "text/html")
   153         self.send_header('Connection', 'close')
   154         self.end_headers()
   155         if body:
   156             self.server.stop_transcoders()
   157             self.wfile.write(utils.getHTML("stop_all",
   158                                            {"menu": self._nav_items()}))
   159     # serve_stop_all_transcoders()
   160 
   161 
   162     def serve_stop_selected_transcoders(self, body, tids=[]):
   163         self.send_response(200)
   164         self.send_header("Content-Type", "text/html")
   165         self.send_header('Connection', 'close')
   166         self.end_headers()
   167         opts = ""
   168         if body:
   169             transcoders = self.server.get_transcoders()
   170 
   171             for tid in tids:
   172                 for t, r in transcoders:
   173                     if t.tid == int(tid):
   174                         try:
   175                             t.stop()
   176                         except Exception, e:
   177                             self.log.info("Plugin already stopped")
   178 
   179                         opts += utils._create_html_item("%s" % t)
   180 
   181                         break
   182 
   183                 self.wfile.write(utils.getHTML("stop_selected",
   184                                                {"menu": self._nav_items(),
   185                                                 "opts": opts}))
   186     # serve_stop_selected_transcoders()
   187 
   188 
   189     def serve_stop_transcoder(self, body):
   190         req = self.query.get("request", None)
   191         tid = self.query.get("tid", None)
   192         if req and "all" in req:
   193             self.serve_stop_all_transcoders(body)
   194         elif tid:
   195             self.serve_stop_selected_transcoders(body, tid[0].split(";"))
   196         else:
   197             self.serve_status(body)
   198     # serve_stop_transcoder()
   199 
   200 
   201     def serve_status(self, body):
   202         self.send_response(200)
   203         self.send_header("Content-Type", "text/html")
   204         self.send_header('Connection', 'close')
   205         self.end_headers()
   206         stopone = ""
   207         running = ""
   208         stopall = ""
   209 
   210         if body:
   211             tl = self.server.get_transcoders()
   212             if not tl and not self.query.get("tid", None) and \
   213                    not self.query.get("running", None):
   214                 running = "<p>No running transcoder.</p>\n"
   215 
   216             elif not tl and self.query.get("tid", None):
   217                 tids = self.query.get("tid")
   218                 for tid in tids:
   219                     stat = self.transcoders_log.get_status(int(tid))
   220                     self.wfile.write("%s<br>" % stat)
   221                 return True
   222 
   223             elif self.query.get("running", None):
   224                 for transcoder, request in tl:
   225                     outf = transcoder.params_first("outfile")
   226                     tid = transcoder.tid
   227                     self.wfile.write("%s:%s<br>" % (tid, outf))
   228                 return True
   229 
   230             elif self.query.get("tid", None):
   231                 req_tid = self.query.get("tid")
   232                 for transcoder, request in tl:
   233                     if str(transcoder.tid) in req_tid:
   234                         self.wfile.write("Status:%s:%s %%" % (\
   235                             transcoder.tid, transcoder.status))
   236                 return True
   237 
   238             else:
   239                 running = "<p>Running transcoders:</p>\n"
   240                 stopall = utils._create_html_item("<a href='%s?request=all'>"
   241                                                  "[STOP ALL]</a>" %
   242                                                  self.menu["Stop"])
   243 
   244                 for transcoder, request in tl:
   245                     stopone += utils._create_html_item("%s;"
   246                                                        "<a href='%s?tid=%s'>"
   247                                                        " [STOP] </a>") % (
   248                         transcoder, self.menu["Stop"], transcoder.tid)
   249 
   250             self.wfile.write(utils.getHTML("status",
   251                                            {"menu": self._nav_items(),
   252                                             "running": running,
   253                                             "stopall": stopall,
   254                                             "stopone": stopone}))
   255     # serve_status()
   256 
   257 
   258     def _get_transcoder(self):
   259         # get transcoder option: mencoder is the default
   260         request_transcoders = self.query.get("transcoder", ["mencoder"])
   261 
   262         for t in request_transcoders:
   263             transcoder = self.transcoders.get(t)
   264             if transcoder:
   265                 return transcoder
   266 
   267         if not transcoder:
   268             return self.transcoders[self.def_transcoder]
   269     # _get_transcoder()
   270 
   271 
   272     def _get_new_id(self, tid):
   273         self.server.last_tid = utils.create_tid(tid)
   274         self.tid_queue.append(self.server.last_tid)
   275         return self.server.last_tid
   276     # _get_new_id()
   277 
   278 
   279     def serve_new_id(self, body):
   280         self.send_response(200)
   281         self.send_header("Content-Type", "text/html")
   282         self.send_header('Connection', 'close')
   283         self.end_headers()
   284 
   285         if body:
   286             self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
   287     # serve_new_id()
   288 
   289     def serve_get_log(self, body):
   290         self.send_response(200)
   291         self.send_header("Content-Type", "text/html")
   292         self.send_header('Connection', 'close')
   293         self.end_headers()
   294 
   295         if body:
   296             if self.query.get("tid", None):
   297                 tid = int(self.query.get("tid")[0])
   298                 stat = self.transcoders_log.get_status(tid)
   299                 self.wfile.write("Status: %s" % stat)
   300             else:
   301                 stat = self.transcoders_log.get_status()
   302                 for rtid, status in stat.iteritems():
   303                     self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
   304     # serve_get_log()
   305 
   306     def serve_get_all_log(self, body):
   307         self.send_response(200)
   308         self.send_header("Content-Type", "text/html")
   309         self.send_header('Connection', 'close')
   310         self.end_headers()
   311 
   312         if body:
   313             if self.query.get("tid", None):
   314                 tid = int(self.query.get("tid")[0])
   315                 stat = self.transcoders_log.get_status(tid, True)
   316                 for status in stat:
   317                     self.wfile.write("%s<br><br>" % status)
   318             else:
   319                 stat = self.transcoders_log.get_status(None, True)
   320                 for rtid, history in stat.iteritems():
   321                     for status in history:
   322                         self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
   323                     self.wfile.write("<br><br>")
   324     # serve_get_all_log()
   325 
   326     def serve_stream(self, body):
   327         transcoder = self._get_transcoder()
   328         try:
   329             obj = transcoder(self.query)
   330         except Exception, e:
   331             self.send_error(500, str(e))
   332             return
   333 
   334         self.send_response(200)
   335         self.send_header("Content-Type", obj.get_mimetype())
   336         self.send_header("Connection", "close")
   337         self.end_headers()
   338 
   339         if body:
   340 
   341             if self.query.get("transcoder", None):
   342                 test_tid = int(self.query.get("tid", "0")[0])
   343                 if test_tid == 0 or test_tid not in self.tid_queue:
   344                     test_tid = self._get_new_id(self.server.last_tid)
   345 
   346                 self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
   347                 obj.tid = test_tid
   348                 obj.log = self.transcoders_log
   349 
   350                 self.server.add_transcoders(self, obj)
   351                 obj.start(self.wfile)
   352                 self.server.del_transcoders(self, obj)
   353                 files.TranscodedFile("", self.query)
   354 
   355             elif self.query.get("type", "")[0] == "file" and \
   356                      self.query.get("uri", None):
   357                 try:
   358                     media = open(self.query.get("uri", None)[0])
   359                     self.wfile.write(media.read())
   360                 except Exception, e:
   361                     self.log.error("Stream error: %s" %e)
   362     # serve_stream()
   363 
   364 
   365     def log_request(self, code='-', size='-'):
   366         self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
   367     # log_request()
   368 
   369 
   370     def log_error(self, format, *args):
   371         self.log.error("%s: %s" % (self.address_string(), format % args))
   372     # log_error()
   373 
   374 
   375     def log_message(self, format, *args):
   376         self.log.info("%s: %s" % (self.address_string(), format % args))
   377     # log_message()
   378 
   379 # RequestHandler