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