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)
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)
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)
124 def delHideTimer(self):
131 self.state = self.STATE_SHOWN
132 self.hideTimer.stop()
133 self.hideTimer.start(5000)
135 def doTimerHide(self):
136 self.hideTimer.stop()
137 if self.state == self.STATE_SHOWN:
139 self.state = self.STATE_HIDDEN
141 def toggleShow(self):
142 if self.state == self.STATE_SHOWN:
144 #pls check animation support, sorry
146 self.hideTimer.stop()
147 self.state = self.STATE_HIDDEN
148 elif self.state == self.STATE_HIDDEN:
153 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
154 self.state = self.STATE_SHOWN
157 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
158 self.state = self.STATE_HIDDEN
160 class NumberZap(Screen):
167 self.close(int(self["number"].getText()))
169 def keyNumberGlobal(self, number):
170 self.Timer.start(3000) #reset timer
171 self.field = self.field + str(number)
172 self["number"].setText(self.field)
173 if len(self.field) >= 4:
176 def __init__(self, session, number):
177 Screen.__init__(self, session)
178 self.field = str(number)
180 self["channel"] = Label(_("Channel:"))
182 self["number"] = Label(self.field)
184 self["actions"] = NumberActionMap( [ "SetupActions" ],
188 "1": self.keyNumberGlobal,
189 "2": self.keyNumberGlobal,
190 "3": self.keyNumberGlobal,
191 "4": self.keyNumberGlobal,
192 "5": self.keyNumberGlobal,
193 "6": self.keyNumberGlobal,
194 "7": self.keyNumberGlobal,
195 "8": self.keyNumberGlobal,
196 "9": self.keyNumberGlobal,
197 "0": self.keyNumberGlobal
200 self.Timer = eTimer()
201 self.Timer.timeout.get().append(self.keyOK)
202 self.Timer.start(3000)
204 class InfoBarPowerKey:
205 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
208 self.powerKeyTimer = eTimer()
209 self.powerKeyTimer.timeout.get().append(self.powertimer)
210 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
212 "powerdown": self.powerdown,
213 "powerup": self.powerup,
214 "discreteStandby": (self.standby, "Go standby"),
215 "discretePowerOff": (self.quit, "Go to deep standby"),
218 def powertimer(self):
219 print "PowerOff - Now!"
223 self.standbyblocked = 0
224 self.powerKeyTimer.start(3000)
227 self.powerKeyTimer.stop()
228 if self.standbyblocked == 0:
229 self.standbyblocked = 1
233 self.session.open(Standby, self)
239 class InfoBarNumberZap:
240 """ Handles an initial number for NumberZapping """
242 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
244 "1": self.keyNumberGlobal,
245 "2": self.keyNumberGlobal,
246 "3": self.keyNumberGlobal,
247 "4": self.keyNumberGlobal,
248 "5": self.keyNumberGlobal,
249 "6": self.keyNumberGlobal,
250 "7": self.keyNumberGlobal,
251 "8": self.keyNumberGlobal,
252 "9": self.keyNumberGlobal,
253 "0": self.keyNumberGlobal,
256 def keyNumberGlobal(self, number):
257 # print "You pressed number " + str(number)
258 self.session.openWithCallback(self.numberEntered, NumberZap, number)
260 def numberEntered(self, retval):
261 # print self.servicelist
263 self.zapToNumber(retval)
265 def searchNumberHelper(self, serviceHandler, num, bouquet):
266 servicelist = serviceHandler.list(bouquet)
267 if not servicelist is None:
269 serviceIterator = servicelist.getNext()
270 if not serviceIterator.valid(): #check end of list
272 if serviceIterator.flags: #assume normal dvb service have no flags set
275 if not num: #found service with searched number ?
276 return serviceIterator, 0
279 def zapToNumber(self, number):
280 bouquet = self.servicelist.bouquet_root
282 serviceHandler = eServiceCenter.getInstance()
283 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
284 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
286 bouquetlist = serviceHandler.list(bouquet)
287 if not bouquetlist is None:
289 bouquet = bouquetlist.getNext()
290 if not bouquet.valid(): #check end of list
292 if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
294 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
295 if not service is None:
296 self.session.nav.playService(service) #play service
297 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
298 self.servicelist.setRoot(bouquet)
299 self.servicelist.setCurrentSelection(service) #select the service in servicelist
301 class InfoBarChannelSelection:
302 """ ChannelSelection - handles the channelSelection dialog and the initial
303 channelChange actions which open the channelSelection dialog """
306 self.servicelist = self.session.instantiateDialog(ChannelSelection)
308 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
310 "switchChannelUp": self.switchChannelUp,
311 "switchChannelDown": self.switchChannelDown,
312 "zapUp": (self.zapUp, _("next channel")),
313 "zapDown": (self.zapDown, _("previous channel")),
316 def switchChannelUp(self):
317 self.servicelist.moveUp()
318 self.session.execDialog(self.servicelist)
320 def switchChannelDown(self):
321 self.servicelist.moveDown()
322 self.session.execDialog(self.servicelist)
325 self.servicelist.moveUp()
326 self.servicelist.zap()
331 self.servicelist.moveDown()
332 self.servicelist.zap()
337 """ Handles a menu action, to open the (main) menu """
339 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
341 "mainMenu": (self.mainMenu, "Enter main menu..."),
345 print "loading mainmenu XML..."
346 menu = mdom.childNodes[0]
347 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
348 self.session.open(MainMenu, menu, menu.childNodes)
351 """ EPG - Opens an EPG list when the showEPGList action fires """
353 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
355 "showEPGList": (self.showEPGList, _("show EPG...")),
358 def showEPGList(self):
359 ref=self.session.nav.getCurrentlyPlayingServiceReference()
360 ptr=eEPGCache.getInstance()
361 if ptr.startTimeQuery(ref) != -1:
362 self.session.open(EPGSelection, ref)
363 else: # try to show now/next
364 print 'no epg for service', ref.toString()
367 service = self.session.nav.getCurrentService()
368 info = service.info()
371 self.epglist.append(ptr)
374 self.epglist.append(ptr)
375 if len(self.epglist) > 0:
376 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
380 def eventViewCallback(self, setEvent, val): #used for now/next displaying
381 if len(self.epglist) > 1:
382 tmp = self.epglist[0]
383 self.epglist[0]=self.epglist[1]
385 setEvent(self.epglist[0])
390 """provides a snr/agc/ber display"""
392 self["snr"] = Label()
393 self["agc"] = Label()
394 self["ber"] = Label()
395 self["snr_percent"] = Label()
396 self["agc_percent"] = Label()
397 self["ber_count"] = Label()
398 self["snr_progress"] = ProgressBar()
399 self["agc_progress"] = ProgressBar()
400 self["ber_progress"] = ProgressBar()
401 self.timer = eTimer()
402 self.timer.timeout.get().append(self.updateTunerInfo)
403 self.timer.start(500)
409 return (long)(log(val)/log(2))
412 def updateTunerInfo(self):
413 if self.instance.isVisible():
414 service = self.session.nav.getCurrentService()
418 if service is not None:
419 feinfo = service.frontendStatusInfo()
420 if feinfo is not None:
421 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
422 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
423 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
424 self["snr_percent"].setText("%d%%"%(snr))
425 self["agc_percent"].setText("%d%%"%(agc))
426 self["ber_count"].setText("%d"%(ber))
427 self["snr_progress"].setValue(snr)
428 self["agc_progress"].setValue(agc)
429 self["ber_progress"].setValue(self.calc(ber))
432 """provides a current/next event info display"""
434 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
435 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
437 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
438 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
440 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
441 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
443 class InfoBarServiceName:
445 self["ServiceName"] = ServiceName(self.session.nav)
449 # ispause, isff, issm, skip
450 SEEK_STATE_PLAY = (0, 0, 0, 0)
451 SEEK_STATE_PAUSE = (1, 0, 0, 0)
452 SEEK_STATE_FF_2X = (0, 2, 0, 0)
453 SEEK_STATE_FF_4X = (0, 4, 0, 0)
454 SEEK_STATE_FF_8X = (0, 8, 0, 0)
455 SEEK_STATE_FF_32X = (0, 0, 0, 32)
456 SEEK_STATE_FF_64X = (0, 0, 0, 64)
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)
462 """handles PVR specific actions like seeking, pause"""
464 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions",
466 "pauseService": (self.pauseService, "pause"),
467 "unPauseService": (self.unPauseService, "continue"),
469 "seekFwd": (self.seekFwd, "skip forward"),
470 "seekBack": (self.seekBack, "skip backward"),
473 self.seekstate = self.SEEK_STATE_PLAY
474 self.seekTimer = eTimer()
475 self.seekTimer.timeout.get().append(self.seekTimerFired)
476 self.skipinterval = 500 # 500ms skip interval
478 def seekTimerFired(self):
479 print "skip", self.skipmode
480 if self.skipmode > 0:
481 self.doSeek(+1, self.skipmode * self.skipinterval)
483 self.doSeek(-1, -self.skipmode * self.skipinterval)
485 def setSeekState(self, state):
486 oldstate = self.seekstate
488 self.seekstate = state
490 service = self.session.nav.getCurrentService()
494 pauseable = service.pause()
495 print "newstate: ", self.seekstate
498 if oldstate[i] != self.seekstate[i]:
499 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
501 def setSkipMode(self, skipmode):
502 self.skipmode = skipmode
504 self.seekTimer.stop()
506 self.seekTimer.start(500)
508 def pauseService(self):
509 self.setSeekState(self.SEEK_STATE_PAUSE);
511 def unPauseService(self):
512 self.setSeekState(self.SEEK_STATE_PLAY);
514 def doSeek(self, dir, seektime):
515 service = self.session.nav.getCurrentService()
519 seekable = service.seek()
522 seekable.seekRelative(dir, 90 * seektime)
526 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
527 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PLAY,
528 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
529 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
530 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
531 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
532 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_64X,
533 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
534 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
535 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X
537 self.setSeekState(lookup[self.seekstate]);
541 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
542 self.SEEK_STATE_PAUSE: self.SEEK_STATE_BACK_4X,
543 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
544 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
545 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
546 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
547 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
548 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
549 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
550 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_64X
552 self.setSeekState(lookup[self.seekstate]);
554 class InfoBarInstantRecord:
555 """Instant Record - handles the instantRecord action in order to
556 start/stop instant records"""
558 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
560 "instantRecord": (self.instantRecord, "Instant Record..."),
562 self.recording = None
564 self["BlinkingPoint"] = BlinkingPixmapConditional()
565 self.onShown.append(self["BlinkingPoint"].hideWidget)
566 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
568 def stopCurrentRecording(self):
569 self.session.nav.RecordTimer.removeEntry(self.recording)
570 self.recording = None
572 def startInstantRecording(self):
573 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
575 # try to get event info
578 service = self.session.nav.getCurrentService()
579 info = service.info()
580 ev = info.getEvent(0)
585 # fix me, description.
586 self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600, serviceref, epg, "instant record")
587 self.recording.dontSave = True
589 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
591 def isInstantRecordRunning(self):
592 if self.recording != None:
593 if self.recording.isRunning():
597 def recordQuestionCallback(self, answer):
601 if self.isInstantRecordRunning():
602 self.stopCurrentRecording()
604 self.startInstantRecording()
606 def instantRecord(self):
608 stat = os.stat("/hdd/movies")
610 self.session.open(MessageBox, "No HDD found!")
613 if self.isInstantRecordRunning():
614 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
616 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
618 from Screens.AudioSelection import AudioSelection
620 class InfoBarAudioSelection:
622 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
624 "audioSelection": (self.audioSelection, "Audio Options..."),
627 def audioSelection(self):
628 service = self.session.nav.getCurrentService()
629 audio = service.audioTracks()
630 n = audio.getNumberOfTracks()
632 self.session.open(AudioSelection, audio)
634 from Screens.SubserviceSelection import SubserviceSelection
636 class InfoBarSubserviceSelection:
638 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
640 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
643 def subserviceSelection(self):
644 service = self.session.nav.getCurrentService()
645 subservices = service.subServices()
646 n = subservices.getNumberOfSubservices()
648 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
650 def subserviceSelected(self, service):
651 if not service is None:
652 self.session.nav.playService(service)
654 class InfoBarAdditionalInfo:
656 self["DolbyActive"] = PixmapConditional()
657 # TODO: get the info from c++ somehow
658 self["DolbyActive"].setConnect(lambda: False)
660 self["CryptActive"] = PixmapConditional()
661 # TODO: get the info from c++ somehow
662 self["CryptActive"].setConnect(lambda: False)
664 self["FormatActive"] = PixmapConditional()
665 # TODO: get the info from c++ somehow
666 self["FormatActive"].setConnect(lambda: False)
668 self["ButtonRed"] = PixmapConditional(withTimer = False)
669 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
670 self.onShown.append(self["ButtonRed"].update)
671 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
672 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
673 self.onShown.append(self["ButtonRedText"].update)
675 self["ButtonGreen"] = PixmapConditional()
676 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
677 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
678 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
680 self["ButtonYellow"] = PixmapConditional()
681 self["ButtonYellow"].setConnect(lambda: False)
683 self["ButtonBlue"] = PixmapConditional()
684 self["ButtonBlue"].setConnect(lambda: False)
686 class InfoBarNotifications:
688 self.onExecBegin.append(self.checkNotifications)
689 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
691 def checkNotificationsIfExecing(self):
693 self.checkNotifications()
695 def checkNotifications(self):
696 if len(Notifications.notifications):
697 n = Notifications.notifications[0]
698 Notifications.notifications = Notifications.notifications[1:]
702 self.session.openWithCallback(cb, *n[1:])
704 self.session.open(*n[1:])