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)
707 service = self.session.nav.getCurrentService()
710 seekable = service.seek()
713 seekable.seekRelative(0, 0)
716 from Screens.PVRState import PVRState
718 class InfoBarPVRState:
720 self.onPlayStateChanged.append(self.__playStateChanged)
721 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
722 self.onShow.append(self.__mayShow)
723 self.onHide.append(self.pvrStateDialog.hide)
726 if self.seekstate != self.SEEK_STATE_PLAY:
727 self.pvrStateDialog.show()
729 def __playStateChanged(self, state):
730 playstateString = state[3]
731 self.pvrStateDialog["state"].setText(playstateString)
734 class InfoBarShowMovies:
736 # i don't really like this class.
737 # it calls a not further specified "movie list" on up/down/movieList,
738 # so this is not more than an action map
740 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
742 "movieList": (self.showMovies, "movie list"),
743 "up": (self.showMovies, "movie list"),
744 "down": (self.showMovies, "movie list")
747 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
751 # Timeshift works the following way:
752 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
753 # - normal playback TUNER unused PLAY enable disable disable
754 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
755 # - user presess pause again FILE record PLAY enable disable enable
756 # - user fast forwards FILE record FF enable disable enable
757 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
758 # - user backwards FILE record BACK # !! enable disable enable
762 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
763 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
764 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
765 # - the user can now PVR around
766 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
767 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
769 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
770 # - if the user rewinds, or press pause, timeshift will be activated again
772 # note that a timeshift can be enabled ("recording") and
773 # activated (currently time-shifting).
775 class InfoBarTimeshift:
777 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
779 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
780 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
782 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
784 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
785 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
788 self.timeshift_enabled = 0
789 self.timeshift_state = 0
790 self.ts_pause_timer = eTimer()
791 self.ts_pause_timer.timeout.get().append(self.pauseService)
793 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
795 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
798 def getTimeshift(self):
799 service = self.session.nav.getCurrentService()
800 return service.timeshift()
802 def startTimeshift(self):
803 # TODO: check for harddisk! (or do this in the interface? would make
804 # more sense... for example radio could be timeshifted in memory,
805 # and the decision can't be made here)
806 print "enable timeshift"
807 ts = self.getTimeshift()
809 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
810 print "no ts interface"
813 if self.timeshift_enabled:
814 print "hu, timeshift already enabled?"
816 if not ts.startTimeshift():
817 self.timeshift_enabled = 1
820 self.setSeekState(self.SEEK_STATE_PAUSE)
822 # enable the "TimeshiftEnableActions", which will override
823 # the startTimeshift actions
824 self.__seekableStatusChanged()
826 print "timeshift failed"
829 def stopTimeshift(self):
830 print "disable timeshift"
831 ts = self.getTimeshift()
835 self.timeshift_enabled = 0
838 self.__seekableStatusChanged()
840 # activates timeshift, and seeks to (almost) the end
841 def activateTimeshiftEnd(self):
842 ts = self.getTimeshift()
847 if ts.isTimeshiftActive():
848 print "!! activate timeshift called - but shouldn't this be a normal pause?"
851 self.setSeekState(self.SEEK_STATE_PLAY)
852 ts.activateTimeshift()
854 # same as activateTimeshiftEnd, but pauses afterwards.
855 def activateTimeshiftEndAndPause(self):
856 state = self.seekstate
857 self.activateTimeshiftEnd()
859 # well, this is "andPause", but it could be pressed from pause,
860 # when pausing on the (fake-)"live" picture, so an un-pause
863 print "now, pauseService"
864 if state == self.SEEK_STATE_PLAY:
865 print "is PLAYING, start pause timer"
866 self.ts_pause_timer.start(200, 1)
869 self.unPauseService()
871 def __seekableStatusChanged(self):
874 print "self.isSeekable", self.isSeekable()
875 print "self.timeshift_enabled", self.timeshift_enabled
877 # when this service is not seekable, but timeshift
878 # is enabled, this means we can activate
880 if not self.isSeekable() and self.timeshift_enabled:
883 print "timeshift activate:", enabled
884 self["TimeshiftActivateActions"].setEnabled(enabled)
886 from RecordTimer import parseEvent
888 class InfoBarInstantRecord:
889 """Instant Record - handles the instantRecord action in order to
890 start/stop instant records"""
892 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
894 "instantRecord": (self.instantRecord, "Instant Record..."),
896 self.recording = None
898 self["BlinkingPoint"] = BlinkingPixmapConditional()
899 self.onShown.append(self["BlinkingPoint"].hideWidget)
900 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
902 def stopCurrentRecording(self):
903 self.session.nav.RecordTimer.removeEntry(self.recording)
904 self.recording = None
906 def startInstantRecording(self):
907 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
909 # try to get event info
912 service = self.session.nav.getCurrentService()
913 info = service.info()
914 ev = info.getEvent(0)
919 if event is not None:
920 data = parseEvent(event)
922 if begin < time.time():
931 data = (begin, end, data[2], data[3], data[4])
933 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
935 # fix me, description.
936 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
937 self.recording.dontSave = True
939 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
941 def isInstantRecordRunning(self):
942 if self.recording != None:
943 if self.recording.isRunning():
947 def recordQuestionCallback(self, answer):
951 if self.isInstantRecordRunning():
952 self.stopCurrentRecording()
954 self.startInstantRecording()
956 def instantRecord(self):
958 stat = os.stat(resolveFilename(SCOPE_HDD))
960 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
963 if self.isInstantRecordRunning():
964 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
966 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
968 from Screens.AudioSelection import AudioSelection
970 class InfoBarAudioSelection:
972 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
974 "audioSelection": (self.audioSelection, "Audio Options..."),
977 def audioSelection(self):
978 service = self.session.nav.getCurrentService()
979 audio = service.audioTracks()
980 n = audio.getNumberOfTracks()
982 self.session.open(AudioSelection, audio)
984 from Screens.SubserviceSelection import SubserviceSelection
986 class InfoBarSubserviceSelection:
988 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
990 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
993 def subserviceSelection(self):
994 service = self.session.nav.getCurrentService()
995 subservices = service.subServices()
996 n = subservices.getNumberOfSubservices()
998 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
1000 def subserviceSelected(self, service):
1001 if not service is None:
1002 self.session.nav.playService(service)
1004 class InfoBarAdditionalInfo:
1006 self["DolbyActive"] = Pixmap()
1007 self["CryptActive"] = Pixmap()
1008 self["FormatActive"] = Pixmap()
1010 self["ButtonRed"] = PixmapConditional(withTimer = False)
1011 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1012 self.onShown.append(self["ButtonRed"].update)
1013 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1014 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1015 self.onShown.append(self["ButtonRedText"].update)
1017 self["ButtonGreen"] = Pixmap()
1018 self["ButtonGreenText"] = Label(_("Subservices"))
1020 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1021 self["ButtonYellow"].setConnect(lambda: False)
1023 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1024 self["ButtonBlue"].setConnect(lambda: False)
1026 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1028 def hideSubServiceIndication(self):
1029 self["ButtonGreen"].hideWidget()
1030 self["ButtonGreenText"].hide()
1032 def showSubServiceIndication(self):
1033 self["ButtonGreen"].showWidget()
1034 self["ButtonGreenText"].show()
1036 def checkFormat(self, service):
1037 info = service.info()
1038 if info is not None:
1039 aspect = info.getInfo(iServiceInformation.sAspect)
1040 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1041 self["FormatActive"].showWidget()
1043 self["FormatActive"].hideWidget()
1045 def checkSubservices(self, service):
1046 if service.subServices().getNumberOfSubservices() > 0:
1047 self.showSubServiceIndication()
1049 self.hideSubServiceIndication()
1051 def checkDolby(self, service):
1054 audio = service.audioTracks()
1055 if audio is not None:
1056 n = audio.getNumberOfTracks()
1058 i = audio.getTrackInfo(x)
1059 description = i.getDescription();
1060 if description.find("AC3") != -1 or description.find("DTS") != -1:
1064 self["DolbyActive"].showWidget()
1066 self["DolbyActive"].hideWidget()
1068 def checkCrypted(self, service):
1069 info = service.info()
1070 if info is not None:
1071 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1072 self["CryptActive"].showWidget()
1074 self["CryptActive"].hideWidget()
1076 def gotServiceEvent(self, ev):
1077 service = self.session.nav.getCurrentService()
1078 if ev == iPlayableService.evUpdatedEventInfo:
1079 self.checkSubservices(service)
1080 self.checkFormat(service)
1081 elif ev == iPlayableService.evUpdatedInfo:
1082 self.checkCrypted(service)
1083 self.checkDolby(service)
1084 elif ev == iPlayableService.evEnd:
1085 self.hideSubServiceIndication()
1086 self["CryptActive"].hideWidget()
1087 self["DolbyActive"].hideWidget()
1088 self["FormatActive"].hideWidget()
1090 class InfoBarNotifications:
1092 self.onExecBegin.append(self.checkNotifications)
1093 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1095 def checkNotificationsIfExecing(self):
1097 self.checkNotifications()
1099 def checkNotifications(self):
1100 if len(Notifications.notifications):
1101 n = Notifications.notifications[0]
1102 Notifications.notifications = Notifications.notifications[1:]
1106 self.session.openWithCallback(cb, *n[1:])
1108 self.session.open(*n[1:])
1110 class InfoBarServiceNotifications:
1112 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1114 iPlayableService.evEnd: self.serviceHasEnded
1117 def serviceHasEnded(self):
1118 print "service end!"
1121 self.setSeekState(self.SEEK_STATE_PLAY)