1 from ChannelSelection import ChannelSelection, BouquetSelector
3 from Components.ActionMap import ActionMap, HelpableActionMap
4 from Components.ActionMap import NumberActionMap
5 from Components.BlinkingPixmap import BlinkingPixmapConditional
6 from Components.Clock import Clock
7 from Components.EventInfo import EventInfo, EventInfoProgress
8 from Components.Harddisk import harddiskmanager
9 from Components.Input import Input
10 from Components.Label import *
11 from Components.Pixmap import Pixmap, PixmapConditional
12 from Components.PluginComponent import plugins
13 from Components.ProgressBar import *
14 from Components.ServiceEventTracker import ServiceEventTracker
15 from Components.ServiceName import ServiceName
16 from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean, configSelection, configElement_nonSave, getConfigListEntry
17 from Components.config import configfile, configsequencearg
18 from Components.TimerList import TimerEntryComponent
19 from Components.TunerInfo import TunerInfo
21 from EpgSelection import EPGSelection
22 from Plugins.Plugin import PluginDescriptor
24 from Screen import Screen
25 from Screens.ChoiceBox import ChoiceBox
26 from Screens.Dish import Dish
27 from Screens.EventView import EventViewEPGSelect, EventViewSimple
28 from Screens.InputBox import InputBox
29 from Screens.MessageBox import MessageBox
30 from Screens.MinuteInput import MinuteInput
31 from Screens.TimerSelection import TimerSelection
32 from Screens.PictureInPicture import PictureInPicture
33 from Screens.SubtitleDisplay import SubtitleDisplay
34 from ServiceReference import ServiceReference
36 from Tools import Notifications
37 from Tools.Directories import *
39 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
46 from Components.config import config, currentConfigSelectionElement
49 from Menu import MainMenu, mdom
53 self.dishDialog = self.session.instantiateDialog(Dish)
54 self.onLayoutFinish.append(self.dishDialog.show)
56 class InfoBarShowHide:
57 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
65 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
67 "toggleShow": self.toggleShow,
71 self.__state = self.STATE_SHOWN
74 self.onExecBegin.append(self.show)
76 self.hideTimer = eTimer()
77 self.hideTimer.timeout.get().append(self.doTimerHide)
78 self.hideTimer.start(5000, True)
80 self.onShow.append(self.__onShow)
81 self.onHide.append(self.__onHide)
84 self.__state = self.STATE_SHOWN
87 def startHideTimer(self):
88 if self.__state == self.STATE_SHOWN and not self.__locked:
89 self.hideTimer.start(5000, True)
92 self.__state = self.STATE_HIDDEN
98 def doTimerHide(self):
100 if self.__state == self.STATE_SHOWN:
103 def toggleShow(self):
104 if self.__state == self.STATE_SHOWN:
106 self.hideTimer.stop()
107 elif self.__state == self.STATE_HIDDEN:
111 self.__locked = self.__locked + 1
114 self.hideTimer.stop()
116 def unlockShow(self):
117 self.__locked = self.__locked - 1
119 self.startHideTimer()
121 # def startShow(self):
122 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
123 # self.__state = self.STATE_SHOWN
125 # def startHide(self):
126 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
127 # self.__state = self.STATE_HIDDEN
129 class NumberZap(Screen):
136 self.close(int(self["number"].getText()))
138 def keyNumberGlobal(self, number):
139 self.Timer.start(3000, True) #reset timer
140 self.field = self.field + str(number)
141 self["number"].setText(self.field)
142 if len(self.field) >= 4:
145 def __init__(self, session, number):
146 Screen.__init__(self, session)
147 self.field = str(number)
149 self["channel"] = Label(_("Channel:"))
151 self["number"] = Label(self.field)
153 self["actions"] = NumberActionMap( [ "SetupActions" ],
157 "1": self.keyNumberGlobal,
158 "2": self.keyNumberGlobal,
159 "3": self.keyNumberGlobal,
160 "4": self.keyNumberGlobal,
161 "5": self.keyNumberGlobal,
162 "6": self.keyNumberGlobal,
163 "7": self.keyNumberGlobal,
164 "8": self.keyNumberGlobal,
165 "9": self.keyNumberGlobal,
166 "0": self.keyNumberGlobal
169 self.Timer = eTimer()
170 self.Timer.timeout.get().append(self.keyOK)
171 self.Timer.start(3000, True)
173 class InfoBarNumberZap:
174 """ Handles an initial number for NumberZapping """
176 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
178 "1": self.keyNumberGlobal,
179 "2": self.keyNumberGlobal,
180 "3": self.keyNumberGlobal,
181 "4": self.keyNumberGlobal,
182 "5": self.keyNumberGlobal,
183 "6": self.keyNumberGlobal,
184 "7": self.keyNumberGlobal,
185 "8": self.keyNumberGlobal,
186 "9": self.keyNumberGlobal,
187 "0": self.keyNumberGlobal,
190 def keyNumberGlobal(self, number):
191 # print "You pressed number " + str(number)
193 self.servicelist.recallPrevService()
196 self.session.openWithCallback(self.numberEntered, NumberZap, number)
198 def numberEntered(self, retval):
199 # print self.servicelist
201 self.zapToNumber(retval)
203 def searchNumberHelper(self, serviceHandler, num, bouquet):
204 servicelist = serviceHandler.list(bouquet)
205 if not servicelist is None:
207 serviceIterator = servicelist.getNext()
208 if not serviceIterator.valid(): #check end of list
210 if serviceIterator.flags: #assume normal dvb service have no flags set
213 if not num: #found service with searched number ?
214 return serviceIterator, 0
217 def zapToNumber(self, number):
218 bouquet = self.servicelist.bouquet_root
220 serviceHandler = eServiceCenter.getInstance()
221 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
222 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
224 bouquetlist = serviceHandler.list(bouquet)
225 if not bouquetlist is None:
227 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
228 if not bouquet.valid(): #check end of list
230 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
232 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
233 if not service is None:
234 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
235 self.servicelist.clearPath()
236 if self.servicelist.bouquet_root != bouquet:
237 self.servicelist.enterPath(self.servicelist.bouquet_root)
238 self.servicelist.enterPath(bouquet)
239 self.servicelist.setCurrentSelection(service) #select the service in servicelist
240 self.servicelist.zap()
242 config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
244 class InfoBarChannelSelection:
245 """ ChannelSelection - handles the channelSelection dialog and the initial
246 channelChange actions which open the channelSelection dialog """
249 self.servicelist = self.session.instantiateDialog(ChannelSelection)
251 if config.misc.initialchannelselection.value == 1:
252 self.onShown.append(self.firstRun)
254 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
256 "switchChannelUp": self.switchChannelUp,
257 "switchChannelDown": self.switchChannelDown,
258 "zapUp": (self.zapUp, _("previous channel")),
259 "zapDown": (self.zapDown, _("next channel")),
260 "historyBack": (self.historyBack, _("previous channel in history")),
261 "historyNext": (self.historyNext, _("next channel in history")),
262 "openServiceList": (self.openServiceList, _("open service list")),
265 def showTvChannelList(self, zap=False):
266 self.servicelist.setModeTv()
268 self.servicelist.zap()
269 self.session.execDialog(self.servicelist)
271 def showRadioChannelList(self, zap=False):
272 self.servicelist.setModeRadio()
274 self.servicelist.zap()
275 self.session.execDialog(self.servicelist)
278 self.onShown.remove(self.firstRun)
279 config.misc.initialchannelselection.value = 0
280 config.misc.initialchannelselection.save()
281 self.switchChannelDown()
283 def historyBack(self):
284 self.servicelist.historyBack()
286 def historyNext(self):
287 self.servicelist.historyNext()
289 def switchChannelUp(self):
290 self.servicelist.moveUp()
291 self.session.execDialog(self.servicelist)
293 def switchChannelDown(self):
294 self.servicelist.moveDown()
295 self.session.execDialog(self.servicelist)
297 def openServiceList(self):
298 self.session.execDialog(self.servicelist)
301 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
302 if self.servicelist.inBouquet() and self.servicelist.atBegin():
303 self.servicelist.prevBouquet()
304 self.servicelist.moveUp()
305 self.servicelist.zap()
309 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
310 self.servicelist.nextBouquet()
312 self.servicelist.moveDown()
313 self.servicelist.zap()
317 """ Handles a menu action, to open the (main) menu """
319 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
321 "mainMenu": (self.mainMenu, "Enter main menu..."),
325 print "loading mainmenu XML..."
326 menu = mdom.childNodes[0]
327 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
328 self.session.open(MainMenu, menu, menu.childNodes)
330 class InfoBarSimpleEventView:
331 """ Opens the Eventview for now/next """
333 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
335 "showEventInfo": (self.openEventView, _("show event details")),
338 def openEventView(self):
340 service = self.session.nav.getCurrentService()
341 ref = self.session.nav.getCurrentlyPlayingServiceReference()
342 info = service.info()
345 self.epglist.append(ptr)
348 self.epglist.append(ptr)
349 if len(self.epglist) > 0:
350 self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
352 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
353 if len(self.epglist) > 1:
354 tmp = self.epglist[0]
355 self.epglist[0]=self.epglist[1]
357 setEvent(self.epglist[0])
360 """ EPG - Opens an EPG list when the showEPGList action fires """
362 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
364 iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
367 self.is_now_next = False
369 self.bouquetSel = None
370 self.eventView = None
371 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
373 "showEventInfo": (self.openEventView, _("show EPG...")),
376 def zapToService(self, service):
377 if not service is None:
378 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
379 self.servicelist.clearPath()
380 if self.servicelist.bouquet_root != self.epg_bouquet:
381 self.servicelist.enterPath(self.servicelist.bouquet_root)
382 self.servicelist.enterPath(self.epg_bouquet)
383 self.servicelist.setCurrentSelection(service) #select the service in servicelist
384 self.servicelist.zap()
386 def getBouquetServices(self, bouquet):
388 servicelist = eServiceCenter.getInstance().list(bouquet)
389 if not servicelist is None:
391 service = servicelist.getNext()
392 if not service.valid(): #check if end of list
394 if service.flags: #ignore non playable services
396 services.append(ServiceReference(service))
399 def openBouquetEPG(self, bouquet, withCallback=True):
400 services = self.getBouquetServices(bouquet)
402 self.epg_bouquet = bouquet
404 self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
406 self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
408 def changeBouquetCB(self, direction, epg):
411 self.bouquetSel.down()
414 bouquet = self.bouquetSel.getCurrent()
415 services = self.getBouquetServices(bouquet)
417 self.epg_bouquet = bouquet
418 epg.setServices(services)
420 def closed(self, ret=False):
421 closedScreen = self.dlg_stack.pop()
422 if self.bouquetSel and closedScreen == self.bouquetSel:
423 self.bouquetSel = None
424 elif self.eventView and closedScreen == self.eventView:
425 self.eventView = None
427 dlgs=len(self.dlg_stack)
429 self.dlg_stack[dlgs-1].close(dlgs > 1)
431 def openMultiServiceEPG(self, withCallback=True):
432 bouquets = self.servicelist.getBouquetList()
437 if cnt > 1: # show bouquet list
439 self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
440 self.dlg_stack.append(self.bouquetSel)
442 self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
444 self.openBouquetEPG(bouquets[0][1], withCallback)
446 def openSingleServiceEPG(self):
447 ref=self.session.nav.getCurrentlyPlayingServiceReference()
448 self.session.open(EPGSelection, ref)
450 def openSimilarList(self, eventid, refstr):
451 self.session.open(EPGSelection, refstr, None, eventid)
453 def getNowNext(self):
455 service = self.session.nav.getCurrentService()
456 info = service and service.info()
457 ptr = info and info.getEvent(0)
459 self.epglist.append(ptr)
460 ptr = info and info.getEvent(1)
462 self.epglist.append(ptr)
464 def __evEventInfoChanged(self):
465 if self.is_now_next and len(self.dlg_stack) == 1:
467 assert self.eventView
468 if len(self.epglist):
469 self.eventView.setEvent(self.epglist[0])
471 def openEventView(self):
472 ref = self.session.nav.getCurrentlyPlayingServiceReference()
474 if len(self.epglist) == 0:
475 self.is_now_next = False
476 epg = eEPGCache.getInstance()
477 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
479 self.epglist.append(ptr)
480 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
482 self.epglist.append(ptr)
484 self.is_now_next = True
485 if len(self.epglist) > 0:
486 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
487 self.dlg_stack.append(self.eventView)
489 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
490 self.openMultiServiceEPG(False)
492 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
493 if len(self.epglist) > 1:
494 tmp = self.epglist[0]
495 self.epglist[0]=self.epglist[1]
497 setEvent(self.epglist[0])
500 """provides a snr/agc/ber display"""
502 self["snr"] = Label()
503 self["agc"] = Label()
504 self["ber"] = Label()
505 self["snr_percent"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
506 self["agc_percent"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
507 self["ber_count"] = TunerInfo(TunerInfo.BER_VALUE, servicefkt = self.session.nav.getCurrentService)
508 self["snr_progress"] = TunerInfo(TunerInfo.SNR_BAR, servicefkt = self.session.nav.getCurrentService)
509 self["agc_progress"] = TunerInfo(TunerInfo.AGC_BAR, servicefkt = self.session.nav.getCurrentService)
510 self["ber_progress"] = TunerInfo(TunerInfo.BER_BAR, servicefkt = self.session.nav.getCurrentService)
511 self.timer = eTimer()
512 self.timer.timeout.get().append(self.updateTunerInfo)
513 self.timer.start(1000)
515 def updateTunerInfo(self):
516 if self.instance.isVisible():
517 self["snr_percent"].update()
518 self["agc_percent"].update()
519 self["ber_count"].update()
520 self["snr_progress"].update()
521 self["agc_progress"].update()
522 self["ber_progress"].update()
525 """provides a current/next event info display"""
527 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
528 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
530 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
531 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
533 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
534 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
536 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
538 class InfoBarServiceName:
540 self["ServiceName"] = ServiceName(self.session.nav)
543 """handles actions like seeking, pause"""
545 # ispause, isff, issm
546 SEEK_STATE_PLAY = (0, 0, 0, ">")
547 SEEK_STATE_PAUSE = (1, 0, 0, "||")
548 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
549 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
550 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
551 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
552 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
553 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
555 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
556 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
557 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
558 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
560 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
561 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
562 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
565 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
567 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
568 iPlayableService.evStart: self.__serviceStarted,
570 iPlayableService.evEOF: self.__evEOF,
571 iPlayableService.evSOF: self.__evSOF,
574 class InfoBarSeekActionMap(HelpableActionMap):
575 def __init__(self, screen, *args, **kwargs):
576 HelpableActionMap.__init__(self, screen, *args, **kwargs)
579 def action(self, contexts, action):
580 if action[:5] == "seek:":
581 time = int(action[5:])
582 self.screen.seekRelative(time * 90000)
585 return HelpableActionMap.action(self, contexts, action)
587 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
589 "pauseService": (self.pauseService, "pause"),
590 "unPauseService": (self.unPauseService, "continue"),
592 "seekFwd": (self.seekFwd, "skip forward"),
593 "seekFwdDown": self.seekFwdDown,
594 "seekFwdUp": self.seekFwdUp,
595 "seekBack": (self.seekBack, "skip backward"),
596 "seekBackDown": self.seekBackDown,
597 "seekBackUp": self.seekBackUp,
599 # give them a little more priority to win over color buttons
601 self.seekstate = self.SEEK_STATE_PLAY
602 self.onClose.append(self.delTimer)
604 self.fwdtimer = False
605 self.fwdKeyTimer = eTimer()
606 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
608 self.rwdtimer = False
609 self.rwdKeyTimer = eTimer()
610 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
612 self.onPlayStateChanged = [ ]
614 self.lockedBecauseOfSkipping = False
627 service = self.session.nav.getCurrentService()
631 seek = service.seek()
633 if seek is None or not seek.isCurrentlySeekable():
638 def isSeekable(self):
639 if self.getSeek() is None:
643 def __seekableStatusChanged(self):
644 print "seekable status changed!"
645 if not self.isSeekable():
646 self["SeekActions"].setEnabled(False)
647 print "not seekable, return to play"
648 self.setSeekState(self.SEEK_STATE_PLAY)
650 self["SeekActions"].setEnabled(True)
653 def __serviceStarted(self):
654 self.seekstate = self.SEEK_STATE_PLAY
656 def setSeekState(self, state):
657 service = self.session.nav.getCurrentService()
662 if not self.isSeekable():
663 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
664 state = self.SEEK_STATE_PLAY
666 pauseable = service.pause()
668 if pauseable is None:
669 print "not pauseable."
670 state = self.SEEK_STATE_PLAY
672 oldstate = self.seekstate
673 self.seekstate = state
676 if oldstate[i] != self.seekstate[i]:
677 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
679 for c in self.onPlayStateChanged:
682 self.checkSkipShowHideLock()
686 def pauseService(self):
687 if self.seekstate == self.SEEK_STATE_PAUSE:
688 print "pause, but in fact unpause"
689 self.unPauseService()
691 if self.seekstate == self.SEEK_STATE_PLAY:
692 print "yes, playing."
694 print "no", self.seekstate
696 self.setSeekState(self.SEEK_STATE_PAUSE);
698 def unPauseService(self):
700 if self.seekstate == self.SEEK_STATE_PLAY:
702 self.setSeekState(self.SEEK_STATE_PLAY);
704 def doSeek(self, seektime):
705 print "doseek", seektime
706 service = self.session.nav.getCurrentService()
710 seekable = self.getSeek()
714 seekable.seekTo(90 * seektime)
716 def seekFwdDown(self):
717 print "start fwd timer"
719 self.fwdKeyTimer.start(1000)
721 def seekBackDown(self):
722 print "start rewind timer"
724 self.rwdKeyTimer.start(1000)
729 self.fwdKeyTimer.stop()
730 self.fwdtimer = False
735 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
736 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
737 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
738 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
739 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
740 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
741 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
742 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
743 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
744 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
745 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
746 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
747 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
748 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
749 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
751 self.setSeekState(lookup[self.seekstate])
753 def seekBackUp(self):
756 self.rwdKeyTimer.stop()
757 self.rwdtimer = False
762 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
763 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
764 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
765 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
766 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
767 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
768 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
769 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
770 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
771 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
772 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
773 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
774 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
775 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
776 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
778 self.setSeekState(lookup[self.seekstate])
780 if self.seekstate == self.SEEK_STATE_PAUSE:
781 seekable = self.getSeek()
782 if seekable is not None:
783 seekable.seekRelative(-1, 3)
785 def fwdTimerFire(self):
786 print "Display seek fwd"
787 self.fwdKeyTimer.stop()
788 self.fwdtimer = False
789 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
791 def fwdSeekTo(self, minutes):
792 print "Seek", minutes, "minutes forward"
794 seekable = self.getSeek()
795 if seekable is not None:
796 seekable.seekRelative(1, minutes * 60 * 90000)
798 def rwdTimerFire(self):
800 self.rwdKeyTimer.stop()
801 self.rwdtimer = False
802 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
804 def rwdSeekTo(self, minutes):
806 self.fwdSeekTo(0 - minutes)
808 def checkSkipShowHideLock(self):
809 wantlock = self.seekstate != self.SEEK_STATE_PLAY
811 if self.lockedBecauseOfSkipping and not wantlock:
813 self.lockedBecauseOfSkipping = False
815 if wantlock and not self.lockedBecauseOfSkipping:
817 self.lockedBecauseOfSkipping = True
820 if self.seekstate != self.SEEK_STATE_PLAY:
821 self.setSeekState(self.SEEK_STATE_PAUSE)
823 #self.getSeek().seekRelative(1, -90000)
824 self.setSeekState(self.SEEK_STATE_PLAY)
826 self.setSeekState(self.SEEK_STATE_PAUSE)
829 self.setSeekState(self.SEEK_STATE_PLAY)
832 def seekRelative(self, diff):
833 seekable = self.getSeek()
834 if seekable is not None:
835 seekable.seekRelative(1, diff)
837 from Screens.PVRState import PVRState, TimeshiftState
839 class InfoBarPVRState:
840 def __init__(self, screen=PVRState):
841 self.onPlayStateChanged.append(self.__playStateChanged)
842 self.pvrStateDialog = self.session.instantiateDialog(screen)
843 self.onShow.append(self.__mayShow)
844 self.onHide.append(self.pvrStateDialog.hide)
847 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
848 self.pvrStateDialog.show()
850 def __playStateChanged(self, state):
851 playstateString = state[3]
852 self.pvrStateDialog["state"].setText(playstateString)
855 class InfoBarTimeshiftState(InfoBarPVRState):
857 InfoBarPVRState.__init__(self, screen=TimeshiftState)
860 class InfoBarShowMovies:
862 # i don't really like this class.
863 # it calls a not further specified "movie list" on up/down/movieList,
864 # so this is not more than an action map
866 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
868 "movieList": (self.showMovies, "movie list"),
869 "up": (self.showMovies, "movie list"),
870 "down": (self.showMovies, "movie list")
873 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
877 # Timeshift works the following way:
878 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
879 # - normal playback TUNER unused PLAY enable disable disable
880 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
881 # - user presess pause again FILE record PLAY enable disable enable
882 # - user fast forwards FILE record FF enable disable enable
883 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
884 # - user backwards FILE record BACK # !! enable disable enable
888 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
889 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
890 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
891 # - the user can now PVR around
892 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
893 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
895 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
896 # - if the user rewinds, or press pause, timeshift will be activated again
898 # note that a timeshift can be enabled ("recording") and
899 # activated (currently time-shifting).
901 class InfoBarTimeshift:
903 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
905 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
906 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
908 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
910 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
911 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
912 }, prio=-1) # priority over record
914 self.timeshift_enabled = 0
915 self.timeshift_state = 0
916 self.ts_pause_timer = eTimer()
917 self.ts_pause_timer.timeout.get().append(self.pauseService)
919 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
921 iPlayableService.evStart: self.__serviceStarted,
922 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
925 def getTimeshift(self):
926 service = self.session.nav.getCurrentService()
927 return service and service.timeshift()
929 def startTimeshift(self):
930 print "enable timeshift"
931 ts = self.getTimeshift()
933 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
934 print "no ts interface"
937 if self.timeshift_enabled:
938 print "hu, timeshift already enabled?"
940 if not ts.startTimeshift():
942 self.timeshift_enabled = 1
943 self.pvrStateDialog["timeshift"].setRelative(time.time())
946 self.setSeekState(self.SEEK_STATE_PAUSE)
948 # enable the "TimeshiftEnableActions", which will override
949 # the startTimeshift actions
950 self.__seekableStatusChanged()
952 print "timeshift failed"
954 def stopTimeshift(self):
955 if not self.timeshift_enabled:
957 print "disable timeshift"
958 ts = self.getTimeshift()
961 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
963 def stopTimeshiftConfirmed(self, confirmed):
967 ts = self.getTimeshift()
972 self.timeshift_enabled = 0
975 self.__seekableStatusChanged()
977 # activates timeshift, and seeks to (almost) the end
978 def activateTimeshiftEnd(self):
979 ts = self.getTimeshift()
984 if ts.isTimeshiftActive():
985 print "!! activate timeshift called - but shouldn't this be a normal pause?"
988 self.setSeekState(self.SEEK_STATE_PLAY)
989 ts.activateTimeshift()
992 # same as activateTimeshiftEnd, but pauses afterwards.
993 def activateTimeshiftEndAndPause(self):
994 state = self.seekstate
995 self.activateTimeshiftEnd()
997 # well, this is "andPause", but it could be pressed from pause,
998 # when pausing on the (fake-)"live" picture, so an un-pause
1001 print "now, pauseService"
1002 if state == self.SEEK_STATE_PLAY:
1003 print "is PLAYING, start pause timer"
1004 self.ts_pause_timer.start(200, 1)
1007 self.unPauseService()
1009 def __seekableStatusChanged(self):
1012 print "self.isSeekable", self.isSeekable()
1013 print "self.timeshift_enabled", self.timeshift_enabled
1015 # when this service is not seekable, but timeshift
1016 # is enabled, this means we can activate
1018 if not self.isSeekable() and self.timeshift_enabled:
1021 print "timeshift activate:", enabled
1022 self["TimeshiftActivateActions"].setEnabled(enabled)
1024 def __serviceStarted(self):
1025 self.timeshift_enabled = False
1026 self.__seekableStatusChanged()
1028 from Screens.PiPSetup import PiPSetup
1030 class InfoBarExtensions:
1032 self.session.pipshown = False
1034 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1036 "extensions": (self.extensions, "Extensions..."),
1045 def extensions(self):
1047 if self.session.pipshown == False:
1048 list.append((_("Activate Picture in Picture"), self.PIPON))
1049 elif self.session.pipshown == True:
1050 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1051 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1052 list.append((_("Swap services"), self.PIPSWAP))
1054 s = self.getCurrentServiceSubtitle()
1055 l = s and s.getSubtitleList() or [ ]
1058 list.append(("DEBUG: Enable Subtitles: " + x[0], self.ENABLE_SUBTITLE, x[1]))
1060 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1062 def extensionCallback(self, answer):
1063 if answer is not None:
1064 if answer[1] == self.PIPON:
1065 self.session.pip = self.session.instantiateDialog(PictureInPicture)
1066 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1067 if self.session.pip.playService(newservice):
1068 self.session.pipshown = True
1069 self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
1071 self.session.pipshown = False
1072 del self.session.pip
1073 self.session.nav.playService(newservice)
1074 elif answer[1] == self.PIPOFF:
1075 del self.session.pip
1076 self.session.pipshown = False
1077 elif answer[1] == self.PIPSWAP:
1078 swapservice = self.session.nav.getCurrentlyPlayingServiceReference()
1079 if self.session.pip.servicePath:
1080 servicepath = self.servicelist.getCurrentServicePath()
1081 ref=servicepath[len(servicepath)-1]
1082 pipref=self.session.pip.getCurrentService()
1083 self.session.pip.playService(swapservice)
1084 self.servicelist.setCurrentServicePath(self.session.pip.servicePath)
1085 if pipref.toString() != ref.toString(): # is a subservice ?
1086 self.session.nav.stopService() # stop portal
1087 self.session.nav.playService(pipref) # start subservice
1088 self.session.pip.servicePath=servicepath
1089 elif answer[1] == self.MOVEPIP:
1090 self.session.open(PiPSetup, pip = self.session.pip)
1091 elif answer[1] == self.ENABLE_SUBTITLE:
1092 self.selected_subtitle = answer[2]
1093 self.subtitles_enabled = True
1095 from RecordTimer import parseEvent
1097 class InfoBarInstantRecord:
1098 """Instant Record - handles the instantRecord action in order to
1099 start/stop instant records"""
1101 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1103 "instantRecord": (self.instantRecord, "Instant Record..."),
1106 self["BlinkingPoint"] = BlinkingPixmapConditional()
1107 self["BlinkingPoint"].hide()
1108 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1110 def stopCurrentRecording(self, entry = -1):
1111 if entry is not None and entry != -1:
1112 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1113 self.recording.remove(self.recording[entry])
1115 def startInstantRecording(self, limitEvent = False):
1116 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1118 # try to get event info
1121 service = self.session.nav.getCurrentService()
1122 epg = eEPGCache.getInstance()
1123 event = epg.lookupEventTime(serviceref, -1, 0)
1125 info = service.info()
1126 ev = info.getEvent(0)
1132 end = time.time() + 3600 * 10
1133 name = "instant record"
1137 if event is not None:
1138 curEvent = parseEvent(event)
1140 description = curEvent[3]
1141 eventid = curEvent[4]
1146 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1148 data = (begin, end, name, description, eventid)
1150 recording = self.session.nav.recordWithTimer(serviceref, *data)
1151 recording.dontSave = True
1152 self.recording.append(recording)
1154 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1156 def isInstantRecordRunning(self):
1157 print "self.recording:", self.recording
1158 if len(self.recording) > 0:
1159 for x in self.recording:
1164 def recordQuestionCallback(self, answer):
1165 print "pre:\n", self.recording
1167 if answer is None or answer[1] == "no":
1170 recording = self.recording[:]
1172 if not x in self.session.nav.RecordTimer.timer_list:
1173 self.recording.remove(x)
1174 elif x.dontSave and x.isRunning():
1175 list.append(TimerEntryComponent(x, False))
1177 if answer[1] == "changeduration":
1178 if len(self.recording) == 1:
1179 self.changeDuration(0)
1181 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1182 elif answer[1] == "stop":
1183 if len(self.recording) == 1:
1184 self.stopCurrentRecording(0)
1186 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1187 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1189 if answer[1] == "event":
1191 if answer[1] == "manualduration":
1192 self.selectedEntry = len(self.recording)
1193 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1194 self.startInstantRecording(limitEvent = limitEvent)
1196 print "after:\n", self.recording
1198 def changeDuration(self, entry):
1199 if entry is not None:
1200 self.selectedEntry = entry
1201 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1203 def inputCallback(self, value):
1204 if value is not None:
1205 print "stopping recording after", int(value), "minutes."
1206 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1207 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1209 def instantRecord(self):
1211 stat = os.stat(resolveFilename(SCOPE_HDD))
1213 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1216 if self.isInstantRecordRunning():
1217 self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("A recording is currently running.\nWhat do you want to do?"), list=[(_("stop recording"), "stop"), (_("change recording (duration)"), "changeduration"), (_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"), (_("do nothing"), "no")])
1219 self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Start recording?"), list=[(_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"),(_("don't record"), "no")])
1221 from Tools.ISO639 import LanguageCodes
1223 class InfoBarAudioSelection:
1225 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1227 "audioSelection": (self.audioSelection, "Audio Options..."),
1230 def audioSelection(self):
1231 service = self.session.nav.getCurrentService()
1232 audio = service.audioTracks()
1233 self.audioTracks = audio
1234 n = audio.getNumberOfTracks()
1235 keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
1237 print "tlist:", tlist
1239 self.audioChannel = service.audioChannel()
1242 i = audio.getTrackInfo(x)
1243 language = i.getLanguage()
1244 description = i.getDescription()
1246 if len(language) == 3:
1247 if language in LanguageCodes:
1248 language = LanguageCodes[language][0]
1250 if len(description):
1251 description += " (" + language + ")"
1253 description = language
1255 tlist.append((description, x))
1257 selectedAudio = tlist[0][1]
1258 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1262 if x[1] != selectedAudio:
1267 tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
1268 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
1270 del self.audioTracks
1272 def audioSelected(self, audio):
1273 if audio is not None:
1274 if isinstance(audio[1], str):
1275 if audio[1] == "mode":
1276 keys = ["red", "green", "yellow"]
1277 selection = self.audioChannel.getCurrentChannel()
1278 tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
1279 self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
1281 del self.audioChannel
1282 if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
1283 self.audioTracks.selectTrack(audio[1])
1285 del self.audioChannel
1286 del self.audioTracks
1288 def modeSelected(self, mode):
1289 if mode is not None:
1290 self.audioChannel.selectChannel(mode[1])
1291 del self.audioChannel
1293 class InfoBarSubserviceSelection:
1295 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1297 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1300 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1302 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1303 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1305 self["SubserviceQuickzapAction"].setEnabled(False)
1307 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1309 def checkSubservicesAvail(self, ev):
1310 if ev == iPlayableService.evUpdatedEventInfo:
1311 service = self.session.nav.getCurrentService()
1312 subservices = service and service.subServices()
1313 if not subservices or subservices.getNumberOfSubservices() == 0:
1314 self["SubserviceQuickzapAction"].setEnabled(False)
1316 def nextSubservice(self):
1317 self.changeSubservice(+1)
1319 def prevSubservice(self):
1320 self.changeSubservice(-1)
1322 def changeSubservice(self, direction):
1323 service = self.session.nav.getCurrentService()
1324 subservices = service and service.subServices()
1325 n = subservices and subservices.getNumberOfSubservices()
1328 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1330 if subservices.getSubservice(x).toString() == ref.toString():
1333 selection += direction
1338 newservice = subservices.getSubservice(selection)
1339 if newservice.valid():
1342 self.session.nav.playService(newservice)
1344 def subserviceSelection(self):
1345 service = self.session.nav.getCurrentService()
1346 subservices = service and service.subServices()
1348 n = subservices and subservices.getNumberOfSubservices()
1351 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1354 i = subservices.getSubservice(x)
1355 if i.toString() == ref.toString():
1357 tlist.append((i.getName(), i))
1359 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1361 def subserviceSelected(self, service):
1362 if not service is None:
1363 self["SubserviceQuickzapAction"].setEnabled(True)
1364 self.session.nav.playService(service[1])
1366 class InfoBarAdditionalInfo:
1368 self["NimA"] = Pixmap()
1369 self["NimB"] = Pixmap()
1370 self["TextActive"] = Pixmap()
1371 self["DolbyActive"] = Pixmap()
1372 self["CryptActive"] = Pixmap()
1373 self["FormatActive"] = Pixmap()
1374 self["NimA_Active"] = Pixmap()
1375 self["NimB_Active"] = Pixmap()
1377 self["ButtonRed"] = PixmapConditional(withTimer = False)
1378 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1379 self.onLayoutFinish.append(self["ButtonRed"].update)
1380 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1381 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1382 self.onLayoutFinish.append(self["ButtonRedText"].update)
1384 self["ButtonGreen"] = Pixmap()
1385 self["ButtonGreenText"] = Label(_("Subservices"))
1387 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1388 self["ButtonYellow"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1389 self["ButtonYellowText"] = LabelConditional(text = _("Timeshifting"), withTimer = False)
1390 self["ButtonYellowText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1391 self.onLayoutFinish.append(self["ButtonYellow"].update)
1392 self.onLayoutFinish.append(self["ButtonYellowText"].update)
1394 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1395 self["ButtonBlue"].setConnect(lambda: True)
1396 self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
1397 self["ButtonBlueText"].setConnect(lambda: True)
1398 self.onLayoutFinish.append(self["ButtonBlue"].update)
1399 self.onLayoutFinish.append(self["ButtonBlueText"].update)
1401 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1402 res_mgr = eDVBResourceManagerPtr()
1403 if eDVBResourceManager.getInstance(res_mgr) == 0:
1404 res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged)
1406 def tunerUseMaskChanged(self, mask):
1408 self["NimA_Active"].show()
1410 self["NimA_Active"].hide()
1412 self["NimB_Active"].show()
1414 self["NimB_Active"].hide()
1416 def hideSubServiceIndication(self):
1417 self["ButtonGreen"].hide()
1418 self["ButtonGreenText"].hide()
1420 def showSubServiceIndication(self):
1421 self["ButtonGreen"].show()
1422 self["ButtonGreenText"].show()
1424 def checkFormat(self, service):
1425 info = service.info()
1427 aspect = info.getInfo(iServiceInformation.sAspect)
1428 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1429 self["FormatActive"].show()
1431 self["FormatActive"].hide()
1433 def checkText(self, service):
1434 info = service.info()
1436 tpid = info.getInfo(iServiceInformation.sTXTPID)
1438 self["TextActive"].show()
1440 self["TextActive"].hide()
1442 def checkSubservices(self, service):
1443 subservices = service.subServices()
1444 if subservices and subservices.getNumberOfSubservices() > 0:
1445 self.showSubServiceIndication()
1447 self.hideSubServiceIndication()
1449 def checkDolby(self, service):
1452 audio = service.audioTracks()
1454 n = audio.getNumberOfTracks()
1456 i = audio.getTrackInfo(x)
1457 description = i.getDescription();
1458 if description.find("AC3") != -1 or description.find("DTS") != -1:
1462 self["DolbyActive"].show()
1464 self["DolbyActive"].hide()
1466 def checkCrypted(self, service):
1467 info = service.info()
1468 if info and info.getInfo(iServiceInformation.sIsCrypted) > 0:
1469 self["CryptActive"].show()
1471 self["CryptActive"].hide()
1473 def checkTunerState(self, service):
1474 info = service.frontendInfo()
1475 feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber)
1476 if feNumber is None:
1486 def gotServiceEvent(self, ev):
1487 service = self.session.nav.getCurrentService()
1488 if ev == iPlayableService.evStart:
1489 self.checkTunerState(service)
1490 elif ev == iPlayableService.evUpdatedEventInfo:
1491 self.checkSubservices(service)
1492 self.checkFormat(service)
1493 elif ev == iPlayableService.evUpdatedInfo:
1494 self.checkCrypted(service)
1495 self.checkDolby(service)
1496 self.checkText(service)
1497 elif ev == iPlayableService.evEnd:
1498 self.hideSubServiceIndication()
1499 self["CryptActive"].hide()
1500 self["DolbyActive"].hide()
1501 self["FormatActive"].hide()
1502 self["TextActive"].hide()
1504 class InfoBarNotifications:
1506 self.onExecBegin.append(self.checkNotifications)
1507 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1508 self.onClose.append(self.__removeNotification)
1510 def __removeNotification(self):
1511 Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
1513 def checkNotificationsIfExecing(self):
1515 self.checkNotifications()
1517 def checkNotifications(self):
1518 if len(Notifications.notifications):
1519 n = Notifications.notifications[0]
1520 Notifications.notifications = Notifications.notifications[1:]
1523 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1525 self.session.open(n[1], *n[2], **n[3])
1527 class InfoBarServiceNotifications:
1529 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1531 iPlayableService.evEnd: self.serviceHasEnded
1534 def serviceHasEnded(self):
1535 print "service end!"
1538 self.setSeekState(self.SEEK_STATE_PLAY)
1542 class InfoBarCueSheetSupport:
1548 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1550 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1551 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1552 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1556 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1558 iPlayableService.evStart: self.__serviceStarted,
1561 def __serviceStarted(self):
1562 print "new service started! trying to download cuts!"
1563 self.downloadCuesheet()
1565 def __getSeekable(self):
1566 service = self.session.nav.getCurrentService()
1569 return service.seek()
1571 def cueGetCurrentPosition(self):
1572 seek = self.__getSeekable()
1575 r = seek.getPlayPosition()
1580 def jumpPreviousNextMark(self, cmp, alternative=None):
1581 current_pos = self.cueGetCurrentPosition()
1582 if current_pos is None:
1584 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1585 if mark is not None:
1587 elif alternative is not None:
1592 seekable = self.__getSeekable()
1593 if seekable is not None:
1594 seekable.seekTo(pts)
1596 def jumpPreviousMark(self):
1597 # we add 2 seconds, so if the play position is <2s after
1598 # the mark, the mark before will be used
1599 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1601 def jumpNextMark(self):
1602 self.jumpPreviousNextMark(lambda x: x)
1604 def getNearestCutPoint(self, pts, cmp=abs):
1607 for cp in self.cut_list:
1608 diff = cmp(cp[0] - pts)
1609 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1613 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1614 current_pos = self.cueGetCurrentPosition()
1615 if current_pos is None:
1616 print "not seekable"
1619 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1621 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1623 return nearest_cutpoint
1625 self.removeMark(nearest_cutpoint)
1626 elif not onlyremove and not onlyreturn:
1627 self.addMark((current_pos, self.CUT_TYPE_MARK))
1632 def addMark(self, point):
1633 bisect.insort(self.cut_list, point)
1634 self.uploadCuesheet()
1636 def removeMark(self, point):
1637 self.cut_list.remove(point)
1638 self.uploadCuesheet()
1640 def __getCuesheet(self):
1641 service = self.session.nav.getCurrentService()
1644 return service.cueSheet()
1646 def uploadCuesheet(self):
1647 cue = self.__getCuesheet()
1650 print "upload failed, no cuesheet interface"
1652 cue.setCutList(self.cut_list)
1654 def downloadCuesheet(self):
1655 cue = self.__getCuesheet()
1658 print "upload failed, no cuesheet interface"
1660 self.cut_list = cue.getCutList()
1662 class InfoBarSummary(Screen):
1664 <screen position="0,0" size="132,64">
1665 <widget name="Clock" position="50,46" size="82,18" font="Regular;16" />
1666 <widget name="CurrentService" position="0,4" size="132,42" font="Regular;18" />
1669 def __init__(self, session, parent):
1670 Screen.__init__(self, session)
1671 self["CurrentService"] = ServiceName(self.session.nav)
1672 self["Clock"] = Clock()
1674 class InfoBarSummarySupport:
1678 def createSummary(self):
1679 return InfoBarSummary
1681 class InfoBarTeletextPlugin:
1683 self.teletext_plugin = None
1685 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1686 self.teletext_plugin = p
1688 if self.teletext_plugin is not None:
1689 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1691 "startTeletext": (self.startTeletext, "View teletext...")
1694 print "no teletext plugin found!"
1696 def startTeletext(self):
1697 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())
1699 class InfoBarSubtitleSupport(object):
1701 object.__init__(self)
1702 self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
1703 self.__subtitles_enabled = False
1705 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1707 iPlayableService.evStart: self.__serviceStarted,
1710 def __serviceStarted(self):
1711 # reenable if it was enabled
1712 r = self.__subtitles_enabled
1713 self.__subtitles_enabled = False
1714 self.__selected_subtitle = None
1715 self.setSubtitlesEnable(r)
1717 def getCurrentServiceSubtitle(self):
1718 service = self.session.nav.getCurrentService()
1719 return service and service.subtitle()
1721 def setSubtitlesEnable(self, enable=True):
1722 subtitle = self.getCurrentServiceSubtitle()
1723 if enable and self.__selected_subtitle:
1724 if subtitle and not self.__subtitles_enabled:
1725 subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
1726 self.subtitle_window.show()
1727 self.__subtitles_enabled = True
1730 subtitle.disableSubtitles(self.subtitle_window.instance)
1732 self.subtitle_window.hide()
1733 self.__subtitles_enabled = False
1735 def setSelectedSubtitle(self, subtitle):
1736 if self.__selected_subtitle != subtitle and self.subtitles_enabled:
1738 self.__selected_subtitle = subtitle
1739 self.__serviceStarted()
1741 self.__selected_subtitle = subtitle
1743 subtitles_enabled = property(lambda self: self.__subtitles_enabled, setSubtitlesEnable)
1744 selected_subtitle = property(lambda self: self.__selected_subtitle, setSelectedSubtitle)