new functions:
[enigma2-plugins.git] / virtualzap / src / plugin.py
1 #
2 #  VirtualZap E2
3 #
4 #  $Id$
5 #
6 #  Coded by Dr.Best (c) 2010
7 #  Coding idea and design by Vali
8 #  Support: www.dreambox-tools.info
9 #
10 #  This plugin is licensed under the Creative Commons 
11 #  Attribution-NonCommercial-ShareAlike 3.0 Unported 
12 #  License. To view a copy of this license, visit
13 #  http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
14 #  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
15 #
16 #  Alternatively, this plugin may be distributed and executed on hardware which
17 #  is licensed by Dream Multimedia GmbH.
18
19 #  This plugin is NOT free software. It is open source, you are allowed to
20 #  modify it (if you keep the license), but it may not be commercially 
21 #  distributed other than under the conditions noted above.
22 #
23 \r
24 from Plugins.Plugin import PluginDescriptor\r
25 from Screens.Screen import Screen\r
26 from Components.ActionMap import ActionMap, NumberActionMap\r
27 from Components.Label import Label\r
28 from enigma import eServiceReference,  eTimer, getDesktop\r
29 from ServiceReference import ServiceReference\r
30 from Components.SystemInfo import SystemInfo
31 from enigma import eServiceCenter, getBestPlayableServiceReference
32 from Components.VideoWindow import VideoWindow
33 from enigma import ePoint, eEPGCache
34 from time import localtime, time
35 from Screens.InfoBarGenerics import InfoBarShowHide, NumberZap
36 from Screens.InfoBar import InfoBar
37
38 from Components.Sources.StaticText import StaticText
39 from Screens.MessageBox import MessageBox
40 from Screens.Standby import TryQuitMainloop
41
42 from Screens.EpgSelection import EPGSelection
43 from Screens.EventView import  EventViewEPGSelect
44 from Screens.PictureInPicture import PictureInPicture
45
46 InfoBarShowHideINIT = None
47
48 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigYesNo, getConfigListEntry, configfile
49 from Components.ConfigList import ConfigList, ConfigListScreen
50
51 # for localized messages
52 from . import _
53
54 config.plugins.virtualzap = ConfigSubsection()
55 config.plugins.virtualzap.mode = ConfigSelection(default="0", choices = [("0", _("as plugin in extended bar")),("1", _("with long OK press")), ("2", _("with exit button"))])
56 config.plugins.virtualzap.usepip = ConfigYesNo(default = True)
57
58 def autostart(reason, **kwargs):
59         if config.plugins.virtualzap.mode.value != "0":
60                 # overide InfoBarShowHide
61                 global InfoBarShowHideINIT
62                 if InfoBarShowHideINIT is None:
63                         InfoBarShowHideINIT = InfoBarShowHide.__init__
64                 InfoBarShowHide.__init__ = InfoBarShowHide__init__
65                 # new method
66                 InfoBarShowHide.showVZ = showVZ
67                 InfoBarShowHide.VirtualZapCallback = VirtualZapCallback
68                 if config.plugins.virtualzap.mode.value == "2":
69                         InfoBarShowHide.newHide = newHide
70
71 def InfoBarShowHide__init__(self):
72         # initialize InfoBarShowHide with original __init__
73         InfoBarShowHideINIT(self)
74         # delete current key map --> we have to use "ok" with b-flag
75         if config.plugins.virtualzap.mode.value == "1":
76                 del self["ShowHideActions"]
77                 # initialize own actionmap with ok = b and longOK = l
78                 self["myactions"] = ActionMap( ["myShowHideActions"] ,
79                 {
80                         "toggleShow": self.toggleShow,
81                         "longOK": self.showVZ,
82                         "hide": self.hide,
83                 }, 1)
84         elif config.plugins.virtualzap.mode.value == "2":
85                 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
86                 {
87                         "toggleShow": self.toggleShow,
88                         "hide": self.newHide,
89                 }, 1)
90
91
92 def showVZ(self):
93         from  Screens.InfoBarGenerics import InfoBarEPG, InfoBarPiP
94         # check for InfoBarEPG --> only start if true
95         if isinstance(self, InfoBarEPG):
96                 # check for PiP
97                 if isinstance(self, InfoBarPiP):
98                         # check if PiP is already shown
99                         if self.pipShown():
100                                 # it is... close it!
101                                 self.showPiP()
102                 if isinstance(self, InfoBar):
103                         self.session.openWithCallback(self.VirtualZapCallback, VirtualZap, self.servicelist)
104
105 def VirtualZapCallback(self, service = None, servicePath = None):
106         from  Screens.InfoBarGenerics import InfoBarEPG, InfoBarPiP
107         if isinstance(self, InfoBarPiP):
108                 if service and servicePath:
109                         self.session.pip = self.session.instantiateDialog(PictureInPicture)
110                         self.session.pip.show()
111                         if self.session.pip.playService(service):
112                                 self.session.pipshown = True
113                                 self.session.pip.servicePath = servicePath
114                         else:
115                                 self.session.pipshown = False
116                                 del self.session.pip
117                                 self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)
118
119 def newHide(self):
120         # remember if infobar is shown
121         visible = self.shown
122         self.hide()
123         if not visible:
124                 # infobar was not shown, start VZ
125                 self.showVZ()
126
127 def Plugins(**kwargs):
128         plist =  [PluginDescriptor(name="Virtual Zap Setup", description=_("Virtual Zap Setup"), where = [PluginDescriptor.WHERE_PLUGINMENU], icon = "plugin.png", fnc = setup)]
129         if config.plugins.virtualzap.mode.value == "0":
130                 plist.append(PluginDescriptor(name="Virtual Zap", description=_("Virtual (PiP) Zap"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU],icon = "plugin.png", fnc = main))
131         elif config.plugins.virtualzap.mode.value == "1" or config.plugins.virtualzap.mode.value == "2":
132                 plist.append(PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART],fnc = autostart))
133         return plist
134
135 def setup(session,**kwargs):
136         session.open(VirtualZapConfig)
137
138 def main(session,**kwargs):
139         session.open(VirtualZap, kwargs["servicelist"])
140
141 class VirtualZap(Screen):\r
142         sz_w = getDesktop(0).size().width()
143
144         #
145         # VirtualZap or VirtualZapNoPiP
146         #
147
148         if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value:
149                 if sz_w == 1280:
150                         skin = """
151                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,505" size="1280,220" title="Virtual Zap">
152                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/hd.png" position="0,0" size="1280,220" zPosition="0"/>
153                                         <widget backgroundColor="transparent" name="video" position="60,50" size="214,120" zPosition="1"/>
154                                         <widget backgroundColor="#101214" font="Regular;26" halign="left" name="NowChannel" position="305,60" size="887,32" transparent="1" zPosition="2"/>
155                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="left" name="NowEPG" position="305,105" size="600,28" transparent="1" zPosition="2"/>
156                                         <widget backgroundColor="#101214" font="Regular;24" halign="left" name="NextEPG" position="305,140" size="600,28" transparent="1" zPosition="2"/>
157                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="right" name="NowTime" position="1070,105" size="124,28" transparent="1" zPosition="2"/>
158                                         <widget backgroundColor="#101214" font="Regular;24" halign="right" name="NextTime" position="1070,140" size="124,28" transparent="1" zPosition="2"/>
159                                 </screen>"""
160                 elif sz_w == 1024:
161                         skin = """
162                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,420" size="1024,176" title="Virtual Zap">
163                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="1024,176" zPosition="0"/>
164                                         <widget backgroundColor="transparent" name="video" position="50,20" size="164,92" zPosition="1"/>
165                                         <widget backgroundColor="#101214" font="Regular;22" halign="left" name="NowChannel" position="230,25" size="741,30" transparent="1" zPosition="2"/>
166                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="230,55" size="600,25" transparent="1" zPosition="2"/>
167                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="230,80" size="600,25" transparent="1" zPosition="2"/>
168                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="850,55" size="124,25" transparent="1" zPosition="2"/>
169                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="850,80" size="124,25" transparent="1" zPosition="2"/>
170                                 </screen>"""
171                 else:
172                         skin = """
173                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,420" size="720,176" title="Virtual Zap">
174                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="720,176" zPosition="0"/>
175                                         <widget backgroundColor="transparent" name="video" position="50,25" size="130,73" zPosition="1"/>
176                                         <widget backgroundColor="#101214" font="Regular;22" halign="left" name="NowChannel" position="190,25" size="480,30" transparent="1" zPosition="2"/>
177                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="190,55" size="360,25" transparent="1" zPosition="2"/>
178                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="190,80" size="360,25" transparent="1" zPosition="2"/>
179                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="550,55" size="120,25" transparent="1" zPosition="2"/>
180                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="550,80" size="120,25" transparent="1" zPosition="2"/>
181                                 </screen>"""
182         else:
183                 if sz_w == 1280:
184                         skin = """
185                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,505" size="1280,220" title="Virtual Zap">
186                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/hd.png" position="0,0" size="1280,220" zPosition="0"/>
187                                         <widget backgroundColor="#101214" font="Regular;26" halign="center" name="NowChannel" position="140,60" size="1000,32" transparent="1" zPosition="2"/>
188                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="left" name="NowEPG" position="140,105" size="860,28" transparent="1" zPosition="2"/>
189                                         <widget backgroundColor="#101214" font="Regular;24" halign="left" name="NextEPG" position="140,140" size="860,28" transparent="1" zPosition="2"/>
190                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="right" name="NowTime" position="1015,105" size="124,28" transparent="1" zPosition="2"/>
191                                         <widget backgroundColor="#101214" font="Regular;24" halign="right" name="NextTime" position="1015,140" size="124,28" transparent="1" zPosition="2"/>
192                                 </screen>"""
193                 elif sz_w == 1024:
194                         skin = """
195                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,420" size="1024,176" title="Virtual Zap">
196                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="1024,176" zPosition="0"/>
197                                         <widget backgroundColor="#101214" font="Regular;22" halign="center" name="NowChannel" position="100,25" size="824,30" transparent="1" zPosition="2"/>
198                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="100,55" size="700,25" transparent="1" zPosition="2"/>
199                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="100,80" size="700,25" transparent="1" zPosition="2"/>
200                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="800,55" size="124,25" transparent="1" zPosition="2"/>
201                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="800,80" size="124,25" transparent="1" zPosition="2"/>
202                                 </screen>"""
203                 else:
204                         skin = """
205                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,420" size="720,176" title="Virtual Zap">
206                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="720,176" zPosition="0"/>
207                                         <widget backgroundColor="#101214" font="Regular;22" halign="center" name="NowChannel" position="50,25" size="620,30" transparent="1" zPosition="2"/>
208                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="50,55" size="500,25" transparent="1" zPosition="2"/>
209                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="50,80" size="500,25" transparent="1" zPosition="2"/>
210                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="550,55" size="120,25" transparent="1" zPosition="2"/>
211                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="550,80" size="120,25" transparent="1" zPosition="2"/>
212                                 </screen>"""
213
214 \r
215         def __init__(self, session, servicelist = None):\r
216                 Screen.__init__(self, session)\r
217                 self.session = session
218                 self.pipAvailable = False
219                 if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value:
220                         self.skinName = "VirtualZap"
221                         self.pipAvailable = True
222                 else:
223                         self.skinName = "VirtualZapNoPiP"
224                 self.epgcache = eEPGCache.getInstance()\r
225                 self.CheckForEPG = eTimer()\r
226                 self.CheckForEPG.callback.append(self.CheckItNow)\r
227                 self["NowChannel"] = Label()\r
228                 self["NowEPG"] = Label()\r
229                 self["NextEPG"] = Label()
230                 self["NowTime"] = Label()\r
231                 self["NextTime"] = Label()\r
232                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ChannelSelectBaseActions", "ChannelSelectEPGActions", "ColorActions"], 
233                 {\r
234                         "ok": self.ok, \r
235                         "cancel": self.closing,\r
236                         "right": self.nextService,\r
237                         "left": self.prevService,
238                         "nextBouquet": self.nextBouquet,
239                         "prevBouquet": self.prevBouquet,
240                         "showEPGList": self.openEventView,
241                         "blue": self.standardPiP,
242                         "yellow": self.switchAndStandardPiP,
243                 },-2)
244                 self["actions2"] = NumberActionMap(["NumberActions"],
245                 {
246                         "0": self.swap,
247                         "1": self.keyNumberGlobal,
248                         "2": self.keyNumberGlobal,
249                         "3": self.keyNumberGlobal,
250                         "4": self.keyNumberGlobal,
251                         "5": self.keyNumberGlobal,
252                         "6": self.keyNumberGlobal,
253                         "7": self.keyNumberGlobal,
254                         "8": self.keyNumberGlobal,
255                         "9": self.keyNumberGlobal,
256                 }, -1)
257                 self.onLayoutFinish.append(self.onLayoutReady)
258                 # PiP
259                 if self.pipAvailable:
260                         # activate PiP support
261                         self["video"] = VideoWindow(fb_width = getDesktop(0).size().width(), fb_height = getDesktop(0).size().height())
262                         self.currentPiP = ""
263                 # this is the servicelist from ChannelSelectionBase
264                 self.servicelist = servicelist
265                 # needed, because if we won't zap, we habe to go back to the current bouquet and service
266                 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
267                 self.curBouquet = self.servicelist.getRoot()
268
269         def onLayoutReady(self):
270                 self.updateInfos()
271
272         def nextService(self):
273                 # get next service
274                 if self.servicelist.inBouquet():
275                         prev = self.servicelist.getCurrentSelection()
276                         if prev:
277                                 prev = prev.toString()
278                                 while True:
279                                         if config.usage.quickzap_bouquet_change.value and self.servicelist.atEnd():
280                                                 self.servicelist.nextBouquet()
281                                         else:
282                                                 self.servicelist.moveDown()
283                                         cur = self.servicelist.getCurrentSelection()
284                                         if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
285                                                 break
286                 else:
287                         self.servicelist.moveDown()
288                 if self.isPlayable():
289                         self.updateInfos()
290                 else:
291                         self.nextService()
292
293         def prevService(self):
294                 # get previous service
295                 if self.servicelist.inBouquet():
296                         prev = self.servicelist.getCurrentSelection()
297                         if prev:
298                                 prev = prev.toString()
299                                 while True:
300                                         if config.usage.quickzap_bouquet_change.value:
301                                                 if self.servicelist.atBegin():
302                                                         self.servicelist.prevBouquet()
303                                         self.servicelist.moveUp()
304                                         cur = self.servicelist.getCurrentSelection()
305                                         if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
306                                                 break
307                 else:
308                         self.servicelist.moveUp()
309                 if self.isPlayable():
310                         self.updateInfos()
311                 else:
312                         self.prevService()
313
314         def isPlayable(self):
315                 # check if service is playable
316                 current = ServiceReference(self.servicelist.getCurrentSelection())
317                 return not (current.ref.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
318
319
320         def nextBouquet(self):
321                 # next bouquet with first service
322                 if config.usage.multibouquet.value:
323                         self.servicelist.nextBouquet()
324                 self.updateInfos()
325
326         def prevBouquet(self):
327                 # previous bouquet with first service
328                 if config.usage.multibouquet.value:
329                         self.servicelist.prevBouquet()
330                 self.updateInfos()
331 \r
332 \r
333         def updateInfos(self):
334                 # update data\r
335                 current = ServiceReference(self.servicelist.getCurrentSelection())
336                 self["NowChannel"].setText(current.getServiceName())
337                 nowepg, nowtimedisplay = self.getEPGNowNext(current.ref,0)
338                 nextepg, nexttimedisplay = self.getEPGNowNext(current.ref,1)
339                 self["NowEPG"].setText(nowepg)
340                 self["NextEPG"].setText(nextepg)
341                 self["NowTime"].setText(nowtimedisplay)
342                 self["NextTime"].setText(nexttimedisplay)
343                 if not nowepg:
344                         # no epg found --> let's try it again, but only if PiP is activated
345                         if self.pipAvailable:
346                                 self.CheckForEPG.start(3000, True)
347                 if self.pipAvailable:
348                         # play in videowindow
349                         self.playService(current.ref)
350
351         def getEPGNowNext(self,ref, modus):
352                 # get now || next event
353                 if self.epgcache is not None:
354                         event = self.epgcache.lookupEvent(['IBDCTSERNX', (ref.toString(), modus, -1)])
355                         if event:
356                                 if event[0][4]:
357                                         t = localtime(event[0][1])
358                                         duration = event[0][2]
359                                         if modus == 0:
360                                                 timedisplay = "+%d min" % (((event[0][1] + duration) - time()) / 60)
361                                         elif modus == 1:
362                                                 timedisplay = "%d min" %  (duration / 60)
363                                         return "%02d:%02d %s" % (t[3],t[4], event[0][4]), timedisplay
364                                 else:
365                                         return "", ""
366                 return "", ""
367
368         def openSingleServiceEPG(self):
369                 # show EPGList
370                 current = ServiceReference(self.servicelist.getCurrentSelection())
371                 self.session.open(EPGSelection, current.ref)
372
373         def openEventView(self):
374                 # show EPG Event
375                 epglist = [ ]
376                 self.epglist = epglist
377                 service = ServiceReference(self.servicelist.getCurrentSelection())
378                 ref = service.ref
379                 evt = self.epgcache.lookupEventTime(ref, -1)
380                 if evt:
381                         epglist.append(evt)
382                 evt = self.epgcache.lookupEventTime(ref, -1, 1)
383                 if evt:
384                         epglist.append(evt)
385                 if epglist:
386                         self.session.open(EventViewEPGSelect, epglist[0], service, self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
387
388         def eventViewCallback(self, setEvent, setService, val):
389                 epglist = self.epglist
390                 if len(epglist) > 1:
391                         tmp = epglist[0]
392                         epglist[0] = epglist[1]
393                         epglist[1] = tmp
394                         setEvent(epglist[0])
395
396         def openMultiServiceEPG(self):
397                 # not supported
398                 pass
399
400         def openSimilarList(self, eventid, refstr):
401                 self.session.open(EPGSelection, refstr, None, eventid)
402
403         def setServicelistSelection(self, bouquet, service):
404                 # we need to select the old service with bouquet
405                 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
406                         self.servicelist.clearPath()
407                         if self.servicelist.bouquet_root != bouquet:
408                                 self.servicelist.enterPath(self.servicelist.bouquet_root)
409                         self.servicelist.enterPath(bouquet)
410                 self.servicelist.setCurrentSelection(service) #select the service in servicelist
411
412         def closing(self):
413                 if self.pipAvailable:
414                         self.pipservice = None
415                 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
416                 self.close()\r
417                         \r
418         def ok(self):
419                 # we have to close PiP first, otherwise the service-display is freezed
420                 if self.pipAvailable:
421                         self.pipservice = None
422                 # play selected service and close virtualzap
423                 self.servicelist.zap()\r
424                 self.close()
425
426         def standardPiP(self):
427                 if not self.pipAvailable:
428                         return
429                 # close PiP
430                 self.pipservice = None
431                 # save current selected service for standard PiP
432                 service = ServiceReference(self.servicelist.getCurrentSelection()).ref
433                 servicePath = self.servicelist.getCurrentServicePath() # same bug as in channcelsection 
434                 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
435                 # close VZ and start standard PiP
436                 self.close(service, servicePath)
437
438         def switchAndStandardPiP(self):
439                 if not self.pipAvailable:
440                         return
441                 self.pipservice = None
442                 # save current selected servicePath for standard PiP
443                 servicePath = self.servicelist.getCurrentServicePath()
444                 # play selected service and close virtualzap
445                 self.servicelist.zap()
446                 # close VZ and start standard PiP
447                 self.close(self.curRef.ref, servicePath)
448 \r
449         def CheckItNow(self):\r
450                 self.CheckForEPG.stop()\r
451                 self.updateInfos()
452
453         # if available play service in PiP 
454         def playService(self, service):
455                 if service and (service.flags & eServiceReference.isGroup):
456                         ref = getBestPlayableServiceReference(service, eServiceReference())
457                 else:
458                         ref = service
459                 if ref and ref.toString() != self.currentPiP:
460                         self.pipservice = eServiceCenter.getInstance().play(ref)
461                         if self.pipservice and not self.pipservice.setTarget(1):
462                                 self.pipservice.start()
463                                 self.currentPiP = ref.toString()
464                         else:
465                                 self.pipservice = None
466                                 self.currentPiP = ""
467
468
469         # switch with numbers
470         def keyNumberGlobal(self, number):
471                 self.session.openWithCallback(self.numberEntered, NumberZap, number)
472
473         def numberEntered(self, retval):
474                 if retval > 0:
475                         self.zapToNumber(retval)
476
477         def searchNumberHelper(self, serviceHandler, num, bouquet):
478                 servicelist = serviceHandler.list(bouquet)
479                 if not servicelist is None:
480                         while num:
481                                 serviceIterator = servicelist.getNext()
482                                 if not serviceIterator.valid(): #check end of list
483                                         break
484                                 playable = not (serviceIterator.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
485                                 if playable:
486                                         num -= 1;
487                         if not num: #found service with searched number ?
488                                 return serviceIterator, 0
489                 return None, num
490
491         def zapToNumber(self, number):
492                 bouquet = self.servicelist.bouquet_root
493                 service = None
494                 serviceHandler = eServiceCenter.getInstance()
495                 bouquetlist = serviceHandler.list(bouquet)
496                 if not bouquetlist is None:
497                         while number:
498                                 bouquet = bouquetlist.getNext()
499                                 if not bouquet.valid(): #check end of list
500                                         break
501                                 if bouquet.flags & eServiceReference.isDirectory:
502                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
503                 if not service is None:
504                         self.setServicelistSelection(bouquet, service)
505                 # update infos, no matter if service is none or not
506                 self.updateInfos()
507
508         def swap(self, number):
509                 # save old values for selecting it in servicelist after zapping
510                 currentRef = self.curRef
511                 currentBouquet = self.curBouquet
512                 # we have to close PiP first, otherwise the service-display is freezed
513                 if self.pipAvailable:
514                         self.pipservice = None
515                 # zap and set new values for the new reference and bouquet
516                 self.servicelist.zap()
517                 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
518                 self.curBouquet = self.servicelist.getRoot()
519                 # select old values in servicelist
520                 self.setServicelistSelection(currentBouquet, currentRef.ref)
521                 # play old service in PiP
522                 self.updateInfos()
523
524 class VirtualZapConfig(Screen, ConfigListScreen):
525
526         skin = """
527                 <screen position="center,center" size="560,110" title="Virtual Zap Config" >
528                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
529                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
530                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
531                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
532                         <widget render="Label" source="key_red" position="0,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
533                         <widget render="Label" source="key_green" position="140,0" size="140,40" zPosition="5" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
534                         <widget name="config" position="20,50" size="520,330" scrollbarMode="showOnDemand" />
535                 </screen>"""
536
537         def __init__(self, session):
538                 Screen.__init__(self, session)
539                 self["key_red"] = StaticText(_("Cancel"))
540                 self["key_green"] = StaticText(_("OK"))
541                 self.list = [ ]
542                 self.list.append(getConfigListEntry(_("Usage"), config.plugins.virtualzap.mode))
543                 if SystemInfo.get("NumVideoDecoders", 1) > 1:
544                         self.list.append(getConfigListEntry(_("Show with PiP"), config.plugins.virtualzap.usepip))
545                 ConfigListScreen.__init__(self, self.list, session)
546                 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
547                 {
548                         "green": self.keySave,
549                         "cancel": self.keyClose,
550                 }, -2)
551
552         def keySave(self):
553                 for x in self["config"].list:
554                         x[1].save()
555                 configfile.save()
556                 restartbox = self.session.openWithCallback(self.restartGUI,MessageBox,_("GUI needs a restart to apply the new settings.\nDo you want to Restart the GUI now?"), MessageBox.TYPE_YESNO)
557                 restartbox.setTitle(_("Restart GUI now?"))
558                 
559
560         def keyClose(self):
561                 for x in self["config"].list:
562                         x[1].cancel()
563                 self.close()
564
565         def restartGUI(self, answer):
566                 if answer is True:
567                         self.session.open(TryQuitMainloop, 3)
568                 else:
569                         self.close()
570