gmyth-stream/server/0.3/lib/request_handler.py
author renatofilho
Thu Aug 02 14:58:15 2007 +0100 (2007-08-02)
branchtrunk
changeset 792 a6ac25bf88a7
parent 774 366b0fd1eead
child 795 2b4e9d183146
permissions -rw-r--r--
[svn r798] fixed bug on video sink element
     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 
   242             else:
   243                 running = "<p>Running transcoders:</p>\n"
   244                 stopall = utils._create_html_item("<a href='%s?request=all'>"
   245                                                  "[STOP ALL]</a>" %
   246                                                  self.menu["Stop"])
   247 
   248                 for transcoder, request in tl:
   249                     stopone += utils._create_html_item("%s;"
   250                                                        "<a href='%s?tid=%s'>"
   251                                                        " [STOP] </a>") % (
   252                         transcoder, self.menu["Stop"], transcoder.tid)
   253 
   254             self.wfile.write(utils.getHTML("status",
   255                                            {"menu": self._nav_items(),
   256                                             "running": running,
   257                                             "stopall": stopall,
   258                                             "stopone": stopone}))
   259     # serve_status()
   260 
   261 
   262     def _get_transcoder(self):
   263         # get transcoder option: mencoder is the default
   264         request_transcoders = self.query.get("transcoder", ["mencoder"])
   265 
   266         for t in request_transcoders:
   267             transcoder = self.transcoders.get(t)
   268             if transcoder:
   269                 return transcoder
   270 
   271         if not transcoder:
   272             return self.transcoders[self.def_transcoder]
   273     # _get_transcoder()
   274 
   275 
   276     def _get_new_id(self, tid):
   277         self.server.last_tid = utils.create_tid(tid)
   278         self.tid_queue.append(self.server.last_tid)
   279         return self.server.last_tid
   280     # _get_new_id()
   281 
   282 
   283     def serve_new_id(self, body):
   284         self.send_response(200)
   285         self.send_header("Content-Type", "text/html")
   286         self.send_header('Connection', 'close')
   287         self.end_headers()
   288 
   289         if body:
   290             self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
   291     # serve_new_id()
   292 
   293     def serve_get_log(self, body):
   294         self.send_response(200)
   295         self.send_header("Content-Type", "text/html")
   296         self.send_header('Connection', 'close')
   297         self.end_headers()
   298 
   299         if body:
   300             if self.query.get("tid", None):
   301                 tid = int(self.query.get("tid")[0])
   302                 stat = self.transcoders_log.get_status(tid)
   303                 self.wfile.write("Status: %s" % stat)
   304             else:
   305                 stat = self.transcoders_log.get_status()
   306                 for rtid, status in stat.iteritems():
   307                     self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
   308     # serve_get_log()
   309 
   310     def serve_get_all_log(self, body):
   311         self.send_response(200)
   312         self.send_header("Content-Type", "text/html")
   313         self.send_header('Connection', 'close')
   314         self.end_headers()
   315 
   316         if body:
   317             if self.query.get("tid", None):
   318                 tid = int(self.query.get("tid")[0])
   319                 stat = self.transcoders_log.get_status(tid, True)
   320                 for status in stat:
   321                     self.wfile.write("%s<br><br>" % status)
   322             else:
   323                 stat = self.transcoders_log.get_status(None, True)
   324                 for rtid, history in stat.iteritems():
   325                     for status in history:
   326                         self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
   327                     self.wfile.write("<br><br>")
   328     # serve_get_all_log()
   329 
   330 
   331     def serve_file_info(self, body):
   332         if body:
   333 
   334             file_dat = self.query.get("file", None)
   335 
   336             if file_dat:
   337                 self.send_response(200)
   338                 self.send_header("Content-Type", "text/html")
   339                 self.send_header('Connection', 'close')
   340                 self.end_headers()
   341 
   342                 try:
   343                     opts = files.TranscodedFile(file_dat[0], self.query).opts
   344                     for key in opts.keys():
   345                         self.wfile.write("%s=%s<br>" % (key, opts.get(key, "None")[0]))
   346 
   347                 except Exception, e:
   348                     self.send_error(500, str(e))
   349                     return
   350     # serve_file_info()
   351 
   352     def serve_stream(self, body):
   353         transcoder = self._get_transcoder()
   354         try:
   355             obj = transcoder(self.query)
   356         except Exception, e:
   357             self.send_error(500, str(e))
   358             return
   359 
   360         self.send_response(200)
   361         self.send_header("Content-Type", obj.get_mimetype())
   362 	self.send_header("Cache-Control","no-cache")
   363 
   364         if (obj.name == "gmencoder"):
   365             self.send_header("Transfer-Encoding", "chunked")
   366 
   367         self.send_header("Connection", "close")
   368         self.end_headers()
   369 
   370         if body:
   371 
   372             test_tid = int(self.query.get("tid", "0")[0])
   373             if test_tid == 0 or test_tid not in self.tid_queue:
   374                 test_tid = self._get_new_id(self.server.last_tid)
   375 
   376 
   377             if self.query.get("transcoder", None):
   378                 self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
   379                 obj.tid = test_tid
   380                 obj.log = self.transcoders_log
   381 
   382                 self.server.add_transcoders(self, obj)
   383                 obj.start(self.wfile)
   384                 self.server.del_transcoders(self, obj)
   385                 files.TranscodedFile("", self.query)
   386 
   387             elif self.query.get("type", "")[0] == "file" and \
   388                      self.query.get("uri", None):
   389 
   390                 filename = self.query.get("uri", None)[0]
   391                 self.transcoders_log.insert(test_tid, "gms.%s" % filename)
   392 
   393                 try:
   394                     media = open(filename)
   395                     data_in = " "
   396                     total_read = 0
   397                     size = int(os.path.getsize(filename))
   398 
   399                     while data_in != "":
   400                         data_in = media.read(4096)
   401                         total_read += 4096
   402                         self.wfile.write(data_in)
   403                         status = utils.progress_bar(total_read, size, 50)
   404                         msg_status = "Status:%s:%s%%" % (test_tid, status)
   405                         self.transcoders_log._update_status(test_tid,
   406                                                             msg_status)
   407 
   408                     self.transcoders_log._update_status(test_tid, "OK: Done")
   409 
   410                 except Exception, e:
   411                     self.log.error("Stream error: %s" %e)
   412                     self.transcoders_log._update_status(test_tid,
   413                                                         "Error: %s" % e)
   414     # serve_stream()
   415 
   416 
   417     def log_request(self, code='-', size='-'):
   418         self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
   419     # log_request()
   420 
   421 
   422     def log_error(self, format, *args):
   423         self.log.error("%s: %s" % (self.address_string(), format % args))
   424     # log_error()
   425 
   426 
   427     def log_message(self, format, *args):
   428         self.log.info("%s: %s" % (self.address_string(), format % args))
   429     # log_message()
   430 
   431 # RequestHandler