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
495 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
497 "pauseService": (self.pauseService, "pause"),
498 "unPauseService": (self.unPauseService, "continue"),
500 "seekFwd": (self.seekFwd, "skip forward"),
501 "seekFwdUp": (self.seekFwdUp, "skip forward"),
502 "seekBack": (self.seekBack, "skip backward"),
503 "seekBackUp": (self.seekBackUp, "skip backward"),
505 # give them a little more priority to win over color buttons
507 self.seekstate = self.SEEK_STATE_PLAY
508 self.seekTimer = eTimer()
509 self.seekTimer.timeout.get().append(self.seekTimerFired)
510 self.skipinterval = 500 # 500ms skip interval
511 self.onClose.append(self.delSeekTimer)
513 self.fwdtimer = False
514 self.fwdKeyTimer = eTimer()
515 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
517 self.rwdtimer = False
518 self.rwdKeyTimer = eTimer()
519 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
527 def delSeekTimer(self):
532 def seekTimerFired(self):
533 self.seekbase += self.skipmode * self.skipinterval
535 # check if we bounced against the beginning of the file
536 if self.seekbase < 0:
538 self.setSeekState(self.SEEK_STATE_PLAY)
540 self.doSeek(self.seekbase)
542 def isSeekable(self):
543 service = self.session.nav.getCurrentService()
546 if service.seek() is None:
551 def __seekableStatusChanged(self):
552 print "seekable status changed!"
553 if not self.isSeekable():
554 self["SeekActions"].setEnabled(False)
555 print "not seekable, return to play"
556 self.setSeekState(self.SEEK_STATE_PLAY)
558 self["SeekActions"].setEnabled(True)
561 def setSeekState(self, state):
562 service = self.session.nav.getCurrentService()
563 self.seekTimer.stop()
568 if service.seek() is None:
569 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
570 state = self.SEEK_STATE_PLAY
572 pauseable = service.pause()
574 if pauseable is None:
575 print "not pauseable."
576 state = self.SEEK_STATE_PLAY
578 oldstate = self.seekstate
579 self.seekstate = state
582 if oldstate[i] != self.seekstate[i]:
583 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
587 def setSkipMode(self, skipmode):
588 print "setskipmode", skipmode
589 self.skipmode = skipmode
591 self.seekTimer.stop()
593 self.seekTimer.start(500)
595 service = self.session.nav.getCurrentService()
599 seekable = service.seek()
604 seekable.setTrickmode(1)
606 seekable.setTrickmode(0)
608 self.seekbase = seekable.getPlayPosition()[1] / 90
610 def pauseService(self):
611 if self.seekstate == self.SEEK_STATE_PAUSE:
612 print "pause, but in fact unpause"
613 self.unPauseService()
615 if self.seekstate == self.SEEK_STATE_PLAY:
616 print "yes, playing."
618 print "no", self.seekstate
620 self.setSeekState(self.SEEK_STATE_PAUSE);
622 def unPauseService(self):
624 self.setSeekState(self.SEEK_STATE_PLAY);
626 def doSeek(self, seektime):
627 print "doseek", seektime
628 service = self.session.nav.getCurrentService()
632 seekable = service.seek()
635 seekable.seekTo(90 * seektime)
638 print "start fwd timer"
640 self.fwdKeyTimer.start(500)
643 print "start rewind timer"
645 self.rwdKeyTimer.start(500)
650 self.fwdKeyTimer.stop()
651 self.fwdtimer = False
653 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
654 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
655 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
656 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
657 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
658 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
659 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
660 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
661 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
662 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
663 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
664 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
665 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
666 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
667 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
669 self.setSeekState(lookup[self.seekstate]);
671 def seekBackUp(self):
674 self.rwdKeyTimer.stop()
675 self.rwdtimer = False
678 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
679 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
680 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
681 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
682 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
683 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
684 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
685 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
686 self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
687 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
688 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
689 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
690 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
691 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
692 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
694 self.setSeekState(lookup[self.seekstate]);
696 def fwdTimerFire(self):
697 print "Display seek fwd"
698 self.fwdKeyTimer.stop()
699 self.fwdtimer = False
700 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
702 def fwdSeekTo(self, minutes):
703 print "Seek", minutes, "minutes forward"
705 service = self.session.nav.getCurrentService()
708 seekable = service.seek()
711 seekable.seekRelative(1, minutes * 60 * 90000)
713 def rwdTimerFire(self):
715 self.rwdKeyTimer.stop()
716 self.rwdtimer = False
717 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
719 def rwdSeekTo(self, minutes):
721 self.fwdSeekTo(0 - minutes)
723 class InfoBarShowMovies:
725 # i don't really like this class.
726 # it calls a not further specified "movie list" on up/down/movieList,
727 # so this is not more than an action map
729 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
731 "movieList": (self.showMovies, "movie list"),
732 "up": (self.showMovies, "movie list"),
733 "down": (self.showMovies, "movie list")
736 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
740 # Timeshift works the following way:
741 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
742 # - normal playback TUNER unused PLAY enable disable disable
743 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
744 # - user presess pause again FILE record PLAY enable disable enable
745 # - user fast forwards FILE record FF enable disable enable
746 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
747 # - user backwards FILE record BACK # !! enable disable enable
751 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
752 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
753 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
754 # - the user can now PVR around
755 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
756 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
758 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
759 # - if the user rewinds, or press pause, timeshift will be activated again
761 # note that a timeshift can be enabled ("recording") and
762 # activated (currently time-shifting).
764 class InfoBarTimeshift:
766 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
768 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
769 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
771 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
773 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
774 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
777 self.timeshift_enabled = 0
778 self.timeshift_state = 0
779 self.ts_pause_timer = eTimer()
780 self.ts_pause_timer.timeout.get().append(self.pauseService)
782 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
784 pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged
787 def getTimeshift(self):
788 service = self.session.nav.getCurrentService()
789 return service.timeshift()
791 def startTimeshift(self):
792 # TODO: check for harddisk! (or do this in the interface? would make
793 # more sense... for example radio could be timeshifted in memory,
794 # and the decision can't be made here)
795 print "enable timeshift"
796 ts = self.getTimeshift()
798 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
799 print "no ts interface"
802 if self.timeshift_enabled:
803 print "hu, timeshift already enabled?"
805 if not ts.startTimeshift():
806 self.timeshift_enabled = 1
809 self.setSeekState(self.SEEK_STATE_PAUSE)
811 # enable the "TimeshiftEnableActions", which will override
812 # the startTimeshift actions
813 self.__seekableStatusChanged()
815 print "timeshift failed"
818 def stopTimeshift(self):
819 print "disable timeshift"
820 ts = self.getTimeshift()
824 self.timeshift_enabled = 0
827 self.__seekableStatusChanged()
829 # activates timeshift, and seeks to (almost) the end
830 def activateTimeshiftEnd(self):
831 ts = self.getTimeshift()
836 if ts.isTimeshiftActive():
837 print "!! activate timeshift called - but shouldn't this be a normal pause?"
840 self.setSeekState(self.SEEK_STATE_PLAY)
841 ts.activateTimeshift()
843 # same as activateTimeshiftEnd, but pauses afterwards.
844 def activateTimeshiftEndAndPause(self):
845 state = self.seekstate
846 self.activateTimeshiftEnd()
848 # well, this is "andPause", but it could be pressed from pause,
849 # when pausing on the (fake-)"live" picture, so an un-pause
852 print "now, pauseService"
853 if state == self.SEEK_STATE_PLAY:
854 print "is PLAYING, start pause timer"
855 self.ts_pause_timer.start(200, 1)
858 self.unPauseService()
860 def __seekableStatusChanged(self):
863 print "self.isSeekable", self.isSeekable()
864 print "self.timeshift_enabled", self.timeshift_enabled
866 # when this service is not seekable, but timeshift
867 # is enabled, this means we can activate
869 if not self.isSeekable() and self.timeshift_enabled:
872 print "timeshift activate:", enabled
873 self["TimeshiftActivateActions"].setEnabled(enabled)
875 from RecordTimer import parseEvent
877 class InfoBarInstantRecord:
878 """Instant Record - handles the instantRecord action in order to
879 start/stop instant records"""
881 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
883 "instantRecord": (self.instantRecord, "Instant Record..."),
885 self.recording = None
887 self["BlinkingPoint"] = BlinkingPixmapConditional()
888 self.onShown.append(self["BlinkingPoint"].hideWidget)
889 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
891 def stopCurrentRecording(self):
892 self.session.nav.RecordTimer.removeEntry(self.recording)
893 self.recording = None
895 def startInstantRecording(self):
896 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
898 # try to get event info
901 service = self.session.nav.getCurrentService()
902 info = service.info()
903 ev = info.getEvent(0)
908 if event is not None:
909 data = parseEvent(event)
911 if begin < time.time():
920 data = (begin, end, data[2], data[3], data[4])
922 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
924 # fix me, description.
925 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
926 self.recording.dontSave = True
928 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
930 def isInstantRecordRunning(self):
931 if self.recording != None:
932 if self.recording.isRunning():
936 def recordQuestionCallback(self, answer):
940 if self.isInstantRecordRunning():
941 self.stopCurrentRecording()
943 self.startInstantRecording()
945 def instantRecord(self):
947 stat = os.stat(resolveFilename(SCOPE_HDD))
949 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
952 if self.isInstantRecordRunning():
953 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
955 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
957 from Screens.AudioSelection import AudioSelection
959 class InfoBarAudioSelection:
961 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
963 "audioSelection": (self.audioSelection, "Audio Options..."),
966 def audioSelection(self):
967 service = self.session.nav.getCurrentService()
968 audio = service.audioTracks()
969 n = audio.getNumberOfTracks()
971 self.session.open(AudioSelection, audio)
973 from Screens.SubserviceSelection import SubserviceSelection
975 class InfoBarSubserviceSelection:
977 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
979 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
982 def subserviceSelection(self):
983 service = self.session.nav.getCurrentService()
984 subservices = service.subServices()
985 n = subservices.getNumberOfSubservices()
987 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
989 def subserviceSelected(self, service):
990 if not service is None:
991 self.session.nav.playService(service)
993 class InfoBarAdditionalInfo:
995 self["DolbyActive"] = Pixmap()
996 self["CryptActive"] = Pixmap()
997 self["FormatActive"] = Pixmap()
999 self["ButtonRed"] = PixmapConditional(withTimer = False)
1000 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1001 self.onShown.append(self["ButtonRed"].update)
1002 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1003 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1004 self.onShown.append(self["ButtonRedText"].update)
1006 self["ButtonGreen"] = Pixmap()
1007 self["ButtonGreenText"] = Label(_("Subservices"))
1009 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1010 self["ButtonYellow"].setConnect(lambda: False)
1012 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1013 self["ButtonBlue"].setConnect(lambda: False)
1015 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1017 def hideSubServiceIndication(self):
1018 self["ButtonGreen"].hideWidget()
1019 self["ButtonGreenText"].hide()
1021 def showSubServiceIndication(self):
1022 self["ButtonGreen"].showWidget()
1023 self["ButtonGreenText"].show()
1025 def checkFormat(self, service):
1026 info = service.info()
1027 if info is not None:
1028 aspect = info.getInfo(iServiceInformation.sAspect)
1029 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1030 self["FormatActive"].showWidget()
1032 self["FormatActive"].hideWidget()
1034 def checkSubservices(self, service):
1035 if service.subServices().getNumberOfSubservices() > 0:
1036 self.showSubServiceIndication()
1038 self.hideSubServiceIndication()
1040 def checkDolby(self, service):
1043 audio = service.audioTracks()
1044 if audio is not None:
1045 n = audio.getNumberOfTracks()
1047 i = audio.getTrackInfo(x)
1048 description = i.getDescription();
1049 if description.find("AC3") != -1 or description.find("DTS") != -1:
1053 self["DolbyActive"].showWidget()
1055 self["DolbyActive"].hideWidget()
1057 def checkCrypted(self, service):
1058 info = service.info()
1059 if info is not None:
1060 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1061 self["CryptActive"].showWidget()
1063 self["CryptActive"].hideWidget()
1065 def gotServiceEvent(self, ev):
1066 service = self.session.nav.getCurrentService()
1067 if ev == pNavigation.evUpdatedEventInfo:
1068 self.checkSubservices(service)
1069 self.checkFormat(service)
1070 elif ev == pNavigation.evUpdatedInfo:
1071 self.checkCrypted(service)
1072 self.checkDolby(service)
1073 elif ev == pNavigation.evStopService:
1074 self.hideSubServiceIndication()
1075 self["CryptActive"].hideWidget()
1076 self["DolbyActive"].hideWidget()
1077 self["FormatActive"].hideWidget()
1079 class InfoBarNotifications:
1081 self.onExecBegin.append(self.checkNotifications)
1082 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1084 def checkNotificationsIfExecing(self):
1086 self.checkNotifications()
1088 def checkNotifications(self):
1089 if len(Notifications.notifications):
1090 n = Notifications.notifications[0]
1091 Notifications.notifications = Notifications.notifications[1:]
1095 self.session.openWithCallback(cb, *n[1:])
1097 self.session.open(*n[1:])
1099 class InfoBarServiceNotifications:
1101 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1103 pNavigation.evEnd: self.serviceHasEnded
1106 def serviceHasEnded(self):
1107 print "service end!"
1110 self.setSeekState(self.SEEK_STATE_PLAY)