Support turbo2.
[vuplus_dvbapp] / lib / python / Plugins / Extensions / StreamTV / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 import os
4 from xml.etree.cElementTree import fromstring, ElementTree
5
6 from enigma import gFont, eTimer, eConsoleAppContainer, ePicLoad, loadPNG, getDesktop, eServiceReference, iPlayableService, eListboxPythonMultiContent, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER
7
8 from Screens.Screen import Screen
9 from Screens.ChoiceBox import ChoiceBox
10 from Screens.MessageBox import MessageBox
11 from Screens.InfoBarGenerics import InfoBarNotifications
12
13 from Components.Button import Button
14 from Components.Label import Label
15 from Components.ConfigList import ConfigListScreen
16 from Components.Sources.StaticText import StaticText
17 from Components.ActionMap import NumberActionMap, ActionMap
18 from Components.config import config, ConfigSelection, getConfigListEntry, ConfigText, ConfigDirectory, ConfigYesNo, ConfigSelection
19 from Components.FileList import FileList, FileEntryComponent
20 from Components.MenuList import MenuList
21 from Components.Pixmap import Pixmap, MovingPixmap
22 from Components.AVSwitch import AVSwitch
23 from Components.ServiceEventTracker import ServiceEventTracker
24
25 from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS
26
27 PLUGIN_PATH = resolveFilename(SCOPE_PLUGINS, "Extensions/StreamTV")
28
29 class StreamTVPlayer(Screen, InfoBarNotifications):
30         skin =  """
31                 <screen name="StreamTVPlayer" flags="wfNoBorder" position="0,570" size="1280,190" title="StreamTV Player" backgroundColor="#41000000" >
32                         <ePixmap position="80,25" size="117,72" pixmap="%s/channel_background.png" zPosition="-1" transparent="1" alphatest="blend" />
33                         <widget name="channel_icon" position="121,43" zPosition="10" size="35,35" backgroundColor="#41000000" />
34                         <widget name="channel_name" position="250,20" size="650,40" font="Regular;36" halign="left" valign="center" foregroundColor="#ffffff" backgroundColor="#41000000" />
35                         <widget name="channel_uri" position="250,70" size="950,60" font="Regular;22" halign="left" valign="top" foregroundColor="#ffffff" backgroundColor="#41000000" />
36                         <widget source="session.CurrentService" render="Label" position="805,20" size="300,40" font="Regular;30" halign="right" valign="center" foregroundColor="#f4df8d" backgroundColor="#41000000" transparent="1" >
37                                 <convert type="ServicePosition">Position</convert>
38                         </widget>
39                 </screen>
40                 """ % (PLUGIN_PATH)
41
42         PLAYER_IDLE     = 0
43         PLAYER_PLAYING  = 1
44         PLAYER_PAUSED   = 2
45         def __init__(self, session, service, cbServiceCommand, chName, chURL, chIcon):
46                 Screen.__init__(self, session)
47                 InfoBarNotifications.__init__(self)
48
49                 isEmpty = lambda x: x is None or len(x)==0 or x == 'None'
50                 if isEmpty(chName): chName = 'Unknown'
51                 if isEmpty(chURL):  chURL  = 'Unknown'
52                 if isEmpty(chIcon): chIcon = 'default.png'
53                 chIcon = '%s/icons/%s'%(PLUGIN_PATH,chIcon)
54                 self.session = session
55                 self.service = service
56                 self.cbServiceCommand = cbServiceCommand
57                 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"], {
58                         "ok": self.doInfoAction,
59                         "cancel": self.doExit,
60                         "stop": self.doExit,
61                         "playpauseService": self.playpauseService,
62                 }, -2)
63
64                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap = {
65                         iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
66                         iPlayableService.evStart: self.__serviceStarted,
67                         iPlayableService.evEOF: self.__evEOF,
68                 })
69
70                 self.hidetimer = eTimer()
71                 self.hidetimer.timeout.get().append(self.doInfoAction)
72
73                 self.state = self.PLAYER_PLAYING
74                 self.lastseekstate = self.PLAYER_PLAYING
75                 self.__seekableStatusChanged()
76         
77                 self.onClose.append(self.__onClose)
78                 self.doPlay()
79
80                 self['channel_icon'] = Pixmap()
81                 self['channel_name'] = Label(chName)
82                 self['channel_uri']  = Label(chURL)
83
84                 self.picload = ePicLoad()
85                 self.scale   = AVSwitch().getFramebufferScale()
86                 self.picload.PictureData.get().append(self.cbDrawChannelIcon)
87                 print self.scale[0]
88                 print self.scale[1]
89                 self.picload.setPara((35, 35, self.scale[0], self.scale[1], False, 0, "#00000000"))
90                 self.picload.startDecode(chIcon)
91
92                 self.bypassExit = False
93                 self.cbServiceCommand(('docommand',self.doCommand))
94
95         def doCommand(self, cmd):
96                 if cmd == 'bypass_exit':
97                         self.bypassExit = True
98                         
99         def cbDrawChannelIcon(self, picInfo=None):
100                 ptr = self.picload.getData()
101                 if ptr != None:
102                         self["channel_icon"].instance.setPixmap(ptr.__deref__())
103                         self["channel_icon"].show()
104
105         def __onClose(self):
106                 self.session.nav.stopService()
107
108         def __seekableStatusChanged(self):
109                 service = self.session.nav.getCurrentService()
110                 if service is not None:
111                         seek = service.seek()
112                         if seek is None or not seek.isCurrentlySeekable():
113                                 self.setSeekState(self.PLAYER_PLAYING)
114
115         def __serviceStarted(self):
116                 self.state = self.PLAYER_PLAYING
117                 self.__seekableStatusChanged()
118
119         def __evEOF(self):
120                 if self.bypassExit:
121                         return
122                 self.doExit()
123
124         def __setHideTimer(self):
125                 self.hidetimer.start(5000)
126
127         def doExit(self):
128                 list = ((_("Yes"), "y"), (_("No"), "n"),)
129                 self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this stream?"), list=list)
130
131         def cbDoExit(self, answer):
132                 answer = answer and answer[1]
133                 if answer == "y":
134                         self.cbServiceCommand()
135                         self.close()
136
137         def setSeekState(self, wantstate):
138                 service = self.session.nav.getCurrentService()
139                 if service is None:
140                         print "No Service found"
141                         return
142
143                 pauseable = service.pause()
144                 if pauseable is not None:
145                         if wantstate == self.PLAYER_PAUSED:
146                                 pauseable.pause()
147                                 self.state = self.PLAYER_PAUSED
148                                 if not self.shown:
149                                         self.hidetimer.stop()
150                                         self.show()
151                         elif wantstate == self.PLAYER_PLAYING:
152                                 pauseable.unpause()
153                                 self.state = self.PLAYER_PLAYING
154                                 if self.shown:
155                                         self.__setHideTimer()
156                 else:
157                         self.state = self.PLAYER_PLAYING
158
159         def doInfoAction(self):
160                 if self.shown:
161                         self.hidetimer.stop()
162                         self.hide()
163                 else:
164                         self.show()
165                         if self.state == self.PLAYER_PLAYING:
166                                 self.__setHideTimer()
167
168         def doPlay(self):
169                 if self.state == self.PLAYER_PAUSED:
170                         if self.shown:
171                                 self.__setHideTimer()   
172                 self.state = self.PLAYER_PLAYING
173                 self.session.nav.playService(self.service)
174                 if self.shown:
175                         self.__setHideTimer()
176
177         def playpauseService(self):
178                 if self.state == self.PLAYER_PLAYING:
179                         self.setSeekState(self.PLAYER_PAUSED)
180                 elif self.state == self.PLAYER_PAUSED:
181                         self.setSeekState(self.PLAYER_PLAYING)
182
183 def parseStreamDB(filename):
184         tvlist = []
185         tree = ElementTree()
186         tree.parse(filename)
187
188         for iptv in tree.findall('iptv'):
189                 n = str(iptv.findtext('name'))
190                 i = str(iptv.findtext('icon'))
191                 u = str(iptv.findtext('uri'))
192                 t = str(iptv.findtext('type'))
193                 tvlist.append({'name':n, 'icon':i, 'type':t, 'uri':u})
194         return tvlist
195
196 def streamListEntry(entry):
197         return [entry,
198                 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 1, 35, 35, loadPNG('%s/icons/%s' % (PLUGIN_PATH, str(entry[1].get('icon'))) )),
199                 (eListboxPythonMultiContent.TYPE_TEXT,45,7,550,37,0,RT_HALIGN_LEFT,entry[0])
200         ] 
201 #(eListboxPythonMultiContent.TYPE_TEXT,250,7,310,37,1,RT_HALIGN_LEFT,entry[1].get('uri'))
202 class StreamTVList(Screen):
203         skin =  """
204                 <screen name="StreamTVList" position="center,120" size="600,380" title="StreamTV List">
205                         <widget name="streamlist" position="0,0" size="600,350" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
206                         <widget name="infolabel" position="0,360" size="50,20" font="Regular;18" halign="left" />
207                         <widget name="infomation" position="50,360" size="550,20" font="Regular;18" halign="left" />
208                 </screen>
209                 """
210         def __init__(self, session):
211                 self.session = session
212                 Screen.__init__(self, session)
213                 self["actions"]  = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", "NumberActions", "MenuActions"], {
214                         "ok"    : self.keyOK,
215                         "cancel": self.keyCancel,
216                         "up"    : self.keyUp,
217                         "down"  : self.keyDown,
218                         "left"  : self.keyLeft,
219                         "right" : self.keyRight,
220                 }, -1)
221
222                 self.streamFile = resolveFilename(SCOPE_PLUGINS, "Extensions/StreamTV/stream.xml")
223
224                 self.streamList = []
225                 self.makeStreamList()
226
227                 self.streamMenuList = MenuList([], enableWrapAround=True, content=eListboxPythonMultiContent)
228                 self.streamMenuList.l.setFont(0, gFont('Regular', 22))
229                 self.streamMenuList.l.setFont(1, gFont('Regular', 18))
230                 self.streamMenuList.l.setItemHeight(37) 
231                 self['streamlist'] = self.streamMenuList
232                 self.streamMenuList.setList(map(streamListEntry, self.streamList))
233
234                 self["infolabel"] = Label("URL :")
235                 self["infomation"] = Label(" ")
236                 self.updateInfomation()
237
238                 self.onLayoutFinish.append(self.layoutFinished)
239
240                 self.beforeService  = None
241                 self.currentService = None
242                 self.playerStoped   = False
243                 self.serviceDoCommand = None
244
245                 self.keyLocked = False
246
247         def layoutFinished(self):
248                 rc = os.popen('ps -ef | grep rtmpdump | grep -v grep').read()
249                 print "a process already running :", rc
250                 if rc is not None:
251                         if rc.strip() != '':
252                                 os.system('killall -INT rtmpdump')
253
254         def updateInfomation(self):
255                 infomation = ''
256                 try:
257                         streamInfo = self["streamlist"].getCurrent()[0][1]
258                         infomation = streamInfo.get('uri').split()[0]
259                 except: infomation = ' '
260                 self["infomation"].setText(infomation)
261
262         def keyLeft(self):
263                 if self.keyLocked:
264                         return
265                 self['streamlist'].pageUp()
266                 self.updateInfomation()
267
268         def keyRight(self):
269                 if self.keyLocked:
270                         return
271                 self['streamlist'].pageDown()
272                 self.updateInfomation()
273
274         def keyUp(self):
275                 if self.keyLocked:
276                         return
277                 self['streamlist'].up()
278                 self.updateInfomation()
279
280         def keyDown(self):
281                 if self.keyLocked:
282                         return
283                 self['streamlist'].down()
284                 self.updateInfomation()
285
286         def keyCancel(self):
287                 self.close()
288
289         def keyOK(self):
290                 if self.keyLocked:
291                         return
292                 self.keyLocked = True
293                 self.beforeService  = None
294                 self.currentService = None
295                 self.playerStoped   = False
296                 self.serviceDoCommand = None
297
298                 streamInfo = self["streamlist"].getCurrent()[0][1]
299                 uri = streamInfo.get('uri')
300                 typeInfo = streamInfo.get('type').split(':')
301
302                 serviceType = typeInfo[1]
303                 bufferSize  = typeInfo[2]
304                 self.doStreamAction(uri, serviceType, bufferSize)
305
306         def doStreamAction(self, uri=None, serviceType='4097', bufferSize=None):
307                 try:
308                         serviceType = int(serviceType)
309                 except: serviceType = 4097
310                 try:
311                         bufferSize = int(bufferSize)
312                 except: bufferSize = None
313
314                 streamInfo = self["streamlist"].getCurrent()[0][1]
315                 serviceRef = "%(TYPE)d:0:1:0:0:0:0:0:0:0:%(URI)s:%(NAME)s" % {
316                         'TYPE' :serviceType,
317                         'URI'  :uri.replace(':','%3a'),
318                         'NAME' :streamInfo.get('name')
319                 }
320                 service = eServiceReference(serviceRef)
321                 #if bufferSize is not None:
322                 #       service.setData(2, bufferSize*1024)
323
324                 self.beforeService  = self.session.nav.getCurrentlyPlayingServiceReference()
325                 self.currentService = self.session.openWithCallback(self.cbFinishedStream, 
326                                                                     StreamTVPlayer, 
327                                                                     service, 
328                                                                     cbServiceCommand=self.cbServiceCommand,
329                                                                     chName=str(streamInfo.get('name')),
330                                                                     chURL =str(streamInfo.get('uri')),
331                                                                     chIcon=str(streamInfo.get('icon'))
332                 )
333
334         def cbServiceCommand(self, params=None):
335                 if params is None:
336                         self.playerStoped = True
337                         return
338                 if params[0] == 'docommand':
339                         self.serviceDoCommand = params[1]
340
341         def cbFinishedStream(self):
342                 self.keyLocked = False
343                 self.session.nav.playService(self.beforeService)
344                 print 'player done!!'
345
346         def makeStreamList(self):
347                 streamDB = parseStreamDB(self.streamFile)
348                 self.streamList = []
349                 for x in streamDB:
350                         self.streamList.append((x.get('name'), x))
351
352 def main(session, **kwargs):
353         session.open(StreamTVList)
354                                                            
355 def Plugins(**kwargs):
356         return PluginDescriptor(name=_("StreamTVPlayer"), description="Watching IPTV implemented by RTSP/RTMP protocol.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)
357
358