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.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["NumberActions"] = NumberActionMap( [ "NumberActions"],
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 "showEventInfo": (self.openEventView, _("show EPG...")),
311 def zapToService(self, service):
312 if not service is None:
313 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
314 self.servicelist.clearPath()
315 if self.servicelist.bouquet_root != self.epg_bouquet:
316 self.servicelist.enterPath(self.servicelist.bouquet_root)
317 self.servicelist.enterPath(self.epg_bouquet)
318 self.servicelist.setCurrentSelection(service) #select the service in servicelist
319 self.servicelist.zap()
321 def openBouquetEPG(self, bouquet):
322 ptr=eEPGCache.getInstance()
324 servicelist = eServiceCenter.getInstance().list(bouquet)
325 if not servicelist is None:
327 service = servicelist.getNext()
328 if not service.valid(): #check if end of list
330 if service.flags: #ignore non playable services
332 services.append(ServiceReference(service))
334 self.epg_bouquet = bouquet
335 self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
337 def closed(self, ret):
341 def openMultiServiceEPG(self):
342 bouquets = self.servicelist.getBouquetList()
347 if cnt > 1: # show bouquet list
348 self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
350 self.openBouquetEPG(bouquets[0][1])
352 def openSingleServiceEPG(self):
353 ref=self.session.nav.getCurrentlyPlayingServiceReference()
354 ptr=eEPGCache.getInstance()
355 self.session.openWithCallback(self.closed, EPGSelection, ref)
357 def openEventView(self):
359 service = self.session.nav.getCurrentService()
360 ref = self.session.nav.getCurrentlyPlayingServiceReference()
361 info = service.info()
364 self.epglist.append(ptr)
367 self.epglist.append(ptr)
368 if len(self.epglist) == 0:
369 epg = eEPGCache.getInstance()
370 ptr = epg.lookupEventTime(ref, -1)
372 self.epglist.append(ptr)
373 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
375 self.epglist.append(ptr)
376 if len(self.epglist) > 0:
377 self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
379 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
380 self.openMultiServiceEPG()
382 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
383 if len(self.epglist) > 1:
384 tmp = self.epglist[0]
385 self.epglist[0]=self.epglist[1]
387 setEvent(self.epglist[0])
392 """provides a snr/agc/ber display"""
394 self["snr"] = Label()
395 self["agc"] = Label()
396 self["ber"] = Label()
397 self["snr_percent"] = Label()
398 self["agc_percent"] = Label()
399 self["ber_count"] = Label()
400 self["snr_progress"] = ProgressBar()
401 self["agc_progress"] = ProgressBar()
402 self["ber_progress"] = ProgressBar()
403 self.timer = eTimer()
404 self.timer.timeout.get().append(self.updateTunerInfo)
405 self.timer.start(1000)
411 return (long)(log(val)/log(2))
414 def updateTunerInfo(self):
415 if self.instance.isVisible():
416 service = self.session.nav.getCurrentService()
420 if service is not None:
421 feinfo = service.frontendStatusInfo()
422 if feinfo is not None:
423 ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
424 snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
425 agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
426 self["snr_percent"].setText("%d%%"%(snr))
427 self["agc_percent"].setText("%d%%"%(agc))
428 self["ber_count"].setText("%d"%(ber))
429 self["snr_progress"].setValue(snr)
430 self["agc_progress"].setValue(agc)
431 self["ber_progress"].setValue(self.calc(ber))
434 """provides a current/next event info display"""
436 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
437 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
439 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
440 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
442 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
443 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
445 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
447 class InfoBarServiceName:
449 self["ServiceName"] = ServiceName(self.session.nav)
452 """handles actions like seeking, pause"""
454 # ispause, isff, issm, skip
455 SEEK_STATE_PLAY = (0, 0, 0, 0)
456 SEEK_STATE_PAUSE = (1, 0, 0, 0)
457 SEEK_STATE_FF_2X = (0, 2, 0, 0)
458 SEEK_STATE_FF_4X = (0, 4, 0, 0)
459 SEEK_STATE_FF_8X = (0, 8, 0, 0)
460 SEEK_STATE_FF_32X = (0, 4, 0, 32)
461 SEEK_STATE_FF_64X = (0, 4, 0, 64)
462 SEEK_STATE_FF_128X = (0, 4, 0, 128)
464 SEEK_STATE_BACK_4X = (0, 0, 0, -4)
465 SEEK_STATE_BACK_32X = (0, 0, 0, -32)
466 SEEK_STATE_BACK_64X = (0, 0, 0, -64)
467 SEEK_STATE_BACK_128X = (0, 0, 0, -128)
469 SEEK_STATE_SM_HALF = (0, 0, 2, 0)
470 SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
471 SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
474 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
476 pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged,
477 pNavigation.evNewService: self.__serviceStarted
479 self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
481 "pauseService": (self.pauseService, "pause"),
482 "unPauseService": (self.unPauseService, "continue"),
484 "seekFwd": (self.seekFwd, "skip forward"),
485 "seekFwdUp": (self.seekFwdUp, "skip forward"),
486 "seekBack": (self.seekBack, "skip backward"),
487 "seekBackUp": (self.seekBackUp, "skip backward"),
489 # give them a little more priority to win over color buttons
491 self.seekstate = self.SEEK_STATE_PLAY
492 self.seekTimer = eTimer()
493 self.seekTimer.timeout.get().append(self.seekTimerFired)
494 self.skipinterval = 500 # 500ms skip interval
495 self.onClose.append(self.delSeekTimer)
497 self.fwdtimer = False
498 self.fwdKeyTimer = eTimer()
499 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
501 self.rwdtimer = False
502 self.rwdKeyTimer = eTimer()
503 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
511 def delSeekTimer(self):
516 def seekTimerFired(self):
517 self.seekbase += self.skipmode * self.skipinterval
519 # check if we bounced against the beginning of the file
520 if self.seekbase < 0:
522 self.setSeekState(self.SEEK_STATE_PLAY)
524 self.doSeek(self.seekbase)
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()
550 self.seekTimer.stop()
555 if service.seek() is None:
556 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
557 state = self.SEEK_STATE_PLAY
559 pauseable = service.pause()
561 if pauseable is None:
562 print "not pauseable."
563 state = self.SEEK_STATE_PLAY
565 oldstate = self.seekstate
566 self.seekstate = state
569 if oldstate[i] != self.seekstate[i]:
570 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
574 def setSkipMode(self, skipmode):
575 print "setskipmode", skipmode
576 self.skipmode = skipmode
578 self.seekTimer.stop()
580 self.seekTimer.start(500)
582 service = self.session.nav.getCurrentService()
586 seekable = service.seek()
591 seekable.setTrickmode(1)
593 seekable.setTrickmode(0)
595 self.seekbase = seekable.getPlayPosition()[1] / 90
597 def pauseService(self):
598 if self.seekstate == self.SEEK_STATE_PAUSE:
599 print "pause, but in fact unpause"
600 self.unPauseService()
602 if self.seekstate == self.SEEK_STATE_PLAY:
603 print "yes, playing."
605 print "no", self.seekstate
607 self.setSeekState(self.SEEK_STATE_PAUSE);
609 def unPauseService(self):
611 self.setSeekState(self.SEEK_STATE_PLAY);
613 def doSeek(self, seektime):
614 print "doseek", seektime
615 service = self.session.nav.getCurrentService()
619 seekable = service.seek()
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 service = self.session.nav.getCurrentService()
695 seekable = service.seek()
698 seekable.seekRelative(1, minutes * 60 * 90000)
700 def rwdTimerFire(self):
702 self.rwdKeyTimer.stop()
703 self.rwdtimer = False
704 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
706 def rwdSeekTo(self, minutes):
708 self.fwdSeekTo(0 - minutes)
710 class InfoBarShowMovies:
712 # i don't really like this class.
713 # it calls a not further specified "movie list" on up/down/movieList,
714 # so this is not more than an action map
716 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
718 "movieList": (self.showMovies, "movie list"),
719 "up": (self.showMovies, "movie list"),
720 "down": (self.showMovies, "movie list")
723 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
727 # Timeshift works the following way:
728 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
729 # - normal playback TUNER unused PLAY enable disable disable
730 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
731 # - user presess pause again FILE record PLAY enable disable enable
732 # - user fast forwards FILE record FF enable disable enable
733 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
734 # - user backwards FILE record BACK # !! enable disable enable
738 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
739 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
740 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
741 # - the user can now PVR around
742 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
743 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
745 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
746 # - if the user rewinds, or press pause, timeshift will be activated again
748 # note that a timeshift can be enabled ("recording") and
749 # activated (currently time-shifting).
751 class InfoBarTimeshift:
753 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
755 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
756 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
758 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
760 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
761 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
764 self.timeshift_enabled = 0
765 self.timeshift_state = 0
766 self.ts_pause_timer = eTimer()
767 self.ts_pause_timer.timeout.get().append(self.pauseService)
769 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
771 pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged
774 def getTimeshift(self):
775 service = self.session.nav.getCurrentService()
776 return service.timeshift()
778 def startTimeshift(self):
779 # TODO: check for harddisk! (or do this in the interface? would make
780 # more sense... for example radio could be timeshifted in memory,
781 # and the decision can't be made here)
782 print "enable timeshift"
783 ts = self.getTimeshift()
785 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
786 print "no ts interface"
789 if self.timeshift_enabled:
790 print "hu, timeshift already enabled?"
792 if not ts.startTimeshift():
793 self.timeshift_enabled = 1
796 self.setSeekState(self.SEEK_STATE_PAUSE)
798 # enable the "TimeshiftEnableActions", which will override
799 # the startTimeshift actions
800 self.__seekableStatusChanged()
802 print "timeshift failed"
805 def stopTimeshift(self):
806 print "disable timeshift"
807 ts = self.getTimeshift()
811 self.timeshift_enabled = 0
814 self.__seekableStatusChanged()
816 # activates timeshift, and seeks to (almost) the end
817 def activateTimeshiftEnd(self):
818 ts = self.getTimeshift()
823 if ts.isTimeshiftActive():
824 print "!! activate timeshift called - but shouldn't this be a normal pause?"
827 self.setSeekState(self.SEEK_STATE_PLAY)
828 ts.activateTimeshift()
830 # same as activateTimeshiftEnd, but pauses afterwards.
831 def activateTimeshiftEndAndPause(self):
832 state = self.seekstate
833 self.activateTimeshiftEnd()
835 # well, this is "andPause", but it could be pressed from pause,
836 # when pausing on the (fake-)"live" picture, so an un-pause
839 print "now, pauseService"
840 if state == self.SEEK_STATE_PLAY:
841 print "is PLAYING, start pause timer"
842 self.ts_pause_timer.start(200, 1)
845 self.unPauseService()
847 def __seekableStatusChanged(self):
850 print "self.isSeekable", self.isSeekable()
851 print "self.timeshift_enabled", self.timeshift_enabled
853 # when this service is not seekable, but timeshift
854 # is enabled, this means we can activate
856 if not self.isSeekable() and self.timeshift_enabled:
859 print "timeshift activate:", enabled
860 self["TimeshiftActivateActions"].setEnabled(enabled)
862 from RecordTimer import parseEvent
864 class InfoBarInstantRecord:
865 """Instant Record - handles the instantRecord action in order to
866 start/stop instant records"""
868 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
870 "instantRecord": (self.instantRecord, "Instant Record..."),
872 self.recording = None
874 self["BlinkingPoint"] = BlinkingPixmapConditional()
875 self.onShown.append(self["BlinkingPoint"].hideWidget)
876 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
878 def stopCurrentRecording(self):
879 self.session.nav.RecordTimer.removeEntry(self.recording)
880 self.recording = None
882 def startInstantRecording(self):
883 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
885 # try to get event info
888 service = self.session.nav.getCurrentService()
889 info = service.info()
890 ev = info.getEvent(0)
895 if event is not None:
896 data = parseEvent(event)
898 if begin < time.time():
907 data = (begin, end, data[2], data[3], data[4])
909 data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
911 # fix me, description.
912 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
913 self.recording.dontSave = True
915 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
917 def isInstantRecordRunning(self):
918 if self.recording != None:
919 if self.recording.isRunning():
923 def recordQuestionCallback(self, answer):
927 if self.isInstantRecordRunning():
928 self.stopCurrentRecording()
930 self.startInstantRecording()
932 def instantRecord(self):
934 stat = os.stat(resolveFilename(SCOPE_HDD))
936 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
939 if self.isInstantRecordRunning():
940 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
942 self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
944 from Screens.AudioSelection import AudioSelection
946 class InfoBarAudioSelection:
948 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
950 "audioSelection": (self.audioSelection, "Audio Options..."),
953 def audioSelection(self):
954 service = self.session.nav.getCurrentService()
955 audio = service.audioTracks()
956 n = audio.getNumberOfTracks()
958 self.session.open(AudioSelection, audio)
960 from Screens.SubserviceSelection import SubserviceSelection
962 class InfoBarSubserviceSelection:
964 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
966 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
969 def subserviceSelection(self):
970 service = self.session.nav.getCurrentService()
971 subservices = service.subServices()
972 n = subservices.getNumberOfSubservices()
974 self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
976 def subserviceSelected(self, service):
977 if not service is None:
978 self.session.nav.playService(service)
980 class InfoBarAdditionalInfo:
982 self["DolbyActive"] = Pixmap()
983 self["CryptActive"] = Pixmap()
984 self["FormatActive"] = Pixmap()
986 self["ButtonRed"] = PixmapConditional(withTimer = False)
987 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
988 self.onShown.append(self["ButtonRed"].update)
989 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
990 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
991 self.onShown.append(self["ButtonRedText"].update)
993 self["ButtonGreen"] = Pixmap()
994 self["ButtonGreenText"] = Label(_("Subservices"))
996 self["ButtonYellow"] = PixmapConditional(withTimer = False)
997 self["ButtonYellow"].setConnect(lambda: False)
999 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1000 self["ButtonBlue"].setConnect(lambda: False)
1002 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1004 def hideSubServiceIndication(self):
1005 self["ButtonGreen"].hideWidget()
1006 self["ButtonGreenText"].hide()
1008 def showSubServiceIndication(self):
1009 self["ButtonGreen"].showWidget()
1010 self["ButtonGreenText"].show()
1012 def checkFormat(self, service):
1013 info = service.info()
1014 if info is not None:
1015 aspect = info.getInfo(iServiceInformation.sAspect)
1016 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1017 self["FormatActive"].showWidget()
1019 self["FormatActive"].hideWidget()
1021 def checkSubservices(self, service):
1022 if service.subServices().getNumberOfSubservices() > 0:
1023 self.showSubServiceIndication()
1025 self.hideSubServiceIndication()
1027 def checkDolby(self, service):
1030 audio = service.audioTracks()
1031 if audio is not None:
1032 n = audio.getNumberOfTracks()
1034 i = audio.getTrackInfo(x)
1035 description = i.getDescription();
1036 if description.find("AC3") != -1 or description.find("DTS") != -1:
1040 self["DolbyActive"].showWidget()
1042 self["DolbyActive"].hideWidget()
1044 def checkCrypted(self, service):
1045 info = service.info()
1046 if info is not None:
1047 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1048 self["CryptActive"].showWidget()
1050 self["CryptActive"].hideWidget()
1052 def gotServiceEvent(self, ev):
1053 service = self.session.nav.getCurrentService()
1054 if ev == pNavigation.evUpdatedEventInfo:
1055 self.checkSubservices(service)
1056 self.checkFormat(service)
1057 elif ev == pNavigation.evUpdatedInfo:
1058 self.checkCrypted(service)
1059 self.checkDolby(service)
1060 elif ev == pNavigation.evStopService:
1061 self.hideSubServiceIndication()
1062 self["CryptActive"].hideWidget()
1063 self["DolbyActive"].hideWidget()
1064 self["FormatActive"].hideWidget()
1066 class InfoBarNotifications:
1068 self.onExecBegin.append(self.checkNotifications)
1069 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1071 def checkNotificationsIfExecing(self):
1073 self.checkNotifications()
1075 def checkNotifications(self):
1076 if len(Notifications.notifications):
1077 n = Notifications.notifications[0]
1078 Notifications.notifications = Notifications.notifications[1:]
1082 self.session.openWithCallback(cb, *n[1:])
1084 self.session.open(*n[1:])
1086 class InfoBarServiceNotifications:
1088 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1090 pNavigation.evEnd: self.serviceHasEnded
1093 def serviceHasEnded(self):
1094 print "service end!"
1097 self.setSeekState(self.SEEK_STATE_PLAY)