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