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.onLayoutFinish.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 currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
292 if self.servicelist.inBouquet() and self.servicelist.atBegin():
293 self.servicelist.prevBouquet()
294 self.servicelist.moveUp()
295 self.servicelist.zap()
299 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
300 self.servicelist.nextBouquet()
302 self.servicelist.moveDown()
303 self.servicelist.zap()
307 """ Handles a menu action, to open the (main) menu """
309 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
311 "mainMenu": (self.mainMenu, "Enter main menu..."),
315 print "loading mainmenu XML..."
316 menu = mdom.childNodes[0]
317 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
318 self.session.open(MainMenu, menu, menu.childNodes)
321 """ EPG - Opens an EPG list when the showEPGList action fires """
323 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
325 "showEventInfo": (self.openEventView, _("show EPG...")),
328 def zapToService(self, service):
329 if not service is None:
330 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
331 self.servicelist.clearPath()
332 if self.servicelist.bouquet_root != self.epg_bouquet:
333 self.servicelist.enterPath(self.servicelist.bouquet_root)
334 self.servicelist.enterPath(self.epg_bouquet)
335 self.servicelist.setCurrentSelection(service) #select the service in servicelist
336 self.servicelist.zap()
338 def openBouquetEPG(self, bouquet):
339 ptr=eEPGCache.getInstance()
341 servicelist = eServiceCenter.getInstance().list(bouquet)
342 if not servicelist is None:
344 service = servicelist.getNext()
345 if not service.valid(): #check if end of list
347 if service.flags: #ignore non playable services
349 services.append(ServiceReference(service))
351 self.epg_bouquet = bouquet
352 self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
354 def closed(self, ret):
358 def openMultiServiceEPG(self):
359 bouquets = self.servicelist.getBouquetList()
364 if cnt > 1: # show bouquet list
365 self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
367 self.openBouquetEPG(bouquets[0][1])
369 def openSingleServiceEPG(self):
370 ref=self.session.nav.getCurrentlyPlayingServiceReference()
371 ptr=eEPGCache.getInstance()
372 self.session.openWithCallback(self.closed, EPGSelection, ref)
374 def openEventView(self):
376 service = self.session.nav.getCurrentService()
377 ref = self.session.nav.getCurrentlyPlayingServiceReference()
378 info = service.info()
381 self.epglist.append(ptr)
384 self.epglist.append(ptr)
385 if len(self.epglist) == 0:
386 epg = eEPGCache.getInstance()
387 ptr = epg.lookupEventTime(ref, -1)
389 self.epglist.append(ptr)
390 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
392 self.epglist.append(ptr)
393 if len(self.epglist) > 0:
394 self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
396 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
397 self.openMultiServiceEPG()
399 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
400 if len(self.epglist) > 1:
401 tmp = self.epglist[0]
402 self.epglist[0]=self.epglist[1]
404 setEvent(self.epglist[0])
409 """provides a snr/agc/ber display"""
411 self["snr"] = Label()
412 self["agc"] = Label()
413 self["ber"] = Label()
414 self["snr_percent"] = Label()
415 self["agc_percent"] = Label()
416 self["ber_count"] = Label()
417 self["snr_progress"] = ProgressBar()
418 self["agc_progress"] = ProgressBar()
419 self["ber_progress"] = ProgressBar()
420 self.timer = eTimer()
421 self.timer.timeout.get().append(self.updateTunerInfo)
422 self.timer.start(1000)
428 return (long)(log(val)/log(2))
431 def updateTunerInfo(self):
432 if self.instance.isVisible():
433 service = self.session.nav.getCurrentService()
437 if service is not None:
438 feinfo = service.frontendStatusInfo()
439 if feinfo is not None:
440 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
441 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
442 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
443 self["snr_percent"].setText("%d%%"%(snr))
444 self["agc_percent"].setText("%d%%"%(agc))
445 self["ber_count"].setText("%d"%(ber))
446 self["snr_progress"].setValue(snr)
447 self["agc_progress"].setValue(agc)
448 self["ber_progress"].setValue(self.calc(ber))
451 """provides a current/next event info display"""
453 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
454 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
456 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
457 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
459 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
460 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
462 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
464 class InfoBarServiceName:
466 self["ServiceName"] = ServiceName(self.session.nav)
469 """handles actions like seeking, pause"""
471 # ispause, isff, issm
472 SEEK_STATE_PLAY = (0, 0, 0, ">")
473 SEEK_STATE_PAUSE = (1, 0, 0, "||")
474 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
475 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
476 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
477 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
478 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
479 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
481 SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
482 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
483 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
484 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
486 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
487 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
488 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
491 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
493 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
494 iPlayableService.evStart: self.__serviceStarted,
496 iPlayableService.evEOF: self.__evEOF,
497 iPlayableService.evSOF: self.__evSOF,
499 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
501 "pauseService": (self.pauseService, "pause"),
502 "unPauseService": (self.unPauseService, "continue"),
504 "seekFwd": (self.seekFwd, "skip forward"),
505 "seekFwdUp": (self.seekFwdUp, "skip forward"),
506 "seekBack": (self.seekBack, "skip backward"),
507 "seekBackUp": (self.seekBackUp, "skip backward"),
509 # give them a little more priority to win over color buttons
511 self.seekstate = self.SEEK_STATE_PLAY
512 self.onClose.append(self.delTimer)
514 self.fwdtimer = False
515 self.fwdKeyTimer = eTimer()
516 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
518 self.rwdtimer = False
519 self.rwdKeyTimer = eTimer()
520 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
522 self.onPlayStateChanged = [ ]
524 self.lockedBecauseOfSkipping = False
537 service = self.session.nav.getCurrentService()
541 seek = service.seek()
543 if seek is None or not seek.isCurrentlySeekable():
548 def isSeekable(self):
549 if self.getSeek() is None:
553 def __seekableStatusChanged(self):
554 print "seekable status changed!"
555 if not self.isSeekable():
556 self["SeekActions"].setEnabled(False)
557 print "not seekable, return to play"
558 self.setSeekState(self.SEEK_STATE_PLAY)
560 self["SeekActions"].setEnabled(True)
563 def __serviceStarted(self):
564 self.seekstate = self.SEEK_STATE_PLAY
566 def setSeekState(self, state):
567 service = self.session.nav.getCurrentService()
572 if not self.isSeekable():
573 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
574 state = self.SEEK_STATE_PLAY
576 pauseable = service.pause()
578 if pauseable is None:
579 print "not pauseable."
580 state = self.SEEK_STATE_PLAY
582 oldstate = self.seekstate
583 self.seekstate = state
586 if oldstate[i] != self.seekstate[i]:
587 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
589 for c in self.onPlayStateChanged:
592 self.checkSkipShowHideLock()
596 def pauseService(self):
597 if self.seekstate == self.SEEK_STATE_PAUSE:
598 print "pause, but in fact unpause"
599 self.unPauseService()
601 if self.seekstate == self.SEEK_STATE_PLAY:
602 print "yes, playing."
604 print "no", self.seekstate
606 self.setSeekState(self.SEEK_STATE_PAUSE);
608 def unPauseService(self):
610 self.setSeekState(self.SEEK_STATE_PLAY);
612 def doSeek(self, seektime):
613 print "doseek", seektime
614 service = self.session.nav.getCurrentService()
618 seekable = self.getSeek()
622 seekable.seekTo(90 * seektime)
625 print "start fwd timer"
627 self.fwdKeyTimer.start(500)
630 print "start rewind timer"
632 self.rwdKeyTimer.start(500)
637 self.fwdKeyTimer.stop()
638 self.fwdtimer = False
640 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
641 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
642 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
643 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
644 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
645 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
646 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
647 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
648 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
649 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
650 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
651 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
652 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
653 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
654 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
656 self.setSeekState(lookup[self.seekstate]);
658 def seekBackUp(self):
661 self.rwdKeyTimer.stop()
662 self.rwdtimer = False
665 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
666 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
667 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
668 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
669 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
670 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
671 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
672 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
673 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
674 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
675 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
676 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
677 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
678 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
679 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
681 self.setSeekState(lookup[self.seekstate]);
683 def fwdTimerFire(self):
684 print "Display seek fwd"
685 self.fwdKeyTimer.stop()
686 self.fwdtimer = False
687 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
689 def fwdSeekTo(self, minutes):
690 print "Seek", minutes, "minutes forward"
692 seekable = self.getSeek()
693 if seekable is not None:
694 seekable.seekRelative(1, minutes * 60 * 90000)
696 def rwdTimerFire(self):
698 self.rwdKeyTimer.stop()
699 self.rwdtimer = False
700 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
702 def rwdSeekTo(self, minutes):
704 self.fwdSeekTo(0 - minutes)
706 def checkSkipShowHideLock(self):
707 wantlock = self.seekstate != self.SEEK_STATE_PLAY
709 if self.lockedBecauseOfSkipping and not wantlock:
711 self.lockedBecauseOfSkipping = False
713 if wantlock and not self.lockedBecauseOfSkipping:
715 self.lockedBecauseOfSkipping = True
718 self.setSeekState(self.SEEK_STATE_PAUSE)
721 self.setSeekState(self.SEEK_STATE_PLAY)
724 def seekRelative(self, diff):
725 seekable = self.getSeek()
726 if seekable is not None:
727 seekable.seekRelative(0, diff)
729 from Screens.PVRState import PVRState
731 class InfoBarPVRState:
733 self.onPlayStateChanged.append(self.__playStateChanged)
734 self.pvrStateDialog = self.session.instantiateDialog(PVRState)
735 self.onShow.append(self.__mayShow)
736 self.onHide.append(self.pvrStateDialog.hide)
739 if self.seekstate != self.SEEK_STATE_PLAY:
740 self.pvrStateDialog.show()
742 def __playStateChanged(self, state):
743 playstateString = state[3]
744 self.pvrStateDialog["state"].setText(playstateString)
747 class InfoBarShowMovies:
749 # i don't really like this class.
750 # it calls a not further specified "movie list" on up/down/movieList,
751 # so this is not more than an action map
753 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
755 "movieList": (self.showMovies, "movie list"),
756 "up": (self.showMovies, "movie list"),
757 "down": (self.showMovies, "movie list")
760 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
764 # Timeshift works the following way:
765 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
766 # - normal playback TUNER unused PLAY enable disable disable
767 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
768 # - user presess pause again FILE record PLAY enable disable enable
769 # - user fast forwards FILE record FF enable disable enable
770 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
771 # - user backwards FILE record BACK # !! enable disable enable
775 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
776 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
777 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
778 # - the user can now PVR around
779 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
780 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
782 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
783 # - if the user rewinds, or press pause, timeshift will be activated again
785 # note that a timeshift can be enabled ("recording") and
786 # activated (currently time-shifting).
788 class InfoBarTimeshift:
790 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
792 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
793 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
795 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
797 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
798 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
799 }, prio=-1) # priority over record
801 self.timeshift_enabled = 0
802 self.timeshift_state = 0
803 self.ts_pause_timer = eTimer()
804 self.ts_pause_timer.timeout.get().append(self.pauseService)
806 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
808 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
811 def getTimeshift(self):
812 service = self.session.nav.getCurrentService()
813 return service.timeshift()
815 def startTimeshift(self):
816 print "enable timeshift"
817 ts = self.getTimeshift()
819 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
820 print "no ts interface"
823 if self.timeshift_enabled:
824 print "hu, timeshift already enabled?"
826 if not ts.startTimeshift():
827 self.timeshift_enabled = 1
830 self.setSeekState(self.SEEK_STATE_PAUSE)
832 # enable the "TimeshiftEnableActions", which will override
833 # the startTimeshift actions
834 self.__seekableStatusChanged()
836 print "timeshift failed"
838 def stopTimeshift(self):
839 print "disable timeshift"
840 ts = self.getTimeshift()
843 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
845 def stopTimeshiftConfirmed(self, confirmed):
849 ts = self.getTimeshift()
854 self.timeshift_enabled = 0
857 self.__seekableStatusChanged()
859 # activates timeshift, and seeks to (almost) the end
860 def activateTimeshiftEnd(self):
861 ts = self.getTimeshift()
866 if ts.isTimeshiftActive():
867 print "!! activate timeshift called - but shouldn't this be a normal pause?"
870 self.setSeekState(self.SEEK_STATE_PLAY)
871 ts.activateTimeshift()
874 # same as activateTimeshiftEnd, but pauses afterwards.
875 def activateTimeshiftEndAndPause(self):
876 state = self.seekstate
877 self.activateTimeshiftEnd()
879 # well, this is "andPause", but it could be pressed from pause,
880 # when pausing on the (fake-)"live" picture, so an un-pause
883 print "now, pauseService"
884 if state == self.SEEK_STATE_PLAY:
885 print "is PLAYING, start pause timer"
886 self.ts_pause_timer.start(200, 1)
889 self.unPauseService()
891 def __seekableStatusChanged(self):
894 print "self.isSeekable", self.isSeekable()
895 print "self.timeshift_enabled", self.timeshift_enabled
897 # when this service is not seekable, but timeshift
898 # is enabled, this means we can activate
900 if not self.isSeekable() and self.timeshift_enabled:
903 print "timeshift activate:", enabled
904 self["TimeshiftActivateActions"].setEnabled(enabled)
906 from RecordTimer import parseEvent
908 class InfoBarInstantRecord:
909 """Instant Record - handles the instantRecord action in order to
910 start/stop instant records"""
912 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
914 "instantRecord": (self.instantRecord, "Instant Record..."),
916 self.recording = None
917 self["BlinkingPoint"] = BlinkingPixmapConditional()
918 self.onLayoutFinish.append(self["BlinkingPoint"].hideWidget)
919 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
921 def stopCurrentRecording(self):
922 self.session.nav.RecordTimer.removeEntry(self.recording)
923 self.recording = None
925 def startInstantRecording(self):
926 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
928 # try to get event info
931 service = self.session.nav.getCurrentService()
932 info = service.info()
933 ev = info.getEvent(0)
938 if event is not None:
939 data = parseEvent(event)
941 end = begin + 3600 * 10
943 data = (begin, end, data[2], data[3], data[4])
945 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
947 # fix me, description.
948 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
949 self.recording.dontSave = True
951 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
953 def isInstantRecordRunning(self):
954 if self.recording != None:
955 if self.recording.isRunning():
959 def recordQuestionCallback(self, answer):
963 if self.isInstantRecordRunning():
964 self.stopCurrentRecording()
966 self.startInstantRecording()
968 def instantRecord(self):
970 stat = os.stat(resolveFilename(SCOPE_HDD))
972 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
975 if self.isInstantRecordRunning():
976 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
978 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
980 from Screens.AudioSelection import AudioSelection
982 class InfoBarAudioSelection:
984 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
986 "audioSelection": (self.audioSelection, "Audio Options..."),
989 def audioSelection(self):
990 service = self.session.nav.getCurrentService()
991 audio = service.audioTracks()
992 n = audio.getNumberOfTracks()
994 self.session.open(AudioSelection, audio)
996 from Screens.SubserviceSelection import SubserviceSelection
998 class InfoBarSubserviceSelection:
1000 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1002 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
1005 def subserviceSelection(self):
1006 service = self.session.nav.getCurrentService()
1007 subservices = service.subServices()
1008 n = subservices.getNumberOfSubservices()
1010 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
1012 def subserviceSelected(self, service):
1013 if not service is None:
1014 self.session.nav.playService(service)
1016 class InfoBarAdditionalInfo:
1018 self["DolbyActive"] = Pixmap()
1019 self["CryptActive"] = Pixmap()
1020 self["FormatActive"] = Pixmap()
1022 self["ButtonRed"] = PixmapConditional(withTimer = False)
1023 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1024 self.onShown.append(self["ButtonRed"].update)
1025 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1026 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1027 self.onShown.append(self["ButtonRedText"].update)
1029 self["ButtonGreen"] = Pixmap()
1030 self["ButtonGreenText"] = Label(_("Subservices"))
1032 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1033 self["ButtonYellow"].setConnect(lambda: False)
1035 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1036 self["ButtonBlue"].setConnect(lambda: False)
1038 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1040 def hideSubServiceIndication(self):
1041 self["ButtonGreen"].hideWidget()
1042 self["ButtonGreenText"].hide()
1044 def showSubServiceIndication(self):
1045 self["ButtonGreen"].showWidget()
1046 self["ButtonGreenText"].show()
1048 def checkFormat(self, service):
1049 info = service.info()
1050 if info is not None:
1051 aspect = info.getInfo(iServiceInformation.sAspect)
1052 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1053 self["FormatActive"].showWidget()
1055 self["FormatActive"].hideWidget()
1057 def checkSubservices(self, service):
1058 if service.subServices().getNumberOfSubservices() > 0:
1059 self.showSubServiceIndication()
1061 self.hideSubServiceIndication()
1063 def checkDolby(self, service):
1066 audio = service.audioTracks()
1067 if audio is not None:
1068 n = audio.getNumberOfTracks()
1070 i = audio.getTrackInfo(x)
1071 description = i.getDescription();
1072 if description.find("AC3") != -1 or description.find("DTS") != -1:
1076 self["DolbyActive"].showWidget()
1078 self["DolbyActive"].hideWidget()
1080 def checkCrypted(self, service):
1081 info = service.info()
1082 if info is not None:
1083 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1084 self["CryptActive"].showWidget()
1086 self["CryptActive"].hideWidget()
1088 def gotServiceEvent(self, ev):
1089 service = self.session.nav.getCurrentService()
1090 if ev == iPlayableService.evUpdatedEventInfo:
1091 self.checkSubservices(service)
1092 self.checkFormat(service)
1093 elif ev == iPlayableService.evUpdatedInfo:
1094 self.checkCrypted(service)
1095 self.checkDolby(service)
1096 elif ev == iPlayableService.evEnd:
1097 self.hideSubServiceIndication()
1098 self["CryptActive"].hideWidget()
1099 self["DolbyActive"].hideWidget()
1100 self["FormatActive"].hideWidget()
1102 class InfoBarNotifications:
1104 self.onExecBegin.append(self.checkNotifications)
1105 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1107 def checkNotificationsIfExecing(self):
1109 self.checkNotifications()
1111 def checkNotifications(self):
1112 if len(Notifications.notifications):
1113 n = Notifications.notifications[0]
1114 Notifications.notifications = Notifications.notifications[1:]
1118 self.session.openWithCallback(cb, *n[1:])
1120 self.session.open(*n[1:])
1122 class InfoBarServiceNotifications:
1124 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1126 iPlayableService.evEnd: self.serviceHasEnded
1129 def serviceHasEnded(self):
1130 print "service end!"
1133 self.setSeekState(self.SEEK_STATE_PLAY)