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