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 EventView
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.instance.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
63 self.onExecBegin.append(self.show)
64 self.onClose.append(self.delHideTimer)
66 self.hideTimer = eTimer()
67 self.hideTimer.timeout.get().append(self.doTimerHide)
68 self.hideTimer.start(5000, True)
70 def delHideTimer(self):
77 self.state = self.STATE_SHOWN
78 self.hideTimer.start(5000, True)
80 def doTimerHide(self):
82 if self.state == self.STATE_SHOWN:
84 self.state = self.STATE_HIDDEN
87 if self.state == self.STATE_SHOWN:
89 #pls check animation support, sorry
92 self.state = self.STATE_HIDDEN
93 elif self.state == self.STATE_HIDDEN:
98 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
99 self.state = self.STATE_SHOWN
102 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
103 self.state = self.STATE_HIDDEN
105 class NumberZap(Screen):
112 self.close(int(self["number"].getText()))
114 def keyNumberGlobal(self, number):
115 self.Timer.start(3000, True) #reset timer
116 self.field = self.field + str(number)
117 self["number"].setText(self.field)
118 if len(self.field) >= 4:
121 def __init__(self, session, number):
122 Screen.__init__(self, session)
123 self.field = str(number)
125 self["channel"] = Label(_("Channel:"))
127 self["number"] = Label(self.field)
129 self["actions"] = NumberActionMap( [ "SetupActions" ],
133 "1": self.keyNumberGlobal,
134 "2": self.keyNumberGlobal,
135 "3": self.keyNumberGlobal,
136 "4": self.keyNumberGlobal,
137 "5": self.keyNumberGlobal,
138 "6": self.keyNumberGlobal,
139 "7": self.keyNumberGlobal,
140 "8": self.keyNumberGlobal,
141 "9": self.keyNumberGlobal,
142 "0": self.keyNumberGlobal
145 self.Timer = eTimer()
146 self.Timer.timeout.get().append(self.keyOK)
147 self.Timer.start(3000, True)
149 class InfoBarPowerKey:
150 """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
153 self.powerKeyTimer = eTimer()
154 self.powerKeyTimer.timeout.get().append(self.powertimer)
155 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
157 "powerdown": self.powerdown,
158 "powerup": self.powerup,
159 "discreteStandby": (self.standby, "Go standby"),
160 "discretePowerOff": (self.quit, "Go to deep standby"),
163 def powertimer(self):
164 print "PowerOff - Now!"
168 self.standbyblocked = 0
169 self.powerKeyTimer.start(3000, True)
172 self.powerKeyTimer.stop()
173 if self.standbyblocked == 0:
174 self.standbyblocked = 1
178 self.session.open(Standby, self)
184 class InfoBarNumberZap:
185 """ Handles an initial number for NumberZapping """
187 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
189 "1": self.keyNumberGlobal,
190 "2": self.keyNumberGlobal,
191 "3": self.keyNumberGlobal,
192 "4": self.keyNumberGlobal,
193 "5": self.keyNumberGlobal,
194 "6": self.keyNumberGlobal,
195 "7": self.keyNumberGlobal,
196 "8": self.keyNumberGlobal,
197 "9": self.keyNumberGlobal,
198 "0": self.keyNumberGlobal,
201 def keyNumberGlobal(self, number):
202 # print "You pressed number " + str(number)
204 self.servicelist.recallPrevService()
208 self.session.openWithCallback(self.numberEntered, NumberZap, number)
210 def numberEntered(self, retval):
211 # print self.servicelist
213 self.zapToNumber(retval)
215 def searchNumberHelper(self, serviceHandler, num, bouquet):
216 servicelist = serviceHandler.list(bouquet)
217 if not servicelist is None:
219 serviceIterator = servicelist.getNext()
220 if not serviceIterator.valid(): #check end of list
222 if serviceIterator.flags: #assume normal dvb service have no flags set
225 if not num: #found service with searched number ?
226 return serviceIterator, 0
229 def zapToNumber(self, number):
230 bouquet = self.servicelist.bouquet_root
232 serviceHandler = eServiceCenter.getInstance()
233 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
234 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
236 bouquetlist = serviceHandler.list(bouquet)
237 if not bouquetlist is None:
239 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
240 if not bouquet.valid(): #check end of list
242 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
244 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
245 if not service is None:
246 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
247 self.servicelist.clearPath()
248 if self.servicelist.bouquet_root != bouquet:
249 self.servicelist.enterPath(self.servicelist.bouquet_root)
250 self.servicelist.enterPath(bouquet)
251 self.servicelist.setCurrentSelection(service) #select the service in servicelist
252 self.servicelist.zap()
254 class InfoBarChannelSelection:
255 """ ChannelSelection - handles the channelSelection dialog and the initial
256 channelChange actions which open the channelSelection dialog """
259 self.servicelist = self.session.instantiateDialog(ChannelSelection)
261 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
263 "switchChannelUp": self.switchChannelUp,
264 "switchChannelDown": self.switchChannelDown,
265 "zapUp": (self.zapUp, _("next channel")),
266 "zapDown": (self.zapDown, _("previous channel")),
269 def switchChannelUp(self):
270 self.servicelist.moveUp()
271 self.session.execDialog(self.servicelist)
273 def switchChannelDown(self):
274 self.servicelist.moveDown()
275 self.session.execDialog(self.servicelist)
278 self.servicelist.moveUp()
279 self.servicelist.zap()
284 self.servicelist.moveDown()
285 self.servicelist.zap()
290 """ Handles a menu action, to open the (main) menu """
292 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
294 "mainMenu": (self.mainMenu, "Enter main menu..."),
298 print "loading mainmenu XML..."
299 menu = mdom.childNodes[0]
300 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
301 self.session.open(MainMenu, menu, menu.childNodes)
304 """ EPG - Opens an EPG list when the showEPGList action fires """
306 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
308 "showEPGList": (self.showEPG, _("show EPG...")),
312 if currentConfigSelectionElement(config.usage.epgtoggle) == "yes":
313 self.openSingleServiceEPG()
317 def showEPGList(self):
318 bouquets = self.servicelist.getBouquetList()
323 if cnt > 1: # show bouquet list
324 self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
325 elif cnt == 1: # add to only one existing bouquet
326 self.openBouquetEPG(bouquets[0][1])
327 else: #no bouquets so we open single epg
328 self.openSingleEPGSelector(self.session.nav.getCurrentlyPlayingServiceReference())
330 def bouquetEPGCallback(self, info):
332 self.openSingleServiceEPG()
334 def singleEPGCallback(self, info):
338 def openEventView(self):
341 service = self.session.nav.getCurrentService()
342 info = service.info()
345 self.epglist.append(ptr)
348 self.epglist.append(ptr)
349 if len(self.epglist) > 0:
350 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
354 def openSingleServiceEPG(self):
355 ref=self.session.nav.getCurrentlyPlayingServiceReference()
356 ptr=eEPGCache.getInstance()
357 if ptr.startTimeQuery(ref) != -1:
358 self.session.openWithCallback(self.singleEPGCallback, EPGSelection, ref)
359 else: # try to show now/next
360 print 'no epg for service', ref.toString()
363 def openBouquetEPG(self, bouquet):
364 ptr=eEPGCache.getInstance()
366 servicelist = eServiceCenter.getInstance().list(bouquet)
367 if not servicelist is None:
369 service = servicelist.getNext()
370 if not service.valid(): #check if end of list
372 if service.flags: #ignore non playable services
374 services.append(ServiceReference(service))
376 self.session.openWithCallback(self.bouquetEPGCallback, EPGSelection, services)
378 def openSingleEPGSelector(self, ref):
379 ptr=eEPGCache.getInstance()
380 if ptr.startTimeQuery(ref) != -1:
381 self.session.open(EPGSelection, ref)
382 else: # try to show now/next
383 print 'no epg for service', ref.toString()
386 service = self.session.nav.getCurrentService()
387 info = service.info()
390 self.epglist.append(ptr)
393 self.epglist.append(ptr)
394 if len(self.epglist) > 0:
395 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
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, skip
472 SEEK_STATE_PLAY = (0, 0, 0, 0)
473 SEEK_STATE_PAUSE = (1, 0, 0, 0)
474 SEEK_STATE_FF_2X = (0, 2, 0, 0)
475 SEEK_STATE_FF_4X = (0, 4, 0, 0)
476 SEEK_STATE_FF_8X = (0, 8, 0, 0)
477 SEEK_STATE_FF_32X = (0, 4, 0, 32)
478 SEEK_STATE_FF_64X = (0, 4, 0, 64)
479 SEEK_STATE_FF_128X = (0, 4, 0, 128)
481 SEEK_STATE_BACK_4X = (0, 0, 0, -4)
482 SEEK_STATE_BACK_32X = (0, 0, 0, -32)
483 SEEK_STATE_BACK_64X = (0, 0, 0, -64)
484 SEEK_STATE_BACK_128X = (0, 0, 0, -128)
486 SEEK_STATE_SM_HALF = (0, 0, 2, 0)
487 SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
488 SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
491 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
493 pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged,
494 pNavigation.evNewService: self.__serviceStarted
496 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
498 "pauseService": (self.pauseService, "pause"),
499 "unPauseService": (self.unPauseService, "continue"),
501 "seekFwd": (self.seekFwd, "skip forward"),
502 "seekFwdUp": (self.seekFwdUp, "skip forward"),
503 "seekBack": (self.seekBack, "skip backward"),
504 "seekBackUp": (self.seekBackUp, "skip backward"),
506 # give them a little more priority to win over color buttons
508 self.seekstate = self.SEEK_STATE_PLAY
509 self.seekTimer = eTimer()
510 self.seekTimer.timeout.get().append(self.seekTimerFired)
511 self.skipinterval = 500 # 500ms skip interval
512 self.onClose.append(self.delSeekTimer)
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)
528 def delSeekTimer(self):
533 def seekTimerFired(self):
534 self.seekbase += self.skipmode * self.skipinterval
536 # check if we bounced against the beginning of the file
537 if self.seekbase < 0:
539 self.setSeekState(self.SEEK_STATE_PLAY)
541 self.doSeek(self.seekbase)
543 def isSeekable(self):
544 service = self.session.nav.getCurrentService()
547 if service.seek() 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()
567 self.seekTimer.stop()
572 if service.seek() is None:
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, self.setSkipMode)[i](self.seekstate[i])
591 def setSkipMode(self, skipmode):
592 print "setskipmode", skipmode
593 self.skipmode = skipmode
595 self.seekTimer.stop()
597 self.seekTimer.start(500)
599 service = self.session.nav.getCurrentService()
603 seekable = service.seek()
608 seekable.setTrickmode(1)
610 seekable.setTrickmode(0)
612 self.seekbase = seekable.getPlayPosition()[1] / 90
614 def pauseService(self):
615 if self.seekstate == self.SEEK_STATE_PAUSE:
616 print "pause, but in fact unpause"
617 self.unPauseService()
619 if self.seekstate == self.SEEK_STATE_PLAY:
620 print "yes, playing."
622 print "no", self.seekstate
624 self.setSeekState(self.SEEK_STATE_PAUSE);
626 def unPauseService(self):
628 self.setSeekState(self.SEEK_STATE_PLAY);
630 def doSeek(self, seektime):
631 print "doseek", seektime
632 service = self.session.nav.getCurrentService()
636 seekable = service.seek()
639 seekable.seekTo(90 * seektime)
642 print "start fwd timer"
644 self.fwdKeyTimer.start(500)
647 print "start rewind timer"
649 self.rwdKeyTimer.start(500)
654 self.fwdKeyTimer.stop()
655 self.fwdtimer = False
657 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
658 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
659 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
660 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
661 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
662 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
663 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
664 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
665 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
666 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
667 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
668 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
669 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
670 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
671 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
673 self.setSeekState(lookup[self.seekstate]);
675 def seekBackUp(self):
678 self.rwdKeyTimer.stop()
679 self.rwdtimer = False
682 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
683 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
684 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
685 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
686 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
687 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
688 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
689 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
690 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
691 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
692 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
693 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
694 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
695 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
696 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
698 self.setSeekState(lookup[self.seekstate]);
700 def fwdTimerFire(self):
701 print "Display seek fwd"
702 self.fwdKeyTimer.stop()
703 self.fwdtimer = False
704 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
706 def fwdSeekTo(self, minutes):
707 print "Seek", minutes, "minutes forward"
709 service = self.session.nav.getCurrentService()
712 seekable = service.seek()
715 seekable.seekRelative(1, minutes * 60 * 90000)
717 def rwdTimerFire(self):
719 self.rwdKeyTimer.stop()
720 self.rwdtimer = False
721 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
723 def rwdSeekTo(self, minutes):
725 self.fwdSeekTo(0 - minutes)
727 class InfoBarShowMovies:
729 # i don't really like this class.
730 # it calls a not further specified "movie list" on up/down/movieList,
731 # so this is not more than an action map
733 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
735 "movieList": (self.showMovies, "movie list"),
736 "up": (self.showMovies, "movie list"),
737 "down": (self.showMovies, "movie list")
740 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
744 # Timeshift works the following way:
745 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
746 # - normal playback TUNER unused PLAY enable disable disable
747 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
748 # - user presess pause again FILE record PLAY enable disable enable
749 # - user fast forwards FILE record FF enable disable enable
750 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
751 # - user backwards FILE record BACK # !! enable disable enable
755 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
756 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
757 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
758 # - the user can now PVR around
759 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
760 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
762 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
763 # - if the user rewinds, or press pause, timeshift will be activated again
765 # note that a timeshift can be enabled ("recording") and
766 # activated (currently time-shifting).
768 class InfoBarTimeshift:
770 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
772 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
773 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
775 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
777 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
778 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
781 self.timeshift_enabled = 0
782 self.timeshift_state = 0
783 self.ts_pause_timer = eTimer()
784 self.ts_pause_timer.timeout.get().append(self.pauseService)
786 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
788 pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged
791 def getTimeshift(self):
792 service = self.session.nav.getCurrentService()
793 return service.timeshift()
795 def startTimeshift(self):
796 # TODO: check for harddisk! (or do this in the interface? would make
797 # more sense... for example radio could be timeshifted in memory,
798 # and the decision can't be made here)
799 print "enable timeshift"
800 ts = self.getTimeshift()
802 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
803 print "no ts interface"
806 if self.timeshift_enabled:
807 print "hu, timeshift already enabled?"
809 if not ts.startTimeshift():
810 self.timeshift_enabled = 1
813 self.setSeekState(self.SEEK_STATE_PAUSE)
815 # enable the "TimeshiftEnableActions", which will override
816 # the startTimeshift actions
817 self.__seekableStatusChanged()
819 print "timeshift failed"
822 def stopTimeshift(self):
823 print "disable timeshift"
824 ts = self.getTimeshift()
828 self.timeshift_enabled = 0
831 self.__seekableStatusChanged()
833 # activates timeshift, and seeks to (almost) the end
834 def activateTimeshiftEnd(self):
835 ts = self.getTimeshift()
840 if ts.isTimeshiftActive():
841 print "!! activate timeshift called - but shouldn't this be a normal pause?"
844 self.setSeekState(self.SEEK_STATE_PLAY)
845 ts.activateTimeshift()
847 # same as activateTimeshiftEnd, but pauses afterwards.
848 def activateTimeshiftEndAndPause(self):
849 state = self.seekstate
850 self.activateTimeshiftEnd()
852 # well, this is "andPause", but it could be pressed from pause,
853 # when pausing on the (fake-)"live" picture, so an un-pause
856 print "now, pauseService"
857 if state == self.SEEK_STATE_PLAY:
858 print "is PLAYING, start pause timer"
859 self.ts_pause_timer.start(200, 1)
862 self.unPauseService()
864 def __seekableStatusChanged(self):
867 print "self.isSeekable", self.isSeekable()
868 print "self.timeshift_enabled", self.timeshift_enabled
870 # when this service is not seekable, but timeshift
871 # is enabled, this means we can activate
873 if not self.isSeekable() and self.timeshift_enabled:
876 print "timeshift activate:", enabled
877 self["TimeshiftActivateActions"].setEnabled(enabled)
879 from RecordTimer import parseEvent
881 class InfoBarInstantRecord:
882 """Instant Record - handles the instantRecord action in order to
883 start/stop instant records"""
885 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
887 "instantRecord": (self.instantRecord, "Instant Record..."),
889 self.recording = None
891 self["BlinkingPoint"] = BlinkingPixmapConditional()
892 self.onShown.append(self["BlinkingPoint"].hideWidget)
893 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
895 def stopCurrentRecording(self):
896 self.session.nav.RecordTimer.removeEntry(self.recording)
897 self.recording = None
899 def startInstantRecording(self):
900 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
902 # try to get event info
905 service = self.session.nav.getCurrentService()
906 info = service.info()
907 ev = info.getEvent(0)
912 if event is not None:
913 data = parseEvent(event)
915 if begin < time.time():
924 data = (begin, end, data[2], data[3], data[4])
926 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
928 # fix me, description.
929 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
930 self.recording.dontSave = True
932 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
934 def isInstantRecordRunning(self):
935 if self.recording != None:
936 if self.recording.isRunning():
940 def recordQuestionCallback(self, answer):
944 if self.isInstantRecordRunning():
945 self.stopCurrentRecording()
947 self.startInstantRecording()
949 def instantRecord(self):
951 stat = os.stat(resolveFilename(SCOPE_HDD))
953 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
956 if self.isInstantRecordRunning():
957 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
959 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
961 from Screens.AudioSelection import AudioSelection
963 class InfoBarAudioSelection:
965 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
967 "audioSelection": (self.audioSelection, "Audio Options..."),
970 def audioSelection(self):
971 service = self.session.nav.getCurrentService()
972 audio = service.audioTracks()
973 n = audio.getNumberOfTracks()
975 self.session.open(AudioSelection, audio)
977 from Screens.SubserviceSelection import SubserviceSelection
979 class InfoBarSubserviceSelection:
981 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
983 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
986 def subserviceSelection(self):
987 service = self.session.nav.getCurrentService()
988 subservices = service.subServices()
989 n = subservices.getNumberOfSubservices()
991 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
993 def subserviceSelected(self, service):
994 if not service is None:
995 self.session.nav.playService(service)
997 class InfoBarAdditionalInfo:
999 self["DolbyActive"] = Pixmap()
1000 self["CryptActive"] = Pixmap()
1001 self["FormatActive"] = Pixmap()
1003 self["ButtonRed"] = PixmapConditional(withTimer = False)
1004 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1005 self.onShown.append(self["ButtonRed"].update)
1006 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1007 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1008 self.onShown.append(self["ButtonRedText"].update)
1010 self["ButtonGreen"] = Pixmap()
1011 self["ButtonGreenText"] = Label(_("Subservices"))
1013 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1014 self["ButtonYellow"].setConnect(lambda: False)
1016 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1017 self["ButtonBlue"].setConnect(lambda: False)
1019 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1021 def hideSubServiceIndication(self):
1022 self["ButtonGreen"].hideWidget()
1023 self["ButtonGreenText"].hide()
1025 def showSubServiceIndication(self):
1026 self["ButtonGreen"].showWidget()
1027 self["ButtonGreenText"].show()
1029 def checkFormat(self, service):
1030 info = service.info()
1031 if info is not None:
1032 aspect = info.getInfo(iServiceInformation.sAspect)
1033 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1034 self["FormatActive"].showWidget()
1036 self["FormatActive"].hideWidget()
1038 def checkSubservices(self, service):
1039 if service.subServices().getNumberOfSubservices() > 0:
1040 self.showSubServiceIndication()
1042 self.hideSubServiceIndication()
1044 def checkDolby(self, service):
1047 audio = service.audioTracks()
1048 if audio is not None:
1049 n = audio.getNumberOfTracks()
1051 i = audio.getTrackInfo(x)
1052 description = i.getDescription();
1053 if description.find("AC3") != -1 or description.find("DTS") != -1:
1057 self["DolbyActive"].showWidget()
1059 self["DolbyActive"].hideWidget()
1061 def checkCrypted(self, service):
1062 info = service.info()
1063 if info is not None:
1064 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1065 self["CryptActive"].showWidget()
1067 self["CryptActive"].hideWidget()
1069 def gotServiceEvent(self, ev):
1070 service = self.session.nav.getCurrentService()
1071 if ev == pNavigation.evUpdatedEventInfo:
1072 self.checkSubservices(service)
1073 self.checkFormat(service)
1074 elif ev == pNavigation.evUpdatedInfo:
1075 self.checkCrypted(service)
1076 self.checkDolby(service)
1077 elif ev == pNavigation.evStopService:
1078 self.hideSubServiceIndication()
1079 self["CryptActive"].hideWidget()
1080 self["DolbyActive"].hideWidget()
1081 self["FormatActive"].hideWidget()
1083 class InfoBarNotifications:
1085 self.onExecBegin.append(self.checkNotifications)
1086 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1088 def checkNotificationsIfExecing(self):
1090 self.checkNotifications()
1092 def checkNotifications(self):
1093 if len(Notifications.notifications):
1094 n = Notifications.notifications[0]
1095 Notifications.notifications = Notifications.notifications[1:]
1099 self.session.openWithCallback(cb, *n[1:])
1101 self.session.open(*n[1:])
1103 class InfoBarServiceNotifications:
1105 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1107 pNavigation.evEnd: self.serviceHasEnded
1110 def serviceHasEnded(self):
1111 print "service end!"
1114 self.setSeekState(self.SEEK_STATE_PLAY)