clean up
[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, InfoBarPiP
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
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         if isinstance(self, InfoBarPiP):
107                 if service and servicePath:
108                         self.session.pip = self.session.instantiateDialog(PictureInPicture)
109                         self.session.pip.show()
110                         if self.session.pip.playService(service):
111                                 self.session.pipshown = True
112                                 self.session.pip.servicePath = servicePath
113                         else:
114                                 self.session.pipshown = False
115                                 del self.session.pip
116                                 self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)
117
118 def newHide(self):
119         # remember if infobar is shown
120         visible = self.shown
121         self.hide()
122         if not visible:
123                 # infobar was not shown, start VZ
124                 self.showVZ()
125
126 def Plugins(**kwargs):
127         plist =  [PluginDescriptor(name="Virtual Zap Setup", description=_("Virtual Zap Setup"), where = [PluginDescriptor.WHERE_PLUGINMENU], icon = "plugin.png", fnc = setup)]
128         if config.plugins.virtualzap.mode.value == "0":
129                 plist.append(PluginDescriptor(name="Virtual Zap", description=_("Virtual (PiP) Zap"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU],icon = "plugin.png", fnc = main))
130         elif config.plugins.virtualzap.mode.value == "1" or config.plugins.virtualzap.mode.value == "2":
131                 plist.append(PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART],fnc = autostart))
132         return plist
133
134 def setup(session,**kwargs):
135         session.open(VirtualZapConfig)
136
137 def main(session,**kwargs):
138         session.open(VirtualZap, kwargs["servicelist"])
139
140 class VirtualZap(Screen):\r
141         sz_w = getDesktop(0).size().width()
142
143         #
144         # VirtualZap or VirtualZapNoPiP
145         #
146
147         if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value:
148                 if sz_w == 1280:
149                         skin = """
150                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,505" size="1280,220" title="Virtual Zap">
151                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/hd.png" position="0,0" size="1280,220" zPosition="0"/>
152                                         <widget backgroundColor="transparent" name="video" position="60,50" size="214,120" zPosition="1"/>
153                                         <widget backgroundColor="#101214" font="Regular;26" halign="left" name="NowChannel" position="305,60" size="887,32" transparent="1" zPosition="2"/>
154                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="left" name="NowEPG" position="305,105" size="600,28" transparent="1" zPosition="2"/>
155                                         <widget backgroundColor="#101214" font="Regular;24" halign="left" name="NextEPG" position="305,140" size="600,28" transparent="1" zPosition="2"/>
156                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="right" name="NowTime" position="1070,105" size="124,28" transparent="1" zPosition="2"/>
157                                         <widget backgroundColor="#101214" font="Regular;24" halign="right" name="NextTime" position="1070,140" size="124,28" transparent="1" zPosition="2"/>
158                                 </screen>"""
159                 elif sz_w == 1024:
160                         skin = """
161                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,420" size="1024,176" title="Virtual Zap">
162                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="1024,176" zPosition="0"/>
163                                         <widget backgroundColor="transparent" name="video" position="50,20" size="164,92" zPosition="1"/>
164                                         <widget backgroundColor="#101214" font="Regular;22" halign="left" name="NowChannel" position="230,25" size="741,30" transparent="1" zPosition="2"/>
165                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="230,55" size="600,25" transparent="1" zPosition="2"/>
166                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="230,80" size="600,25" transparent="1" zPosition="2"/>
167                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="850,55" size="124,25" transparent="1" zPosition="2"/>
168                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="850,80" size="124,25" transparent="1" zPosition="2"/>
169                                 </screen>"""
170                 else:
171                         skin = """
172                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZap" position="0,420" size="720,176" title="Virtual Zap">
173                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="720,176" zPosition="0"/>
174                                         <widget backgroundColor="transparent" name="video" position="50,25" size="130,73" zPosition="1"/>
175                                         <widget backgroundColor="#101214" font="Regular;22" halign="left" name="NowChannel" position="190,25" size="480,30" transparent="1" zPosition="2"/>
176                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="190,55" size="360,25" transparent="1" zPosition="2"/>
177                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="190,80" size="360,25" transparent="1" zPosition="2"/>
178                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="550,55" size="120,25" transparent="1" zPosition="2"/>
179                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="550,80" size="120,25" transparent="1" zPosition="2"/>
180                                 </screen>"""
181         else:
182                 if sz_w == 1280:
183                         skin = """
184                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,505" size="1280,220" title="Virtual Zap">
185                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/hd.png" position="0,0" size="1280,220" zPosition="0"/>
186                                         <widget backgroundColor="#101214" font="Regular;26" halign="center" name="NowChannel" position="140,60" size="1000,32" transparent="1" zPosition="2"/>
187                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="left" name="NowEPG" position="140,105" size="860,28" transparent="1" zPosition="2"/>
188                                         <widget backgroundColor="#101214" font="Regular;24" halign="left" name="NextEPG" position="140,140" size="860,28" transparent="1" zPosition="2"/>
189                                         <widget backgroundColor="#101214" font="Regular;24" foregroundColor="#fcc000" halign="right" name="NowTime" position="1015,105" size="124,28" transparent="1" zPosition="2"/>
190                                         <widget backgroundColor="#101214" font="Regular;24" halign="right" name="NextTime" position="1015,140" size="124,28" transparent="1" zPosition="2"/>
191                                 </screen>"""
192                 elif sz_w == 1024:
193                         skin = """
194                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,420" size="1024,176" title="Virtual Zap">
195                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="1024,176" zPosition="0"/>
196                                         <widget backgroundColor="#101214" font="Regular;22" halign="center" name="NowChannel" position="100,25" size="824,30" transparent="1" zPosition="2"/>
197                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="100,55" size="700,25" transparent="1" zPosition="2"/>
198                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="100,80" size="700,25" transparent="1" zPosition="2"/>
199                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="800,55" size="124,25" transparent="1" zPosition="2"/>
200                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="800,80" size="124,25" transparent="1" zPosition="2"/>
201                                 </screen>"""
202                 else:
203                         skin = """
204                                 <screen backgroundColor="#101214" flags="wfNoBorder" name="VirtualZapNoPiP" position="0,420" size="720,176" title="Virtual Zap">
205                                         <ePixmap alphatest="off" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap/sd.png" position="0,0" size="720,176" zPosition="0"/>
206                                         <widget backgroundColor="#101214" font="Regular;22" halign="center" name="NowChannel" position="50,25" size="620,30" transparent="1" zPosition="2"/>
207                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="left" name="NowEPG" position="50,55" size="500,25" transparent="1" zPosition="2"/>
208                                         <widget backgroundColor="#101214" font="Regular;20" halign="left" name="NextEPG" position="50,80" size="500,25" transparent="1" zPosition="2"/>
209                                         <widget backgroundColor="#101214" font="Regular;20" foregroundColor="#fcc000" halign="right" name="NowTime" position="550,55" size="120,25" transparent="1" zPosition="2"/>
210                                         <widget backgroundColor="#101214" font="Regular;20" halign="right" name="NextTime" position="550,80" size="120,25" transparent="1" zPosition="2"/>
211                                 </screen>"""
212
213 \r
214         def __init__(self, session, servicelist = None):\r
215                 Screen.__init__(self, session)\r
216                 self.session = session
217                 self.pipAvailable = False
218                 if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value:
219                         self.skinName = "VirtualZap"
220                         self.pipAvailable = True
221                 else:
222                         self.skinName = "VirtualZapNoPiP"
223                 self.epgcache = eEPGCache.getInstance()\r
224                 self.CheckForEPG = eTimer()\r
225                 self.CheckForEPG.callback.append(self.CheckItNow)\r
226                 self["NowChannel"] = Label()\r
227                 self["NowEPG"] = Label()\r
228                 self["NextEPG"] = Label()
229                 self["NowTime"] = Label()\r
230                 self["NextTime"] = Label()\r
231                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ChannelSelectBaseActions", "ChannelSelectEPGActions", "ColorActions"], 
232                 {\r
233                         "ok": self.ok, \r
234                         "cancel": self.closing,\r
235                         "right": self.nextService,\r
236                         "left": self.prevService,
237                         "nextBouquet": self.nextBouquet,
238                         "prevBouquet": self.prevBouquet,
239                         "showEPGList": self.openEventView,
240                         "blue": self.standardPiP,
241                         "yellow": self.switchAndStandardPiP,
242                 },-2)
243                 self["actions2"] = NumberActionMap(["NumberActions"],
244                 {
245                         "0": self.swap,
246                         "1": self.keyNumberGlobal,
247                         "2": self.keyNumberGlobal,
248                         "3": self.keyNumberGlobal,
249                         "4": self.keyNumberGlobal,
250                         "5": self.keyNumberGlobal,
251                         "6": self.keyNumberGlobal,
252                         "7": self.keyNumberGlobal,
253                         "8": self.keyNumberGlobal,
254                         "9": self.keyNumberGlobal,
255                 }, -1)
256                 self.onLayoutFinish.append(self.onLayoutReady)
257                 # PiP
258                 if self.pipAvailable:
259                         # activate PiP support
260                         self["video"] = VideoWindow(fb_width = getDesktop(0).size().width(), fb_height = getDesktop(0).size().height())
261                         self.currentPiP = ""
262                 # this is the servicelist from ChannelSelectionBase
263                 self.servicelist = servicelist
264                 # needed, because if we won't zap, we habe to go back to the current bouquet and service
265                 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
266                 self.curBouquet = self.servicelist.getRoot()
267
268         def onLayoutReady(self):
269                 self.updateInfos()
270
271         def nextService(self):
272                 # get next service
273                 if self.servicelist.inBouquet():
274                         prev = self.servicelist.getCurrentSelection()
275                         if prev:
276                                 prev = prev.toString()
277                                 while True:
278                                         if config.usage.quickzap_bouquet_change.value and self.servicelist.atEnd():
279                                                 self.servicelist.nextBouquet()
280                                         else:
281                                                 self.servicelist.moveDown()
282                                         cur = self.servicelist.getCurrentSelection()
283                                         if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
284                                                 break
285                 else:
286                         self.servicelist.moveDown()
287                 if self.isPlayable():
288                         self.updateInfos()
289                 else:
290                         self.nextService()
291
292         def prevService(self):
293                 # get previous service
294                 if self.servicelist.inBouquet():
295                         prev = self.servicelist.getCurrentSelection()
296                         if prev:
297                                 prev = prev.toString()
298                                 while True:
299                                         if config.usage.quickzap_bouquet_change.value:
300                                                 if self.servicelist.atBegin():
301                                                         self.servicelist.prevBouquet()
302                                         self.servicelist.moveUp()
303                                         cur = self.servicelist.getCurrentSelection()
304                                         if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
305                                                 break
306                 else:
307                         self.servicelist.moveUp()
308                 if self.isPlayable():
309                         self.updateInfos()
310                 else:
311                         self.prevService()
312
313         def isPlayable(self):
314                 # check if service is playable
315                 current = ServiceReference(self.servicelist.getCurrentSelection())
316                 return not (current.ref.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
317
318
319         def nextBouquet(self):
320                 # next bouquet with first service
321                 if config.usage.multibouquet.value:
322                         self.servicelist.nextBouquet()
323                 self.updateInfos()
324
325         def prevBouquet(self):
326                 # previous bouquet with first service
327                 if config.usage.multibouquet.value:
328                         self.servicelist.prevBouquet()
329                 self.updateInfos()
330 \r
331 \r
332         def updateInfos(self):
333                 # update data\r
334                 current = ServiceReference(self.servicelist.getCurrentSelection())
335                 self["NowChannel"].setText(current.getServiceName())
336                 nowepg, nowtimedisplay = self.getEPGNowNext(current.ref,0)
337                 nextepg, nexttimedisplay = self.getEPGNowNext(current.ref,1)
338                 self["NowEPG"].setText(nowepg)
339                 self["NextEPG"].setText(nextepg)
340                 self["NowTime"].setText(nowtimedisplay)
341                 self["NextTime"].setText(nexttimedisplay)
342                 if not nowepg:
343                         # no epg found --> let's try it again, but only if PiP is activated
344                         if self.pipAvailable:
345                                 self.CheckForEPG.start(3000, True)
346                 if self.pipAvailable:
347                         # play in videowindow
348                         self.playService(current.ref)
349
350         def getEPGNowNext(self,ref, modus):
351                 # get now || next event
352                 if self.epgcache is not None:
353                         event = self.epgcache.lookupEvent(['IBDCTSERNX', (ref.toString(), modus, -1)])
354                         if event:
355                                 if event[0][4]:
356                                         t = localtime(event[0][1])
357                                         duration = event[0][2]
358                                         if modus == 0:
359                                                 timedisplay = "+%d min" % (((event[0][1] + duration) - time()) / 60)
360                                         elif modus == 1:
361                                                 timedisplay = "%d min" %  (duration / 60)
362                                         return "%02d:%02d %s" % (t[3],t[4], event[0][4]), timedisplay
363                                 else:
364                                         return "", ""
365                 return "", ""
366
367         def openSingleServiceEPG(self):
368                 # show EPGList
369                 current = ServiceReference(self.servicelist.getCurrentSelection())
370                 self.session.open(EPGSelection, current.ref)
371
372         def openEventView(self):
373                 # show EPG Event
374                 epglist = [ ]
375                 self.epglist = epglist
376                 service = ServiceReference(self.servicelist.getCurrentSelection())
377                 ref = service.ref
378                 evt = self.epgcache.lookupEventTime(ref, -1)
379                 if evt:
380                         epglist.append(evt)
381                 evt = self.epgcache.lookupEventTime(ref, -1, 1)
382                 if evt:
383                         epglist.append(evt)
384                 if epglist:
385                         self.session.open(EventViewEPGSelect, epglist[0], service, self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
386
387         def eventViewCallback(self, setEvent, setService, val):
388                 epglist = self.epglist
389                 if len(epglist) > 1:
390                         tmp = epglist[0]
391                         epglist[0] = epglist[1]
392                         epglist[1] = tmp
393                         setEvent(epglist[0])
394
395         def openMultiServiceEPG(self):
396                 # not supported
397                 pass
398
399         def openSimilarList(self, eventid, refstr):
400                 self.session.open(EPGSelection, refstr, None, eventid)
401
402         def setServicelistSelection(self, bouquet, service):
403                 # we need to select the old service with bouquet
404                 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
405                         self.servicelist.clearPath()
406                         if self.servicelist.bouquet_root != bouquet:
407                                 self.servicelist.enterPath(self.servicelist.bouquet_root)
408                         self.servicelist.enterPath(bouquet)
409                 self.servicelist.setCurrentSelection(service) #select the service in servicelist
410
411         def closing(self):
412                 if self.pipAvailable:
413                         self.pipservice = None
414                 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
415                 self.close()\r
416                         \r
417         def ok(self):
418                 # we have to close PiP first, otherwise the service-display is freezed
419                 if self.pipAvailable:
420                         self.pipservice = None
421                 # play selected service and close virtualzap
422                 self.servicelist.zap()\r
423                 self.close()
424
425         def standardPiP(self):
426                 if not self.pipAvailable:
427                         return
428                 # close PiP
429                 self.pipservice = None
430                 # save current selected service for standard PiP
431                 service = ServiceReference(self.servicelist.getCurrentSelection()).ref
432                 servicePath = self.servicelist.getCurrentServicePath() # same bug as in channelselection 
433                 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
434                 # close VZ and start standard PiP
435                 self.close(service, servicePath)
436
437         def switchAndStandardPiP(self):
438                 if not self.pipAvailable:
439                         return
440                 self.pipservice = None
441                 # save current selected servicePath for standard PiP
442                 servicePath = self.servicelist.getCurrentServicePath()
443                 # play selected service and close virtualzap
444                 self.servicelist.zap()
445                 # close VZ and start standard PiP
446                 self.close(self.curRef.ref, servicePath)
447 \r
448         def CheckItNow(self):\r
449                 self.CheckForEPG.stop()\r
450                 self.updateInfos()
451
452         # if available play service in PiP 
453         def playService(self, service):
454                 if service and (service.flags & eServiceReference.isGroup):
455                         ref = getBestPlayableServiceReference(service, eServiceReference())
456                 else:
457                         ref = service
458                 if ref and ref.toString() != self.currentPiP:
459                         self.pipservice = eServiceCenter.getInstance().play(ref)
460                         if self.pipservice and not self.pipservice.setTarget(1):
461                                 self.pipservice.start()
462                                 self.currentPiP = ref.toString()
463                         else:
464                                 self.pipservice = None
465                                 self.currentPiP = ""
466
467
468         # switch with numbers
469         def keyNumberGlobal(self, number):
470                 self.session.openWithCallback(self.numberEntered, NumberZap, number)
471
472         def numberEntered(self, retval):
473                 if retval > 0:
474                         self.zapToNumber(retval)
475
476         def searchNumberHelper(self, serviceHandler, num, bouquet):
477                 servicelist = serviceHandler.list(bouquet)
478                 if not servicelist is None:
479                         while num:
480                                 serviceIterator = servicelist.getNext()
481                                 if not serviceIterator.valid(): #check end of list
482                                         break
483                                 playable = not (serviceIterator.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
484                                 if playable:
485                                         num -= 1;
486                         if not num: #found service with searched number ?
487                                 return serviceIterator, 0
488                 return None, num
489
490         def zapToNumber(self, number):
491                 bouquet = self.servicelist.bouquet_root
492                 service = None
493                 serviceHandler = eServiceCenter.getInstance()
494                 bouquetlist = serviceHandler.list(bouquet)
495                 if not bouquetlist is None:
496                         while number:
497                                 bouquet = bouquetlist.getNext()
498                                 if not bouquet.valid(): #check end of list
499                                         break
500                                 if bouquet.flags & eServiceReference.isDirectory:
501                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
502                 if not service is None:
503                         self.setServicelistSelection(bouquet, service)
504                 # update infos, no matter if service is none or not
505                 self.updateInfos()
506
507         def swap(self, number):
508                 # save old values for selecting it in servicelist after zapping
509                 currentRef = self.curRef
510                 currentBouquet = self.curBouquet
511                 # we have to close PiP first, otherwise the service-display is freezed
512                 if self.pipAvailable:
513                         self.pipservice = None
514                 # zap and set new values for the new reference and bouquet
515                 self.servicelist.zap()
516                 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
517                 self.curBouquet = self.servicelist.getRoot()
518                 # select old values in servicelist
519                 self.setServicelistSelection(currentBouquet, currentRef.ref)
520                 # play old service in PiP
521                 self.updateInfos()
522
523 class VirtualZapConfig(Screen, ConfigListScreen):
524
525         skin = """
526                 <screen position="center,center" size="560,110" title="Virtual Zap Config" >
527                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
528                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
529                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
530                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
531                         <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" />
532                         <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" />
533                         <widget name="config" position="20,50" size="520,330" scrollbarMode="showOnDemand" />
534                 </screen>"""
535
536         def __init__(self, session):
537                 Screen.__init__(self, session)
538                 self["key_red"] = StaticText(_("Cancel"))
539                 self["key_green"] = StaticText(_("OK"))
540                 self.list = [ ]
541                 self.list.append(getConfigListEntry(_("Usage"), config.plugins.virtualzap.mode))
542                 if SystemInfo.get("NumVideoDecoders", 1) > 1:
543                         self.list.append(getConfigListEntry(_("Show with PiP"), config.plugins.virtualzap.usepip))
544                 ConfigListScreen.__init__(self, self.list, session)
545                 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
546                 {
547                         "green": self.keySave,
548                         "cancel": self.keyClose,
549                 }, -2)
550
551         def keySave(self):
552                 for x in self["config"].list:
553                         x[1].save()
554                 configfile.save()
555                 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)
556                 restartbox.setTitle(_("Restart GUI now?"))
557                 
558
559         def keyClose(self):
560                 for x in self["config"].list:
561                         x[1].cancel()
562                 self.close()
563
564         def restartGUI(self, answer):
565                 if answer is True:
566                         self.session.open(TryQuitMainloop, 3)
567                 else:
568                         self.close()
569