add StreamingM3U
authorFelix Domke <tmbinc@elitedvb.net>
Tue, 9 Jan 2007 22:54:32 +0000 (22:54 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Tue, 9 Jan 2007 22:54:32 +0000 (22:54 +0000)
lib/python/Plugins/Extensions/WebInterface/webif.py

index a452cb7..e69de29 100644 (file)
@@ -1,347 +0,0 @@
-#
-# OK, this is more than a proof of concept
-# things to improve:
-#  - nicer code
-#  - screens need to be defined somehow else. 
-#    I don't know how, yet. Probably each in an own file.
-#  - more components, like the channellist
-#  - better error handling
-#  - use namespace parser
-
-from Screens.Screen import Screen
-from Tools.Import import my_import
-
-# for our testscreen
-from Screens.InfoBarGenerics import InfoBarServiceName, InfoBarEvent
-from Components.Sources.Clock import Clock
-#from Components.Sources.Config import Config
-from Components.Sources.ServiceList import ServiceList
-from Components.Converter.Converter import Converter
-#from Components.config import config
-from Components.Element import Element
-
-from xml.sax import make_parser
-from xml.sax.handler import ContentHandler, feature_namespaces
-from twisted.python import util
-import sys
-import time
-
-# prototype of the new web frontend template system.
-
-class WebScreen(Screen):
-       def __init__(self, session):
-               Screen.__init__(self, session)
-               self.stand_alone = True
-
-# a test screen
-class TestScreen(InfoBarServiceName, InfoBarEvent, WebScreen):
-       def __init__(self, session):
-               WebScreen.__init__(self, session)
-               InfoBarServiceName.__init__(self)
-               InfoBarEvent.__init__(self)
-               self["CurrentTime"] = Clock()
-#              self["TVSystem"] = Config(config.av.tvsystem)
-#              self["OSDLanguage"] = Config(config.osd.language)
-#              self["FirstRun"] = Config(config.misc.firstrun)
-               from enigma import eServiceReference
-               fav = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet')
-               self["ServiceList"] = ServiceList(fav, command_func = self.zapTo)
-               self["ServiceListBrowse"] = ServiceList(fav, command_func = self.browseTo)
-
-       def browseTo(self, reftobrowse):
-               self["ServiceListBrowse"].root = reftobrowse
-
-       def zapTo(self, reftozap):
-               self.session.nav.playService(reftozap)
-
-class Streaming(WebScreen):
-       def __init__(self, session):
-               WebScreen.__init__(self, session)
-               from Components.Sources.StreamService import StreamService
-               self["StreamService"] = StreamService(self.session.nav)
-
-# implements the 'render'-call.
-# this will act as a downstream_element, like a renderer.
-class OneTimeElement(Element):
-       def __init__(self, id):
-               Element.__init__(self)
-               self.source_id = id
-
-       # CHECKME: is this ok performance-wise?
-       def handleCommand(self, args):
-               for c in args.get(self.source_id, []):
-                       self.source.handleCommand(c)
-
-       def render(self, stream):
-               t = self.source.getHTML(self.source_id)
-               if isinstance(t, unicode):
-                       t = t.encode("utf-8")
-               stream.write(t)
-
-       def execBegin(self):
-               pass
-       
-       def execEnd(self):
-               pass
-       
-       def onShow(self):
-               pass
-
-       def onHide(self):
-               pass
-       
-       def destroy(self):
-               pass
-
-class StreamingElement(OneTimeElement):
-       def __init__(self, id):
-               OneTimeElement.__init__(self, id)
-               self.stream = None
-
-       def changed(self, what):
-               if self.stream:
-                       self.render(self.stream)
-
-       def setStream(self, stream):
-               self.stream = stream
-
-# a to-be-filled list item
-class ListItem:
-       def __init__(self, name):
-               self.name = name
-
-class TextToHTML(Converter):
-       def __init__(self, arg):
-               Converter.__init__(self, arg)
-
-       def getHTML(self, id):
-               return self.source.text # encode & etc. here!
-
-# a null-output. Useful if you only want to issue a command.
-class Null(Converter):
-       def __init__(self, arg):
-               Converter.__init__(self, arg)
-
-       def getHTML(self, id):
-               return ""
-
-def escape(s):
-       return s.replace("\\", "\\\\").replace("\n", "\\n").replace('"', '\\"')
-
-class JavascriptUpdate(Converter):
-       def __init__(self, arg):
-               Converter.__init__(self, arg)
-
-       def getHTML(self, id):
-               return '<script>set("' + id + '", "' + escape(self.source.text) + '");</script>\n'
-
-# the performant 'listfiller'-engine (plfe)
-class ListFiller(Converter):
-       def __init__(self, arg):
-               Converter.__init__(self, arg)
-
-       def getText(self):
-               l = self.source.list
-               lut = self.source.lut
-               
-               # now build a ["string", 1, "string", 2]-styled list, with indices into the 
-               # list to avoid lookup of item name for each entry
-               lutlist = []
-               for element in self.converter_arguments:
-                       if isinstance(element, str):
-                               lutlist.append(element)
-                       elif isinstance(element, ListItem):
-                               lutlist.append(lut[element.name])
-               
-               # now, for the huge list, do:
-               res = ""
-               for item in l:
-                       for element in lutlist:
-                               if isinstance(element, str):
-                                       res += element
-                               else:
-                                       res += str(item[element])
-               # (this will be done in c++ later!)
-               return res
-               
-       text = property(getText)
-
-class webifHandler(ContentHandler):
-       def __init__(self, session):
-               self.res = [ ]
-               self.mode = 0
-               self.screen = None
-               self.session = session
-               self.screens = [ ]
-       
-       def startElement(self, name, attrs):
-               if name == "e2:screen":
-                       self.screen = eval(attrs["name"])(self.session) # fixme
-                       self.screens.append(self.screen)
-                       return
-       
-               if name[:3] == "e2:":
-                       self.mode += 1
-               
-               tag = "<" + name + ''.join([' ' + key + '="' + val + '"' for (key, val) in attrs.items()]) + ">"
-               tag = tag.encode("UTF-8")
-               
-               if self.mode == 0:
-                       self.res.append(tag)
-               elif self.mode == 1: # expect "<e2:element>"
-                       assert name == "e2:element", "found %s instead of e2:element" % name
-                       source = attrs["source"]
-                       self.source_id = str(attrs.get("id", source))
-                       self.source = self.screen[source]
-                       self.is_streaming = "streaming" in attrs
-               elif self.mode == 2: # expect "<e2:convert>"
-                       if name[:3] == "e2:":
-                               assert name == "e2:convert"
-                               
-                               ctype = attrs["type"]
-                               if ctype[:4] == "web:": # for now
-                                       self.converter = eval(ctype[4:])
-                               else:
-                                       self.converter = my_import('.'.join(["Components", "Converter", ctype])).__dict__.get(ctype)
-                               self.sub = [ ]
-                       else:
-                               self.sub.append(tag)
-               elif self.mode == 3:
-                       assert name == "e2:item", "found %s instead of e2:item!" % name
-                       assert "name" in attrs, "e2:item must have a name= attribute!"
-                       self.sub.append(ListItem(attrs["name"]))
-
-       def endElement(self, name):
-               if name == "e2:screen":
-                       self.screen = None
-                       return
-
-               tag = "</" + name + ">"
-               if self.mode == 0:
-                       self.res.append(tag)
-               elif self.mode == 2 and name[:3] != "e2:":
-                       self.sub.append(tag)
-               elif self.mode == 2: # closed 'convert' -> sub
-                       self.sub = lreduce(self.sub)
-                       if len(self.sub) == 1:
-                               self.sub = self.sub[0]
-                       c = self.converter(self.sub)
-                       c.connect(self.source)
-                       self.source = c
-                       
-                       del self.sub
-               elif self.mode == 1: # closed 'element'
-                       # instatiate either a StreamingElement or a OneTimeElement, depending on what's required.
-                       if not self.is_streaming:
-                               c = OneTimeElement(self.source_id)
-                       else:
-                               c = StreamingElement(self.source_id)
-                       
-                       c.connect(self.source)
-                       self.res.append(c)
-                       self.screen.renderer.append(c)
-                       del self.source
-
-               if name[:3] == "e2:":
-                       self.mode -= 1
-
-       def processingInstruction(self, target, data):
-               self.res.append('<?' + target + ' ' + data + '>')
-       
-       def characters(self, ch):
-               ch = ch.encode("UTF-8")
-               if self.mode == 0:
-                       self.res.append(ch)
-               elif self.mode == 2:
-                       self.sub.append(ch)
-       
-       def startEntity(self, name):
-               self.res.append('&' + name + ';');
-
-       def execBegin(self):
-               for screen in self.screens:
-                       screen.execBegin()
-
-       def cleanup(self):
-               print "screen cleanup!"
-               for screen in self.screens:
-                       screen.execEnd()
-                       screen.doClose()
-               self.screens = [ ]
-
-def lreduce(list):
-       # ouch, can be made better
-       res = [ ]
-       string = None
-       for x in list:
-               if isinstance(x, str) or isinstance(x, unicode):
-                       if isinstance(x, unicode):
-                               x = x.encode("UTF-8")
-                       if string is None:
-                               string = x
-                       else:
-                               string += x
-               else:
-                       if string is not None:
-                               res.append(string)
-                               string = None
-                       res.append(x)
-       if string is not None:
-               res.append(string)
-               string = None
-       return res
-
-def renderPage(stream, path, req, session):
-       
-       # read in the template, create required screens
-       # we don't have persistense yet.
-       # if we had, this first part would only be done once.
-       handler = webifHandler(session)
-       parser = make_parser()
-       parser.setFeature(feature_namespaces, 0)
-       parser.setContentHandler(handler)
-       parser.parse(open(util.sibpath(__file__, path)))
-       
-       # by default, we have non-streaming pages
-       finish = True
-       
-       # first, apply "commands" (aka. URL argument)
-       for x in handler.res:
-               if isinstance(x, Element):
-                       x.handleCommand(req.args)
-
-       handler.execBegin()
-
-       # now, we have a list with static texts mixed
-       # with non-static Elements.
-       # flatten this list, write into the stream.
-       for x in lreduce(handler.res):
-               if isinstance(x, Element):
-                       if isinstance(x, StreamingElement):
-                               finish = False
-                               x.setStream(stream)
-                       x.render(stream)
-               else:
-                       stream.write(str(x))
-
-       def ping(s):
-               from twisted.internet import reactor
-               s.write("\n");
-               reactor.callLater(3, ping, s)
-
-       # if we met a "StreamingElement", there is at least one
-       # element which wants to output data more than once,
-       # i.e. on host-originated changes.
-       # in this case, don't finish yet, don't cleanup yet,
-       # but instead do that when the client disconnects.
-       if finish:
-               handler.cleanup()
-               stream.finish()
-       else:
-               # ok.
-               # you *need* something which constantly sends something in a regular interval,
-               # in order to detect disconnected clients.
-               # i agree that this "ping" sucks terrible, so better be sure to have something 
-               # similar. A "CurrentTime" is fine. Or anything that creates *some* output.
-               ping(stream)
-               stream.closed_callback = lambda: handler.cleanup()