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)
833 class InfoBarShowMovies:
835 # i don't really like this class.
836 # it calls a not further specified "movie list" on up/down/movieList,
837 # so this is not more than an action map
839 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
841 "movieList": (self.showMovies, "movie list"),
842 "up": (self.showMovies, "movie list"),
843 "down": (self.showMovies, "movie list")
846 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
850 # Timeshift works the following way:
851 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
852 # - normal playback TUNER unused PLAY enable disable disable
853 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
854 # - user presess pause again FILE record PLAY enable disable enable
855 # - user fast forwards FILE record FF enable disable enable
856 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
857 # - user backwards FILE record BACK # !! enable disable enable
861 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
862 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
863 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
864 # - the user can now PVR around
865 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
866 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
868 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
869 # - if the user rewinds, or press pause, timeshift will be activated again
871 # note that a timeshift can be enabled ("recording") and
872 # activated (currently time-shifting).
874 class InfoBarTimeshift:
876 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
878 "timeshiftStart": (self.startTimeshift, _("start timeshift")), # the "yellow key"
879 "timeshiftStop": (self.stopTimeshift, _("stop timeshift")) # currently undefined :), probably 'TV'
881 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
883 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
884 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
885 }, prio=-1) # priority over record
887 self.timeshift_enabled = 0
888 self.timeshift_state = 0
889 self.ts_pause_timer = eTimer()
890 self.ts_pause_timer.timeout.get().append(self.pauseService)
892 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
894 iPlayableService.evStart: self.__serviceStarted,
895 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
898 def getTimeshift(self):
899 service = self.session.nav.getCurrentService()
900 return service and service.timeshift()
902 def startTimeshift(self):
903 print "enable timeshift"
904 ts = self.getTimeshift()
906 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
907 print "no ts interface"
910 if self.timeshift_enabled:
911 print "hu, timeshift already enabled?"
913 if not ts.startTimeshift():
915 self.timeshift_enabled = 1
917 # we remove the "relative time" for now.
918 #self.pvrStateDialog["timeshift"].setRelative(time.time())
921 self.setSeekState(self.SEEK_STATE_PAUSE)
923 # enable the "TimeshiftEnableActions", which will override
924 # the startTimeshift actions
925 self.__seekableStatusChanged()
927 print "timeshift failed"
929 def stopTimeshift(self):
930 if not self.timeshift_enabled:
932 print "disable timeshift"
933 ts = self.getTimeshift()
936 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
938 def stopTimeshiftConfirmed(self, confirmed):
942 ts = self.getTimeshift()
947 self.timeshift_enabled = 0
950 self.__seekableStatusChanged()
952 # activates timeshift, and seeks to (almost) the end
953 def activateTimeshiftEnd(self):
954 ts = self.getTimeshift()
959 if ts.isTimeshiftActive():
960 print "!! activate timeshift called - but shouldn't this be a normal pause?"
963 self.setSeekState(self.SEEK_STATE_PLAY)
964 ts.activateTimeshift()
967 # same as activateTimeshiftEnd, but pauses afterwards.
968 def activateTimeshiftEndAndPause(self):
969 state = self.seekstate
970 self.activateTimeshiftEnd()
972 # well, this is "andPause", but it could be pressed from pause,
973 # when pausing on the (fake-)"live" picture, so an un-pause
976 print "now, pauseService"
977 if state == self.SEEK_STATE_PLAY:
978 print "is PLAYING, start pause timer"
979 self.ts_pause_timer.start(200, 1)
982 self.unPauseService()
984 def __seekableStatusChanged(self):
987 print "self.isSeekable", self.isSeekable()
988 print "self.timeshift_enabled", self.timeshift_enabled
990 # when this service is not seekable, but timeshift
991 # is enabled, this means we can activate
993 if not self.isSeekable() and self.timeshift_enabled:
996 print "timeshift activate:", enabled
997 self["TimeshiftActivateActions"].setEnabled(enabled)
999 def __serviceStarted(self):
1000 self.timeshift_enabled = False
1001 self.__seekableStatusChanged()
1003 from Screens.PiPSetup import PiPSetup
1005 class InfoBarExtensions:
1007 self.session.pipshown = False
1009 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1011 "extensions": (self.extensions, _("view extensions...")),
1020 def extensions(self):
1022 if self.session.pipshown == False:
1023 list.append((_("Activate Picture in Picture"), self.PIPON))
1024 elif self.session.pipshown == True:
1025 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1026 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1027 list.append((_("Swap services"), self.PIPSWAP))
1029 s = self.getCurrentServiceSubtitle()
1030 l = s and s.getSubtitleList() or [ ]
1033 list.append(("DEBUG: Enable Subtitles: " + x[0], self.ENABLE_SUBTITLE, x[1]))
1035 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1037 def extensionCallback(self, answer):
1038 if answer is not None:
1039 if answer[1] == self.PIPON:
1040 self.session.pip = self.session.instantiateDialog(PictureInPicture)
1041 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1042 if self.session.pip.playService(newservice):
1043 self.session.pipshown = True
1044 self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
1046 self.session.pipshown = False
1047 del self.session.pip
1048 self.session.nav.playService(newservice)
1049 elif answer[1] == self.PIPOFF:
1050 del self.session.pip
1051 self.session.pipshown = False
1052 elif answer[1] == self.PIPSWAP:
1053 swapservice = self.session.nav.getCurrentlyPlayingServiceReference()
1054 if self.session.pip.servicePath:
1055 servicepath = self.servicelist.getCurrentServicePath()
1056 ref=servicepath[len(servicepath)-1]
1057 pipref=self.session.pip.getCurrentService()
1058 self.session.pip.playService(swapservice)
1059 self.servicelist.setCurrentServicePath(self.session.pip.servicePath)
1060 if pipref.toString() != ref.toString(): # is a subservice ?
1061 self.session.nav.stopService() # stop portal
1062 self.session.nav.playService(pipref) # start subservice
1063 self.session.pip.servicePath=servicepath
1064 elif answer[1] == self.MOVEPIP:
1065 self.session.open(PiPSetup, pip = self.session.pip)
1066 elif answer[1] == self.ENABLE_SUBTITLE:
1067 self.selected_subtitle = answer[2]
1068 self.subtitles_enabled = True
1070 from RecordTimer import parseEvent
1072 class InfoBarInstantRecord:
1073 """Instant Record - handles the instantRecord action in order to
1074 start/stop instant records"""
1076 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1078 "instantRecord": (self.instantRecord, _("Instant Record...")),
1081 self["BlinkingPoint"] = BlinkingPixmapConditional()
1082 self["BlinkingPoint"].hide()
1083 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1085 def stopCurrentRecording(self, entry = -1):
1086 if entry is not None and entry != -1:
1087 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1088 self.recording.remove(self.recording[entry])
1090 def startInstantRecording(self, limitEvent = False):
1091 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1093 # try to get event info
1096 service = self.session.nav.getCurrentService()
1097 epg = eEPGCache.getInstance()
1098 event = epg.lookupEventTime(serviceref, -1, 0)
1100 info = service.info()
1101 ev = info.getEvent(0)
1107 end = time.time() + 3600 * 10
1108 name = "instant record"
1112 if event is not None:
1113 curEvent = parseEvent(event)
1115 description = curEvent[3]
1116 eventid = curEvent[4]
1121 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1123 data = (begin, end, name, description, eventid)
1125 recording = self.session.nav.recordWithTimer(serviceref, *data)
1126 recording.dontSave = True
1127 self.recording.append(recording)
1129 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1131 def isInstantRecordRunning(self):
1132 print "self.recording:", self.recording
1133 if len(self.recording) > 0:
1134 for x in self.recording:
1139 def recordQuestionCallback(self, answer):
1140 print "pre:\n", self.recording
1142 if answer is None or answer[1] == "no":
1145 recording = self.recording[:]
1147 if not x in self.session.nav.RecordTimer.timer_list:
1148 self.recording.remove(x)
1149 elif x.dontSave and x.isRunning():
1150 list.append(TimerEntryComponent(x, False))
1152 if answer[1] == "changeduration":
1153 if len(self.recording) == 1:
1154 self.changeDuration(0)
1156 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1157 elif answer[1] == "stop":
1158 if len(self.recording) == 1:
1159 self.stopCurrentRecording(0)
1161 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1162 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1164 if answer[1] == "event":
1166 if answer[1] == "manualduration":
1167 self.selectedEntry = len(self.recording)
1168 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1169 self.startInstantRecording(limitEvent = limitEvent)
1171 print "after:\n", self.recording
1173 def changeDuration(self, entry):
1174 if entry is not None:
1175 self.selectedEntry = entry
1176 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1178 def inputCallback(self, value):
1179 if value is not None:
1180 print "stopping recording after", int(value), "minutes."
1181 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1182 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1184 def instantRecord(self):
1186 stat = os.stat(resolveFilename(SCOPE_HDD))
1188 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1191 if self.isInstantRecordRunning():
1192 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")])
1194 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")])
1196 from Tools.ISO639 import LanguageCodes
1198 class InfoBarAudioSelection:
1200 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1202 "audioSelection": (self.audioSelection, _("Audio Options...")),
1205 def audioSelection(self):
1206 service = self.session.nav.getCurrentService()
1207 audio = service and service.audioTracks()
1208 self.audioTracks = audio
1209 n = audio and audio.getNumberOfTracks()
1210 keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
1212 print "tlist:", tlist
1214 self.audioChannel = service.audioChannel()
1217 i = audio.getTrackInfo(x)
1218 language = i.getLanguage()
1219 description = i.getDescription()
1221 if len(language) == 3:
1222 if language in LanguageCodes:
1223 language = LanguageCodes[language][0]
1225 if len(description):
1226 description += " (" + language + ")"
1228 description = language
1230 tlist.append((description, x))
1232 selectedAudio = tlist[0][1]
1233 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1237 if x[1] != selectedAudio:
1242 tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
1243 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
1245 del self.audioTracks
1247 def audioSelected(self, audio):
1248 if audio is not None:
1249 if isinstance(audio[1], str):
1250 if audio[1] == "mode":
1251 keys = ["red", "green", "yellow"]
1252 selection = self.audioChannel.getCurrentChannel()
1253 tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
1254 self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
1256 del self.audioChannel
1257 if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
1258 self.audioTracks.selectTrack(audio[1])
1260 del self.audioChannel
1261 del self.audioTracks
1263 def modeSelected(self, mode):
1264 if mode is not None:
1265 self.audioChannel.selectChannel(mode[1])
1266 del self.audioChannel
1268 class InfoBarSubserviceSelection:
1270 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1272 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1275 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1277 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1278 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1280 self["SubserviceQuickzapAction"].setEnabled(False)
1282 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1284 def checkSubservicesAvail(self, ev):
1285 if ev == iPlayableService.evUpdatedEventInfo:
1286 service = self.session.nav.getCurrentService()
1287 subservices = service and service.subServices()
1288 if not subservices or subservices.getNumberOfSubservices() == 0:
1289 self["SubserviceQuickzapAction"].setEnabled(False)
1291 def nextSubservice(self):
1292 self.changeSubservice(+1)
1294 def prevSubservice(self):
1295 self.changeSubservice(-1)
1297 def changeSubservice(self, direction):
1298 service = self.session.nav.getCurrentService()
1299 subservices = service and service.subServices()
1300 n = subservices and subservices.getNumberOfSubservices()
1303 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1305 if subservices.getSubservice(x).toString() == ref.toString():
1308 selection += direction
1313 newservice = subservices.getSubservice(selection)
1314 if newservice.valid():
1317 self.session.nav.playService(newservice)
1319 def subserviceSelection(self):
1320 service = self.session.nav.getCurrentService()
1321 subservices = service and service.subServices()
1323 n = subservices and subservices.getNumberOfSubservices()
1326 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1329 i = subservices.getSubservice(x)
1330 if i.toString() == ref.toString():
1332 tlist.append((i.getName(), i))
1334 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1336 def subserviceSelected(self, service):
1337 if not service is None:
1338 self["SubserviceQuickzapAction"].setEnabled(True)
1339 self.session.nav.playService(service[1])
1341 class InfoBarAdditionalInfo:
1343 self["NimA"] = Pixmap()
1344 self["NimB"] = Pixmap()
1345 self["NimA_Active"] = Pixmap()
1346 self["NimB_Active"] = Pixmap()
1348 self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0)
1349 self["TimeshiftPossible"] = self["RecordingPossible"]
1350 self["ExtensionsAvailable"] = Boolean(fixed=1)
1352 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1353 res_mgr = eDVBResourceManagerPtr()
1354 if eDVBResourceManager.getInstance(res_mgr) == 0:
1355 res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged)
1357 def tunerUseMaskChanged(self, mask):
1359 self["NimA_Active"].show()
1361 self["NimA_Active"].hide()
1363 self["NimB_Active"].show()
1365 self["NimB_Active"].hide()
1367 def checkTunerState(self, service):
1368 info = service.frontendInfo()
1369 feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber)
1370 if feNumber is None:
1380 def gotServiceEvent(self, ev):
1381 service = self.session.nav.getCurrentService()
1382 if ev == iPlayableService.evStart:
1383 self.checkTunerState(service)
1385 class InfoBarNotifications:
1387 self.onExecBegin.append(self.checkNotifications)
1388 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1389 self.onClose.append(self.__removeNotification)
1391 def __removeNotification(self):
1392 Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
1394 def checkNotificationsIfExecing(self):
1396 self.checkNotifications()
1398 def checkNotifications(self):
1399 if len(Notifications.notifications):
1400 n = Notifications.notifications[0]
1401 Notifications.notifications = Notifications.notifications[1:]
1404 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1406 self.session.open(n[1], *n[2], **n[3])
1408 class InfoBarServiceNotifications:
1410 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1412 iPlayableService.evEnd: self.serviceHasEnded
1415 def serviceHasEnded(self):
1416 print "service end!"
1419 self.setSeekState(self.SEEK_STATE_PLAY)
1423 class InfoBarCueSheetSupport:
1429 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1431 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1432 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1433 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1437 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1439 iPlayableService.evStart: self.__serviceStarted,
1442 def __serviceStarted(self):
1443 print "new service started! trying to download cuts!"
1444 self.downloadCuesheet()
1446 def __getSeekable(self):
1447 service = self.session.nav.getCurrentService()
1450 return service.seek()
1452 def cueGetCurrentPosition(self):
1453 seek = self.__getSeekable()
1456 r = seek.getPlayPosition()
1461 def jumpPreviousNextMark(self, cmp, alternative=None):
1462 current_pos = self.cueGetCurrentPosition()
1463 if current_pos is None:
1465 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1466 if mark is not None:
1468 elif alternative is not None:
1473 seekable = self.__getSeekable()
1474 if seekable is not None:
1475 seekable.seekTo(pts)
1477 def jumpPreviousMark(self):
1478 # we add 2 seconds, so if the play position is <2s after
1479 # the mark, the mark before will be used
1480 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1482 def jumpNextMark(self):
1483 self.jumpPreviousNextMark(lambda x: x)
1485 def getNearestCutPoint(self, pts, cmp=abs):
1488 for cp in self.cut_list:
1489 diff = cmp(cp[0] - pts)
1490 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1494 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1495 current_pos = self.cueGetCurrentPosition()
1496 if current_pos is None:
1497 print "not seekable"
1500 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1502 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1504 return nearest_cutpoint
1506 self.removeMark(nearest_cutpoint)
1507 elif not onlyremove and not onlyreturn:
1508 self.addMark((current_pos, self.CUT_TYPE_MARK))
1513 def addMark(self, point):
1514 bisect.insort(self.cut_list, point)
1515 self.uploadCuesheet()
1517 def removeMark(self, point):
1518 self.cut_list.remove(point)
1519 self.uploadCuesheet()
1521 def __getCuesheet(self):
1522 service = self.session.nav.getCurrentService()
1525 return service.cueSheet()
1527 def uploadCuesheet(self):
1528 cue = self.__getCuesheet()
1531 print "upload failed, no cuesheet interface"
1533 cue.setCutList(self.cut_list)
1535 def downloadCuesheet(self):
1536 cue = self.__getCuesheet()
1539 print "upload failed, no cuesheet interface"
1541 self.cut_list = cue.getCutList()
1543 class InfoBarSummary(Screen):
1545 <screen position="0,0" size="132,64">
1546 <widget source="CurrentTime" render="Label" position="50,46" size="82,18" font="Regular;16" >
1547 <convert type="ClockToText">WithSeconds</convert>
1549 <widget source="CurrentService" render="Label" position="0,4" size="132,42" font="Regular;18" >
1550 <convert type="ServiceName">Name</convert>
1554 def __init__(self, session, parent):
1555 Screen.__init__(self, session)
1556 self["CurrentService"] = CurrentService(self.session.nav)
1557 self["CurrentTime"] = Clock()
1559 class InfoBarSummarySupport:
1563 def createSummary(self):
1564 return InfoBarSummary
1566 class InfoBarTeletextPlugin:
1568 self.teletext_plugin = None
1570 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1571 self.teletext_plugin = p
1573 if self.teletext_plugin is not None:
1574 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1576 "startTeletext": (self.startTeletext, _("View teletext..."))
1579 print "no teletext plugin found!"
1581 def startTeletext(self):
1582 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())
1584 class InfoBarSubtitleSupport(object):
1586 object.__init__(self)
1587 self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
1588 self.__subtitles_enabled = False
1590 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1592 iPlayableService.evStart: self.__serviceStarted,
1595 def __serviceStarted(self):
1596 # reenable if it was enabled
1597 r = self.__subtitles_enabled
1598 self.__subtitles_enabled = False
1599 self.__selected_subtitle = None
1600 self.setSubtitlesEnable(r)
1602 def getCurrentServiceSubtitle(self):
1603 service = self.session.nav.getCurrentService()
1604 return service and service.subtitle()
1606 def setSubtitlesEnable(self, enable=True):
1607 subtitle = self.getCurrentServiceSubtitle()
1608 if enable and self.__selected_subtitle:
1609 if subtitle and not self.__subtitles_enabled:
1610 subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
1611 self.subtitle_window.show()
1612 self.__subtitles_enabled = True
1615 subtitle.disableSubtitles(self.subtitle_window.instance)
1617 self.subtitle_window.hide()
1618 self.__subtitles_enabled = False
1620 def setSelectedSubtitle(self, subtitle):
1621 if self.__selected_subtitle != subtitle and self.subtitles_enabled:
1623 self.__selected_subtitle = subtitle
1624 self.__serviceStarted()
1626 self.__selected_subtitle = subtitle
1628 subtitles_enabled = property(lambda self: self.__subtitles_enabled, setSubtitlesEnable)
1629 selected_subtitle = property(lambda self: self.__selected_subtitle, setSelectedSubtitle)