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
88 def doTimerHide(self):
90 if self.__state == self.STATE_SHOWN:
94 if self.__state == self.STATE_SHOWN:
97 elif self.__state == self.STATE_HIDDEN:
101 self.__locked = self.__locked + 1
104 self.hideTimer.stop()
106 def unlockShow(self):
107 self.__locked = self.__locked - 1
109 self.startHideTimer()
111 # def startShow(self):
112 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
113 # self.__state = self.STATE_SHOWN
115 # def startHide(self):
116 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
117 # self.__state = self.STATE_HIDDEN
119 class NumberZap(Screen):
126 self.close(int(self["number"].getText()))
128 def keyNumberGlobal(self, number):
129 self.Timer.start(3000, True) #reset timer
130 self.field = self.field + str(number)
131 self["number"].setText(self.field)
132 if len(self.field) >= 4:
135 def __init__(self, session, number):
136 Screen.__init__(self, session)
137 self.field = str(number)
139 self["channel"] = Label(_("Channel:"))
141 self["number"] = Label(self.field)
143 self["actions"] = NumberActionMap( [ "SetupActions" ],
147 "1": self.keyNumberGlobal,
148 "2": self.keyNumberGlobal,
149 "3": self.keyNumberGlobal,
150 "4": self.keyNumberGlobal,
151 "5": self.keyNumberGlobal,
152 "6": self.keyNumberGlobal,
153 "7": self.keyNumberGlobal,
154 "8": self.keyNumberGlobal,
155 "9": self.keyNumberGlobal,
156 "0": self.keyNumberGlobal
159 self.Timer = eTimer()
160 self.Timer.timeout.get().append(self.keyOK)
161 self.Timer.start(3000, True)
163 class InfoBarPowerKey:
164 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
167 self.powerKeyTimer = eTimer()
168 self.powerKeyTimer.timeout.get().append(self.powertimer)
169 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
171 "powerdown": self.powerdown,
172 "powerup": self.powerup,
173 "discreteStandby": (self.standby, "Go standby"),
174 "discretePowerOff": (self.quit, "Go to deep standby"),
177 def powertimer(self):
178 print "PowerOff - Now!"
182 self.standbyblocked = 0
183 self.powerKeyTimer.start(3000, True)
186 self.powerKeyTimer.stop()
187 if self.standbyblocked == 0:
188 self.standbyblocked = 1
192 self.session.open(Standby, self)
198 class InfoBarNumberZap:
199 """ Handles an initial number for NumberZapping """
201 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
203 "1": self.keyNumberGlobal,
204 "2": self.keyNumberGlobal,
205 "3": self.keyNumberGlobal,
206 "4": self.keyNumberGlobal,
207 "5": self.keyNumberGlobal,
208 "6": self.keyNumberGlobal,
209 "7": self.keyNumberGlobal,
210 "8": self.keyNumberGlobal,
211 "9": self.keyNumberGlobal,
212 "0": self.keyNumberGlobal,
215 def keyNumberGlobal(self, number):
216 # print "You pressed number " + str(number)
218 self.servicelist.recallPrevService()
221 self.session.openWithCallback(self.numberEntered, NumberZap, number)
223 def numberEntered(self, retval):
224 # print self.servicelist
226 self.zapToNumber(retval)
228 def searchNumberHelper(self, serviceHandler, num, bouquet):
229 servicelist = serviceHandler.list(bouquet)
230 if not servicelist is None:
232 serviceIterator = servicelist.getNext()
233 if not serviceIterator.valid(): #check end of list
235 if serviceIterator.flags: #assume normal dvb service have no flags set
238 if not num: #found service with searched number ?
239 return serviceIterator, 0
242 def zapToNumber(self, number):
243 bouquet = self.servicelist.bouquet_root
245 serviceHandler = eServiceCenter.getInstance()
246 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
247 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
249 bouquetlist = serviceHandler.list(bouquet)
250 if not bouquetlist is None:
252 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
253 if not bouquet.valid(): #check end of list
255 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
257 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
258 if not service is None:
259 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
260 self.servicelist.clearPath()
261 if self.servicelist.bouquet_root != bouquet:
262 self.servicelist.enterPath(self.servicelist.bouquet_root)
263 self.servicelist.enterPath(bouquet)
264 self.servicelist.setCurrentSelection(service) #select the service in servicelist
265 self.servicelist.zap()
267 class InfoBarChannelSelection:
268 """ ChannelSelection - handles the channelSelection dialog and the initial
269 channelChange actions which open the channelSelection dialog """
272 self.servicelist = self.session.instantiateDialog(ChannelSelection)
274 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
276 "switchChannelUp": self.switchChannelUp,
277 "switchChannelDown": self.switchChannelDown,
278 "zapUp": (self.zapUp, _("next channel")),
279 "zapDown": (self.zapDown, _("previous channel")),
282 def switchChannelUp(self):
283 self.servicelist.moveUp()
284 self.session.execDialog(self.servicelist)
286 def switchChannelDown(self):
287 self.servicelist.moveDown()
288 self.session.execDialog(self.servicelist)
291 if self.servicelist.inBouquet() and self.servicelist.atBegin():
292 self.servicelist.prevBouquet()
293 self.servicelist.moveUp()
294 self.servicelist.zap()
298 if self.servicelist.inBouquet() and self.servicelist.atEnd():
299 self.servicelist.nextBouquet()
301 self.servicelist.moveDown()
302 self.servicelist.zap()
306 """ Handles a menu action, to open the (main) menu """
308 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
310 "mainMenu": (self.mainMenu, "Enter main menu..."),
314 print "loading mainmenu XML..."
315 menu = mdom.childNodes[0]
316 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
317 self.session.open(MainMenu, menu, menu.childNodes)
320 """ EPG - Opens an EPG list when the showEPGList action fires """
322 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
324 "showEventInfo": (self.openEventView, _("show EPG...")),
327 def zapToService(self, service):
328 if not service is None:
329 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
330 self.servicelist.clearPath()
331 if self.servicelist.bouquet_root != self.epg_bouquet:
332 self.servicelist.enterPath(self.servicelist.bouquet_root)
333 self.servicelist.enterPath(self.epg_bouquet)
334 self.servicelist.setCurrentSelection(service) #select the service in servicelist
335 self.servicelist.zap()
337 def openBouquetEPG(self, bouquet):
338 ptr=eEPGCache.getInstance()
340 servicelist = eServiceCenter.getInstance().list(bouquet)
341 if not servicelist is None:
343 service = servicelist.getNext()
344 if not service.valid(): #check if end of list
346 if service.flags: #ignore non playable services
348 services.append(ServiceReference(service))
350 self.epg_bouquet = bouquet
351 self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
353 def closed(self, ret):
357 def openMultiServiceEPG(self):
358 bouquets = self.servicelist.getBouquetList()
363 if cnt > 1: # show bouquet list
364 self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
366 self.openBouquetEPG(bouquets[0][1])
368 def openSingleServiceEPG(self):
369 ref=self.session.nav.getCurrentlyPlayingServiceReference()
370 ptr=eEPGCache.getInstance()
371 self.session.openWithCallback(self.closed, EPGSelection, ref)
373 def openEventView(self):
375 service = self.session.nav.getCurrentService()
376 ref = self.session.nav.getCurrentlyPlayingServiceReference()
377 info = service.info()
380 self.epglist.append(ptr)
383 self.epglist.append(ptr)
384 if len(self.epglist) == 0:
385 epg = eEPGCache.getInstance()
386 ptr = epg.lookupEventTime(ref, -1)
388 self.epglist.append(ptr)
389 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
391 self.epglist.append(ptr)
392 if len(self.epglist) > 0:
393 self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
395 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
396 self.openMultiServiceEPG()
398 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
399 if len(self.epglist) > 1:
400 tmp = self.epglist[0]
401 self.epglist[0]=self.epglist[1]
403 setEvent(self.epglist[0])
408 """provides a snr/agc/ber display"""
410 self["snr"] = Label()
411 self["agc"] = Label()
412 self["ber"] = Label()
413 self["snr_percent"] = Label()
414 self["agc_percent"] = Label()
415 self["ber_count"] = Label()
416 self["snr_progress"] = ProgressBar()
417 self["agc_progress"] = ProgressBar()
418 self["ber_progress"] = ProgressBar()
419 self.timer = eTimer()
420 self.timer.timeout.get().append(self.updateTunerInfo)
421 self.timer.start(1000)
427 return (long)(log(val)/log(2))
430 def updateTunerInfo(self):
431 if self.instance.isVisible():
432 service = self.session.nav.getCurrentService()
436 if service is not None:
437 feinfo = service.frontendStatusInfo()
438 if feinfo is not None:
439 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
440 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
441 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
442 self["snr_percent"].setText("%d%%"%(snr))
443 self["agc_percent"].setText("%d%%"%(agc))
444 self["ber_count"].setText("%d"%(ber))
445 self["snr_progress"].setValue(snr)
446 self["agc_progress"].setValue(agc)
447 self["ber_progress"].setValue(self.calc(ber))
450 """provides a current/next event info display"""
452 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
453 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
455 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
456 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
458 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
459 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
461 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
463 class InfoBarServiceName:
465 self["ServiceName"] = ServiceName(self.session.nav)
468 """handles actions like seeking, pause"""
470 # ispause, isff, issm
471 SEEK_STATE_PLAY = (0, 0, 0, ">")
472 SEEK_STATE_PAUSE = (1, 0, 0, "||")
473 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
474 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
475 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
476 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
477 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
478 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
480 SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
481 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
482 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
483 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
485 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
486 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
487 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
490 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
492 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
493 iPlayableService.evStart: self.__serviceStarted,
495 iPlayableService.evEOF: self.__evEOF,
496 iPlayableService.evSOF: self.__evSOF,
498 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
500 "pauseService": (self.pauseService, "pause"),
501 "unPauseService": (self.unPauseService, "continue"),
503 "seekFwd": (self.seekFwd, "skip forward"),
504 "seekFwdUp": (self.seekFwdUp, "skip forward"),
505 "seekBack": (self.seekBack, "skip backward"),
506 "seekBackUp": (self.seekBackUp, "skip backward"),
508 # give them a little more priority to win over color buttons
510 self.seekstate = self.SEEK_STATE_PLAY
511 self.onClose.append(self.delTimer)
513 self.fwdtimer = False
514 self.fwdKeyTimer = eTimer()
515 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
517 self.rwdtimer = False
518 self.rwdKeyTimer = eTimer()
519 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
521 self.onPlayStateChanged = [ ]
523 self.lockedBecauseOfSkipping = False
536 service = self.session.nav.getCurrentService()
540 seek = service.seek()
542 if seek is None or not seek.isCurrentlySeekable():
547 def isSeekable(self):
548 if self.getSeek() is None:
552 def __seekableStatusChanged(self):
553 print "seekable status changed!"
554 if not self.isSeekable():
555 self["SeekActions"].setEnabled(False)
556 print "not seekable, return to play"
557 self.setSeekState(self.SEEK_STATE_PLAY)
559 self["SeekActions"].setEnabled(True)
562 def __serviceStarted(self):
563 self.seekstate = self.SEEK_STATE_PLAY
565 def setSeekState(self, state):
566 service = self.session.nav.getCurrentService()
571 if not self.isSeekable():
572 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
573 state = self.SEEK_STATE_PLAY
575 pauseable = service.pause()
577 if pauseable is None:
578 print "not pauseable."
579 state = self.SEEK_STATE_PLAY
581 oldstate = self.seekstate
582 self.seekstate = state
585 if oldstate[i] != self.seekstate[i]:
586 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
588 for c in self.onPlayStateChanged:
591 self.checkSkipShowHideLock()
595 def pauseService(self):
596 if self.seekstate == self.SEEK_STATE_PAUSE:
597 print "pause, but in fact unpause"
598 self.unPauseService()
600 if self.seekstate == self.SEEK_STATE_PLAY:
601 print "yes, playing."
603 print "no", self.seekstate
605 self.setSeekState(self.SEEK_STATE_PAUSE);
607 def unPauseService(self):
609 self.setSeekState(self.SEEK_STATE_PLAY);
611 def doSeek(self, seektime):
612 print "doseek", seektime
613 service = self.session.nav.getCurrentService()
617 seekable = self.getSeek()
621 seekable.seekTo(90 * seektime)
624 print "start fwd timer"
626 self.fwdKeyTimer.start(500)
629 print "start rewind timer"
631 self.rwdKeyTimer.start(500)
636 self.fwdKeyTimer.stop()
637 self.fwdtimer = False
639 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
640 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
641 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
642 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
643 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
644 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
645 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
646 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
647 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
648 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
649 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
650 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
651 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
652 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
653 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
655 self.setSeekState(lookup[self.seekstate]);
657 def seekBackUp(self):
660 self.rwdKeyTimer.stop()
661 self.rwdtimer = False
664 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
665 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
666 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
667 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
668 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
669 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
670 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
671 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
672 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
673 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
674 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
675 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
676 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
677 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
678 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
680 self.setSeekState(lookup[self.seekstate]);
682 def fwdTimerFire(self):
683 print "Display seek fwd"
684 self.fwdKeyTimer.stop()
685 self.fwdtimer = False
686 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
688 def fwdSeekTo(self, minutes):
689 print "Seek", minutes, "minutes forward"
691 seekable = self.getSeek()
692 if seekable is not None:
693 seekable.seekRelative(1, minutes * 60 * 90000)
695 def rwdTimerFire(self):
697 self.rwdKeyTimer.stop()
698 self.rwdtimer = False
699 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
701 def rwdSeekTo(self, minutes):
703 self.fwdSeekTo(0 - minutes)
705 def checkSkipShowHideLock(self):
706 wantlock = self.seekstate != self.SEEK_STATE_PLAY
708 if self.lockedBecauseOfSkipping and not wantlock:
710 self.lockedBecauseOfSkipping = False
712 if wantlock and not self.lockedBecauseOfSkipping:
714 self.lockedBecauseOfSkipping = True
717 self.setSeekState(self.SEEK_STATE_PAUSE)
720 self.setSeekState(self.SEEK_STATE_PLAY)
723 def seekRelative(self, diff):
724 seekable = self.getSeek()
725 if seekable is not None:
726 seekable.seekRelative(0, diff)
728 from Screens.PVRState import PVRState
730 class InfoBarPVRState:
732 self.onPlayStateChanged.append(self.__playStateChanged)
733 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
734 self.onShow.append(self.__mayShow)
735 self.onHide.append(self.pvrStateDialog.hide)
738 if self.seekstate != self.SEEK_STATE_PLAY:
739 self.pvrStateDialog.show()
741 def __playStateChanged(self, state):
742 playstateString = state[3]
743 self.pvrStateDialog["state"].setText(playstateString)
746 class InfoBarShowMovies:
748 # i don't really like this class.
749 # it calls a not further specified "movie list" on up/down/movieList,
750 # so this is not more than an action map
752 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
754 "movieList": (self.showMovies, "movie list"),
755 "up": (self.showMovies, "movie list"),
756 "down": (self.showMovies, "movie list")
759 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
763 # Timeshift works the following way:
764 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
765 # - normal playback TUNER unused PLAY enable disable disable
766 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
767 # - user presess pause again FILE record PLAY enable disable enable
768 # - user fast forwards FILE record FF enable disable enable
769 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
770 # - user backwards FILE record BACK # !! enable disable enable
774 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
775 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
776 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
777 # - the user can now PVR around
778 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
779 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
781 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
782 # - if the user rewinds, or press pause, timeshift will be activated again
784 # note that a timeshift can be enabled ("recording") and
785 # activated (currently time-shifting).
787 class InfoBarTimeshift:
789 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
791 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
792 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
794 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
796 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
797 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
798 }, prio=-1) # priority over record
800 self.timeshift_enabled = 0
801 self.timeshift_state = 0
802 self.ts_pause_timer = eTimer()
803 self.ts_pause_timer.timeout.get().append(self.pauseService)
805 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
807 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
810 def getTimeshift(self):
811 service = self.session.nav.getCurrentService()
812 return service.timeshift()
814 def startTimeshift(self):
815 print "enable timeshift"
816 ts = self.getTimeshift()
818 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
819 print "no ts interface"
822 if self.timeshift_enabled:
823 print "hu, timeshift already enabled?"
825 if not ts.startTimeshift():
826 self.timeshift_enabled = 1
829 self.setSeekState(self.SEEK_STATE_PAUSE)
831 # enable the "TimeshiftEnableActions", which will override
832 # the startTimeshift actions
833 self.__seekableStatusChanged()
835 print "timeshift failed"
837 def stopTimeshift(self):
838 print "disable timeshift"
839 ts = self.getTimeshift()
843 self.timeshift_enabled = 0
846 self.__seekableStatusChanged()
848 # activates timeshift, and seeks to (almost) the end
849 def activateTimeshiftEnd(self):
850 ts = self.getTimeshift()
855 if ts.isTimeshiftActive():
856 print "!! activate timeshift called - but shouldn't this be a normal pause?"
859 self.setSeekState(self.SEEK_STATE_PLAY)
860 ts.activateTimeshift()
863 # same as activateTimeshiftEnd, but pauses afterwards.
864 def activateTimeshiftEndAndPause(self):
865 state = self.seekstate
866 self.activateTimeshiftEnd()
868 # well, this is "andPause", but it could be pressed from pause,
869 # when pausing on the (fake-)"live" picture, so an un-pause
872 print "now, pauseService"
873 if state == self.SEEK_STATE_PLAY:
874 print "is PLAYING, start pause timer"
875 self.ts_pause_timer.start(200, 1)
878 self.unPauseService()
880 def __seekableStatusChanged(self):
883 print "self.isSeekable", self.isSeekable()
884 print "self.timeshift_enabled", self.timeshift_enabled
886 # when this service is not seekable, but timeshift
887 # is enabled, this means we can activate
889 if not self.isSeekable() and self.timeshift_enabled:
892 print "timeshift activate:", enabled
893 self["TimeshiftActivateActions"].setEnabled(enabled)
895 from RecordTimer import parseEvent
897 class InfoBarInstantRecord:
898 """Instant Record - handles the instantRecord action in order to
899 start/stop instant records"""
901 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
903 "instantRecord": (self.instantRecord, "Instant Record..."),
905 self.recording = None
907 self["BlinkingPoint"] = BlinkingPixmapConditional()
908 self.onShown.append(self["BlinkingPoint"].hideWidget)
909 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
911 def stopCurrentRecording(self):
912 self.session.nav.RecordTimer.removeEntry(self.recording)
913 self.recording = None
915 def startInstantRecording(self):
916 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
918 # try to get event info
921 service = self.session.nav.getCurrentService()
922 info = service.info()
923 ev = info.getEvent(0)
928 if event is not None:
929 data = parseEvent(event)
931 end = begin + 3600 * 10
933 data = (begin, end, data[2], data[3], data[4])
935 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
937 # fix me, description.
938 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
939 self.recording.dontSave = True
941 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
943 def isInstantRecordRunning(self):
944 if self.recording != None:
945 if self.recording.isRunning():
949 def recordQuestionCallback(self, answer):
953 if self.isInstantRecordRunning():
954 self.stopCurrentRecording()
956 self.startInstantRecording()
958 def instantRecord(self):
960 stat = os.stat(resolveFilename(SCOPE_HDD))
962 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
965 if self.isInstantRecordRunning():
966 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
968 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
970 from Screens.AudioSelection import AudioSelection
972 class InfoBarAudioSelection:
974 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
976 "audioSelection": (self.audioSelection, "Audio Options..."),
979 def audioSelection(self):
980 service = self.session.nav.getCurrentService()
981 audio = service.audioTracks()
982 n = audio.getNumberOfTracks()
984 self.session.open(AudioSelection, audio)
986 from Screens.SubserviceSelection import SubserviceSelection
988 class InfoBarSubserviceSelection:
990 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
992 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
995 def subserviceSelection(self):
996 service = self.session.nav.getCurrentService()
997 subservices = service.subServices()
998 n = subservices.getNumberOfSubservices()
1000 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
1002 def subserviceSelected(self, service):
1003 if not service is None:
1004 self.session.nav.playService(service)
1006 class InfoBarAdditionalInfo:
1008 self["DolbyActive"] = Pixmap()
1009 self["CryptActive"] = Pixmap()
1010 self["FormatActive"] = Pixmap()
1012 self["ButtonRed"] = PixmapConditional(withTimer = False)
1013 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1014 self.onShown.append(self["ButtonRed"].update)
1015 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1016 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1017 self.onShown.append(self["ButtonRedText"].update)
1019 self["ButtonGreen"] = Pixmap()
1020 self["ButtonGreenText"] = Label(_("Subservices"))
1022 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1023 self["ButtonYellow"].setConnect(lambda: False)
1025 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1026 self["ButtonBlue"].setConnect(lambda: False)
1028 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1030 def hideSubServiceIndication(self):
1031 self["ButtonGreen"].hideWidget()
1032 self["ButtonGreenText"].hide()
1034 def showSubServiceIndication(self):
1035 self["ButtonGreen"].showWidget()
1036 self["ButtonGreenText"].show()
1038 def checkFormat(self, service):
1039 info = service.info()
1040 if info is not None:
1041 aspect = info.getInfo(iServiceInformation.sAspect)
1042 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1043 self["FormatActive"].showWidget()
1045 self["FormatActive"].hideWidget()
1047 def checkSubservices(self, service):
1048 if service.subServices().getNumberOfSubservices() > 0:
1049 self.showSubServiceIndication()
1051 self.hideSubServiceIndication()
1053 def checkDolby(self, service):
1056 audio = service.audioTracks()
1057 if audio is not None:
1058 n = audio.getNumberOfTracks()
1060 i = audio.getTrackInfo(x)
1061 description = i.getDescription();
1062 if description.find("AC3") != -1 or description.find("DTS") != -1:
1066 self["DolbyActive"].showWidget()
1068 self["DolbyActive"].hideWidget()
1070 def checkCrypted(self, service):
1071 info = service.info()
1072 if info is not None:
1073 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1074 self["CryptActive"].showWidget()
1076 self["CryptActive"].hideWidget()
1078 def gotServiceEvent(self, ev):
1079 service = self.session.nav.getCurrentService()
1080 if ev == iPlayableService.evUpdatedEventInfo:
1081 self.checkSubservices(service)
1082 self.checkFormat(service)
1083 elif ev == iPlayableService.evUpdatedInfo:
1084 self.checkCrypted(service)
1085 self.checkDolby(service)
1086 elif ev == iPlayableService.evEnd:
1087 self.hideSubServiceIndication()
1088 self["CryptActive"].hideWidget()
1089 self["DolbyActive"].hideWidget()
1090 self["FormatActive"].hideWidget()
1092 class InfoBarNotifications:
1094 self.onExecBegin.append(self.checkNotifications)
1095 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1097 def checkNotificationsIfExecing(self):
1099 self.checkNotifications()
1101 def checkNotifications(self):
1102 if len(Notifications.notifications):
1103 n = Notifications.notifications[0]
1104 Notifications.notifications = Notifications.notifications[1:]
1108 self.session.openWithCallback(cb, *n[1:])
1110 self.session.open(*n[1:])
1112 class InfoBarServiceNotifications:
1114 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1116 iPlayableService.evEnd: self.serviceHasEnded
1119 def serviceHasEnded(self):
1120 print "service end!"
1123 self.setSeekState(self.SEEK_STATE_PLAY)