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
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 Components.Harddisk import harddiskmanager
26 from Tools import Notifications
28 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
35 from Menu import MainMenu, mdom
37 class InfoBarVolumeControl:
38 """Volume control, handles volUp, volDown, volMute actions and display
39 a corresponding dialog"""
41 config.audio = ConfigSubsection()
42 config.audio.volume = configElement("config.audio.volume", configSequence, [5], configsequencearg.get("INTEGER", (0, 100)))
44 self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
46 "volumeUp": self.volUp,
47 "volumeDown": self.volDown,
48 "volumeMute": self.volMute,
51 self.volumeDialog = self.session.instantiateDialog(Volume)
52 self.muteDialog = self.session.instantiateDialog(Mute)
54 self.hideVolTimer = eTimer()
55 self.hideVolTimer.timeout.get().append(self.volHide)
57 vol = config.audio.volume.value[0]
58 self.volumeDialog.setValue(vol)
59 eDVBVolumecontrol.getInstance().setVolume(vol, vol)
62 config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
63 config.audio.volume.save()
66 if (eDVBVolumecontrol.getInstance().isMuted()):
68 eDVBVolumecontrol.getInstance().volumeUp()
69 self.volumeDialog.instance.show()
70 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
72 self.hideVolTimer.start(3000, True)
75 if (eDVBVolumecontrol.getInstance().isMuted()):
77 eDVBVolumecontrol.getInstance().volumeDown()
78 self.volumeDialog.instance.show()
79 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
81 self.hideVolTimer.start(3000, True)
84 self.volumeDialog.instance.hide()
87 eDVBVolumecontrol.getInstance().volumeToggleMute()
88 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
90 if (eDVBVolumecontrol.getInstance().isMuted()):
91 self.muteDialog.instance.show()
93 self.muteDialog.instance.hide()
97 self.dishDialog = self.session.instantiateDialog(Dish)
98 self.onShown.append(self.dishDialog.instance.hide)
100 class InfoBarShowHide:
101 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
102 fancy animations. """
109 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
111 "toggleShow": self.toggleShow,
115 self.state = self.STATE_SHOWN
117 self.onExecBegin.append(self.show)
118 self.onClose.append(self.delHideTimer)
120 self.hideTimer = eTimer()
121 self.hideTimer.timeout.get().append(self.doTimerHide)
122 self.hideTimer.start(5000, True)
124 def delHideTimer(self):
131 self.state = self.STATE_SHOWN
132 self.hideTimer.start(5000, True)
134 def doTimerHide(self):
135 self.hideTimer.stop()
136 if self.state == self.STATE_SHOWN:
138 self.state = self.STATE_HIDDEN
140 def toggleShow(self):
141 if self.state == self.STATE_SHOWN:
143 #pls check animation support, sorry
145 self.hideTimer.stop()
146 self.state = self.STATE_HIDDEN
147 elif self.state == self.STATE_HIDDEN:
152 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
153 self.state = self.STATE_SHOWN
156 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
157 self.state = self.STATE_HIDDEN
159 class NumberZap(Screen):
166 self.close(int(self["number"].getText()))
168 def keyNumberGlobal(self, number):
169 self.Timer.start(3000, True) #reset timer
170 self.field = self.field + str(number)
171 self["number"].setText(self.field)
172 if len(self.field) >= 4:
175 def __init__(self, session, number):
176 Screen.__init__(self, session)
177 self.field = str(number)
179 self["channel"] = Label(_("Channel:"))
181 self["number"] = Label(self.field)
183 self["actions"] = NumberActionMap( [ "SetupActions" ],
187 "1": self.keyNumberGlobal,
188 "2": self.keyNumberGlobal,
189 "3": self.keyNumberGlobal,
190 "4": self.keyNumberGlobal,
191 "5": self.keyNumberGlobal,
192 "6": self.keyNumberGlobal,
193 "7": self.keyNumberGlobal,
194 "8": self.keyNumberGlobal,
195 "9": self.keyNumberGlobal,
196 "0": self.keyNumberGlobal
199 self.Timer = eTimer()
200 self.Timer.timeout.get().append(self.keyOK)
201 self.Timer.start(3000, True)
203 class InfoBarPowerKey:
204 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
207 self.powerKeyTimer = eTimer()
208 self.powerKeyTimer.timeout.get().append(self.powertimer)
209 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
211 "powerdown": self.powerdown,
212 "powerup": self.powerup,
213 "discreteStandby": (self.standby, "Go standby"),
214 "discretePowerOff": (self.quit, "Go to deep standby"),
217 def powertimer(self):
218 print "PowerOff - Now!"
222 self.standbyblocked = 0
223 self.powerKeyTimer.start(3000, True)
226 self.powerKeyTimer.stop()
227 if self.standbyblocked == 0:
228 self.standbyblocked = 1
232 self.session.open(Standby, self)
238 class InfoBarNumberZap:
239 """ Handles an initial number for NumberZapping """
241 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
243 "1": self.keyNumberGlobal,
244 "2": self.keyNumberGlobal,
245 "3": self.keyNumberGlobal,
246 "4": self.keyNumberGlobal,
247 "5": self.keyNumberGlobal,
248 "6": self.keyNumberGlobal,
249 "7": self.keyNumberGlobal,
250 "8": self.keyNumberGlobal,
251 "9": self.keyNumberGlobal,
252 "0": self.keyNumberGlobal,
255 def keyNumberGlobal(self, number):
256 # print "You pressed number " + str(number)
257 self.session.openWithCallback(self.numberEntered, NumberZap, number)
259 def numberEntered(self, retval):
260 # print self.servicelist
262 self.zapToNumber(retval)
264 def searchNumberHelper(self, serviceHandler, num, bouquet):
265 servicelist = serviceHandler.list(bouquet)
266 if not servicelist is None:
268 serviceIterator = servicelist.getNext()
269 if not serviceIterator.valid(): #check end of list
271 if serviceIterator.flags: #assume normal dvb service have no flags set
274 if not num: #found service with searched number ?
275 return serviceIterator, 0
278 def zapToNumber(self, number):
279 bouquet = self.servicelist.bouquet_root
281 serviceHandler = eServiceCenter.getInstance()
282 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
283 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
285 bouquetlist = serviceHandler.list(bouquet)
286 if not bouquetlist is None:
288 bouquet = bouquetlist.getNext()
289 if not bouquet.valid(): #check end of list
291 if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
293 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
294 if not service is None:
295 self.session.nav.playService(service) #play service
296 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
297 self.servicelist.setRoot(bouquet)
298 self.servicelist.setCurrentSelection(service) #select the service in servicelist
300 class InfoBarChannelSelection:
301 """ ChannelSelection - handles the channelSelection dialog and the initial
302 channelChange actions which open the channelSelection dialog """
305 self.servicelist = self.session.instantiateDialog(ChannelSelection)
307 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
309 "switchChannelUp": self.switchChannelUp,
310 "switchChannelDown": self.switchChannelDown,
311 "zapUp": (self.zapUp, _("next channel")),
312 "zapDown": (self.zapDown, _("previous channel")),
315 def switchChannelUp(self):
316 self.servicelist.moveUp()
317 self.session.execDialog(self.servicelist)
319 def switchChannelDown(self):
320 self.servicelist.moveDown()
321 self.session.execDialog(self.servicelist)
324 self.servicelist.moveUp()
325 self.servicelist.zap()
330 self.servicelist.moveDown()
331 self.servicelist.zap()
336 """ Handles a menu action, to open the (main) menu """
338 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
340 "mainMenu": (self.mainMenu, "Enter main menu..."),
344 print "loading mainmenu XML..."
345 menu = mdom.childNodes[0]
346 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
347 self.session.open(MainMenu, menu, menu.childNodes)
350 """ EPG - Opens an EPG list when the showEPGList action fires """
352 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
354 "showEPGList": (self.showEPGList, _("show EPG...")),
357 def showEPGList(self):
358 ref=self.session.nav.getCurrentlyPlayingServiceReference()
359 ptr=eEPGCache.getInstance()
360 if ptr.startTimeQuery(ref) != -1:
361 self.session.open(EPGSelection, ref)
362 else: # try to show now/next
363 print 'no epg for service', ref.toString()
366 service = self.session.nav.getCurrentService()
367 info = service.info()
370 self.epglist.append(ptr)
373 self.epglist.append(ptr)
374 if len(self.epglist) > 0:
375 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
379 def eventViewCallback(self, setEvent, val): #used for now/next displaying
380 if len(self.epglist) > 1:
381 tmp = self.epglist[0]
382 self.epglist[0]=self.epglist[1]
384 setEvent(self.epglist[0])
389 """provides a snr/agc/ber display"""
391 self["snr"] = Label()
392 self["agc"] = Label()
393 self["ber"] = Label()
394 self["snr_percent"] = Label()
395 self["agc_percent"] = Label()
396 self["ber_count"] = Label()
397 self["snr_progress"] = ProgressBar()
398 self["agc_progress"] = ProgressBar()
399 self["ber_progress"] = ProgressBar()
400 self.timer = eTimer()
401 self.timer.timeout.get().append(self.updateTunerInfo)
402 self.timer.start(1000)
408 return (long)(log(val)/log(2))
411 def updateTunerInfo(self):
412 if self.instance.isVisible():
413 service = self.session.nav.getCurrentService()
417 if service is not None:
418 feinfo = service.frontendStatusInfo()
419 if feinfo is not None:
420 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
421 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
422 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
423 self["snr_percent"].setText("%d%%"%(snr))
424 self["agc_percent"].setText("%d%%"%(agc))
425 self["ber_count"].setText("%d"%(ber))
426 self["snr_progress"].setValue(snr)
427 self["agc_progress"].setValue(agc)
428 self["ber_progress"].setValue(self.calc(ber))
431 """provides a current/next event info display"""
433 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
434 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
436 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
437 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
439 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
440 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
442 class InfoBarServiceName:
444 self["ServiceName"] = ServiceName(self.session.nav)
448 # ispause, isff, issm, skip
449 SEEK_STATE_PLAY = (0, 0, 0, 0)
450 SEEK_STATE_PAUSE = (1, 0, 0, 0)
451 SEEK_STATE_FF_2X = (0, 2, 0, 0)
452 SEEK_STATE_FF_4X = (0, 4, 0, 0)
453 SEEK_STATE_FF_8X = (0, 8, 0, 0)
454 SEEK_STATE_FF_32X = (0, 0, 0, 32)
455 SEEK_STATE_FF_64X = (0, 0, 0, 64)
457 SEEK_STATE_BACK_4X = (0, 0, 0, -4)
458 SEEK_STATE_BACK_32X = (0, 0, 0, -32)
459 SEEK_STATE_BACK_64X = (0, 0, 0, -64)
461 SEEK_STATE_SM_HALF = (0, 0, 2, 0)
462 SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
463 SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
465 """handles PVR specific actions like seeking, pause"""
467 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions",
469 "pauseService": (self.pauseService, "pause"),
470 "unPauseService": (self.unPauseService, "continue"),
472 "seekFwd": (self.seekFwd, "skip forward"),
473 "seekBack": (self.seekBack, "skip backward"),
476 self.seekstate = self.SEEK_STATE_PLAY
477 self.seekTimer = eTimer()
478 self.seekTimer.timeout.get().append(self.seekTimerFired)
479 self.skipinterval = 500 # 500ms skip interval
481 def seekTimerFired(self):
482 if self.skipmode > 0:
483 self.doSeek(+1, self.skipmode * self.skipinterval)
485 self.doSeek(-1, -self.skipmode * self.skipinterval)
487 def setSeekState(self, state):
488 oldstate = self.seekstate
490 self.seekstate = state
492 service = self.session.nav.getCurrentService()
496 pauseable = service.pause()
499 if oldstate[i] != self.seekstate[i]:
500 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
502 def setSkipMode(self, skipmode):
503 self.skipmode = skipmode
505 self.seekTimer.stop()
507 self.seekTimer.start(500)
509 def pauseService(self):
510 self.setSeekState(self.SEEK_STATE_PAUSE);
512 def unPauseService(self):
513 self.setSeekState(self.SEEK_STATE_PLAY);
515 def doSeek(self, dir, seektime):
516 service = self.session.nav.getCurrentService()
520 seekable = service.seek()
523 seekable.seekRelative(dir, 90 * seektime)
527 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
528 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
529 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
530 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
531 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
532 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
533 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_64X,
534 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
535 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
536 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
537 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
538 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
539 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
541 self.setSeekState(lookup[self.seekstate]);
545 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
546 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
547 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
548 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
549 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
550 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
551 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
552 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
553 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
554 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_64X,
555 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
556 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
557 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
559 self.setSeekState(lookup[self.seekstate]);
561 class InfoBarInstantRecord:
562 """Instant Record - handles the instantRecord action in order to
563 start/stop instant records"""
565 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
567 "instantRecord": (self.instantRecord, "Instant Record..."),
569 self.recording = None
571 self["BlinkingPoint"] = BlinkingPixmapConditional()
572 self.onShown.append(self["BlinkingPoint"].hideWidget)
573 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
575 def stopCurrentRecording(self):
576 self.session.nav.RecordTimer.removeEntry(self.recording)
577 self.recording = None
579 def startInstantRecording(self):
580 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
582 # try to get event info
585 service = self.session.nav.getCurrentService()
586 info = service.info()
587 ev = info.getEvent(0)
592 # fix me, description.
593 self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600, serviceref, epg, "instant record")
594 self.recording.dontSave = True
596 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
598 def isInstantRecordRunning(self):
599 if self.recording != None:
600 if self.recording.isRunning():
604 def recordQuestionCallback(self, answer):
608 if self.isInstantRecordRunning():
609 self.stopCurrentRecording()
611 self.startInstantRecording()
613 def instantRecord(self):
615 stat = os.stat("/hdd/movies")
617 self.session.open(MessageBox, "No HDD found!")
620 if self.isInstantRecordRunning():
621 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
623 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
625 from Screens.AudioSelection import AudioSelection
627 class InfoBarAudioSelection:
629 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
631 "audioSelection": (self.audioSelection, "Audio Options..."),
634 def audioSelection(self):
635 service = self.session.nav.getCurrentService()
636 audio = service.audioTracks()
637 n = audio.getNumberOfTracks()
639 self.session.open(AudioSelection, audio)
641 from Screens.SubserviceSelection import SubserviceSelection
643 class InfoBarSubserviceSelection:
645 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
647 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
650 def subserviceSelection(self):
651 service = self.session.nav.getCurrentService()
652 subservices = service.subServices()
653 n = subservices.getNumberOfSubservices()
655 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
657 def subserviceSelected(self, service):
658 if not service is None:
659 self.session.nav.playService(service)
661 class InfoBarAdditionalInfo:
663 self["DolbyActive"] = PixmapConditional()
664 # TODO: get the info from c++ somehow
665 self["DolbyActive"].setConnect(lambda: False)
667 self["CryptActive"] = PixmapConditional()
668 # TODO: get the info from c++ somehow
669 self["CryptActive"].setConnect(lambda: False)
671 self["FormatActive"] = PixmapConditional()
672 # TODO: get the info from c++ somehow
673 self["FormatActive"].setConnect(lambda: False)
675 self["ButtonRed"] = PixmapConditional(withTimer = False)
676 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
677 self.onShown.append(self["ButtonRed"].update)
678 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
679 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
680 self.onShown.append(self["ButtonRedText"].update)
682 self["ButtonGreen"] = PixmapConditional()
683 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
684 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
685 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
687 self["ButtonYellow"] = PixmapConditional()
688 self["ButtonYellow"].setConnect(lambda: False)
690 self["ButtonBlue"] = PixmapConditional()
691 self["ButtonBlue"].setConnect(lambda: False)
693 class InfoBarNotifications:
695 self.onExecBegin.append(self.checkNotifications)
696 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
698 def checkNotificationsIfExecing(self):
700 self.checkNotifications()
702 def checkNotifications(self):
703 if len(Notifications.notifications):
704 n = Notifications.notifications[0]
705 Notifications.notifications = Notifications.notifications[1:]
709 self.session.openWithCallback(cb, *n[1:])
711 self.session.open(*n[1:])