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 def unlockShow(self):
101 self.__locked = self.__locked - 1
102 self.startHideTimer()
104 # def startShow(self):
105 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
106 # self.__state = self.STATE_SHOWN
108 # def startHide(self):
109 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
110 # self.__state = self.STATE_HIDDEN
112 class NumberZap(Screen):
119 self.close(int(self["number"].getText()))
121 def keyNumberGlobal(self, number):
122 self.Timer.start(3000, True) #reset timer
123 self.field = self.field + str(number)
124 self["number"].setText(self.field)
125 if len(self.field) >= 4:
128 def __init__(self, session, number):
129 Screen.__init__(self, session)
130 self.field = str(number)
132 self["channel"] = Label(_("Channel:"))
134 self["number"] = Label(self.field)
136 self["actions"] = NumberActionMap( [ "SetupActions" ],
140 "1": self.keyNumberGlobal,
141 "2": self.keyNumberGlobal,
142 "3": self.keyNumberGlobal,
143 "4": self.keyNumberGlobal,
144 "5": self.keyNumberGlobal,
145 "6": self.keyNumberGlobal,
146 "7": self.keyNumberGlobal,
147 "8": self.keyNumberGlobal,
148 "9": self.keyNumberGlobal,
149 "0": self.keyNumberGlobal
152 self.Timer = eTimer()
153 self.Timer.timeout.get().append(self.keyOK)
154 self.Timer.start(3000, True)
156 class InfoBarPowerKey:
157 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
160 self.powerKeyTimer = eTimer()
161 self.powerKeyTimer.timeout.get().append(self.powertimer)
162 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
164 "powerdown": self.powerdown,
165 "powerup": self.powerup,
166 "discreteStandby": (self.standby, "Go standby"),
167 "discretePowerOff": (self.quit, "Go to deep standby"),
170 def powertimer(self):
171 print "PowerOff - Now!"
175 self.standbyblocked = 0
176 self.powerKeyTimer.start(3000, True)
179 self.powerKeyTimer.stop()
180 if self.standbyblocked == 0:
181 self.standbyblocked = 1
185 self.session.open(Standby, self)
191 class InfoBarNumberZap:
192 """ Handles an initial number for NumberZapping """
194 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
196 "1": self.keyNumberGlobal,
197 "2": self.keyNumberGlobal,
198 "3": self.keyNumberGlobal,
199 "4": self.keyNumberGlobal,
200 "5": self.keyNumberGlobal,
201 "6": self.keyNumberGlobal,
202 "7": self.keyNumberGlobal,
203 "8": self.keyNumberGlobal,
204 "9": self.keyNumberGlobal,
205 "0": self.keyNumberGlobal,
208 def keyNumberGlobal(self, number):
209 # print "You pressed number " + str(number)
211 self.servicelist.recallPrevService()
214 self.session.openWithCallback(self.numberEntered, NumberZap, number)
216 def numberEntered(self, retval):
217 # print self.servicelist
219 self.zapToNumber(retval)
221 def searchNumberHelper(self, serviceHandler, num, bouquet):
222 servicelist = serviceHandler.list(bouquet)
223 if not servicelist is None:
225 serviceIterator = servicelist.getNext()
226 if not serviceIterator.valid(): #check end of list
228 if serviceIterator.flags: #assume normal dvb service have no flags set
231 if not num: #found service with searched number ?
232 return serviceIterator, 0
235 def zapToNumber(self, number):
236 bouquet = self.servicelist.bouquet_root
238 serviceHandler = eServiceCenter.getInstance()
239 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
240 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
242 bouquetlist = serviceHandler.list(bouquet)
243 if not bouquetlist is None:
245 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
246 if not bouquet.valid(): #check end of list
248 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
250 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
251 if not service is None:
252 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
253 self.servicelist.clearPath()
254 if self.servicelist.bouquet_root != bouquet:
255 self.servicelist.enterPath(self.servicelist.bouquet_root)
256 self.servicelist.enterPath(bouquet)
257 self.servicelist.setCurrentSelection(service) #select the service in servicelist
258 self.servicelist.zap()
260 class InfoBarChannelSelection:
261 """ ChannelSelection - handles the channelSelection dialog and the initial
262 channelChange actions which open the channelSelection dialog """
265 self.servicelist = self.session.instantiateDialog(ChannelSelection)
267 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
269 "switchChannelUp": self.switchChannelUp,
270 "switchChannelDown": self.switchChannelDown,
271 "zapUp": (self.zapUp, _("next channel")),
272 "zapDown": (self.zapDown, _("previous channel")),
275 def switchChannelUp(self):
276 self.servicelist.moveUp()
277 self.session.execDialog(self.servicelist)
279 def switchChannelDown(self):
280 self.servicelist.moveDown()
281 self.session.execDialog(self.servicelist)
284 self.servicelist.moveUp()
285 self.servicelist.zap()
289 self.servicelist.moveDown()
290 self.servicelist.zap()
294 """ Handles a menu action, to open the (main) menu """
296 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
298 "mainMenu": (self.mainMenu, "Enter main menu..."),
302 print "loading mainmenu XML..."
303 menu = mdom.childNodes[0]
304 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
305 self.session.open(MainMenu, menu, menu.childNodes)
308 """ EPG - Opens an EPG list when the showEPGList action fires """
310 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
312 "showEventInfo": (self.openEventView, _("show EPG...")),
315 def zapToService(self, service):
316 if not service is None:
317 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
318 self.servicelist.clearPath()
319 if self.servicelist.bouquet_root != self.epg_bouquet:
320 self.servicelist.enterPath(self.servicelist.bouquet_root)
321 self.servicelist.enterPath(self.epg_bouquet)
322 self.servicelist.setCurrentSelection(service) #select the service in servicelist
323 self.servicelist.zap()
325 def openBouquetEPG(self, bouquet):
326 ptr=eEPGCache.getInstance()
328 servicelist = eServiceCenter.getInstance().list(bouquet)
329 if not servicelist is None:
331 service = servicelist.getNext()
332 if not service.valid(): #check if end of list
334 if service.flags: #ignore non playable services
336 services.append(ServiceReference(service))
338 self.epg_bouquet = bouquet
339 self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
341 def closed(self, ret):
345 def openMultiServiceEPG(self):
346 bouquets = self.servicelist.getBouquetList()
351 if cnt > 1: # show bouquet list
352 self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
354 self.openBouquetEPG(bouquets[0][1])
356 def openSingleServiceEPG(self):
357 ref=self.session.nav.getCurrentlyPlayingServiceReference()
358 ptr=eEPGCache.getInstance()
359 self.session.openWithCallback(self.closed, EPGSelection, ref)
361 def openEventView(self):
363 service = self.session.nav.getCurrentService()
364 ref = self.session.nav.getCurrentlyPlayingServiceReference()
365 info = service.info()
368 self.epglist.append(ptr)
371 self.epglist.append(ptr)
372 if len(self.epglist) == 0:
373 epg = eEPGCache.getInstance()
374 ptr = epg.lookupEventTime(ref, -1)
376 self.epglist.append(ptr)
377 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
379 self.epglist.append(ptr)
380 if len(self.epglist) > 0:
381 self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
383 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
384 self.openMultiServiceEPG()
386 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
387 if len(self.epglist) > 1:
388 tmp = self.epglist[0]
389 self.epglist[0]=self.epglist[1]
391 setEvent(self.epglist[0])
396 """provides a snr/agc/ber display"""
398 self["snr"] = Label()
399 self["agc"] = Label()
400 self["ber"] = Label()
401 self["snr_percent"] = Label()
402 self["agc_percent"] = Label()
403 self["ber_count"] = Label()
404 self["snr_progress"] = ProgressBar()
405 self["agc_progress"] = ProgressBar()
406 self["ber_progress"] = ProgressBar()
407 self.timer = eTimer()
408 self.timer.timeout.get().append(self.updateTunerInfo)
409 self.timer.start(1000)
415 return (long)(log(val)/log(2))
418 def updateTunerInfo(self):
419 if self.instance.isVisible():
420 service = self.session.nav.getCurrentService()
424 if service is not None:
425 feinfo = service.frontendStatusInfo()
426 if feinfo is not None:
427 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
428 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
429 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
430 self["snr_percent"].setText("%d%%"%(snr))
431 self["agc_percent"].setText("%d%%"%(agc))
432 self["ber_count"].setText("%d"%(ber))
433 self["snr_progress"].setValue(snr)
434 self["agc_progress"].setValue(agc)
435 self["ber_progress"].setValue(self.calc(ber))
438 """provides a current/next event info display"""
440 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
441 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
443 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
444 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
446 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
447 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
449 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
451 class InfoBarServiceName:
453 self["ServiceName"] = ServiceName(self.session.nav)
456 """handles actions like seeking, pause"""
458 # ispause, isff, issm
459 SEEK_STATE_PLAY = (0, 0, 0, "")
460 SEEK_STATE_PAUSE = (1, 0, 0, "||")
461 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
462 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
463 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
464 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
465 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
466 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
468 SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
469 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
470 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
471 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
473 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
474 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
475 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
478 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
480 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
481 iPlayableService.evStart: self.__serviceStarted,
483 iPlayableService.evEOF: self.__evEOF,
484 iPlayableService.evSOF: self.__evSOF,
486 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
488 "pauseService": (self.pauseService, "pause"),
489 "unPauseService": (self.unPauseService, "continue"),
491 "seekFwd": (self.seekFwd, "skip forward"),
492 "seekFwdUp": (self.seekFwdUp, "skip forward"),
493 "seekBack": (self.seekBack, "skip backward"),
494 "seekBackUp": (self.seekBackUp, "skip backward"),
496 # give them a little more priority to win over color buttons
498 self.seekstate = self.SEEK_STATE_PLAY
499 self.onClose.append(self.delTimer)
501 self.fwdtimer = False
502 self.fwdKeyTimer = eTimer()
503 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
505 self.rwdtimer = False
506 self.rwdKeyTimer = eTimer()
507 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
509 self.onPlayStateChanged = [ ]
511 self.lockedBecauseOfSkipping = False
523 def isSeekable(self):
524 service = self.session.nav.getCurrentService()
527 if service.seek() is None:
532 def __seekableStatusChanged(self):
533 print "seekable status changed!"
534 if not self.isSeekable():
535 self["SeekActions"].setEnabled(False)
536 print "not seekable, return to play"
537 self.setSeekState(self.SEEK_STATE_PLAY)
539 self["SeekActions"].setEnabled(True)
542 def __serviceStarted(self):
543 self.seekstate = self.SEEK_STATE_PLAY
545 def setSeekState(self, state):
546 service = self.session.nav.getCurrentService()
551 if service.seek() is None:
552 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
553 state = self.SEEK_STATE_PLAY
555 pauseable = service.pause()
557 if pauseable is None:
558 print "not pauseable."
559 state = self.SEEK_STATE_PLAY
561 oldstate = self.seekstate
562 self.seekstate = state
565 if oldstate[i] != self.seekstate[i]:
566 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
568 for c in self.onPlayStateChanged:
571 self.checkSkipShowHideLock()
575 def pauseService(self):
576 if self.seekstate == self.SEEK_STATE_PAUSE:
577 print "pause, but in fact unpause"
578 self.unPauseService()
580 if self.seekstate == self.SEEK_STATE_PLAY:
581 print "yes, playing."
583 print "no", self.seekstate
585 self.setSeekState(self.SEEK_STATE_PAUSE);
587 def unPauseService(self):
589 self.setSeekState(self.SEEK_STATE_PLAY);
591 def doSeek(self, seektime):
592 print "doseek", seektime
593 service = self.session.nav.getCurrentService()
597 seekable = service.seek()
600 seekable.seekTo(90 * seektime)
603 print "start fwd timer"
605 self.fwdKeyTimer.start(500)
608 print "start rewind timer"
610 self.rwdKeyTimer.start(500)
615 self.fwdKeyTimer.stop()
616 self.fwdtimer = False
618 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
619 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
620 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
621 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
622 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
623 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
624 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
625 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
626 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
627 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
628 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
629 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
630 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
631 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
632 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
634 self.setSeekState(lookup[self.seekstate]);
636 def seekBackUp(self):
639 self.rwdKeyTimer.stop()
640 self.rwdtimer = False
643 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
644 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
645 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
646 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
647 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
648 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
649 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
650 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
651 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
652 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
653 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
654 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
655 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
656 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
657 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
659 self.setSeekState(lookup[self.seekstate]);
661 def fwdTimerFire(self):
662 print "Display seek fwd"
663 self.fwdKeyTimer.stop()
664 self.fwdtimer = False
665 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
667 def fwdSeekTo(self, minutes):
668 print "Seek", minutes, "minutes forward"
670 service = self.session.nav.getCurrentService()
673 seekable = service.seek()
676 seekable.seekRelative(1, minutes * 60 * 90000)
678 def rwdTimerFire(self):
680 self.rwdKeyTimer.stop()
681 self.rwdtimer = False
682 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
684 def rwdSeekTo(self, minutes):
686 self.fwdSeekTo(0 - minutes)
688 def checkSkipShowHideLock(self):
689 wantlock = self.seekstate != self.SEEK_STATE_PLAY
691 if self.lockedBecauseOfSkipping and not wantlock:
693 self.lockedBecauseOfSkipping = False
695 if wantlock and not self.lockedBecauseOfSkipping:
697 self.lockedBecauseOfSkipping = True
700 self.setSeekState(self.SEEK_STATE_PAUSE)
703 self.setSeekState(self.SEEK_STATE_PLAY)
705 from Screens.PVRState import PVRState
707 class InfoBarPVRState:
709 self.onPlayStateChanged.append(self.__playStateChanged)
710 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
711 self.onShow.append(self.pvrStateDialog.show)
712 self.onHide.append(self.pvrStateDialog.hide)
714 def __playStateChanged(self, state):
715 playstateString = state[3]
716 self.pvrStateDialog["state"].setText(playstateString)
718 class InfoBarShowMovies:
720 # i don't really like this class.
721 # it calls a not further specified "movie list" on up/down/movieList,
722 # so this is not more than an action map
724 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
726 "movieList": (self.showMovies, "movie list"),
727 "up": (self.showMovies, "movie list"),
728 "down": (self.showMovies, "movie list")
731 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
735 # Timeshift works the following way:
736 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
737 # - normal playback TUNER unused PLAY enable disable disable
738 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
739 # - user presess pause again FILE record PLAY enable disable enable
740 # - user fast forwards FILE record FF enable disable enable
741 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
742 # - user backwards FILE record BACK # !! enable disable enable
746 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
747 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
748 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
749 # - the user can now PVR around
750 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
751 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
753 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
754 # - if the user rewinds, or press pause, timeshift will be activated again
756 # note that a timeshift can be enabled ("recording") and
757 # activated (currently time-shifting).
759 class InfoBarTimeshift:
761 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
763 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
764 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
766 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
768 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
769 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
772 self.timeshift_enabled = 0
773 self.timeshift_state = 0
774 self.ts_pause_timer = eTimer()
775 self.ts_pause_timer.timeout.get().append(self.pauseService)
777 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
779 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
782 def getTimeshift(self):
783 service = self.session.nav.getCurrentService()
784 return service.timeshift()
786 def startTimeshift(self):
787 # TODO: check for harddisk! (or do this in the interface? would make
788 # more sense... for example radio could be timeshifted in memory,
789 # and the decision can't be made here)
790 print "enable timeshift"
791 ts = self.getTimeshift()
793 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
794 print "no ts interface"
797 if self.timeshift_enabled:
798 print "hu, timeshift already enabled?"
800 if not ts.startTimeshift():
801 self.timeshift_enabled = 1
804 self.setSeekState(self.SEEK_STATE_PAUSE)
806 # enable the "TimeshiftEnableActions", which will override
807 # the startTimeshift actions
808 self.__seekableStatusChanged()
810 print "timeshift failed"
813 def stopTimeshift(self):
814 print "disable timeshift"
815 ts = self.getTimeshift()
819 self.timeshift_enabled = 0
822 self.__seekableStatusChanged()
824 # activates timeshift, and seeks to (almost) the end
825 def activateTimeshiftEnd(self):
826 ts = self.getTimeshift()
831 if ts.isTimeshiftActive():
832 print "!! activate timeshift called - but shouldn't this be a normal pause?"
835 self.setSeekState(self.SEEK_STATE_PLAY)
836 ts.activateTimeshift()
838 # same as activateTimeshiftEnd, but pauses afterwards.
839 def activateTimeshiftEndAndPause(self):
840 state = self.seekstate
841 self.activateTimeshiftEnd()
843 # well, this is "andPause", but it could be pressed from pause,
844 # when pausing on the (fake-)"live" picture, so an un-pause
847 print "now, pauseService"
848 if state == self.SEEK_STATE_PLAY:
849 print "is PLAYING, start pause timer"
850 self.ts_pause_timer.start(200, 1)
853 self.unPauseService()
855 def __seekableStatusChanged(self):
858 print "self.isSeekable", self.isSeekable()
859 print "self.timeshift_enabled", self.timeshift_enabled
861 # when this service is not seekable, but timeshift
862 # is enabled, this means we can activate
864 if not self.isSeekable() and self.timeshift_enabled:
867 print "timeshift activate:", enabled
868 self["TimeshiftActivateActions"].setEnabled(enabled)
870 from RecordTimer import parseEvent
872 class InfoBarInstantRecord:
873 """Instant Record - handles the instantRecord action in order to
874 start/stop instant records"""
876 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
878 "instantRecord": (self.instantRecord, "Instant Record..."),
880 self.recording = None
882 self["BlinkingPoint"] = BlinkingPixmapConditional()
883 self.onShown.append(self["BlinkingPoint"].hideWidget)
884 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
886 def stopCurrentRecording(self):
887 self.session.nav.RecordTimer.removeEntry(self.recording)
888 self.recording = None
890 def startInstantRecording(self):
891 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
893 # try to get event info
896 service = self.session.nav.getCurrentService()
897 info = service.info()
898 ev = info.getEvent(0)
903 if event is not None:
904 data = parseEvent(event)
906 if begin < time.time():
915 data = (begin, end, data[2], data[3], data[4])
917 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
919 # fix me, description.
920 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
921 self.recording.dontSave = True
923 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
925 def isInstantRecordRunning(self):
926 if self.recording != None:
927 if self.recording.isRunning():
931 def recordQuestionCallback(self, answer):
935 if self.isInstantRecordRunning():
936 self.stopCurrentRecording()
938 self.startInstantRecording()
940 def instantRecord(self):
942 stat = os.stat(resolveFilename(SCOPE_HDD))
944 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
947 if self.isInstantRecordRunning():
948 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
950 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
952 from Screens.AudioSelection import AudioSelection
954 class InfoBarAudioSelection:
956 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
958 "audioSelection": (self.audioSelection, "Audio Options..."),
961 def audioSelection(self):
962 service = self.session.nav.getCurrentService()
963 audio = service.audioTracks()
964 n = audio.getNumberOfTracks()
966 self.session.open(AudioSelection, audio)
968 from Screens.SubserviceSelection import SubserviceSelection
970 class InfoBarSubserviceSelection:
972 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
974 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
977 def subserviceSelection(self):
978 service = self.session.nav.getCurrentService()
979 subservices = service.subServices()
980 n = subservices.getNumberOfSubservices()
982 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
984 def subserviceSelected(self, service):
985 if not service is None:
986 self.session.nav.playService(service)
988 class InfoBarAdditionalInfo:
990 self["DolbyActive"] = Pixmap()
991 self["CryptActive"] = Pixmap()
992 self["FormatActive"] = Pixmap()
994 self["ButtonRed"] = PixmapConditional(withTimer = False)
995 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
996 self.onShown.append(self["ButtonRed"].update)
997 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
998 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
999 self.onShown.append(self["ButtonRedText"].update)
1001 self["ButtonGreen"] = Pixmap()
1002 self["ButtonGreenText"] = Label(_("Subservices"))
1004 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1005 self["ButtonYellow"].setConnect(lambda: False)
1007 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1008 self["ButtonBlue"].setConnect(lambda: False)
1010 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1012 def hideSubServiceIndication(self):
1013 self["ButtonGreen"].hideWidget()
1014 self["ButtonGreenText"].hide()
1016 def showSubServiceIndication(self):
1017 self["ButtonGreen"].showWidget()
1018 self["ButtonGreenText"].show()
1020 def checkFormat(self, service):
1021 info = service.info()
1022 if info is not None:
1023 aspect = info.getInfo(iServiceInformation.sAspect)
1024 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1025 self["FormatActive"].showWidget()
1027 self["FormatActive"].hideWidget()
1029 def checkSubservices(self, service):
1030 if service.subServices().getNumberOfSubservices() > 0:
1031 self.showSubServiceIndication()
1033 self.hideSubServiceIndication()
1035 def checkDolby(self, service):
1038 audio = service.audioTracks()
1039 if audio is not None:
1040 n = audio.getNumberOfTracks()
1042 i = audio.getTrackInfo(x)
1043 description = i.getDescription();
1044 if description.find("AC3") != -1 or description.find("DTS") != -1:
1048 self["DolbyActive"].showWidget()
1050 self["DolbyActive"].hideWidget()
1052 def checkCrypted(self, service):
1053 info = service.info()
1054 if info is not None:
1055 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1056 self["CryptActive"].showWidget()
1058 self["CryptActive"].hideWidget()
1060 def gotServiceEvent(self, ev):
1061 service = self.session.nav.getCurrentService()
1062 if ev == iPlayableService.evUpdatedEventInfo:
1063 self.checkSubservices(service)
1064 self.checkFormat(service)
1065 elif ev == iPlayableService.evUpdatedInfo:
1066 self.checkCrypted(service)
1067 self.checkDolby(service)
1068 elif ev == iPlayableService.evEnd:
1069 self.hideSubServiceIndication()
1070 self["CryptActive"].hideWidget()
1071 self["DolbyActive"].hideWidget()
1072 self["FormatActive"].hideWidget()
1074 class InfoBarNotifications:
1076 self.onExecBegin.append(self.checkNotifications)
1077 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1079 def checkNotificationsIfExecing(self):
1081 self.checkNotifications()
1083 def checkNotifications(self):
1084 if len(Notifications.notifications):
1085 n = Notifications.notifications[0]
1086 Notifications.notifications = Notifications.notifications[1:]
1090 self.session.openWithCallback(cb, *n[1:])
1092 self.session.open(*n[1:])
1094 class InfoBarServiceNotifications:
1096 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1098 iPlayableService.evEnd: self.serviceHasEnded
1101 def serviceHasEnded(self):
1102 print "service end!"
1105 self.setSeekState(self.SEEK_STATE_PLAY)