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