1 from Screen import Screen
2 from Components.ActionMap import ActionMap, HelpableActionMap
3 from Components.ActionMap import NumberActionMap
4 from Components.Label import *
5 from Components.ProgressBar import *
6 from Components.config import configfile, configsequencearg
7 from Components.config import config, configElement, ConfigSubsection, configSequence
8 from ChannelSelection import ChannelSelection, BouquetSelector
10 from Components.Pixmap import Pixmap, PixmapConditional
11 from Components.BlinkingPixmap import BlinkingPixmapConditional
12 from Components.ServiceName import ServiceName
13 from Components.EventInfo import EventInfo
15 from ServiceReference import ServiceReference
16 from EpgSelection import EPGSelection
18 from Screens.MessageBox import MessageBox
19 from Screens.Volume import Volume
20 from Screens.Mute import Mute
21 from Screens.Dish import Dish
22 from Screens.Standby import Standby
23 from Screens.EventView import EventView
24 from Screens.MinuteInput import MinuteInput
25 from Components.Harddisk import harddiskmanager
27 from Tools import Notifications
28 from Tools.Directories import *
30 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
37 from Menu import MainMenu, mdom
39 class InfoBarVolumeControl:
40 """Volume control, handles volUp, volDown, volMute actions and display
41 a corresponding dialog"""
43 config.audio = ConfigSubsection()
44 config.audio.volume = configElement("config.audio.volume", configSequence, [100], configsequencearg.get("INTEGER", (0, 100)))
46 self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
48 "volumeUp": self.volUp,
49 "volumeDown": self.volDown,
50 "volumeMute": self.volMute,
53 self.volumeDialog = self.session.instantiateDialog(Volume)
54 self.muteDialog = self.session.instantiateDialog(Mute)
56 self.hideVolTimer = eTimer()
57 self.hideVolTimer.timeout.get().append(self.volHide)
59 vol = config.audio.volume.value[0]
60 self.volumeDialog.setValue(vol)
61 eDVBVolumecontrol.getInstance().setVolume(vol, vol)
64 config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
65 config.audio.volume.save()
68 if (eDVBVolumecontrol.getInstance().isMuted()):
70 eDVBVolumecontrol.getInstance().volumeUp()
71 self.volumeDialog.instance.show()
72 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
74 self.hideVolTimer.start(3000, True)
77 if (eDVBVolumecontrol.getInstance().isMuted()):
79 eDVBVolumecontrol.getInstance().volumeDown()
80 self.volumeDialog.instance.show()
81 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
83 self.hideVolTimer.start(3000, True)
86 self.volumeDialog.instance.hide()
89 eDVBVolumecontrol.getInstance().volumeToggleMute()
90 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
92 if (eDVBVolumecontrol.getInstance().isMuted()):
93 self.muteDialog.instance.show()
95 self.muteDialog.instance.hide()
99 self.dishDialog = self.session.instantiateDialog(Dish)
100 self.onShown.append(self.dishDialog.instance.hide)
102 class InfoBarShowHide:
103 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
104 fancy animations. """
111 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
113 "toggleShow": self.toggleShow,
117 self.state = self.STATE_SHOWN
119 self.onExecBegin.append(self.show)
120 self.onClose.append(self.delHideTimer)
122 self.hideTimer = eTimer()
123 self.hideTimer.timeout.get().append(self.doTimerHide)
124 self.hideTimer.start(5000, True)
126 def delHideTimer(self):
133 self.state = self.STATE_SHOWN
134 self.hideTimer.start(5000, True)
136 def doTimerHide(self):
137 self.hideTimer.stop()
138 if self.state == self.STATE_SHOWN:
140 self.state = self.STATE_HIDDEN
142 def toggleShow(self):
143 if self.state == self.STATE_SHOWN:
145 #pls check animation support, sorry
147 self.hideTimer.stop()
148 self.state = self.STATE_HIDDEN
149 elif self.state == self.STATE_HIDDEN:
154 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
155 self.state = self.STATE_SHOWN
158 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
159 self.state = self.STATE_HIDDEN
161 class NumberZap(Screen):
168 self.close(int(self["number"].getText()))
170 def keyNumberGlobal(self, number):
171 self.Timer.start(3000, True) #reset timer
172 self.field = self.field + str(number)
173 self["number"].setText(self.field)
174 if len(self.field) >= 4:
177 def __init__(self, session, number):
178 Screen.__init__(self, session)
179 self.field = str(number)
181 self["channel"] = Label(_("Channel:"))
183 self["number"] = Label(self.field)
185 self["actions"] = NumberActionMap( [ "SetupActions" ],
189 "1": self.keyNumberGlobal,
190 "2": self.keyNumberGlobal,
191 "3": self.keyNumberGlobal,
192 "4": self.keyNumberGlobal,
193 "5": self.keyNumberGlobal,
194 "6": self.keyNumberGlobal,
195 "7": self.keyNumberGlobal,
196 "8": self.keyNumberGlobal,
197 "9": self.keyNumberGlobal,
198 "0": self.keyNumberGlobal
201 self.Timer = eTimer()
202 self.Timer.timeout.get().append(self.keyOK)
203 self.Timer.start(3000, True)
205 class InfoBarPowerKey:
206 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
209 self.powerKeyTimer = eTimer()
210 self.powerKeyTimer.timeout.get().append(self.powertimer)
211 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
213 "powerdown": self.powerdown,
214 "powerup": self.powerup,
215 "discreteStandby": (self.standby, "Go standby"),
216 "discretePowerOff": (self.quit, "Go to deep standby"),
219 def powertimer(self):
220 print "PowerOff - Now!"
224 self.standbyblocked = 0
225 self.powerKeyTimer.start(3000, True)
228 self.powerKeyTimer.stop()
229 if self.standbyblocked == 0:
230 self.standbyblocked = 1
234 self.session.open(Standby, self)
240 class InfoBarNumberZap:
241 """ Handles an initial number for NumberZapping """
243 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
245 "1": self.keyNumberGlobal,
246 "2": self.keyNumberGlobal,
247 "3": self.keyNumberGlobal,
248 "4": self.keyNumberGlobal,
249 "5": self.keyNumberGlobal,
250 "6": self.keyNumberGlobal,
251 "7": self.keyNumberGlobal,
252 "8": self.keyNumberGlobal,
253 "9": self.keyNumberGlobal,
254 "0": self.keyNumberGlobal,
257 def keyNumberGlobal(self, number):
258 # print "You pressed number " + str(number)
260 self.session.nav.zapLast()
264 self.session.openWithCallback(self.numberEntered, NumberZap, number)
266 def numberEntered(self, retval):
267 # print self.servicelist
269 self.zapToNumber(retval)
271 def searchNumberHelper(self, serviceHandler, num, bouquet):
272 servicelist = serviceHandler.list(bouquet)
273 if not servicelist is None:
275 serviceIterator = servicelist.getNext()
276 if not serviceIterator.valid(): #check end of list
278 if serviceIterator.flags: #assume normal dvb service have no flags set
281 if not num: #found service with searched number ?
282 return serviceIterator, 0
285 def zapToNumber(self, number):
286 bouquet = self.servicelist.bouquet_root
288 serviceHandler = eServiceCenter.getInstance()
289 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
290 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
292 bouquetlist = serviceHandler.list(bouquet)
293 if not bouquetlist is None:
295 bouquet = bouquetlist.getNext()
296 if not bouquet.valid(): #check end of list
298 if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
300 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
301 if not service is None:
302 self.session.nav.playService(service) #play service
303 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
304 self.servicelist.setRoot(bouquet)
305 self.servicelist.setCurrentSelection(service) #select the service in servicelist
307 class InfoBarChannelSelection:
308 """ ChannelSelection - handles the channelSelection dialog and the initial
309 channelChange actions which open the channelSelection dialog """
312 self.servicelist = self.session.instantiateDialog(ChannelSelection)
314 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
316 "switchChannelUp": self.switchChannelUp,
317 "switchChannelDown": self.switchChannelDown,
318 "zapUp": (self.zapUp, _("next channel")),
319 "zapDown": (self.zapDown, _("previous channel")),
322 def switchChannelUp(self):
323 self.servicelist.moveUp()
324 self.session.execDialog(self.servicelist)
326 def switchChannelDown(self):
327 self.servicelist.moveDown()
328 self.session.execDialog(self.servicelist)
331 self.servicelist.moveUp()
332 self.servicelist.zap()
337 self.servicelist.moveDown()
338 self.servicelist.zap()
343 """ Handles a menu action, to open the (main) menu """
345 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
347 "mainMenu": (self.mainMenu, "Enter main menu..."),
351 print "loading mainmenu XML..."
352 menu = mdom.childNodes[0]
353 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
354 self.session.open(MainMenu, menu, menu.childNodes)
357 """ EPG - Opens an EPG list when the showEPGList action fires """
359 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
361 "showEPGList": (self.showEPGList, _("show EPG...")),
364 def showEPGList(self):
365 bouquets = self.servicelist.getBouquetList()
370 if cnt > 1: # show bouquet list
371 self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
372 elif cnt == 1: # add to only one existing bouquet
373 self.openBouquetEPG(bouquets[0][1])
374 else: #no bouquets so we open single epg
375 self.openSingleEPGSelector(self.session.nav.getCurrentlyPlayingServiceReference())
377 def openBouquetEPG(self, bouquet):
378 ptr=eEPGCache.getInstance()
380 servicelist = eServiceCenter.getInstance().list(bouquet)
381 if not servicelist is None:
383 service = servicelist.getNext()
384 if not service.valid(): #check if end of list
386 if service.flags: #ignore non playable services
388 services.append(ServiceReference(service))
390 self.session.open(EPGSelection, services)
392 def openSingleEPGSelector(self, ref):
393 ptr=eEPGCache.getInstance()
394 if ptr.startTimeQuery(ref) != -1:
395 self.session.open(EPGSelection, ref)
396 else: # try to show now/next
397 print 'no epg for service', ref.toString()
400 service = self.session.nav.getCurrentService()
401 info = service.info()
404 self.epglist.append(ptr)
407 self.epglist.append(ptr)
408 if len(self.epglist) > 0:
409 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
413 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
414 if len(self.epglist) > 1:
415 tmp = self.epglist[0]
416 self.epglist[0]=self.epglist[1]
418 setEvent(self.epglist[0])
423 """provides a snr/agc/ber display"""
425 self["snr"] = Label()
426 self["agc"] = Label()
427 self["ber"] = Label()
428 self["snr_percent"] = Label()
429 self["agc_percent"] = Label()
430 self["ber_count"] = Label()
431 self["snr_progress"] = ProgressBar()
432 self["agc_progress"] = ProgressBar()
433 self["ber_progress"] = ProgressBar()
434 self.timer = eTimer()
435 self.timer.timeout.get().append(self.updateTunerInfo)
436 self.timer.start(1000)
442 return (long)(log(val)/log(2))
445 def updateTunerInfo(self):
446 if self.instance.isVisible():
447 service = self.session.nav.getCurrentService()
451 if service is not None:
452 feinfo = service.frontendStatusInfo()
453 if feinfo is not None:
454 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
455 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
456 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
457 self["snr_percent"].setText("%d%%"%(snr))
458 self["agc_percent"].setText("%d%%"%(agc))
459 self["ber_count"].setText("%d"%(ber))
460 self["snr_progress"].setValue(snr)
461 self["agc_progress"].setValue(agc)
462 self["ber_progress"].setValue(self.calc(ber))
465 """provides a current/next event info display"""
467 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
468 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
470 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
471 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
473 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
474 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
476 class InfoBarServiceName:
478 self["ServiceName"] = ServiceName(self.session.nav)
482 # ispause, isff, issm, skip
483 SEEK_STATE_PLAY = (0, 0, 0, 0)
484 SEEK_STATE_PAUSE = (1, 0, 0, 0)
485 SEEK_STATE_FF_2X = (0, 2, 0, 0)
486 SEEK_STATE_FF_4X = (0, 4, 0, 0)
487 SEEK_STATE_FF_8X = (0, 8, 0, 0)
488 SEEK_STATE_FF_32X = (0, 4, 0, 32)
489 SEEK_STATE_FF_64X = (0, 4, 0, 64)
490 SEEK_STATE_FF_128X = (0, 4, 0, 128)
492 SEEK_STATE_BACK_4X = (0, 0, 0, -4)
493 SEEK_STATE_BACK_32X = (0, 0, 0, -32)
494 SEEK_STATE_BACK_64X = (0, 0, 0, -64)
495 SEEK_STATE_BACK_128X = (0, 0, 0, -128)
497 SEEK_STATE_SM_HALF = (0, 0, 2, 0)
498 SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
499 SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
501 """handles PVR specific actions like seeking, pause"""
503 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions",
505 "pauseService": (self.pauseService, "pause"),
506 "unPauseService": (self.unPauseService, "continue"),
508 "seekFwd": (self.seekFwd, "skip forward"),
509 "seekFwdUp": (self.seekFwdUp, "skip forward"),
510 "seekBack": (self.seekBack, "skip backward"),
511 "seekBackUp": (self.seekBackUp, "skip backward"),
513 "up": (self.showMovies, "movie list"),
514 "down": (self.showMovies, "movie list")
517 self.seekstate = self.SEEK_STATE_PLAY
518 self.seekTimer = eTimer()
519 self.seekTimer.timeout.get().append(self.seekTimerFired)
520 self.skipinterval = 500 # 500ms skip interval
521 self.onClose.append(self.delSeekTimer)
523 self.fwdtimer = False
524 self.fwdKeyTimer = eTimer()
525 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
527 self.rwdtimer = False
528 self.rwdKeyTimer = eTimer()
529 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
537 def delSeekTimer(self):
540 def seekTimerFired(self):
541 self.seekbase += self.skipmode * self.skipinterval
543 # check if we bounced against the beginning of the file
544 if self.seekbase < 0:
546 self.setSeekState(self.SEEK_STATE_PLAY)
548 self.doSeek(self.seekbase)
550 def setSeekState(self, state):
551 oldstate = self.seekstate
553 self.seekstate = state
555 service = self.session.nav.getCurrentService()
559 pauseable = service.pause()
562 if oldstate[i] != self.seekstate[i]:
563 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
565 def setSkipMode(self, skipmode):
566 self.skipmode = skipmode
568 self.seekTimer.stop()
570 self.seekTimer.start(500)
572 service = self.session.nav.getCurrentService()
576 seekable = service.seek()
581 seekable.setTrickmode(1)
583 seekable.setTrickmode(0)
585 self.seekbase = seekable.getPlayPosition()[1] / 90
587 def pauseService(self):
588 if (self.seekstate == self.SEEK_STATE_PAUSE):
589 self.unPauseService()
591 self.setSeekState(self.SEEK_STATE_PAUSE);
593 def unPauseService(self):
594 self.setSeekState(self.SEEK_STATE_PLAY);
596 def doSeek(self, seektime):
597 service = self.session.nav.getCurrentService()
601 seekable = service.seek()
604 seekable.seekTo(90 * seektime)
607 print "start fwd timer"
609 self.fwdKeyTimer.start(500)
612 print "start rewind timer"
614 self.rwdKeyTimer.start(500)
618 self.fwdKeyTimer.stop()
619 self.fwdtimer = False
621 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
622 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
623 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
624 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
625 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
626 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
627 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
628 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
629 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
630 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
631 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
632 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
633 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
634 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
635 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
637 self.setSeekState(lookup[self.seekstate]);
639 def seekBackUp(self):
641 self.rwdKeyTimer.stop()
642 self.rwdtimer = False
645 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
646 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
647 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
648 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
649 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
650 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
651 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
652 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
653 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
654 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
655 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
656 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
657 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
658 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
659 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
661 self.setSeekState(lookup[self.seekstate]);
663 def fwdTimerFire(self):
664 print "Display seek fwd"
665 self.fwdKeyTimer.stop()
666 self.fwdtimer = False
667 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
669 def fwdSeekTo(self, minutes):
670 print "Seek", minutes, "minutes forward"
672 service = self.session.nav.getCurrentService()
675 seekable = service.seek()
678 seekable.seekRelative(1, minutes * 60 * 90000)
680 def rwdTimerFire(self):
681 self.rwdKeyTimer.stop()
682 self.rwdtimer = False
683 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
685 def rwdSeekTo(self, minutes):
686 self.fwdSeekTo(0 - minutes)
688 from RecordTimer import parseEvent
690 class InfoBarInstantRecord:
691 """Instant Record - handles the instantRecord action in order to
692 start/stop instant records"""
694 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
696 "instantRecord": (self.instantRecord, "Instant Record..."),
698 self.recording = None
700 self["BlinkingPoint"] = BlinkingPixmapConditional()
701 self.onShown.append(self["BlinkingPoint"].hideWidget)
702 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
704 def stopCurrentRecording(self):
705 self.session.nav.RecordTimer.removeEntry(self.recording)
706 self.recording = None
708 def startInstantRecording(self):
709 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
711 # try to get event info
714 service = self.session.nav.getCurrentService()
715 info = service.info()
716 ev = info.getEvent(0)
721 if event is not None:
722 data = parseEvent(event)
723 data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
725 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
727 # fix me, description.
728 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
729 self.recording.dontSave = True
731 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
733 def isInstantRecordRunning(self):
734 if self.recording != None:
735 if self.recording.isRunning():
739 def recordQuestionCallback(self, answer):
743 if self.isInstantRecordRunning():
744 self.stopCurrentRecording()
746 self.startInstantRecording()
748 def instantRecord(self):
750 stat = os.stat(resolveFilename(SCOPE_HDD))
752 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
755 if self.isInstantRecordRunning():
756 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
758 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
760 from Screens.AudioSelection import AudioSelection
762 class InfoBarAudioSelection:
764 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
766 "audioSelection": (self.audioSelection, "Audio Options..."),
769 def audioSelection(self):
770 service = self.session.nav.getCurrentService()
771 audio = service.audioTracks()
772 n = audio.getNumberOfTracks()
774 self.session.open(AudioSelection, audio)
776 from Screens.SubserviceSelection import SubserviceSelection
778 class InfoBarSubserviceSelection:
780 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
782 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
785 def subserviceSelection(self):
786 service = self.session.nav.getCurrentService()
787 subservices = service.subServices()
788 n = subservices.getNumberOfSubservices()
790 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
792 def subserviceSelected(self, service):
793 if not service is None:
794 self.session.nav.playService(service)
796 class InfoBarAdditionalInfo:
798 self["DolbyActive"] = Pixmap()
799 self["CryptActive"] = Pixmap()
800 self["FormatActive"] = Pixmap()
802 self["ButtonRed"] = PixmapConditional(withTimer = False)
803 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
804 self.onShown.append(self["ButtonRed"].update)
805 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
806 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
807 self.onShown.append(self["ButtonRedText"].update)
809 self["ButtonGreen"] = Pixmap()
810 self["ButtonGreenText"] = Label(_("Subservices"))
812 self["ButtonYellow"] = PixmapConditional(withTimer = False)
813 self["ButtonYellow"].setConnect(lambda: False)
815 self["ButtonBlue"] = PixmapConditional(withTimer = False)
816 self["ButtonBlue"].setConnect(lambda: False)
818 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
820 def hideSubServiceIndication(self):
821 self["ButtonGreen"].hideWidget()
822 self["ButtonGreenText"].hide()
824 def showSubServiceIndication(self):
825 self["ButtonGreen"].showWidget()
826 self["ButtonGreenText"].show()
828 def checkFormat(self, service):
829 info = service.info()
831 aspect = info.getInfo(iServiceInformation.sAspect)
832 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
833 self["FormatActive"].showWidget()
835 self["FormatActive"].hideWidget()
837 def checkSubservices(self, service):
838 if service.subServices().getNumberOfSubservices() > 0:
839 self.showSubServiceIndication()
841 self.hideSubServiceIndication()
843 def checkDolby(self, service):
845 audio = service.audioTracks()
846 if audio is not None:
847 n = audio.getNumberOfTracks()
849 i = audio.getTrackInfo(x)
850 description = i.getDescription();
851 if description.find("AC3") != -1 or description.find("DTS") != -1:
855 self["DolbyActive"].showWidget()
857 self["DolbyActive"].hideWidget()
859 def checkCrypted(self, service):
860 info = service.info()
862 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
863 self["CryptActive"].showWidget()
865 self["CryptActive"].hideWidget()
867 def gotServiceEvent(self, ev):
868 service = self.session.nav.getCurrentService()
869 if ev == pNavigation.evUpdatedEventInfo:
870 self.checkSubservices(service)
871 self.checkFormat(service)
872 elif ev == pNavigation.evUpdatedInfo:
873 self.checkCrypted(service)
874 self.checkDolby(service)
875 elif ev == pNavigation.evStopService:
876 self.hideSubServiceIndication()
877 self["CryptActive"].hideWidget()
878 self["DolbyActive"].hideWidget()
879 self["FormatActive"].hideWidget()
881 class InfoBarNotifications:
883 self.onExecBegin.append(self.checkNotifications)
884 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
886 def checkNotificationsIfExecing(self):
888 self.checkNotifications()
890 def checkNotifications(self):
891 if len(Notifications.notifications):
892 n = Notifications.notifications[0]
893 Notifications.notifications = Notifications.notifications[1:]
897 self.session.openWithCallback(cb, *n[1:])
899 self.session.open(*n[1:])