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