6 # Coded by Dr.Best (c) 2010
7 # Coding idea and design by Vali
8 # Support: www.dreambox-tools.info
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.
16 # Alternatively, this plugin may be distributed and executed on hardware which
17 # is licensed by Dream Multimedia GmbH.
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.
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
38 from Components.Sources.StaticText import StaticText
39 from Screens.MessageBox import MessageBox
40 from Screens.Standby import TryQuitMainloop
42 from Screens.EpgSelection import EPGSelection
43 from Screens.EventView import EventViewEPGSelect
44 from Screens.PictureInPicture import PictureInPicture
46 InfoBarShowHideINIT = None
48 from Components.config import config, ConfigSubsection, ConfigSelection, ConfigYesNo, getConfigListEntry, configfile, ConfigPosition, ConfigText, ConfigInteger
49 from Components.ConfigList import ConfigList, ConfigListScreen
51 # for localized messages
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))
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__
71 InfoBarShowHide.showVZ = showVZ
72 InfoBarShowHide.VirtualZapCallback = VirtualZapCallback
73 if config.plugins.virtualzap.mode.value == "2":
74 InfoBarShowHide.newHide = newHide
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"] ,
85 "toggleShow": self.toggleShow,
86 "longOK": self.showVZ,
89 elif config.plugins.virtualzap.mode.value == "2":
90 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
92 "toggleShow": self.toggleShow,
98 from Screens.InfoBarGenerics import InfoBarEPG
99 # check for InfoBarEPG --> only start if true
100 if isinstance(self, InfoBarEPG):
102 if isinstance(self, InfoBarPiP):
103 # check if PiP is already shown
107 if isinstance(self, InfoBar):
108 self.session.openWithCallback(self.VirtualZapCallback, VirtualZap, self.servicelist)
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
119 self.session.pipshown = False
121 self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)
124 # remember if infobar is shown
128 # infobar was not shown, start VZ
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))
139 def setup(session,**kwargs):
140 session.open(VirtualZapConfig)
142 def main(session,**kwargs):
143 session.open(VirtualZap, kwargs["servicelist"])
145 class VirtualZap(Screen):
\r
146 sz_w = getDesktop(0).size().width()
149 # VirtualZap or VirtualZapNoPiP
152 if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value and config.plugins.virtualzap.showpipininfobar.value:
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"/>
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"/>
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"/>
189 if SystemInfo.get("NumVideoDecoders", 1) > 1 and config.plugins.virtualzap.usepip.value and not config.plugins.virtualzap.showpipininfobar.value:
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]
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)
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)
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)
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
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"],
258 "cancel": self.closing,
\r
259 "right": self.nextService,
\r
260 "left": self.prevService,
261 "nextBouquet": self.showFavourites,
262 "prevBouquet": self.openServiceList,
263 "showEPGList": self.openEventView,
264 "blue": self.standardPiP,
265 "yellow": self.switchAndStandardPiP,
266 "down": self.switchChannelDown,
267 "up": self.switchChannelUp,
269 self["actions2"] = NumberActionMap(["NumberActions"],
272 "1": self.keyNumberGlobal,
273 "2": self.keyNumberGlobal,
274 "3": self.keyNumberGlobal,
275 "4": self.keyNumberGlobal,
276 "5": self.keyNumberGlobal,
277 "6": self.keyNumberGlobal,
278 "7": self.keyNumberGlobal,
279 "8": self.keyNumberGlobal,
280 "9": self.keyNumberGlobal,
282 self.onLayoutFinish.append(self.onLayoutReady)
284 if self.pipAvailable:
285 # activate PiP support
286 if config.plugins.virtualzap.usepip.value and not config.plugins.virtualzap.showpipininfobar.value:
287 # activate standard PiP
288 self["video"] = VideoWindow()
290 # show PiP in Infobar
291 self["video"] = VideoWindow(fb_width = getDesktop(0).size().width(), fb_height = getDesktop(0).size().height())
295 self["video"] = Label()
296 # this is the servicelist from ChannelSelectionBase
297 self.servicelist = servicelist
298 # save orig. method of zap in servicelist
299 self.servicelist_orig_zap = self.servicelist.zap
300 # when displaying ChannelSelection, do not zap when pressing "ok", so new method is needed
301 self.servicelist.zap = self.servicelist_overwrite_zap
302 # overwrite the actionmap of ChannelSelection
303 self.servicelist["actions"] = ActionMap(["OkCancelActions"],
305 "cancel": self.cancelChannelSelection,
306 "ok": self.servicelist.channelSelected,
308 # temp. vars, needed when pressing cancel in ChannelSelection
309 self.curSelectedRef = None
310 self.curSelectedBouquet = None
311 # needed, because if we won't zap, we have to go back to the current bouquet and service
312 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
313 self.curBouquet = self.servicelist.getRoot()
314 # start with last used service
315 if config.plugins.virtualzap.saveLastService.value:
316 # get service and bouquet ref
317 ref = eServiceReference(config.plugins.virtualzap.curref.value)
318 bouquet = eServiceReference(config.plugins.virtualzap.curbouquet.value)
319 if ref.valid() and bouquet.valid():
320 # select bouquet and ref in servicelist
321 self.setServicelistSelection(bouquet, ref)
323 self.exitTimer = eTimer()
324 self.exitTimer.timeout.get().append(self.standardPiP)
325 # reverse changes of ChannelSelection when closing plugin
326 self.onClose.append(self.__onClose)
328 def onLayoutReady(self):
331 def resetExitTimer(self):
332 # if enabled, run exit timer
333 if config.plugins.virtualzap.exittimer.value != 0:
334 if self.exitTimer.isActive():
335 self.exitTimer.stop()
336 self.exitTimer.start(config.plugins.virtualzap.exittimer.value * 1000)
338 def nextService(self):
340 if self.servicelist.inBouquet():
341 prev = self.servicelist.getCurrentSelection()
343 prev = prev.toString()
345 if config.usage.quickzap_bouquet_change.value and self.servicelist.atEnd():
346 self.servicelist.nextBouquet()
348 self.servicelist.moveDown()
349 cur = self.servicelist.getCurrentSelection()
350 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
353 self.servicelist.moveDown()
354 if self.isPlayable():
359 def prevService(self):
360 # get previous service
361 if self.servicelist.inBouquet():
362 prev = self.servicelist.getCurrentSelection()
364 prev = prev.toString()
366 if config.usage.quickzap_bouquet_change.value:
367 if self.servicelist.atBegin():
368 self.servicelist.prevBouquet()
369 self.servicelist.moveUp()
370 cur = self.servicelist.getCurrentSelection()
371 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
374 self.servicelist.moveUp()
375 if self.isPlayable():
380 def isPlayable(self):
381 # check if service is playable
382 current = ServiceReference(self.servicelist.getCurrentSelection())
383 return not (current.ref.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
386 def nextBouquet(self):
387 # next bouquet with first service
388 if config.usage.multibouquet.value:
389 self.servicelist.nextBouquet()
392 def prevBouquet(self):
393 # previous bouquet with first service
394 if config.usage.multibouquet.value:
395 self.servicelist.prevBouquet()
399 def updateInfos(self):
400 self.resetExitTimer()
402 current = ServiceReference(self.servicelist.getCurrentSelection())
403 self["NowChannel"].setText(current.getServiceName())
404 nowepg, nowtimedisplay = self.getEPGNowNext(current.ref,0)
405 nextepg, nexttimedisplay = self.getEPGNowNext(current.ref,1)
406 self["NowEPG"].setText(nowepg)
407 self["NextEPG"].setText(nextepg)
408 self["NowTime"].setText(nowtimedisplay)
409 self["NextTime"].setText(nexttimedisplay)
411 # no epg found --> let's try it again, but only if PiP is activated
412 if self.pipAvailable:
413 self.CheckForEPG.start(3000, True)
414 if self.pipAvailable:
415 # play in videowindow
416 self.playService(current.ref)
418 def getEPGNowNext(self,ref, modus):
419 # get now || next event
420 if self.epgcache is not None:
421 event = self.epgcache.lookupEvent(['IBDCTSERNX', (ref.toString(), modus, -1)])
424 t = localtime(event[0][1])
425 duration = event[0][2]
427 timedisplay = "+%d min" % (((event[0][1] + duration) - time()) / 60)
429 timedisplay = "%d min" % (duration / 60)
430 return "%02d:%02d %s" % (t[3],t[4], event[0][4]), timedisplay
435 def openSingleServiceEPG(self):
437 current = ServiceReference(self.servicelist.getCurrentSelection())
438 self.session.open(EPGSelection, current.ref)
440 def openEventView(self):
442 if self.exitTimer.isActive():
443 self.exitTimer.stop()
446 self.epglist = epglist
447 service = ServiceReference(self.servicelist.getCurrentSelection())
449 evt = self.epgcache.lookupEventTime(ref, -1)
452 evt = self.epgcache.lookupEventTime(ref, -1, 1)
456 self.session.openWithCallback(self.EventViewEPGSelectCallBack, EventViewEPGSelect, epglist[0], service, self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
458 def EventViewEPGSelectCallBack(self):
459 # if enabled, start ExitTimer
460 self.resetExitTimer()
462 def eventViewCallback(self, setEvent, setService, val):
463 epglist = self.epglist
466 epglist[0] = epglist[1]
470 def openMultiServiceEPG(self):
474 def openSimilarList(self, eventid, refstr):
475 self.session.open(EPGSelection, refstr, None, eventid)
477 def setServicelistSelection(self, bouquet, service):
478 # we need to select the old service with bouquet
479 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
480 self.servicelist.clearPath()
481 self.servicelist.enterPath(self.servicelist.bouquet_root)
482 self.servicelist.enterPath(bouquet)
483 self.servicelist.setCurrentSelection(service) #select the service in servicelist
486 if self.pipAvailable:
487 self.pipservice = None
488 # save last used service and bouqet ref
489 self.saveLastService(self.servicelist.getCurrentSelection().toString(), self.servicelist.getRoot().toString())
490 # select running service in servicelist again
491 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
495 # we have to close PiP first, otherwise the service-display is freezed
496 if self.pipAvailable:
497 self.pipservice = None
498 # play selected service and close virtualzap
499 self.servicelist_orig_zap()
500 # save last used service and bouqet ref
501 self.saveLastService(self.curRef.ref.toString(), self.curBouquet.toString())
504 def standardPiP(self):
505 if not self.pipAvailable:
508 self.pipservice = None
509 # save current selected service for standard PiP
510 service = ServiceReference(self.servicelist.getCurrentSelection()).ref
511 servicePath = self.servicelist.getCurrentServicePath() # same bug as in channelselection
512 # save last used service and bouqet ref
513 self.saveLastService(self.servicelist.getCurrentSelection().toString(), self.servicelist.getRoot().toString())
514 # select running service in servicelist
515 self.setServicelistSelection(self.curBouquet, self.curRef.ref)
516 # close VZ and start standard PiP
517 self.close(service, servicePath)
519 def switchAndStandardPiP(self):
520 if not self.pipAvailable:
522 self.pipservice = None
523 # save current selected servicePath for standard PiP
524 servicePath = self.servicelist.getCurrentServicePath()
525 # save last used service and bouqet ref
526 self.saveLastService(self.curRef.ref.toString(), self.curBouquet.toString())
527 # play selected service
528 self.servicelist_orig_zap()
529 # close VZ and start standard PiP
530 self.close(self.curRef.ref, servicePath)
532 def saveLastService(self, ref, bouquet):
533 if config.plugins.virtualzap.saveLastService.value:
534 # save last VZ service
535 config.plugins.virtualzap.curref.value = ref
536 config.plugins.virtualzap.curbouquet.value = bouquet
537 config.plugins.virtualzap.save()
539 if self.exitTimer.isActive():
540 self.exitTimer.stop()
542 def CheckItNow(self):
\r
543 self.CheckForEPG.stop()
\r
546 # if available play service in PiP
547 def playService(self, service):
548 if service and (service.flags & eServiceReference.isGroup):
549 ref = getBestPlayableServiceReference(service, eServiceReference())
552 if ref and ref.toString() != self.currentPiP:
553 self.pipservice = eServiceCenter.getInstance().play(ref)
554 if self.pipservice and not self.pipservice.setTarget(1):
555 self.pipservice.start()
556 self.currentPiP = ref.toString()
558 self.pipservice = None
562 # switch with numbers
563 def keyNumberGlobal(self, number):
564 self.session.openWithCallback(self.numberEntered, NumberZap, number)
566 def numberEntered(self, retval):
568 self.zapToNumber(retval)
570 def searchNumberHelper(self, serviceHandler, num, bouquet):
571 servicelist = serviceHandler.list(bouquet)
572 if not servicelist is None:
574 serviceIterator = servicelist.getNext()
575 if not serviceIterator.valid(): #check end of list
577 playable = not (serviceIterator.flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
580 if not num: #found service with searched number ?
581 return serviceIterator, 0
584 def zapToNumber(self, number):
585 bouquet = self.servicelist.bouquet_root
587 serviceHandler = eServiceCenter.getInstance()
588 bouquetlist = serviceHandler.list(bouquet)
589 if not bouquetlist is None:
591 bouquet = bouquetlist.getNext()
592 if not bouquet.valid(): #check end of list
594 if bouquet.flags & eServiceReference.isDirectory:
595 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
596 if not service is None:
597 self.setServicelistSelection(bouquet, service)
598 # update infos, no matter if service is none or not
601 def swap(self, number):
602 # save old values for selecting it in servicelist after zapping
603 currentRef = self.curRef
604 currentBouquet = self.curBouquet
605 # we have to close PiP first, otherwise the service-display is freezed
606 if self.pipAvailable:
607 self.pipservice = None
608 # zap and set new values for the new reference and bouquet
609 self.servicelist_orig_zap()
610 self.curRef = ServiceReference(self.servicelist.getCurrentSelection())
611 self.curBouquet = self.servicelist.getRoot()
612 # select old values in servicelist
613 self.setServicelistSelection(currentBouquet, currentRef.ref)
614 # play old service in PiP
617 # ChannelSelection Support
618 def prepareChannelSelectionDisplay(self):
620 if self.exitTimer.isActive():
621 self.exitTimer.stop()
623 if self.pipAvailable:
624 self.pipservice = None
625 # save current ref and bouquet ( for cancel )
626 self.curSelectedRef = eServiceReference(self.servicelist.getCurrentSelection().toString())
627 self.curSelectedBouquet = self.servicelist.getRoot()
629 def cancelChannelSelection(self):
630 # select service and bouquet selected before started ChannelSelection
631 if self.servicelist.revertMode is None:
632 ref = self.curSelectedRef
633 bouquet = self.curSelectedBouquet
634 if ref.valid() and bouquet.valid():
635 # select bouquet and ref in servicelist
636 self.setServicelistSelection(bouquet, ref)
637 # close ChannelSelection
638 self.servicelist.revertMode = None
639 self.servicelist.asciiOff()
640 self.servicelist.close(None)
643 self.curSelectedRef = None
644 self.curSelectedBouquet = None
646 self.servicelist_overwrite_zap()
648 def switchChannelDown(self):
649 self.prepareChannelSelectionDisplay()
650 self.servicelist.moveDown()
651 # show ChannelSelection
652 self.session.execDialog(self.servicelist)
654 def switchChannelUp(self):
655 self.prepareChannelSelectionDisplay()
656 self.servicelist.moveUp()
657 # show ChannelSelection
658 self.session.execDialog(self.servicelist)
660 def showFavourites(self):
661 self.prepareChannelSelectionDisplay()
662 self.servicelist.showFavourites()
663 # show ChannelSelection
664 self.session.execDialog(self.servicelist)
666 def openServiceList(self):
667 self.prepareChannelSelectionDisplay()
668 # show ChannelSelection
669 self.session.execDialog(self.servicelist)
671 def servicelist_overwrite_zap(self, *args, **kwargs):
672 # we do not really want to zap to the service, just display data for VZ
674 if self.isPlayable():
678 # reverse changes of ChannelSelection
679 self.servicelist.zap = self.servicelist_orig_zap
680 self.servicelist["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
682 "cancel": self.servicelist.cancel,
683 "ok": self.servicelist.channelSelected,
684 "keyRadio": self.servicelist.setModeRadio,
685 "keyTV": self.servicelist.setModeTv,
688 class VirtualZapConfig(Screen, ConfigListScreen):
691 <screen position="center,center" size="560,180" title="Virtual Zap Config" >
692 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
693 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
694 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
695 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
696 <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" />
697 <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" />
698 <widget name="config" position="20,50" size="520,330" scrollbarMode="showOnDemand" />
701 def __init__(self, session):
702 Screen.__init__(self, session)
703 self["key_red"] = StaticText(_("Cancel"))
704 self["key_green"] = StaticText(_("OK"))
706 self.list.append(getConfigListEntry(_("Usage"), config.plugins.virtualzap.mode))
707 if SystemInfo.get("NumVideoDecoders", 1) > 1:
708 self.list.append(getConfigListEntry(_("Use PiP"), config.plugins.virtualzap.usepip))
709 self.list.append(getConfigListEntry(_("Show PiP in Infobar"), config.plugins.virtualzap.showpipininfobar))
710 self.list.append(getConfigListEntry(_("Start standard PiP after x secs (0 = disabled)"), config.plugins.virtualzap.exittimer))
711 self.list.append(getConfigListEntry(_("Remember last service"), config.plugins.virtualzap.saveLastService))
712 ConfigListScreen.__init__(self, self.list, session)
713 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
715 "green": self.keySave,
716 "cancel": self.keyClose,
720 for x in self["config"].list:
723 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)
724 restartbox.setTitle(_("Restart GUI now?"))
728 for x in self["config"].list:
732 def restartGUI(self, answer):
734 self.session.open(TryQuitMainloop, 3)