X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fpython%2FPlugins%2FExtensions%2FStreamTV%2Fplugin.py;fp=lib%2Fpython%2FPlugins%2FExtensions%2FStreamTV%2Fplugin.py;h=691506a3a4d1574a01f2fc2e64210d72c9d61e6e;hp=0000000000000000000000000000000000000000;hb=0ca21ce174763f6e0d94b0cde73f6aa443e898dc;hpb=b7496bd976d8ff7e4da95905e62af61c29fc64fd
diff --git a/lib/python/Plugins/Extensions/StreamTV/plugin.py b/lib/python/Plugins/Extensions/StreamTV/plugin.py
new file mode 100644
index 0000000..691506a
--- /dev/null
+++ b/lib/python/Plugins/Extensions/StreamTV/plugin.py
@@ -0,0 +1,405 @@
+from Plugins.Plugin import PluginDescriptor
+
+import os
+from xml.etree.cElementTree import fromstring, ElementTree
+
+from enigma import gFont, eTimer, eConsoleAppContainer, ePicLoad, loadPNG, getDesktop, eServiceReference, iPlayableService, eListboxPythonMultiContent, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER
+
+from Screens.Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
+from Screens.MessageBox import MessageBox
+from Screens.InfoBarGenerics import InfoBarNotifications
+
+from Components.Button import Button
+from Components.Label import Label
+from Components.ConfigList import ConfigListScreen
+from Components.Sources.StaticText import StaticText
+from Components.ActionMap import NumberActionMap, ActionMap
+from Components.config import config, ConfigSelection, getConfigListEntry, ConfigText, ConfigDirectory, ConfigYesNo, ConfigSelection
+from Components.FileList import FileList, FileEntryComponent
+from Components.MenuList import MenuList
+from Components.Pixmap import Pixmap, MovingPixmap
+from Components.AVSwitch import AVSwitch
+from Components.ServiceEventTracker import ServiceEventTracker
+
+from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS
+
+PLUGIN_PATH = resolveFilename(SCOPE_PLUGINS, "Extensions/StreamTV")
+
+class StreamTVPlayer(Screen, InfoBarNotifications):
+ skin = """
+
+
+
+
+
+
+ Position
+
+
+ """ % (PLUGIN_PATH)
+
+ PLAYER_IDLE = 0
+ PLAYER_PLAYING = 1
+ PLAYER_PAUSED = 2
+ def __init__(self, session, service, cbServiceCommand, chName, chURL, chIcon):
+ Screen.__init__(self, session)
+ InfoBarNotifications.__init__(self)
+
+ isEmpty = lambda x: x is None or len(x)==0 or x == 'None'
+ if isEmpty(chName): chName = 'Unknown'
+ if isEmpty(chURL): chURL = 'Unknown'
+ if isEmpty(chIcon): chIcon = 'default.png'
+ chIcon = '%s/icons/%s'%(PLUGIN_PATH,chIcon)
+ self.session = session
+ self.service = service
+ self.cbServiceCommand = cbServiceCommand
+ self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"], {
+ "ok": self.doInfoAction,
+ "cancel": self.doExit,
+ "stop": self.doExit,
+ "playpauseService": self.playpauseService,
+ }, -2)
+
+ self.__event_tracker = ServiceEventTracker(screen = self, eventmap = {
+ iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+ iPlayableService.evStart: self.__serviceStarted,
+ iPlayableService.evEOF: self.__evEOF,
+ })
+
+ self.hidetimer = eTimer()
+ self.hidetimer.timeout.get().append(self.doInfoAction)
+
+ self.state = self.PLAYER_PLAYING
+ self.lastseekstate = self.PLAYER_PLAYING
+ self.__seekableStatusChanged()
+
+ self.onClose.append(self.__onClose)
+ self.doPlay()
+
+ self['channel_icon'] = Pixmap()
+ self['channel_name'] = Label(chName)
+ self['channel_uri'] = Label(chURL)
+
+ self.picload = ePicLoad()
+ self.scale = AVSwitch().getFramebufferScale()
+ self.picload.PictureData.get().append(self.cbDrawChannelIcon)
+ print self.scale[0]
+ print self.scale[1]
+ self.picload.setPara((35, 35, self.scale[0], self.scale[1], False, 0, "#00000000"))
+ self.picload.startDecode(chIcon)
+
+ self.bypassExit = False
+ self.cbServiceCommand(('docommand',self.doCommand))
+
+ def doCommand(self, cmd):
+ if cmd == 'bypass_exit':
+ self.bypassExit = True
+
+ def cbDrawChannelIcon(self, picInfo=None):
+ ptr = self.picload.getData()
+ if ptr != None:
+ self["channel_icon"].instance.setPixmap(ptr.__deref__())
+ self["channel_icon"].show()
+
+ def __onClose(self):
+ self.session.nav.stopService()
+
+ def __seekableStatusChanged(self):
+ service = self.session.nav.getCurrentService()
+ if service is not None:
+ seek = service.seek()
+ if seek is None or not seek.isCurrentlySeekable():
+ self.setSeekState(self.PLAYER_PLAYING)
+
+ def __serviceStarted(self):
+ self.state = self.PLAYER_PLAYING
+ self.__seekableStatusChanged()
+
+ def __evEOF(self):
+ if self.bypassExit:
+ return
+ self.doExit()
+
+ def __setHideTimer(self):
+ self.hidetimer.start(5000)
+
+ def doExit(self):
+ list = ((_("Yes"), "y"), (_("No"), "n"),)
+ self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this stream?"), list=list)
+
+ def cbDoExit(self, answer):
+ answer = answer and answer[1]
+ if answer == "y":
+ self.cbServiceCommand()
+ self.close()
+
+ def setSeekState(self, wantstate):
+ service = self.session.nav.getCurrentService()
+ if service is None:
+ print "No Service found"
+ return
+
+ pauseable = service.pause()
+ if pauseable is not None:
+ if wantstate == self.PLAYER_PAUSED:
+ pauseable.pause()
+ self.state = self.PLAYER_PAUSED
+ if not self.shown:
+ self.hidetimer.stop()
+ self.show()
+ elif wantstate == self.PLAYER_PLAYING:
+ pauseable.unpause()
+ self.state = self.PLAYER_PLAYING
+ if self.shown:
+ self.__setHideTimer()
+ else:
+ self.state = self.PLAYER_PLAYING
+
+ def doInfoAction(self):
+ if self.shown:
+ self.hidetimer.stop()
+ self.hide()
+ else:
+ self.show()
+ if self.state == self.PLAYER_PLAYING:
+ self.__setHideTimer()
+
+ def doPlay(self):
+ if self.state == self.PLAYER_PAUSED:
+ if self.shown:
+ self.__setHideTimer()
+ self.state = self.PLAYER_PLAYING
+ self.session.nav.playService(self.service)
+ if self.shown:
+ self.__setHideTimer()
+
+ def playpauseService(self):
+ if self.state == self.PLAYER_PLAYING:
+ self.setSeekState(self.PLAYER_PAUSED)
+ elif self.state == self.PLAYER_PAUSED:
+ self.setSeekState(self.PLAYER_PLAYING)
+
+class StreamURIParser:
+ def __init__(self, xml):
+ self.xml = xml
+
+ def parseStreamList(self):
+ tvlist = []
+ tree = ElementTree()
+ tree.parse(self.xml)
+
+ for iptv in tree.findall('iptv'):
+ n = str(iptv.findtext('name'))
+ i = str(iptv.findtext('icon'))
+ u = str(iptv.findtext('uri'))
+ t = str(iptv.findtext('type'))
+ tvlist.append({'name':n, 'icon':i, 'type':t, 'uri':self.parseStreamURI(u)})
+ return tvlist
+
+ def parseStreamURI(self, uri):
+ uriInfo = {}
+ splitedURI = uri.split()
+ uriInfo['URL'] = splitedURI[0]
+ for x in splitedURI[1:]:
+ i = x.find('=')
+ uriInfo[x[:i].upper()] = str(x[i+1:])
+ return uriInfo
+
+def streamListEntry(entry):
+ #print entry
+ uriInfo = entry[1].get('uri')
+ return [entry,
+ (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 1, 35, 35, loadPNG('%s/icons/%s' % (PLUGIN_PATH, str(entry[1].get('icon'))) )),
+ (eListboxPythonMultiContent.TYPE_TEXT,45,7,200,37,0,RT_HALIGN_LEFT,entry[0]),
+ (eListboxPythonMultiContent.TYPE_TEXT,250,7,310,37,1,RT_HALIGN_LEFT,str(uriInfo.get('URL')))
+ ]
+
+class StreamTVList(Screen):
+ skin = """
+
+
+
+ """
+ def __init__(self, session):
+ self.session = session
+ Screen.__init__(self, session)
+ self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", "NumberActions", "MenuActions"], {
+ "ok" : self.keyOK,
+ "cancel": self.keyCancel,
+ "up" : self.keyUp,
+ "down" : self.keyDown,
+ "left" : self.keyLeft,
+ "right" : self.keyRight,
+ }, -1)
+
+ self.streamBin = resolveFilename(SCOPE_PLUGINS, "Extensions/StreamTV/rtmpdump")
+ self.streamFile = resolveFilename(SCOPE_PLUGINS, "Extensions/StreamTV/stream.xml")
+
+ self.streamList = []
+ self.makeStreamList()
+
+ self.streamMenuList = MenuList([], enableWrapAround=True, content=eListboxPythonMultiContent)
+ self.streamMenuList.l.setFont(0, gFont('Regular', 22))
+ self.streamMenuList.l.setFont(1, gFont('Regular', 18))
+ self.streamMenuList.l.setItemHeight(37)
+ self['streamlist'] = self.streamMenuList
+ self.streamMenuList.setList(map(streamListEntry, self.streamList))
+
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ self.rtmpConsole = None
+ self.beforeService = None
+ self.currentService = None
+ self.playerStoped = False
+ self.serviceDoCommand = None
+
+ self.keyLocked = False
+
+ def layoutFinished(self):
+ rc = os.popen('ps -ef | grep rtmpdump | grep -v grep').read()
+ print "a process already running :", rc
+ if rc is not None:
+ if rc.strip() != '':
+ os.system('killall -INT rtmpdump')
+ def keyLeft(self):
+ if self.keyLocked:
+ return
+ self['streamlist'].pageUp()
+
+ def keyRight(self):
+ if self.keyLocked:
+ return
+ self['streamlist'].pageDown()
+
+ def keyUp(self):
+ if self.keyLocked:
+ return
+ self['streamlist'].up()
+
+ def keyDown(self):
+ if self.keyLocked:
+ return
+ self['streamlist'].down()
+
+ def keyCancel(self):
+ self.cbAppClosed(True)
+ self.close()
+
+ def keyOK(self):
+ if self.keyLocked:
+ return
+ self.keyLocked = True
+ self.rtmpConsole = None
+ self.beforeService = None
+ self.currentService = None
+ self.playerStoped = False
+ self.serviceDoCommand = None
+
+ streamInfo = self["streamlist"].getCurrent()[0][1]
+ uriInfo = streamInfo.get('uri')
+ typeInfo = streamInfo.get('type').split(':')
+
+ protocol = typeInfo[0]
+ url = uriInfo.get('URL')
+ if protocol == 'rtmp':
+ self.layoutFinished()
+ self.rtmpConsole = eConsoleAppContainer()
+ self.rtmpConsole.dataAvail.append(self.cbDataAvail)
+ self.rtmpConsole.appClosed.append(self.cbAppClosed)
+ self.rtmpConsole.execute(self.makeCommand(uriInfo))
+ elif protocol in ('rtsp', 'http', 'hls'):
+ serviceType = typeInfo[1]
+ bufferSize = typeInfo[2]
+ self.doStreamAction(url, serviceType, bufferSize)
+
+ def doStreamAction(self, url=None, serviceType='4097', bufferSize=None):
+ if url is None:
+ url='/tmp/stream.avi'
+ self.streamPlayerTimer.stop()
+ #if os.path.exists(url):
+ # os.unlink(url)
+ try:
+ serviceType = int(serviceType)
+ except: serviceType = 4097
+ try:
+ bufferSize = int(bufferSize)
+ except: bufferSize = None
+
+ service = eServiceReference(serviceType, 0, url)
+ #if bufferSize is not None:
+ # service.setData(2, bufferSize*1024)
+
+ streamInfo = self["streamlist"].getCurrent()[0][1]
+ uriInfo = streamInfo.get('uri')
+ self.beforeService = self.session.nav.getCurrentlyPlayingServiceReference()
+ self.currentService = self.session.openWithCallback(self.cbFinishedStream,
+ StreamTVPlayer,
+ service,
+ cbServiceCommand=self.cbServiceCommand,
+ chName=str(streamInfo.get('name')),
+ chURL =str(uriInfo.get('URL')),
+ chIcon=str(streamInfo.get('icon')))
+
+ def cbServiceCommand(self, params=None):
+ if params is None:
+ self.playerStoped = True
+ return
+ if params[0] == 'docommand':
+ self.serviceDoCommand = params[1]
+
+ def cbAppClosed(self, ret):
+ print ret
+ self.doConsoleStop()
+ if self.currentService is not None and not self.playerStoped:
+ self.serviceDoCommand('bypass_exit')
+ message = "The connection was terminated from the stream server."
+ self.session.open(MessageBox, message, type=MessageBox.TYPE_INFO)
+ self.currentService.close()
+ self.currentService = None
+ self.serviceDoCommand = None
+
+ def cbDataAvail(self, data):
+ print data
+ if str(data) == 'Connected...':
+ self.streamPlayerTimer = eTimer()
+ self.streamPlayerTimer.timeout.get().append(self.doStreamAction)
+ self.streamPlayerTimer.start(1000)
+
+ def cbFinishedStream(self):
+ self.doConsoleStop()
+ print 'done!!'
+
+ def doConsoleStop(self):
+ self.keyLocked = False
+ if self.rtmpConsole is not None:
+ self.rtmpConsole.sendCtrlC()
+ self.rtmpConsole = None
+
+ def makeCommand(self, uriInfo):
+ def appendCommand(key, option):
+ try:
+ d = uriInfo.get(key)
+ if d is not None:
+ return "-%s %s " %(option, d)
+ except: pass
+ return ''
+ command = '%s -v ' % (self.streamBin)
+ command += appendCommand('URL', 'r')
+ command += appendCommand('PLAYPATH', 'y')
+ command += appendCommand('SWFURL', 'W')
+ return command
+
+ def makeStreamList(self):
+ streamDB = StreamURIParser(self.streamFile).parseStreamList()
+ self.streamList = []
+ for x in streamDB:
+ self.streamList.append((x.get('name'), x))
+
+def main(session, **kwargs):
+ session.open(StreamTVList)
+
+def Plugins(**kwargs):
+ return PluginDescriptor(name=_("StreamTVPalyer"), description="Watching IPTV implemented by RTSP/RTMP protocol.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
+
+