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, BouquetSelector
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, EventInfoProgress
15 from ServiceReference import ServiceReference
16 from EpgSelection import EPGSelection
18 from Screens.MessageBox import MessageBox
19 from Screens.Dish import Dish
20 from Screens.Standby import Standby
21 from Screens.EventView import EventViewEPGSelect
22 from Screens.MinuteInput import MinuteInput
23 from Components.Harddisk import harddiskmanager
25 from Components.ServiceEventTracker import ServiceEventTracker
27 from Tools import Notifications
28 from Tools.Directories import *
30 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
36 from Components.config import config, currentConfigSelectionElement
39 from Menu import MainMenu, mdom
43 self.dishDialog = self.session.instantiateDialog(Dish)
44 self.onShown.append(self.dishDialog.show)
46 class InfoBarShowHide:
47 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
55 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
57 "toggleShow": self.toggleShow,
61 self.__state = self.STATE_SHOWN
64 self.onExecBegin.append(self.show)
66 self.hideTimer = eTimer()
67 self.hideTimer.timeout.get().append(self.doTimerHide)
68 self.hideTimer.start(5000, True)
70 self.onShow.append(self.__onShow)
71 self.onHide.append(self.__onHide)
74 self.__state = self.STATE_SHOWN
77 def startHideTimer(self):
78 if self.__state == self.STATE_SHOWN and not self.__locked:
79 self.hideTimer.start(5000, True)
82 self.__state = self.STATE_HIDDEN
84 def doTimerHide(self):
86 if self.__state == self.STATE_SHOWN:
90 if self.__state == self.STATE_SHOWN:
93 elif self.__state == self.STATE_HIDDEN:
97 self.__locked = self.__locked + 1
100 self.hideTimer.stop()
102 def unlockShow(self):
103 self.__locked = self.__locked - 1
105 self.startHideTimer()
107 # def startShow(self):
108 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
109 # self.__state = self.STATE_SHOWN
111 # def startHide(self):
112 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
113 # self.__state = self.STATE_HIDDEN
115 class NumberZap(Screen):
122 self.close(int(self["number"].getText()))
124 def keyNumberGlobal(self, number):
125 self.Timer.start(3000, True) #reset timer
126 self.field = self.field + str(number)
127 self["number"].setText(self.field)
128 if len(self.field) >= 4:
131 def __init__(self, session, number):
132 Screen.__init__(self, session)
133 self.field = str(number)
135 self["channel"] = Label(_("Channel:"))
137 self["number"] = Label(self.field)
139 self["actions"] = NumberActionMap( [ "SetupActions" ],
143 "1": self.keyNumberGlobal,
144 "2": self.keyNumberGlobal,
145 "3": self.keyNumberGlobal,
146 "4": self.keyNumberGlobal,
147 "5": self.keyNumberGlobal,
148 "6": self.keyNumberGlobal,
149 "7": self.keyNumberGlobal,
150 "8": self.keyNumberGlobal,
151 "9": self.keyNumberGlobal,
152 "0": self.keyNumberGlobal
155 self.Timer = eTimer()
156 self.Timer.timeout.get().append(self.keyOK)
157 self.Timer.start(3000, True)
159 class InfoBarPowerKey:
160 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
163 self.powerKeyTimer = eTimer()
164 self.powerKeyTimer.timeout.get().append(self.powertimer)
165 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
167 "powerdown": self.powerdown,
168 "powerup": self.powerup,
169 "discreteStandby": (self.standby, "Go standby"),
170 "discretePowerOff": (self.quit, "Go to deep standby"),
173 def powertimer(self):
174 print "PowerOff - Now!"
178 self.standbyblocked = 0
179 self.powerKeyTimer.start(3000, True)
182 self.powerKeyTimer.stop()
183 if self.standbyblocked == 0:
184 self.standbyblocked = 1
188 self.session.open(Standby, self)
194 class InfoBarNumberZap:
195 """ Handles an initial number for NumberZapping """
197 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
199 "1": self.keyNumberGlobal,
200 "2": self.keyNumberGlobal,
201 "3": self.keyNumberGlobal,
202 "4": self.keyNumberGlobal,
203 "5": self.keyNumberGlobal,
204 "6": self.keyNumberGlobal,
205 "7": self.keyNumberGlobal,
206 "8": self.keyNumberGlobal,
207 "9": self.keyNumberGlobal,
208 "0": self.keyNumberGlobal,
211 def keyNumberGlobal(self, number):
212 # print "You pressed number " + str(number)
214 self.servicelist.recallPrevService()
217 self.session.openWithCallback(self.numberEntered, NumberZap, number)
219 def numberEntered(self, retval):
220 # print self.servicelist
222 self.zapToNumber(retval)
224 def searchNumberHelper(self, serviceHandler, num, bouquet):
225 servicelist = serviceHandler.list(bouquet)
226 if not servicelist is None:
228 serviceIterator = servicelist.getNext()
229 if not serviceIterator.valid(): #check end of list
231 if serviceIterator.flags: #assume normal dvb service have no flags set
234 if not num: #found service with searched number ?
235 return serviceIterator, 0
238 def zapToNumber(self, number):
239 bouquet = self.servicelist.bouquet_root
241 serviceHandler = eServiceCenter.getInstance()
242 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
243 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
245 bouquetlist = serviceHandler.list(bouquet)
246 if not bouquetlist is None:
248 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
249 if not bouquet.valid(): #check end of list
251 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
253 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
254 if not service is None:
255 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
256 self.servicelist.clearPath()
257 if self.servicelist.bouquet_root != bouquet:
258 self.servicelist.enterPath(self.servicelist.bouquet_root)
259 self.servicelist.enterPath(bouquet)
260 self.servicelist.setCurrentSelection(service) #select the service in servicelist
261 self.servicelist.zap()
263 class InfoBarChannelSelection:
264 """ ChannelSelection - handles the channelSelection dialog and the initial
265 channelChange actions which open the channelSelection dialog """
268 self.servicelist = self.session.instantiateDialog(ChannelSelection)
270 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
272 "switchChannelUp": self.switchChannelUp,
273 "switchChannelDown": self.switchChannelDown,
274 "zapUp": (self.zapUp, _("next channel")),
275 "zapDown": (self.zapDown, _("previous channel")),
278 def switchChannelUp(self):
279 self.servicelist.moveUp()
280 self.session.execDialog(self.servicelist)
282 def switchChannelDown(self):
283 self.servicelist.moveDown()
284 self.session.execDialog(self.servicelist)
287 self.servicelist.moveUp()
288 self.servicelist.zap()
292 self.servicelist.moveDown()
293 self.servicelist.zap()
297 """ Handles a menu action, to open the (main) menu """
299 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
301 "mainMenu": (self.mainMenu, "Enter main menu..."),
305 print "loading mainmenu XML..."
306 menu = mdom.childNodes[0]
307 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
308 self.session.open(MainMenu, menu, menu.childNodes)
311 """ EPG - Opens an EPG list when the showEPGList action fires """
313 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
315 "showEventInfo": (self.openEventView, _("show EPG...")),
318 def zapToService(self, service):
319 if not service is None:
320 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
321 self.servicelist.clearPath()
322 if self.servicelist.bouquet_root != self.epg_bouquet:
323 self.servicelist.enterPath(self.servicelist.bouquet_root)
324 self.servicelist.enterPath(self.epg_bouquet)
325 self.servicelist.setCurrentSelection(service) #select the service in servicelist
326 self.servicelist.zap()
328 def openBouquetEPG(self, bouquet):
329 ptr=eEPGCache.getInstance()
331 servicelist = eServiceCenter.getInstance().list(bouquet)
332 if not servicelist is None:
334 service = servicelist.getNext()
335 if not service.valid(): #check if end of list
337 if service.flags: #ignore non playable services
339 services.append(ServiceReference(service))
341 self.epg_bouquet = bouquet
342 self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
344 def closed(self, ret):
348 def openMultiServiceEPG(self):
349 bouquets = self.servicelist.getBouquetList()
354 if cnt > 1: # show bouquet list
355 self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
357 self.openBouquetEPG(bouquets[0][1])
359 def openSingleServiceEPG(self):
360 ref=self.session.nav.getCurrentlyPlayingServiceReference()
361 ptr=eEPGCache.getInstance()
362 self.session.openWithCallback(self.closed, EPGSelection, ref)
364 def openEventView(self):
366 service = self.session.nav.getCurrentService()
367 ref = self.session.nav.getCurrentlyPlayingServiceReference()
368 info = service.info()
371 self.epglist.append(ptr)
374 self.epglist.append(ptr)
375 if len(self.epglist) == 0:
376 epg = eEPGCache.getInstance()
377 ptr = epg.lookupEventTime(ref, -1)
379 self.epglist.append(ptr)
380 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
382 self.epglist.append(ptr)
383 if len(self.epglist) > 0:
384 self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
386 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
387 self.openMultiServiceEPG()
389 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
390 if len(self.epglist) > 1:
391 tmp = self.epglist[0]
392 self.epglist[0]=self.epglist[1]
394 setEvent(self.epglist[0])
399 """provides a snr/agc/ber display"""
401 self["snr"] = Label()
402 self["agc"] = Label()
403 self["ber"] = Label()
404 self["snr_percent"] = Label()
405 self["agc_percent"] = Label()
406 self["ber_count"] = Label()
407 self["snr_progress"] = ProgressBar()
408 self["agc_progress"] = ProgressBar()
409 self["ber_progress"] = ProgressBar()
410 self.timer = eTimer()
411 self.timer.timeout.get().append(self.updateTunerInfo)
412 self.timer.start(1000)
418 return (long)(log(val)/log(2))
421 def updateTunerInfo(self):
422 if self.instance.isVisible():
423 service = self.session.nav.getCurrentService()
427 if service is not None:
428 feinfo = service.frontendStatusInfo()
429 if feinfo is not None:
430 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
431 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
432 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
433 self["snr_percent"].setText("%d%%"%(snr))
434 self["agc_percent"].setText("%d%%"%(agc))
435 self["ber_count"].setText("%d"%(ber))
436 self["snr_progress"].setValue(snr)
437 self["agc_progress"].setValue(agc)
438 self["ber_progress"].setValue(self.calc(ber))
441 """provides a current/next event info display"""
443 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
444 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
446 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
447 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
449 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
450 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
452 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
454 class InfoBarServiceName:
456 self["ServiceName"] = ServiceName(self.session.nav)
459 """handles actions like seeking, pause"""
461 # ispause, isff, issm
462 SEEK_STATE_PLAY = (0, 0, 0, ">")
463 SEEK_STATE_PAUSE = (1, 0, 0, "||")
464 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
465 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
466 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
467 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
468 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
469 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
471 SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
472 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
473 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
474 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
476 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
477 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
478 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
481 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
483 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
484 iPlayableService.evStart: self.__serviceStarted,
486 iPlayableService.evEOF: self.__evEOF,
487 iPlayableService.evSOF: self.__evSOF,
489 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
491 "pauseService": (self.pauseService, "pause"),
492 "unPauseService": (self.unPauseService, "continue"),
494 "seekFwd": (self.seekFwd, "skip forward"),
495 "seekFwdUp": (self.seekFwdUp, "skip forward"),
496 "seekBack": (self.seekBack, "skip backward"),
497 "seekBackUp": (self.seekBackUp, "skip backward"),
499 # give them a little more priority to win over color buttons
501 self.seekstate = self.SEEK_STATE_PLAY
502 self.onClose.append(self.delTimer)
504 self.fwdtimer = False
505 self.fwdKeyTimer = eTimer()
506 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
508 self.rwdtimer = False
509 self.rwdKeyTimer = eTimer()
510 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
512 self.onPlayStateChanged = [ ]
514 self.lockedBecauseOfSkipping = False
526 def isSeekable(self):
527 service = self.session.nav.getCurrentService()
530 if service.seek() is None:
535 def __seekableStatusChanged(self):
536 print "seekable status changed!"
537 if not self.isSeekable():
538 self["SeekActions"].setEnabled(False)
539 print "not seekable, return to play"
540 self.setSeekState(self.SEEK_STATE_PLAY)
542 self["SeekActions"].setEnabled(True)
545 def __serviceStarted(self):
546 self.seekstate = self.SEEK_STATE_PLAY
548 def setSeekState(self, state):
549 service = self.session.nav.getCurrentService()
554 if service.seek() is None:
555 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
556 state = self.SEEK_STATE_PLAY
558 pauseable = service.pause()
560 if pauseable is None:
561 print "not pauseable."
562 state = self.SEEK_STATE_PLAY
564 oldstate = self.seekstate
565 self.seekstate = state
568 if oldstate[i] != self.seekstate[i]:
569 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
571 for c in self.onPlayStateChanged:
574 self.checkSkipShowHideLock()
578 def pauseService(self):
579 if self.seekstate == self.SEEK_STATE_PAUSE:
580 print "pause, but in fact unpause"
581 self.unPauseService()
583 if self.seekstate == self.SEEK_STATE_PLAY:
584 print "yes, playing."
586 print "no", self.seekstate
588 self.setSeekState(self.SEEK_STATE_PAUSE);
590 def unPauseService(self):
592 self.setSeekState(self.SEEK_STATE_PLAY);
594 def doSeek(self, seektime):
595 print "doseek", seektime
596 service = self.session.nav.getCurrentService()
600 seekable = service.seek()
603 seekable.seekTo(90 * seektime)
606 print "start fwd timer"
608 self.fwdKeyTimer.start(500)
611 print "start rewind timer"
613 self.rwdKeyTimer.start(500)
618 self.fwdKeyTimer.stop()
619 self.fwdtimer = False
621 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
622 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
623 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
624 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
625 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
626 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
627 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
628 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
629 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
630 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
631 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
632 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
633 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
634 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
635 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
637 self.setSeekState(lookup[self.seekstate]);
639 def seekBackUp(self):
642 self.rwdKeyTimer.stop()
643 self.rwdtimer = False
646 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
647 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
648 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
649 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
650 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
651 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
652 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
653 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
654 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
655 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
656 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
657 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
658 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
659 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
660 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
662 self.setSeekState(lookup[self.seekstate]);
664 def fwdTimerFire(self):
665 print "Display seek fwd"
666 self.fwdKeyTimer.stop()
667 self.fwdtimer = False
668 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
670 def fwdSeekTo(self, minutes):
671 print "Seek", minutes, "minutes forward"
673 service = self.session.nav.getCurrentService()
676 seekable = service.seek()
679 seekable.seekRelative(1, minutes * 60 * 90000)
681 def rwdTimerFire(self):
683 self.rwdKeyTimer.stop()
684 self.rwdtimer = False
685 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
687 def rwdSeekTo(self, minutes):
689 self.fwdSeekTo(0 - minutes)
691 def checkSkipShowHideLock(self):
692 wantlock = self.seekstate != self.SEEK_STATE_PLAY
694 if self.lockedBecauseOfSkipping and not wantlock:
696 self.lockedBecauseOfSkipping = False
698 if wantlock and not self.lockedBecauseOfSkipping:
700 self.lockedBecauseOfSkipping = True
703 self.setSeekState(self.SEEK_STATE_PAUSE)
706 self.setSeekState(self.SEEK_STATE_PLAY)
708 from Screens.PVRState import PVRState
710 class InfoBarPVRState:
712 self.onPlayStateChanged.append(self.__playStateChanged)
713 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
714 self.onShow.append(self.__mayShow)
715 self.onHide.append(self.pvrStateDialog.hide)
718 if self.seekstate != self.SEEK_STATE_PLAY:
719 self.pvrStateDialog.show()
721 def __playStateChanged(self, state):
722 playstateString = state[3]
723 self.pvrStateDialog["state"].setText(playstateString)
726 class InfoBarShowMovies:
728 # i don't really like this class.
729 # it calls a not further specified "movie list" on up/down/movieList,
730 # so this is not more than an action map
732 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
734 "movieList": (self.showMovies, "movie list"),
735 "up": (self.showMovies, "movie list"),
736 "down": (self.showMovies, "movie list")
739 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
743 # Timeshift works the following way:
744 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
745 # - normal playback TUNER unused PLAY enable disable disable
746 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
747 # - user presess pause again FILE record PLAY enable disable enable
748 # - user fast forwards FILE record FF enable disable enable
749 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
750 # - user backwards FILE record BACK # !! enable disable enable
754 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
755 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
756 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
757 # - the user can now PVR around
758 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
759 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
761 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
762 # - if the user rewinds, or press pause, timeshift will be activated again
764 # note that a timeshift can be enabled ("recording") and
765 # activated (currently time-shifting).
767 class InfoBarTimeshift:
769 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
771 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
772 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
774 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
776 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
777 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
780 self.timeshift_enabled = 0
781 self.timeshift_state = 0
782 self.ts_pause_timer = eTimer()
783 self.ts_pause_timer.timeout.get().append(self.pauseService)
785 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
787 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
790 def getTimeshift(self):
791 service = self.session.nav.getCurrentService()
792 return service.timeshift()
794 def startTimeshift(self):
795 # TODO: check for harddisk! (or do this in the interface? would make
796 # more sense... for example radio could be timeshifted in memory,
797 # and the decision can't be made here)
798 print "enable timeshift"
799 ts = self.getTimeshift()
801 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
802 print "no ts interface"
805 if self.timeshift_enabled:
806 print "hu, timeshift already enabled?"
808 if not ts.startTimeshift():
809 self.timeshift_enabled = 1
812 self.setSeekState(self.SEEK_STATE_PAUSE)
814 # enable the "TimeshiftEnableActions", which will override
815 # the startTimeshift actions
816 self.__seekableStatusChanged()
818 print "timeshift failed"
821 def stopTimeshift(self):
822 print "disable timeshift"
823 ts = self.getTimeshift()
827 self.timeshift_enabled = 0
830 self.__seekableStatusChanged()
832 # activates timeshift, and seeks to (almost) the end
833 def activateTimeshiftEnd(self):
834 ts = self.getTimeshift()
839 if ts.isTimeshiftActive():
840 print "!! activate timeshift called - but shouldn't this be a normal pause?"
843 self.setSeekState(self.SEEK_STATE_PLAY)
844 ts.activateTimeshift()
846 # same as activateTimeshiftEnd, but pauses afterwards.
847 def activateTimeshiftEndAndPause(self):
848 state = self.seekstate
849 self.activateTimeshiftEnd()
851 # well, this is "andPause", but it could be pressed from pause,
852 # when pausing on the (fake-)"live" picture, so an un-pause
855 print "now, pauseService"
856 if state == self.SEEK_STATE_PLAY:
857 print "is PLAYING, start pause timer"
858 self.ts_pause_timer.start(200, 1)
861 self.unPauseService()
863 def __seekableStatusChanged(self):
866 print "self.isSeekable", self.isSeekable()
867 print "self.timeshift_enabled", self.timeshift_enabled
869 # when this service is not seekable, but timeshift
870 # is enabled, this means we can activate
872 if not self.isSeekable() and self.timeshift_enabled:
875 print "timeshift activate:", enabled
876 self["TimeshiftActivateActions"].setEnabled(enabled)
878 from RecordTimer import parseEvent
880 class InfoBarInstantRecord:
881 """Instant Record - handles the instantRecord action in order to
882 start/stop instant records"""
884 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
886 "instantRecord": (self.instantRecord, "Instant Record..."),
888 self.recording = None
890 self["BlinkingPoint"] = BlinkingPixmapConditional()
891 self.onShown.append(self["BlinkingPoint"].hideWidget)
892 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
894 def stopCurrentRecording(self):
895 self.session.nav.RecordTimer.removeEntry(self.recording)
896 self.recording = None
898 def startInstantRecording(self):
899 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
901 # try to get event info
904 service = self.session.nav.getCurrentService()
905 info = service.info()
906 ev = info.getEvent(0)
911 if event is not None:
912 data = parseEvent(event)
914 if begin < time.time():
923 data = (begin, end, data[2], data[3], data[4])
925 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
927 # fix me, description.
928 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
929 self.recording.dontSave = True
931 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
933 def isInstantRecordRunning(self):
934 if self.recording != None:
935 if self.recording.isRunning():
939 def recordQuestionCallback(self, answer):
943 if self.isInstantRecordRunning():
944 self.stopCurrentRecording()
946 self.startInstantRecording()
948 def instantRecord(self):
950 stat = os.stat(resolveFilename(SCOPE_HDD))
952 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
955 if self.isInstantRecordRunning():
956 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
958 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
960 from Screens.AudioSelection import AudioSelection
962 class InfoBarAudioSelection:
964 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
966 "audioSelection": (self.audioSelection, "Audio Options..."),
969 def audioSelection(self):
970 service = self.session.nav.getCurrentService()
971 audio = service.audioTracks()
972 n = audio.getNumberOfTracks()
974 self.session.open(AudioSelection, audio)
976 from Screens.SubserviceSelection import SubserviceSelection
978 class InfoBarSubserviceSelection:
980 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
982 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
985 def subserviceSelection(self):
986 service = self.session.nav.getCurrentService()
987 subservices = service.subServices()
988 n = subservices.getNumberOfSubservices()
990 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
992 def subserviceSelected(self, service):
993 if not service is None:
994 self.session.nav.playService(service)
996 class InfoBarAdditionalInfo:
998 self["DolbyActive"] = Pixmap()
999 self["CryptActive"] = Pixmap()
1000 self["FormatActive"] = Pixmap()
1002 self["ButtonRed"] = PixmapConditional(withTimer = False)
1003 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1004 self.onShown.append(self["ButtonRed"].update)
1005 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1006 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1007 self.onShown.append(self["ButtonRedText"].update)
1009 self["ButtonGreen"] = Pixmap()
1010 self["ButtonGreenText"] = Label(_("Subservices"))
1012 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1013 self["ButtonYellow"].setConnect(lambda: False)
1015 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1016 self["ButtonBlue"].setConnect(lambda: False)
1018 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1020 def hideSubServiceIndication(self):
1021 self["ButtonGreen"].hideWidget()
1022 self["ButtonGreenText"].hide()
1024 def showSubServiceIndication(self):
1025 self["ButtonGreen"].showWidget()
1026 self["ButtonGreenText"].show()
1028 def checkFormat(self, service):
1029 info = service.info()
1030 if info is not None:
1031 aspect = info.getInfo(iServiceInformation.sAspect)
1032 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1033 self["FormatActive"].showWidget()
1035 self["FormatActive"].hideWidget()
1037 def checkSubservices(self, service):
1038 if service.subServices().getNumberOfSubservices() > 0:
1039 self.showSubServiceIndication()
1041 self.hideSubServiceIndication()
1043 def checkDolby(self, service):
1046 audio = service.audioTracks()
1047 if audio is not None:
1048 n = audio.getNumberOfTracks()
1050 i = audio.getTrackInfo(x)
1051 description = i.getDescription();
1052 if description.find("AC3") != -1 or description.find("DTS") != -1:
1056 self["DolbyActive"].showWidget()
1058 self["DolbyActive"].hideWidget()
1060 def checkCrypted(self, service):
1061 info = service.info()
1062 if info is not None:
1063 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1064 self["CryptActive"].showWidget()
1066 self["CryptActive"].hideWidget()
1068 def gotServiceEvent(self, ev):
1069 service = self.session.nav.getCurrentService()
1070 if ev == iPlayableService.evUpdatedEventInfo:
1071 self.checkSubservices(service)
1072 self.checkFormat(service)
1073 elif ev == iPlayableService.evUpdatedInfo:
1074 self.checkCrypted(service)
1075 self.checkDolby(service)
1076 elif ev == iPlayableService.evEnd:
1077 self.hideSubServiceIndication()
1078 self["CryptActive"].hideWidget()
1079 self["DolbyActive"].hideWidget()
1080 self["FormatActive"].hideWidget()
1082 class InfoBarNotifications:
1084 self.onExecBegin.append(self.checkNotifications)
1085 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1087 def checkNotificationsIfExecing(self):
1089 self.checkNotifications()
1091 def checkNotifications(self):
1092 if len(Notifications.notifications):
1093 n = Notifications.notifications[0]
1094 Notifications.notifications = Notifications.notifications[1:]
1098 self.session.openWithCallback(cb, *n[1:])
1100 self.session.open(*n[1:])
1102 class InfoBarServiceNotifications:
1104 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1106 iPlayableService.evEnd: self.serviceHasEnded
1109 def serviceHasEnded(self):
1110 print "service end!"
1113 self.setSeekState(self.SEEK_STATE_PLAY)