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, [100], 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
480 self.onClose.append(self.delSeekTimer)
482 def delSeekTimer(self):
485 def seekTimerFired(self):
486 if self.skipmode > 0:
487 self.doSeek(+1, self.skipmode * self.skipinterval)
489 self.doSeek(-1, -self.skipmode * self.skipinterval)
491 def setSeekState(self, state):
492 oldstate = self.seekstate
494 self.seekstate = state
496 service = self.session.nav.getCurrentService()
500 pauseable = service.pause()
503 if oldstate[i] != self.seekstate[i]:
504 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
506 def setSkipMode(self, skipmode):
507 self.skipmode = skipmode
509 self.seekTimer.stop()
511 self.seekTimer.start(500)
513 def pauseService(self):
514 self.setSeekState(self.SEEK_STATE_PAUSE);
516 def unPauseService(self):
517 self.setSeekState(self.SEEK_STATE_PLAY);
519 def doSeek(self, dir, seektime):
520 service = self.session.nav.getCurrentService()
524 seekable = service.seek()
527 seekable.seekRelative(dir, 90 * seektime)
531 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
532 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
533 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
534 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
535 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
536 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
537 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_64X,
538 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
539 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
540 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
541 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
542 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
543 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
545 self.setSeekState(lookup[self.seekstate]);
549 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
550 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
551 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
552 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
553 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
554 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
555 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
556 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
557 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
558 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_64X,
559 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
560 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
561 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
563 self.setSeekState(lookup[self.seekstate]);
565 class InfoBarInstantRecord:
566 """Instant Record - handles the instantRecord action in order to
567 start/stop instant records"""
569 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
571 "instantRecord": (self.instantRecord, "Instant Record..."),
573 self.recording = None
575 self["BlinkingPoint"] = BlinkingPixmapConditional()
576 self.onShown.append(self["BlinkingPoint"].hideWidget)
577 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
579 def stopCurrentRecording(self):
580 self.session.nav.RecordTimer.removeEntry(self.recording)
581 self.recording = None
583 def startInstantRecording(self):
584 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
586 # try to get event info
589 service = self.session.nav.getCurrentService()
590 info = service.info()
591 ev = info.getEvent(0)
596 # fix me, description.
597 self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600 * 10, serviceref, epg, "instant record")
598 self.recording.dontSave = True
600 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
602 def isInstantRecordRunning(self):
603 if self.recording != None:
604 if self.recording.isRunning():
608 def recordQuestionCallback(self, answer):
612 if self.isInstantRecordRunning():
613 self.stopCurrentRecording()
615 self.startInstantRecording()
617 def instantRecord(self):
619 stat = os.stat("/hdd/movies")
621 self.session.open(MessageBox, "No HDD found!")
624 if self.isInstantRecordRunning():
625 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
627 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
629 from Screens.AudioSelection import AudioSelection
631 class InfoBarAudioSelection:
633 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
635 "audioSelection": (self.audioSelection, "Audio Options..."),
638 def audioSelection(self):
639 service = self.session.nav.getCurrentService()
640 audio = service.audioTracks()
641 n = audio.getNumberOfTracks()
643 self.session.open(AudioSelection, audio)
645 from Screens.SubserviceSelection import SubserviceSelection
647 class InfoBarSubserviceSelection:
649 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
651 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
654 def subserviceSelection(self):
655 service = self.session.nav.getCurrentService()
656 subservices = service.subServices()
657 n = subservices.getNumberOfSubservices()
659 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
661 def subserviceSelected(self, service):
662 if not service is None:
663 self.session.nav.playService(service)
665 class InfoBarAdditionalInfo:
667 self["DolbyActive"] = PixmapConditional()
668 # TODO: get the info from c++ somehow
669 self["DolbyActive"].setConnect(lambda: False)
671 self["CryptActive"] = PixmapConditional()
672 # TODO: get the info from c++ somehow
673 self["CryptActive"].setConnect(lambda: False)
675 self["FormatActive"] = PixmapConditional()
676 # TODO: get the info from c++ somehow
677 self["FormatActive"].setConnect(lambda: False)
679 self["ButtonRed"] = PixmapConditional(withTimer = False)
680 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
681 self.onShown.append(self["ButtonRed"].update)
682 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
683 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
684 self.onShown.append(self["ButtonRedText"].update)
686 self["ButtonGreen"] = PixmapConditional()
687 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
688 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
689 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
691 self["ButtonYellow"] = PixmapConditional()
692 self["ButtonYellow"].setConnect(lambda: False)
694 self["ButtonBlue"] = PixmapConditional()
695 self["ButtonBlue"].setConnect(lambda: False)
697 class InfoBarNotifications:
699 self.onExecBegin.append(self.checkNotifications)
700 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
702 def checkNotificationsIfExecing(self):
704 self.checkNotifications()
706 def checkNotifications(self):
707 if len(Notifications.notifications):
708 n = Notifications.notifications[0]
709 Notifications.notifications = Notifications.notifications[1:]
713 self.session.openWithCallback(cb, *n[1:])
715 self.session.open(*n[1:])