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 from RecordTimer import parseEvent
567 class InfoBarInstantRecord:
568 """Instant Record - handles the instantRecord action in order to
569 start/stop instant records"""
571 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
573 "instantRecord": (self.instantRecord, "Instant Record..."),
575 self.recording = None
577 self["BlinkingPoint"] = BlinkingPixmapConditional()
578 self.onShown.append(self["BlinkingPoint"].hideWidget)
579 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
581 def stopCurrentRecording(self):
582 self.session.nav.RecordTimer.removeEntry(self.recording)
583 self.recording = None
585 def startInstantRecording(self):
586 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
588 # try to get event info
591 service = self.session.nav.getCurrentService()
592 info = service.info()
593 ev = info.getEvent(0)
598 if event is not None:
599 data = parseEvent(event)
600 data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
602 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
604 # fix me, description.
605 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
606 self.recording.dontSave = True
608 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
610 def isInstantRecordRunning(self):
611 if self.recording != None:
612 if self.recording.isRunning():
616 def recordQuestionCallback(self, answer):
620 if self.isInstantRecordRunning():
621 self.stopCurrentRecording()
623 self.startInstantRecording()
625 def instantRecord(self):
627 stat = os.stat("/hdd/movies")
629 self.session.open(MessageBox, "No HDD found!")
632 if self.isInstantRecordRunning():
633 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
635 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
637 from Screens.AudioSelection import AudioSelection
639 class InfoBarAudioSelection:
641 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
643 "audioSelection": (self.audioSelection, "Audio Options..."),
646 def audioSelection(self):
647 service = self.session.nav.getCurrentService()
648 audio = service.audioTracks()
649 n = audio.getNumberOfTracks()
651 self.session.open(AudioSelection, audio)
653 from Screens.SubserviceSelection import SubserviceSelection
655 class InfoBarSubserviceSelection:
657 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
659 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
662 def subserviceSelection(self):
663 service = self.session.nav.getCurrentService()
664 subservices = service.subServices()
665 n = subservices.getNumberOfSubservices()
667 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
669 def subserviceSelected(self, service):
670 if not service is None:
671 self.session.nav.playService(service)
673 class InfoBarAdditionalInfo:
675 self["DolbyActive"] = PixmapConditional()
676 # TODO: get the info from c++ somehow
677 self["DolbyActive"].setConnect(lambda: False)
679 self["CryptActive"] = PixmapConditional()
680 # TODO: get the info from c++ somehow
681 self["CryptActive"].setConnect(lambda: False)
683 self["FormatActive"] = PixmapConditional()
684 # TODO: get the info from c++ somehow
685 self["FormatActive"].setConnect(lambda: False)
687 self["ButtonRed"] = PixmapConditional(withTimer = False)
688 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
689 self.onShown.append(self["ButtonRed"].update)
690 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
691 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
692 self.onShown.append(self["ButtonRedText"].update)
694 self["ButtonGreen"] = PixmapConditional()
695 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
696 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
697 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
699 self["ButtonYellow"] = PixmapConditional()
700 self["ButtonYellow"].setConnect(lambda: False)
702 self["ButtonBlue"] = PixmapConditional()
703 self["ButtonBlue"].setConnect(lambda: False)
705 class InfoBarNotifications:
707 self.onExecBegin.append(self.checkNotifications)
708 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
710 def checkNotificationsIfExecing(self):
712 self.checkNotifications()
714 def checkNotifications(self):
715 if len(Notifications.notifications):
716 n = Notifications.notifications[0]
717 Notifications.notifications = Notifications.notifications[1:]
721 self.session.openWithCallback(cb, *n[1:])
723 self.session.open(*n[1:])