1 from ChannelSelection import ChannelSelection, BouquetSelector
3 from Components.ActionMap import ActionMap, HelpableActionMap
4 from Components.ActionMap import NumberActionMap
5 from Components.BlinkingPixmap import BlinkingPixmapConditional
6 from Components.Harddisk import harddiskmanager
7 from Components.Input import Input
8 from Components.Label import *
9 from Components.Pixmap import Pixmap, PixmapConditional
10 from Components.PluginComponent import plugins
11 from Components.ProgressBar import *
12 from Components.ServiceEventTracker import ServiceEventTracker
13 from Components.Sources.CurrentService import CurrentService
14 from Components.Sources.EventInfo import EventInfo
15 from Components.Sources.FrontendStatus import FrontendStatus
16 from Components.Sources.Boolean import Boolean
17 from Components.Sources.Clock import Clock
18 from Components.TimerList import TimerEntryComponent
19 from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean, configSelection, configElement_nonSave, getConfigListEntry
20 from Components.config import configfile, configsequencearg
22 from EpgSelection import EPGSelection
23 from Plugins.Plugin import PluginDescriptor
25 from Screen import Screen
26 from Screens.ChoiceBox import ChoiceBox
27 from Screens.Dish import Dish
28 from Screens.EventView import EventViewEPGSelect, EventViewSimple
29 from Screens.InputBox import InputBox
30 from Screens.MessageBox import MessageBox
31 from Screens.MinuteInput import MinuteInput
32 from Screens.TimerSelection import TimerSelection
33 from Screens.PictureInPicture import PictureInPicture
34 from Screens.SubtitleDisplay import SubtitleDisplay
35 from ServiceReference import ServiceReference
37 from Tools import Notifications
38 from Tools.Directories import *
40 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
47 from Components.config import config, currentConfigSelectionElement
50 from Menu import MainMenu, mdom
54 self.dishDialog = self.session.instantiateDialog(Dish)
55 self.onLayoutFinish.append(self.dishDialog.show)
57 class InfoBarShowHide:
58 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
66 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
68 "toggleShow": self.toggleShow,
72 self.__state = self.STATE_SHOWN
75 self.onExecBegin.append(self.show)
77 self.hideTimer = eTimer()
78 self.hideTimer.timeout.get().append(self.doTimerHide)
79 self.hideTimer.start(5000, True)
81 self.onShow.append(self.__onShow)
82 self.onHide.append(self.__onHide)
85 self.__state = self.STATE_SHOWN
88 def startHideTimer(self):
89 if self.__state == self.STATE_SHOWN and not self.__locked:
90 self.hideTimer.start(5000, True)
93 self.__state = self.STATE_HIDDEN
99 def doTimerHide(self):
100 self.hideTimer.stop()
101 if self.__state == self.STATE_SHOWN:
104 def toggleShow(self):
105 if self.__state == self.STATE_SHOWN:
107 self.hideTimer.stop()
108 elif self.__state == self.STATE_HIDDEN:
112 self.__locked = self.__locked + 1
115 self.hideTimer.stop()
117 def unlockShow(self):
118 self.__locked = self.__locked - 1
120 self.startHideTimer()
122 # def startShow(self):
123 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
124 # self.__state = self.STATE_SHOWN
126 # def startHide(self):
127 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
128 # self.__state = self.STATE_HIDDEN
130 class NumberZap(Screen):
137 self.close(int(self["number"].getText()))
139 def keyNumberGlobal(self, number):
140 self.Timer.start(3000, True) #reset timer
141 self.field = self.field + str(number)
142 self["number"].setText(self.field)
143 if len(self.field) >= 4:
146 def __init__(self, session, number):
147 Screen.__init__(self, session)
148 self.field = str(number)
150 self["channel"] = Label(_("Channel:"))
152 self["number"] = Label(self.field)
154 self["actions"] = NumberActionMap( [ "SetupActions" ],
158 "1": self.keyNumberGlobal,
159 "2": self.keyNumberGlobal,
160 "3": self.keyNumberGlobal,
161 "4": self.keyNumberGlobal,
162 "5": self.keyNumberGlobal,
163 "6": self.keyNumberGlobal,
164 "7": self.keyNumberGlobal,
165 "8": self.keyNumberGlobal,
166 "9": self.keyNumberGlobal,
167 "0": self.keyNumberGlobal
170 self.Timer = eTimer()
171 self.Timer.timeout.get().append(self.keyOK)
172 self.Timer.start(3000, True)
174 class InfoBarNumberZap:
175 """ Handles an initial number for NumberZapping """
177 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
179 "1": self.keyNumberGlobal,
180 "2": self.keyNumberGlobal,
181 "3": self.keyNumberGlobal,
182 "4": self.keyNumberGlobal,
183 "5": self.keyNumberGlobal,
184 "6": self.keyNumberGlobal,
185 "7": self.keyNumberGlobal,
186 "8": self.keyNumberGlobal,
187 "9": self.keyNumberGlobal,
188 "0": self.keyNumberGlobal,
191 def keyNumberGlobal(self, number):
192 # print "You pressed number " + str(number)
194 self.servicelist.recallPrevService()
197 self.session.openWithCallback(self.numberEntered, NumberZap, number)
199 def numberEntered(self, retval):
200 # print self.servicelist
202 self.zapToNumber(retval)
204 def searchNumberHelper(self, serviceHandler, num, bouquet):
205 servicelist = serviceHandler.list(bouquet)
206 if not servicelist is None:
208 serviceIterator = servicelist.getNext()
209 if not serviceIterator.valid(): #check end of list
211 if serviceIterator.flags: #assume normal dvb service have no flags set
214 if not num: #found service with searched number ?
215 return serviceIterator, 0
218 def zapToNumber(self, number):
219 bouquet = self.servicelist.bouquet_root
221 serviceHandler = eServiceCenter.getInstance()
222 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
223 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
225 bouquetlist = serviceHandler.list(bouquet)
226 if not bouquetlist is None:
228 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
229 if not bouquet.valid(): #check end of list
231 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
233 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
234 if not service is None:
235 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
236 self.servicelist.clearPath()
237 if self.servicelist.bouquet_root != bouquet:
238 self.servicelist.enterPath(self.servicelist.bouquet_root)
239 self.servicelist.enterPath(bouquet)
240 self.servicelist.setCurrentSelection(service) #select the service in servicelist
241 self.servicelist.zap()
243 config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
245 class InfoBarChannelSelection:
246 """ ChannelSelection - handles the channelSelection dialog and the initial
247 channelChange actions which open the channelSelection dialog """
250 self.servicelist = self.session.instantiateDialog(ChannelSelection)
252 if config.misc.initialchannelselection.value == 1:
253 self.onShown.append(self.firstRun)
255 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
257 "switchChannelUp": (self.switchChannelUp, _("open servicelist(up)")),
258 "switchChannelDown": (self.switchChannelDown, _("open servicelist(down)")),
259 "zapUp": (self.zapUp, _("previous channel")),
260 "zapDown": (self.zapDown, _("next channel")),
261 "historyBack": (self.historyBack, _("previous channel in history")),
262 "historyNext": (self.historyNext, _("next channel in history")),
263 "openServiceList": (self.openServiceList, _("open servicelist")),
266 def showTvChannelList(self, zap=False):
267 self.servicelist.setModeTv()
269 self.servicelist.zap()
270 self.session.execDialog(self.servicelist)
272 def showRadioChannelList(self, zap=False):
273 self.servicelist.setModeRadio()
275 self.servicelist.zap()
276 self.session.execDialog(self.servicelist)
279 self.onShown.remove(self.firstRun)
280 config.misc.initialchannelselection.value = 0
281 config.misc.initialchannelselection.save()
282 self.switchChannelDown()
284 def historyBack(self):
285 self.servicelist.historyBack()
287 def historyNext(self):
288 self.servicelist.historyNext()
290 def switchChannelUp(self):
291 self.servicelist.moveUp()
292 self.session.execDialog(self.servicelist)
294 def switchChannelDown(self):
295 self.servicelist.moveDown()
296 self.session.execDialog(self.servicelist)
298 def openServiceList(self):
299 self.session.execDialog(self.servicelist)
302 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
303 if self.servicelist.inBouquet() and self.servicelist.atBegin():
304 self.servicelist.prevBouquet()
305 self.servicelist.moveUp()
306 self.servicelist.zap()
310 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
311 self.servicelist.nextBouquet()
313 self.servicelist.moveDown()
314 self.servicelist.zap()
318 """ Handles a menu action, to open the (main) menu """
320 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
322 "mainMenu": (self.mainMenu, _("Enter main menu...")),
326 print "loading mainmenu XML..."
327 menu = mdom.childNodes[0]
328 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
329 self.session.open(MainMenu, menu, menu.childNodes)
331 class InfoBarSimpleEventView:
332 """ Opens the Eventview for now/next """
334 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
336 "showEventInfo": (self.openEventView, _("show event details")),
339 def openEventView(self):
341 service = self.session.nav.getCurrentService()
342 ref = self.session.nav.getCurrentlyPlayingServiceReference()
343 info = service.info()
346 self.epglist.append(ptr)
349 self.epglist.append(ptr)
350 if len(self.epglist) > 0:
351 self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
353 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
354 if len(self.epglist) > 1:
355 tmp = self.epglist[0]
356 self.epglist[0]=self.epglist[1]
358 setEvent(self.epglist[0])
361 """ EPG - Opens an EPG list when the showEPGList action fires """
363 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
365 iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
368 self.is_now_next = False
370 self.bouquetSel = None
371 self.eventView = None
372 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
374 "showEventInfo": (self.openEventView, _("show EPG...")),
377 def zapToService(self, service):
378 if not service is None:
379 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
380 self.servicelist.clearPath()
381 if self.servicelist.bouquet_root != self.epg_bouquet:
382 self.servicelist.enterPath(self.servicelist.bouquet_root)
383 self.servicelist.enterPath(self.epg_bouquet)
384 self.servicelist.setCurrentSelection(service) #select the service in servicelist
385 self.servicelist.zap()
387 def getBouquetServices(self, bouquet):
389 servicelist = eServiceCenter.getInstance().list(bouquet)
390 if not servicelist is None:
392 service = servicelist.getNext()
393 if not service.valid(): #check if end of list
395 if service.flags: #ignore non playable services
397 services.append(ServiceReference(service))
400 def openBouquetEPG(self, bouquet, withCallback=True):
401 services = self.getBouquetServices(bouquet)
403 self.epg_bouquet = bouquet
405 self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
407 self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
409 def changeBouquetCB(self, direction, epg):
412 self.bouquetSel.down()
415 bouquet = self.bouquetSel.getCurrent()
416 services = self.getBouquetServices(bouquet)
418 self.epg_bouquet = bouquet
419 epg.setServices(services)
421 def closed(self, ret=False):
422 closedScreen = self.dlg_stack.pop()
423 if self.bouquetSel and closedScreen == self.bouquetSel:
424 self.bouquetSel = None
425 elif self.eventView and closedScreen == self.eventView:
426 self.eventView = None
428 dlgs=len(self.dlg_stack)
430 self.dlg_stack[dlgs-1].close(dlgs > 1)
432 def openMultiServiceEPG(self, withCallback=True):
433 bouquets = self.servicelist.getBouquetList()
438 if cnt > 1: # show bouquet list
440 self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
441 self.dlg_stack.append(self.bouquetSel)
443 self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
445 self.openBouquetEPG(bouquets[0][1], withCallback)
447 def openSingleServiceEPG(self):
448 ref=self.session.nav.getCurrentlyPlayingServiceReference()
449 self.session.open(EPGSelection, ref)
451 def openSimilarList(self, eventid, refstr):
452 self.session.open(EPGSelection, refstr, None, eventid)
454 def getNowNext(self):
456 service = self.session.nav.getCurrentService()
457 info = service and service.info()
458 ptr = info and info.getEvent(0)
460 self.epglist.append(ptr)
461 ptr = info and info.getEvent(1)
463 self.epglist.append(ptr)
465 def __evEventInfoChanged(self):
466 if self.is_now_next and len(self.dlg_stack) == 1:
468 assert self.eventView
469 if len(self.epglist):
470 self.eventView.setEvent(self.epglist[0])
472 def openEventView(self):
473 ref = self.session.nav.getCurrentlyPlayingServiceReference()
475 if len(self.epglist) == 0:
476 self.is_now_next = False
477 epg = eEPGCache.getInstance()
478 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
480 self.epglist.append(ptr)
481 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
483 self.epglist.append(ptr)
485 self.is_now_next = True
486 if len(self.epglist) > 0:
487 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
488 self.dlg_stack.append(self.eventView)
490 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
491 self.openMultiServiceEPG(False)
493 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
494 if len(self.epglist) > 1:
495 tmp = self.epglist[0]
496 self.epglist[0]=self.epglist[1]
498 setEvent(self.epglist[0])
501 """provides a snr/agc/ber display"""
503 self["FrontendStatus"] = FrontendStatus(service_source = self.session.nav.getCurrentService)
506 """provides a current/next event info display"""
508 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.NOW)
509 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.NEXT)
511 class InfoBarServiceName:
513 self["CurrentService"] = CurrentService(self.session.nav)
516 """handles actions like seeking, pause"""
518 # ispause, isff, issm
519 SEEK_STATE_PLAY = (0, 0, 0, ">")
520 SEEK_STATE_PAUSE = (1, 0, 0, "||")
521 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
522 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
523 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
524 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
525 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
526 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
528 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
529 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
530 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
531 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
533 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
534 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
535 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
538 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
540 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
541 iPlayableService.evStart: self.__serviceStarted,
543 iPlayableService.evEOF: self.__evEOF,
544 iPlayableService.evSOF: self.__evSOF,
547 class InfoBarSeekActionMap(HelpableActionMap):
548 def __init__(self, screen, *args, **kwargs):
549 HelpableActionMap.__init__(self, screen, *args, **kwargs)
552 def action(self, contexts, action):
553 if action[:5] == "seek:":
554 time = int(action[5:])
555 self.screen.seekRelative(time * 90000)
558 return HelpableActionMap.action(self, contexts, action)
560 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
562 "pauseService": (self.pauseService, _("pause")),
563 "unPauseService": (self.unPauseService, _("continue")),
565 "seekFwd": (self.seekFwd, _("skip forward")),
566 "seekFwdDown": self.seekFwdDown,
567 "seekFwdUp": self.seekFwdUp,
568 "seekBack": (self.seekBack, _("skip backward")),
569 "seekBackDown": self.seekBackDown,
570 "seekBackUp": self.seekBackUp,
572 # give them a little more priority to win over color buttons
574 self.seekstate = self.SEEK_STATE_PLAY
575 self.onClose.append(self.delTimer)
577 self.fwdtimer = False
578 self.fwdKeyTimer = eTimer()
579 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
581 self.rwdtimer = False
582 self.rwdKeyTimer = eTimer()
583 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
585 self.onPlayStateChanged = [ ]
587 self.lockedBecauseOfSkipping = False
600 service = self.session.nav.getCurrentService()
604 seek = service.seek()
606 if seek is None or not seek.isCurrentlySeekable():
611 def isSeekable(self):
612 if self.getSeek() is None:
616 def __seekableStatusChanged(self):
617 print "seekable status changed!"
618 if not self.isSeekable():
619 self["SeekActions"].setEnabled(False)
620 print "not seekable, return to play"
621 self.setSeekState(self.SEEK_STATE_PLAY)
623 self["SeekActions"].setEnabled(True)
626 def __serviceStarted(self):
627 self.seekstate = self.SEEK_STATE_PLAY
629 def setSeekState(self, state):
630 service = self.session.nav.getCurrentService()
635 if not self.isSeekable():
636 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
637 state = self.SEEK_STATE_PLAY
639 pauseable = service.pause()
641 if pauseable is None:
642 print "not pauseable."
643 state = self.SEEK_STATE_PLAY
645 oldstate = self.seekstate
646 self.seekstate = state
649 if oldstate[i] != self.seekstate[i]:
650 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
652 for c in self.onPlayStateChanged:
655 self.checkSkipShowHideLock()
659 def pauseService(self):
660 if self.seekstate == self.SEEK_STATE_PAUSE:
661 print "pause, but in fact unpause"
662 self.unPauseService()
664 if self.seekstate == self.SEEK_STATE_PLAY:
665 print "yes, playing."
667 print "no", self.seekstate
669 self.setSeekState(self.SEEK_STATE_PAUSE);
671 def unPauseService(self):
673 if self.seekstate == self.SEEK_STATE_PLAY:
675 self.setSeekState(self.SEEK_STATE_PLAY);
677 def doSeek(self, seektime):
678 print "doseek", seektime
679 service = self.session.nav.getCurrentService()
683 seekable = self.getSeek()
687 seekable.seekTo(90 * seektime)
689 def seekFwdDown(self):
690 print "start fwd timer"
692 self.fwdKeyTimer.start(1000)
694 def seekBackDown(self):
695 print "start rewind timer"
697 self.rwdKeyTimer.start(1000)
702 self.fwdKeyTimer.stop()
703 self.fwdtimer = False
708 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
709 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
710 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
711 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
712 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
713 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
714 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
715 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
716 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
717 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
718 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
719 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
720 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
721 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
722 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
724 self.setSeekState(lookup[self.seekstate])
726 def seekBackUp(self):
729 self.rwdKeyTimer.stop()
730 self.rwdtimer = False
735 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
736 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
737 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
738 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
739 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
740 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
741 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
742 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
743 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
744 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
745 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
746 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
747 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
748 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
749 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
751 self.setSeekState(lookup[self.seekstate])
753 if self.seekstate == self.SEEK_STATE_PAUSE:
754 seekable = self.getSeek()
755 if seekable is not None:
756 seekable.seekRelative(-1, 3)
758 def fwdTimerFire(self):
759 print "Display seek fwd"
760 self.fwdKeyTimer.stop()
761 self.fwdtimer = False
762 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
764 def fwdSeekTo(self, minutes):
765 print "Seek", minutes, "minutes forward"
767 seekable = self.getSeek()
768 if seekable is not None:
769 seekable.seekRelative(1, minutes * 60 * 90000)
771 def rwdTimerFire(self):
773 self.rwdKeyTimer.stop()
774 self.rwdtimer = False
775 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
777 def rwdSeekTo(self, minutes):
779 self.fwdSeekTo(0 - minutes)
781 def checkSkipShowHideLock(self):
782 wantlock = self.seekstate != self.SEEK_STATE_PLAY
784 if self.lockedBecauseOfSkipping and not wantlock:
786 self.lockedBecauseOfSkipping = False
788 if wantlock and not self.lockedBecauseOfSkipping:
790 self.lockedBecauseOfSkipping = True
793 if self.seekstate != self.SEEK_STATE_PLAY:
794 self.setSeekState(self.SEEK_STATE_PAUSE)
796 #self.getSeek().seekRelative(1, -90000)
797 self.setSeekState(self.SEEK_STATE_PLAY)
799 self.setSeekState(self.SEEK_STATE_PAUSE)
802 self.setSeekState(self.SEEK_STATE_PLAY)
805 def seekRelative(self, diff):
806 seekable = self.getSeek()
807 if seekable is not None:
808 seekable.seekRelative(1, diff)
810 from Screens.PVRState import PVRState, TimeshiftState
812 class InfoBarPVRState:
813 def __init__(self, screen=PVRState):
814 self.onPlayStateChanged.append(self.__playStateChanged)
815 self.pvrStateDialog = self.session.instantiateDialog(screen)
816 self.onShow.append(self.__mayShow)
817 self.onHide.append(self.pvrStateDialog.hide)
820 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
821 self.pvrStateDialog.show()
823 def __playStateChanged(self, state):
824 playstateString = state[3]
825 self.pvrStateDialog["state"].setText(playstateString)
828 class InfoBarTimeshiftState(InfoBarPVRState):
830 InfoBarPVRState.__init__(self, screen=TimeshiftState)
832 class InfoBarShowMovies:
834 # i don't really like this class.
835 # it calls a not further specified "movie list" on up/down/movieList,
836 # so this is not more than an action map
838 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
840 "movieList": (self.showMovies, "movie list"),
841 "up": (self.showMovies, "movie list"),
842 "down": (self.showMovies, "movie list")
845 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
849 # Timeshift works the following way:
850 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
851 # - normal playback TUNER unused PLAY enable disable disable
852 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
853 # - user presess pause again FILE record PLAY enable disable enable
854 # - user fast forwards FILE record FF enable disable enable
855 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
856 # - user backwards FILE record BACK # !! enable disable enable
860 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
861 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
862 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
863 # - the user can now PVR around
864 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
865 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
867 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
868 # - if the user rewinds, or press pause, timeshift will be activated again
870 # note that a timeshift can be enabled ("recording") and
871 # activated (currently time-shifting).
873 class InfoBarTimeshift:
875 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
877 "timeshiftStart": (self.startTimeshift, _("start timeshift")), # the "yellow key"
878 "timeshiftStop": (self.stopTimeshift, _("stop timeshift")) # currently undefined :), probably 'TV'
880 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
882 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
883 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
884 }, prio=-1) # priority over record
886 self.timeshift_enabled = 0
887 self.timeshift_state = 0
888 self.ts_pause_timer = eTimer()
889 self.ts_pause_timer.timeout.get().append(self.pauseService)
891 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
893 iPlayableService.evStart: self.__serviceStarted,
894 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
897 def getTimeshift(self):
898 service = self.session.nav.getCurrentService()
899 return service and service.timeshift()
901 def startTimeshift(self):
902 print "enable timeshift"
903 ts = self.getTimeshift()
905 # self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
906 # print "no ts interface"
909 if self.timeshift_enabled:
910 print "hu, timeshift already enabled?"
912 if not ts.startTimeshift():
914 self.timeshift_enabled = 1
916 # we remove the "relative time" for now.
917 #self.pvrStateDialog["timeshift"].setRelative(time.time())
920 self.setSeekState(self.SEEK_STATE_PAUSE)
922 # enable the "TimeshiftEnableActions", which will override
923 # the startTimeshift actions
924 self.__seekableStatusChanged()
926 print "timeshift failed"
928 def stopTimeshift(self):
929 if not self.timeshift_enabled:
931 print "disable timeshift"
932 ts = self.getTimeshift()
935 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
937 def stopTimeshiftConfirmed(self, confirmed):
941 ts = self.getTimeshift()
946 self.timeshift_enabled = 0
949 self.__seekableStatusChanged()
951 # activates timeshift, and seeks to (almost) the end
952 def activateTimeshiftEnd(self):
953 ts = self.getTimeshift()
958 if ts.isTimeshiftActive():
959 print "!! activate timeshift called - but shouldn't this be a normal pause?"
962 self.setSeekState(self.SEEK_STATE_PLAY)
963 ts.activateTimeshift()
966 # same as activateTimeshiftEnd, but pauses afterwards.
967 def activateTimeshiftEndAndPause(self):
968 state = self.seekstate
969 self.activateTimeshiftEnd()
971 # well, this is "andPause", but it could be pressed from pause,
972 # when pausing on the (fake-)"live" picture, so an un-pause
975 print "now, pauseService"
976 if state == self.SEEK_STATE_PLAY:
977 print "is PLAYING, start pause timer"
978 self.ts_pause_timer.start(200, 1)
981 self.unPauseService()
983 def __seekableStatusChanged(self):
986 print "self.isSeekable", self.isSeekable()
987 print "self.timeshift_enabled", self.timeshift_enabled
989 # when this service is not seekable, but timeshift
990 # is enabled, this means we can activate
992 if not self.isSeekable() and self.timeshift_enabled:
995 print "timeshift activate:", enabled
996 self["TimeshiftActivateActions"].setEnabled(enabled)
998 def __serviceStarted(self):
999 self.timeshift_enabled = False
1000 self.__seekableStatusChanged()
1002 from Screens.PiPSetup import PiPSetup
1004 class InfoBarExtensions:
1006 self.session.pipshown = False
1008 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1010 "extensions": (self.extensions, _("view extensions...")),
1019 def extensions(self):
1021 if self.session.pipshown == False:
1022 list.append((_("Activate Picture in Picture"), self.PIPON))
1023 elif self.session.pipshown == True:
1024 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1025 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1026 list.append((_("Swap services"), self.PIPSWAP))
1028 s = self.getCurrentServiceSubtitle()
1029 l = s and s.getSubtitleList() or [ ]
1032 list.append(("Enable Subtitles: " + x[0], self.ENABLE_SUBTITLE, x[1]))
1034 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1036 def extensionCallback(self, answer):
1037 if answer is not None:
1038 if answer[1] == self.PIPON:
1039 self.session.pip = self.session.instantiateDialog(PictureInPicture)
1040 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1041 if self.session.pip.playService(newservice):
1042 self.session.pipshown = True
1043 self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
1045 self.session.pipshown = False
1046 del self.session.pip
1047 self.session.nav.playService(newservice)
1048 elif answer[1] == self.PIPOFF:
1049 del self.session.pip
1050 self.session.pipshown = False
1051 elif answer[1] == self.PIPSWAP:
1052 swapservice = self.session.nav.getCurrentlyPlayingServiceReference()
1053 if self.session.pip.servicePath:
1054 servicepath = self.servicelist.getCurrentServicePath()
1055 ref=servicepath[len(servicepath)-1]
1056 pipref=self.session.pip.getCurrentService()
1057 self.session.pip.playService(swapservice)
1058 self.servicelist.setCurrentServicePath(self.session.pip.servicePath)
1059 if pipref.toString() != ref.toString(): # is a subservice ?
1060 self.session.nav.stopService() # stop portal
1061 self.session.nav.playService(pipref) # start subservice
1062 self.session.pip.servicePath=servicepath
1063 elif answer[1] == self.MOVEPIP:
1064 self.session.open(PiPSetup, pip = self.session.pip)
1065 elif answer[1] == self.ENABLE_SUBTITLE:
1066 self.selected_subtitle = answer[2]
1067 self.subtitles_enabled = True
1069 from RecordTimer import parseEvent
1071 class InfoBarInstantRecord:
1072 """Instant Record - handles the instantRecord action in order to
1073 start/stop instant records"""
1075 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1077 "instantRecord": (self.instantRecord, _("Instant Record...")),
1080 self["BlinkingPoint"] = BlinkingPixmapConditional()
1081 self["BlinkingPoint"].hide()
1082 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1084 def stopCurrentRecording(self, entry = -1):
1085 if entry is not None and entry != -1:
1086 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1087 self.recording.remove(self.recording[entry])
1089 def startInstantRecording(self, limitEvent = False):
1090 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1092 # try to get event info
1095 service = self.session.nav.getCurrentService()
1096 epg = eEPGCache.getInstance()
1097 event = epg.lookupEventTime(serviceref, -1, 0)
1099 info = service.info()
1100 ev = info.getEvent(0)
1106 end = time.time() + 3600 * 10
1107 name = "instant record"
1111 if event is not None:
1112 curEvent = parseEvent(event)
1114 description = curEvent[3]
1115 eventid = curEvent[4]
1120 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1122 data = (begin, end, name, description, eventid)
1124 recording = self.session.nav.recordWithTimer(serviceref, *data)
1125 recording.dontSave = True
1126 self.recording.append(recording)
1128 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1130 def isInstantRecordRunning(self):
1131 print "self.recording:", self.recording
1132 if len(self.recording) > 0:
1133 for x in self.recording:
1138 def recordQuestionCallback(self, answer):
1139 print "pre:\n", self.recording
1141 if answer is None or answer[1] == "no":
1144 recording = self.recording[:]
1146 if not x in self.session.nav.RecordTimer.timer_list:
1147 self.recording.remove(x)
1148 elif x.dontSave and x.isRunning():
1149 list.append(TimerEntryComponent(x, False))
1151 if answer[1] == "changeduration":
1152 if len(self.recording) == 1:
1153 self.changeDuration(0)
1155 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1156 elif answer[1] == "stop":
1157 if len(self.recording) == 1:
1158 self.stopCurrentRecording(0)
1160 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1161 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1163 if answer[1] == "event":
1165 if answer[1] == "manualduration":
1166 self.selectedEntry = len(self.recording)
1167 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1168 self.startInstantRecording(limitEvent = limitEvent)
1170 print "after:\n", self.recording
1172 def changeDuration(self, entry):
1173 if entry is not None:
1174 self.selectedEntry = entry
1175 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1177 def inputCallback(self, value):
1178 if value is not None:
1179 print "stopping recording after", int(value), "minutes."
1180 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1181 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1183 def instantRecord(self):
1185 stat = os.stat(resolveFilename(SCOPE_HDD))
1187 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1190 if self.isInstantRecordRunning():
1191 self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("A recording is currently running.\nWhat do you want to do?"), list=[(_("stop recording"), "stop"), (_("change recording (duration)"), "changeduration"), (_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"), (_("do nothing"), "no")])
1193 self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Start recording?"), list=[(_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"),(_("don't record"), "no")])
1195 from Tools.ISO639 import LanguageCodes
1197 class InfoBarAudioSelection:
1199 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1201 "audioSelection": (self.audioSelection, _("Audio Options...")),
1204 def audioSelection(self):
1205 service = self.session.nav.getCurrentService()
1206 audio = service and service.audioTracks()
1207 self.audioTracks = audio
1208 n = audio and audio.getNumberOfTracks()
1209 keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
1211 print "tlist:", tlist
1213 self.audioChannel = service.audioChannel()
1216 i = audio.getTrackInfo(x)
1217 language = i.getLanguage()
1218 description = i.getDescription()
1220 if len(language) == 3:
1221 if language in LanguageCodes:
1222 language = LanguageCodes[language][0]
1224 if len(description):
1225 description += " (" + language + ")"
1227 description = language
1229 tlist.append((description, x))
1231 selectedAudio = tlist[0][1]
1232 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1236 if x[1] != selectedAudio:
1241 tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
1242 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
1244 del self.audioTracks
1246 def audioSelected(self, audio):
1247 if audio is not None:
1248 if isinstance(audio[1], str):
1249 if audio[1] == "mode":
1250 keys = ["red", "green", "yellow"]
1251 selection = self.audioChannel.getCurrentChannel()
1252 tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
1253 self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
1255 del self.audioChannel
1256 if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
1257 self.audioTracks.selectTrack(audio[1])
1259 del self.audioChannel
1260 del self.audioTracks
1262 def modeSelected(self, mode):
1263 if mode is not None:
1264 self.audioChannel.selectChannel(mode[1])
1265 del self.audioChannel
1267 class InfoBarSubserviceSelection:
1269 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1271 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1274 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1276 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1277 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1279 self["SubserviceQuickzapAction"].setEnabled(False)
1281 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1283 def checkSubservicesAvail(self, ev):
1284 if ev == iPlayableService.evUpdatedEventInfo:
1285 service = self.session.nav.getCurrentService()
1286 subservices = service and service.subServices()
1287 if not subservices or subservices.getNumberOfSubservices() == 0:
1288 self["SubserviceQuickzapAction"].setEnabled(False)
1290 def nextSubservice(self):
1291 self.changeSubservice(+1)
1293 def prevSubservice(self):
1294 self.changeSubservice(-1)
1296 def changeSubservice(self, direction):
1297 service = self.session.nav.getCurrentService()
1298 subservices = service and service.subServices()
1299 n = subservices and subservices.getNumberOfSubservices()
1302 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1304 if subservices.getSubservice(x).toString() == ref.toString():
1307 selection += direction
1312 newservice = subservices.getSubservice(selection)
1313 if newservice.valid():
1316 self.session.nav.playService(newservice)
1318 def subserviceSelection(self):
1319 service = self.session.nav.getCurrentService()
1320 subservices = service and service.subServices()
1322 n = subservices and subservices.getNumberOfSubservices()
1325 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1328 i = subservices.getSubservice(x)
1329 if i.toString() == ref.toString():
1331 tlist.append((i.getName(), i))
1333 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1335 def subserviceSelected(self, service):
1336 if not service is None:
1337 self["SubserviceQuickzapAction"].setEnabled(True)
1338 self.session.nav.playService(service[1])
1340 class InfoBarAdditionalInfo:
1342 self["NimA"] = Pixmap()
1343 self["NimB"] = Pixmap()
1344 self["NimA_Active"] = Pixmap()
1345 self["NimB_Active"] = Pixmap()
1347 self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0)
1348 self["TimeshiftPossible"] = self["RecordingPossible"]
1349 self["ExtensionsAvailable"] = Boolean(fixed=1)
1351 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1352 res_mgr = eDVBResourceManagerPtr()
1353 if eDVBResourceManager.getInstance(res_mgr) == 0:
1354 res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged)
1356 def tunerUseMaskChanged(self, mask):
1358 self["NimA_Active"].show()
1360 self["NimA_Active"].hide()
1362 self["NimB_Active"].show()
1364 self["NimB_Active"].hide()
1366 def checkTunerState(self, service):
1367 info = service.frontendInfo()
1368 feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber)
1369 if feNumber is None:
1379 def gotServiceEvent(self, ev):
1380 service = self.session.nav.getCurrentService()
1381 if ev == iPlayableService.evStart:
1382 self.checkTunerState(service)
1384 class InfoBarNotifications:
1386 self.onExecBegin.append(self.checkNotifications)
1387 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1388 self.onClose.append(self.__removeNotification)
1390 def __removeNotification(self):
1391 Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
1393 def checkNotificationsIfExecing(self):
1395 self.checkNotifications()
1397 def checkNotifications(self):
1398 if len(Notifications.notifications):
1399 n = Notifications.notifications[0]
1400 Notifications.notifications = Notifications.notifications[1:]
1403 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1405 self.session.open(n[1], *n[2], **n[3])
1407 class InfoBarServiceNotifications:
1409 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1411 iPlayableService.evEnd: self.serviceHasEnded
1414 def serviceHasEnded(self):
1415 print "service end!"
1418 self.setSeekState(self.SEEK_STATE_PLAY)
1422 class InfoBarCueSheetSupport:
1428 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1430 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1431 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1432 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1436 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1438 iPlayableService.evStart: self.__serviceStarted,
1441 def __serviceStarted(self):
1442 print "new service started! trying to download cuts!"
1443 self.downloadCuesheet()
1445 def __getSeekable(self):
1446 service = self.session.nav.getCurrentService()
1449 return service.seek()
1451 def cueGetCurrentPosition(self):
1452 seek = self.__getSeekable()
1455 r = seek.getPlayPosition()
1460 def jumpPreviousNextMark(self, cmp, alternative=None):
1461 current_pos = self.cueGetCurrentPosition()
1462 if current_pos is None:
1464 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1465 if mark is not None:
1467 elif alternative is not None:
1472 seekable = self.__getSeekable()
1473 if seekable is not None:
1474 seekable.seekTo(pts)
1476 def jumpPreviousMark(self):
1477 # we add 2 seconds, so if the play position is <2s after
1478 # the mark, the mark before will be used
1479 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1481 def jumpNextMark(self):
1482 self.jumpPreviousNextMark(lambda x: x)
1484 def getNearestCutPoint(self, pts, cmp=abs):
1487 for cp in self.cut_list:
1488 diff = cmp(cp[0] - pts)
1489 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1493 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1494 current_pos = self.cueGetCurrentPosition()
1495 if current_pos is None:
1496 print "not seekable"
1499 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1501 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1503 return nearest_cutpoint
1505 self.removeMark(nearest_cutpoint)
1506 elif not onlyremove and not onlyreturn:
1507 self.addMark((current_pos, self.CUT_TYPE_MARK))
1512 def addMark(self, point):
1513 bisect.insort(self.cut_list, point)
1514 self.uploadCuesheet()
1516 def removeMark(self, point):
1517 self.cut_list.remove(point)
1518 self.uploadCuesheet()
1520 def __getCuesheet(self):
1521 service = self.session.nav.getCurrentService()
1524 return service.cueSheet()
1526 def uploadCuesheet(self):
1527 cue = self.__getCuesheet()
1530 print "upload failed, no cuesheet interface"
1532 cue.setCutList(self.cut_list)
1534 def downloadCuesheet(self):
1535 cue = self.__getCuesheet()
1538 print "upload failed, no cuesheet interface"
1540 self.cut_list = cue.getCutList()
1542 class InfoBarSummary(Screen):
1544 <screen position="0,0" size="132,64">
1545 <widget source="CurrentTime" render="Label" position="50,46" size="82,18" font="Regular;16" >
1546 <convert type="ClockToText">WithSeconds</convert>
1548 <widget source="CurrentService" render="Label" position="0,4" size="132,42" font="Regular;18" >
1549 <convert type="ServiceName">Name</convert>
1553 def __init__(self, session, parent):
1554 Screen.__init__(self, session)
1555 self["CurrentService"] = CurrentService(self.session.nav)
1556 self["CurrentTime"] = Clock()
1558 class InfoBarSummarySupport:
1562 def createSummary(self):
1563 return InfoBarSummary
1565 class InfoBarTeletextPlugin:
1567 self.teletext_plugin = None
1569 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1570 self.teletext_plugin = p
1572 if self.teletext_plugin is not None:
1573 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1575 "startTeletext": (self.startTeletext, _("View teletext..."))
1578 print "no teletext plugin found!"
1580 def startTeletext(self):
1581 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())
1583 class InfoBarSubtitleSupport(object):
1585 object.__init__(self)
1586 self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
1587 self.__subtitles_enabled = False
1589 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1591 iPlayableService.evStart: self.__serviceStarted,
1594 def __serviceStarted(self):
1595 # reenable if it was enabled
1596 r = self.__subtitles_enabled
1597 self.__subtitles_enabled = False
1598 self.__selected_subtitle = None
1599 self.setSubtitlesEnable(r)
1601 def getCurrentServiceSubtitle(self):
1602 service = self.session.nav.getCurrentService()
1603 return service and service.subtitle()
1605 def setSubtitlesEnable(self, enable=True):
1606 subtitle = self.getCurrentServiceSubtitle()
1607 if enable and self.__selected_subtitle:
1608 if subtitle and not self.__subtitles_enabled:
1609 subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
1610 self.subtitle_window.show()
1611 self.__subtitles_enabled = True
1614 subtitle.disableSubtitles(self.subtitle_window.instance)
1616 self.subtitle_window.hide()
1617 self.__subtitles_enabled = False
1619 def setSelectedSubtitle(self, subtitle):
1620 if self.__selected_subtitle != subtitle and self.subtitles_enabled:
1622 self.__selected_subtitle = subtitle
1623 self.__serviceStarted()
1625 self.__selected_subtitle = subtitle
1627 subtitles_enabled = property(lambda self: self.__subtitles_enabled, setSubtitlesEnable)
1628 selected_subtitle = property(lambda self: self.__selected_subtitle, setSelectedSubtitle)