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)
456 SEEK_STATE_FF_128X = (0, 0, 0, 128)
458 SEEK_STATE_BACK_4X = (0, 0, 0, -4)
459 SEEK_STATE_BACK_32X = (0, 0, 0, -32)
460 SEEK_STATE_BACK_64X = (0, 0, 0, -64)
461 SEEK_STATE_BACK_128X = (0, 0, 0, -128)
463 SEEK_STATE_SM_HALF = (0, 0, 2, 0)
464 SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
465 SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
467 """handles PVR specific actions like seeking, pause"""
469 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions",
471 "pauseService": (self.pauseService, "pause"),
472 "unPauseService": (self.unPauseService, "continue"),
474 "seekFwd": (self.seekFwd, "skip forward"),
475 "seekBack": (self.seekBack, "skip backward"),
478 self.seekstate = self.SEEK_STATE_PLAY
479 self.seekTimer = eTimer()
480 self.seekTimer.timeout.get().append(self.seekTimerFired)
481 self.skipinterval = 500 # 500ms skip interval
482 self.onClose.append(self.delSeekTimer)
484 def delSeekTimer(self):
487 def seekTimerFired(self):
488 self.seekbase += self.skipmode * self.skipinterval
490 # check if we bounced against the beginning of the file
491 if self.seekbase < 0:
493 self.setSeekState(self.SEEK_STATE_PLAY)
495 self.doSeek(self.seekbase)
497 def setSeekState(self, state):
498 oldstate = self.seekstate
500 self.seekstate = state
502 service = self.session.nav.getCurrentService()
506 pauseable = service.pause()
509 if oldstate[i] != self.seekstate[i]:
510 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
512 def setSkipMode(self, skipmode):
513 self.skipmode = skipmode
515 self.seekTimer.stop()
517 self.seekTimer.start(500)
519 service = self.session.nav.getCurrentService()
523 seekable = service.seek()
528 seekable.setTrickmode(1)
530 seekable.setTrickmode(0)
532 self.seekbase = seekable.getPlayPosition()[1] / 90
534 def pauseService(self):
535 self.setSeekState(self.SEEK_STATE_PAUSE);
537 def unPauseService(self):
538 self.setSeekState(self.SEEK_STATE_PLAY);
540 def doSeek(self, seektime):
541 service = self.session.nav.getCurrentService()
545 seekable = service.seek()
548 seekable.seekTo(90 * seektime)
552 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
553 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
554 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
555 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
556 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
557 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
558 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
559 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
560 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
561 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
562 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
563 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
564 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
565 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
566 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
568 self.setSeekState(lookup[self.seekstate]);
572 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
573 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
574 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
575 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
576 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
577 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
578 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
579 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
580 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
581 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
582 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
583 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
584 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
585 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
586 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
588 self.setSeekState(lookup[self.seekstate]);
590 from RecordTimer import parseEvent
592 class InfoBarInstantRecord:
593 """Instant Record - handles the instantRecord action in order to
594 start/stop instant records"""
596 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
598 "instantRecord": (self.instantRecord, "Instant Record..."),
600 self.recording = None
602 self["BlinkingPoint"] = BlinkingPixmapConditional()
603 self.onShown.append(self["BlinkingPoint"].hideWidget)
604 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
606 def stopCurrentRecording(self):
607 self.session.nav.RecordTimer.removeEntry(self.recording)
608 self.recording = None
610 def startInstantRecording(self):
611 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
613 # try to get event info
616 service = self.session.nav.getCurrentService()
617 info = service.info()
618 ev = info.getEvent(0)
623 if event is not None:
624 data = parseEvent(event)
625 data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
627 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
629 # fix me, description.
630 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
631 self.recording.dontSave = True
633 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
635 def isInstantRecordRunning(self):
636 if self.recording != None:
637 if self.recording.isRunning():
641 def recordQuestionCallback(self, answer):
645 if self.isInstantRecordRunning():
646 self.stopCurrentRecording()
648 self.startInstantRecording()
650 def instantRecord(self):
652 stat = os.stat("/hdd/movies")
654 self.session.open(MessageBox, "No HDD found!")
657 if self.isInstantRecordRunning():
658 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
660 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
662 from Screens.AudioSelection import AudioSelection
664 class InfoBarAudioSelection:
666 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
668 "audioSelection": (self.audioSelection, "Audio Options..."),
671 def audioSelection(self):
672 service = self.session.nav.getCurrentService()
673 audio = service.audioTracks()
674 n = audio.getNumberOfTracks()
676 self.session.open(AudioSelection, audio)
678 from Screens.SubserviceSelection import SubserviceSelection
680 class InfoBarSubserviceSelection:
682 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
684 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
687 def subserviceSelection(self):
688 service = self.session.nav.getCurrentService()
689 subservices = service.subServices()
690 n = subservices.getNumberOfSubservices()
692 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
694 def subserviceSelected(self, service):
695 if not service is None:
696 self.session.nav.playService(service)
698 class InfoBarAdditionalInfo:
700 self["DolbyActive"] = PixmapConditional()
701 # TODO: get the info from c++ somehow
702 self["DolbyActive"].setConnect(lambda: False)
704 self["CryptActive"] = PixmapConditional()
705 # TODO: get the info from c++ somehow
706 self["CryptActive"].setConnect(lambda: False)
708 self["FormatActive"] = PixmapConditional()
709 # TODO: get the info from c++ somehow
710 self["FormatActive"].setConnect(lambda: False)
712 self["ButtonRed"] = PixmapConditional(withTimer = False)
713 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
714 self.onShown.append(self["ButtonRed"].update)
715 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
716 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
717 self.onShown.append(self["ButtonRedText"].update)
719 self["ButtonGreen"] = PixmapConditional()
720 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
721 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
722 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
724 self["ButtonYellow"] = PixmapConditional()
725 self["ButtonYellow"].setConnect(lambda: False)
727 self["ButtonBlue"] = PixmapConditional()
728 self["ButtonBlue"].setConnect(lambda: False)
730 class InfoBarNotifications:
732 self.onExecBegin.append(self.checkNotifications)
733 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
735 def checkNotificationsIfExecing(self):
737 self.checkNotifications()
739 def checkNotifications(self):
740 if len(Notifications.notifications):
741 n = Notifications.notifications[0]
742 Notifications.notifications = Notifications.notifications[1:]
746 self.session.openWithCallback(cb, *n[1:])
748 self.session.open(*n[1:])