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