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 self.servicelist.inBouquet():
303 prev = self.servicelist.getCurrentSelection()
305 prev = prev.toString()
307 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
308 if self.servicelist.atBegin():
309 self.servicelist.prevBouquet()
310 self.servicelist.moveUp()
311 cur = self.servicelist.getCurrentSelection()
312 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
315 self.servicelist.moveUp()
316 self.servicelist.zap()
320 if self.servicelist.inBouquet():
321 prev = self.servicelist.getCurrentSelection()
323 prev = prev.toString()
325 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
326 if self.servicelist.atEnd():
327 self.servicelist.nextBouquet()
329 self.servicelist.moveDown()
331 self.servicelist.moveDown()
332 cur = self.servicelist.getCurrentSelection()
333 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
336 self.servicelist.moveDown()
337 self.servicelist.zap()
341 """ Handles a menu action, to open the (main) menu """
343 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
345 "mainMenu": (self.mainMenu, _("Enter main menu...")),
349 print "loading mainmenu XML..."
350 menu = mdom.childNodes[0]
351 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
352 self.session.open(MainMenu, menu, menu.childNodes)
354 class InfoBarSimpleEventView:
355 """ Opens the Eventview for now/next """
357 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
359 "showEventInfo": (self.openEventView, _("show event details")),
362 def openEventView(self):
364 service = self.session.nav.getCurrentService()
365 ref = self.session.nav.getCurrentlyPlayingServiceReference()
366 info = service.info()
369 self.epglist.append(ptr)
372 self.epglist.append(ptr)
373 if len(self.epglist) > 0:
374 self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
376 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
377 if len(self.epglist) > 1:
378 tmp = self.epglist[0]
379 self.epglist[0]=self.epglist[1]
381 setEvent(self.epglist[0])
384 """ EPG - Opens an EPG list when the showEPGList action fires """
386 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
388 iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
391 self.is_now_next = False
393 self.bouquetSel = None
394 self.eventView = None
395 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
397 "showEventInfo": (self.openEventView, _("show EPG...")),
400 def zapToService(self, service):
401 if not service is None:
402 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
403 self.servicelist.clearPath()
404 if self.servicelist.bouquet_root != self.epg_bouquet:
405 self.servicelist.enterPath(self.servicelist.bouquet_root)
406 self.servicelist.enterPath(self.epg_bouquet)
407 self.servicelist.setCurrentSelection(service) #select the service in servicelist
408 self.servicelist.zap()
410 def getBouquetServices(self, bouquet):
412 servicelist = eServiceCenter.getInstance().list(bouquet)
413 if not servicelist is None:
415 service = servicelist.getNext()
416 if not service.valid(): #check if end of list
418 if service.flags: #ignore non playable services
420 services.append(ServiceReference(service))
423 def openBouquetEPG(self, bouquet, withCallback=True):
424 services = self.getBouquetServices(bouquet)
426 self.epg_bouquet = bouquet
428 self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
430 self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
432 def changeBouquetCB(self, direction, epg):
435 self.bouquetSel.down()
438 bouquet = self.bouquetSel.getCurrent()
439 services = self.getBouquetServices(bouquet)
441 self.epg_bouquet = bouquet
442 epg.setServices(services)
444 def closed(self, ret=False):
445 closedScreen = self.dlg_stack.pop()
446 if self.bouquetSel and closedScreen == self.bouquetSel:
447 self.bouquetSel = None
448 elif self.eventView and closedScreen == self.eventView:
449 self.eventView = None
451 dlgs=len(self.dlg_stack)
453 self.dlg_stack[dlgs-1].close(dlgs > 1)
455 def openMultiServiceEPG(self, withCallback=True):
456 bouquets = self.servicelist.getBouquetList()
461 if cnt > 1: # show bouquet list
463 self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
464 self.dlg_stack.append(self.bouquetSel)
466 self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
468 self.openBouquetEPG(bouquets[0][1], withCallback)
470 def openSingleServiceEPG(self):
471 ref=self.session.nav.getCurrentlyPlayingServiceReference()
472 self.session.open(EPGSelection, ref)
474 def openSimilarList(self, eventid, refstr):
475 self.session.open(EPGSelection, refstr, None, eventid)
477 def getNowNext(self):
479 service = self.session.nav.getCurrentService()
480 info = service and service.info()
481 ptr = info and info.getEvent(0)
483 self.epglist.append(ptr)
484 ptr = info and info.getEvent(1)
486 self.epglist.append(ptr)
488 def __evEventInfoChanged(self):
489 if self.is_now_next and len(self.dlg_stack) == 1:
491 assert self.eventView
492 if len(self.epglist):
493 self.eventView.setEvent(self.epglist[0])
495 def openEventView(self):
496 ref = self.session.nav.getCurrentlyPlayingServiceReference()
498 if len(self.epglist) == 0:
499 self.is_now_next = False
500 epg = eEPGCache.getInstance()
501 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
503 self.epglist.append(ptr)
504 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
506 self.epglist.append(ptr)
508 self.is_now_next = True
509 if len(self.epglist) > 0:
510 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
511 self.dlg_stack.append(self.eventView)
513 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
514 self.openMultiServiceEPG(False)
516 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
517 if len(self.epglist) > 1:
518 tmp = self.epglist[0]
519 self.epglist[0]=self.epglist[1]
521 setEvent(self.epglist[0])
524 """provides a snr/agc/ber display"""
526 self["FrontendStatus"] = FrontendStatus(service_source = self.session.nav.getCurrentService)
529 """provides a current/next event info display"""
531 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.NOW)
532 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.NEXT)
534 class InfoBarServiceName:
536 self["CurrentService"] = CurrentService(self.session.nav)
539 """handles actions like seeking, pause"""
541 # ispause, isff, issm
542 SEEK_STATE_PLAY = (0, 0, 0, ">")
543 SEEK_STATE_PAUSE = (1, 0, 0, "||")
544 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
545 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
546 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
547 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
548 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
549 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
551 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
552 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
553 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
554 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
556 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
557 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
558 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
561 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
563 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
564 iPlayableService.evStart: self.__serviceStarted,
566 iPlayableService.evEOF: self.__evEOF,
567 iPlayableService.evSOF: self.__evSOF,
570 class InfoBarSeekActionMap(HelpableActionMap):
571 def __init__(self, screen, *args, **kwargs):
572 HelpableActionMap.__init__(self, screen, *args, **kwargs)
575 def action(self, contexts, action):
576 if action[:5] == "seek:":
577 time = int(action[5:])
578 self.screen.seekRelative(time * 90000)
581 return HelpableActionMap.action(self, contexts, action)
583 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
585 "pauseService": (self.pauseService, _("pause")),
586 "unPauseService": (self.unPauseService, _("continue")),
588 "seekFwd": (self.seekFwd, _("skip forward")),
589 "seekFwdDown": self.seekFwdDown,
590 "seekFwdUp": self.seekFwdUp,
591 "seekBack": (self.seekBack, _("skip backward")),
592 "seekBackDown": self.seekBackDown,
593 "seekBackUp": self.seekBackUp,
595 # give them a little more priority to win over color buttons
597 self.seekstate = self.SEEK_STATE_PLAY
598 self.onClose.append(self.delTimer)
600 self.fwdtimer = False
601 self.fwdKeyTimer = eTimer()
602 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
604 self.rwdtimer = False
605 self.rwdKeyTimer = eTimer()
606 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
608 self.onPlayStateChanged = [ ]
610 self.lockedBecauseOfSkipping = False
623 service = self.session.nav.getCurrentService()
627 seek = service.seek()
629 if seek is None or not seek.isCurrentlySeekable():
634 def isSeekable(self):
635 if self.getSeek() is None:
639 def __seekableStatusChanged(self):
640 print "seekable status changed!"
641 if not self.isSeekable():
642 self["SeekActions"].setEnabled(False)
643 print "not seekable, return to play"
644 self.setSeekState(self.SEEK_STATE_PLAY)
646 self["SeekActions"].setEnabled(True)
649 def __serviceStarted(self):
650 self.seekstate = self.SEEK_STATE_PLAY
652 def setSeekState(self, state):
653 service = self.session.nav.getCurrentService()
658 if not self.isSeekable():
659 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
660 state = self.SEEK_STATE_PLAY
662 pauseable = service.pause()
664 if pauseable is None:
665 print "not pauseable."
666 state = self.SEEK_STATE_PLAY
668 oldstate = self.seekstate
669 self.seekstate = state
672 if oldstate[i] != self.seekstate[i]:
673 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
675 for c in self.onPlayStateChanged:
678 self.checkSkipShowHideLock()
682 def pauseService(self):
683 if self.seekstate == self.SEEK_STATE_PAUSE:
684 print "pause, but in fact unpause"
685 self.unPauseService()
687 if self.seekstate == self.SEEK_STATE_PLAY:
688 print "yes, playing."
690 print "no", self.seekstate
692 self.setSeekState(self.SEEK_STATE_PAUSE);
694 def unPauseService(self):
696 if self.seekstate == self.SEEK_STATE_PLAY:
698 self.setSeekState(self.SEEK_STATE_PLAY);
700 def doSeek(self, seektime):
701 print "doseek", seektime
702 service = self.session.nav.getCurrentService()
706 seekable = self.getSeek()
710 seekable.seekTo(90 * seektime)
712 def seekFwdDown(self):
713 print "start fwd timer"
715 self.fwdKeyTimer.start(1000)
717 def seekBackDown(self):
718 print "start rewind timer"
720 self.rwdKeyTimer.start(1000)
725 self.fwdKeyTimer.stop()
726 self.fwdtimer = False
731 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
732 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
733 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
734 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
735 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
736 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
737 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
738 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
739 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
740 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
741 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
742 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
743 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
744 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
745 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
747 self.setSeekState(lookup[self.seekstate])
749 def seekBackUp(self):
752 self.rwdKeyTimer.stop()
753 self.rwdtimer = False
758 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
759 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
760 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
761 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
762 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
763 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
764 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
765 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
766 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
767 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
768 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
769 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
770 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
771 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
772 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
774 self.setSeekState(lookup[self.seekstate])
776 if self.seekstate == self.SEEK_STATE_PAUSE:
777 seekable = self.getSeek()
778 if seekable is not None:
779 seekable.seekRelative(-1, 3)
781 def fwdTimerFire(self):
782 print "Display seek fwd"
783 self.fwdKeyTimer.stop()
784 self.fwdtimer = False
785 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
787 def fwdSeekTo(self, minutes):
788 print "Seek", minutes, "minutes forward"
790 seekable = self.getSeek()
791 if seekable is not None:
792 seekable.seekRelative(1, minutes * 60 * 90000)
794 def rwdTimerFire(self):
796 self.rwdKeyTimer.stop()
797 self.rwdtimer = False
798 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
800 def rwdSeekTo(self, minutes):
802 self.fwdSeekTo(0 - minutes)
804 def checkSkipShowHideLock(self):
805 wantlock = self.seekstate != self.SEEK_STATE_PLAY
807 if self.lockedBecauseOfSkipping and not wantlock:
809 self.lockedBecauseOfSkipping = False
811 if wantlock and not self.lockedBecauseOfSkipping:
813 self.lockedBecauseOfSkipping = True
816 if self.seekstate != self.SEEK_STATE_PLAY:
817 self.setSeekState(self.SEEK_STATE_PAUSE)
819 #self.getSeek().seekRelative(1, -90000)
820 self.setSeekState(self.SEEK_STATE_PLAY)
822 self.setSeekState(self.SEEK_STATE_PAUSE)
825 self.setSeekState(self.SEEK_STATE_PLAY)
828 def seekRelative(self, diff):
829 seekable = self.getSeek()
830 if seekable is not None:
831 seekable.seekRelative(1, diff)
833 from Screens.PVRState import PVRState, TimeshiftState
835 class InfoBarPVRState:
836 def __init__(self, screen=PVRState):
837 self.onPlayStateChanged.append(self.__playStateChanged)
838 self.pvrStateDialog = self.session.instantiateDialog(screen)
839 self.onShow.append(self.__mayShow)
840 self.onHide.append(self.pvrStateDialog.hide)
843 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
844 self.pvrStateDialog.show()
846 def __playStateChanged(self, state):
847 playstateString = state[3]
848 self.pvrStateDialog["state"].setText(playstateString)
851 class InfoBarTimeshiftState(InfoBarPVRState):
853 InfoBarPVRState.__init__(self, screen=TimeshiftState)
855 class InfoBarShowMovies:
857 # i don't really like this class.
858 # it calls a not further specified "movie list" on up/down/movieList,
859 # so this is not more than an action map
861 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
863 "movieList": (self.showMovies, "movie list"),
864 "up": (self.showMovies, "movie list"),
865 "down": (self.showMovies, "movie list")
868 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
872 # Timeshift works the following way:
873 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
874 # - normal playback TUNER unused PLAY enable disable disable
875 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
876 # - user presess pause again FILE record PLAY enable disable enable
877 # - user fast forwards FILE record FF enable disable enable
878 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
879 # - user backwards FILE record BACK # !! enable disable enable
883 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
884 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
885 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
886 # - the user can now PVR around
887 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
888 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
890 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
891 # - if the user rewinds, or press pause, timeshift will be activated again
893 # note that a timeshift can be enabled ("recording") and
894 # activated (currently time-shifting).
896 class InfoBarTimeshift:
898 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
900 "timeshiftStart": (self.startTimeshift, _("start timeshift")), # the "yellow key"
901 "timeshiftStop": (self.stopTimeshift, _("stop timeshift")) # currently undefined :), probably 'TV'
903 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
905 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
906 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
907 }, prio=-1) # priority over record
909 self.timeshift_enabled = 0
910 self.timeshift_state = 0
911 self.ts_pause_timer = eTimer()
912 self.ts_pause_timer.timeout.get().append(self.pauseService)
914 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
916 iPlayableService.evStart: self.__serviceStarted,
917 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
920 def getTimeshift(self):
921 service = self.session.nav.getCurrentService()
922 return service and service.timeshift()
924 def startTimeshift(self):
925 print "enable timeshift"
926 ts = self.getTimeshift()
928 # self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
929 # print "no ts interface"
932 if self.timeshift_enabled:
933 print "hu, timeshift already enabled?"
935 if not ts.startTimeshift():
937 self.timeshift_enabled = 1
939 # we remove the "relative time" for now.
940 #self.pvrStateDialog["timeshift"].setRelative(time.time())
943 self.setSeekState(self.SEEK_STATE_PAUSE)
945 # enable the "TimeshiftEnableActions", which will override
946 # the startTimeshift actions
947 self.__seekableStatusChanged()
949 print "timeshift failed"
951 def stopTimeshift(self):
952 if not self.timeshift_enabled:
954 print "disable timeshift"
955 ts = self.getTimeshift()
958 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
960 def stopTimeshiftConfirmed(self, confirmed):
964 ts = self.getTimeshift()
969 self.timeshift_enabled = 0
972 self.__seekableStatusChanged()
974 # activates timeshift, and seeks to (almost) the end
975 def activateTimeshiftEnd(self):
976 ts = self.getTimeshift()
981 if ts.isTimeshiftActive():
982 print "!! activate timeshift called - but shouldn't this be a normal pause?"
985 self.setSeekState(self.SEEK_STATE_PLAY)
986 ts.activateTimeshift()
989 # same as activateTimeshiftEnd, but pauses afterwards.
990 def activateTimeshiftEndAndPause(self):
991 state = self.seekstate
992 self.activateTimeshiftEnd()
994 # well, this is "andPause", but it could be pressed from pause,
995 # when pausing on the (fake-)"live" picture, so an un-pause
998 print "now, pauseService"
999 if state == self.SEEK_STATE_PLAY:
1000 print "is PLAYING, start pause timer"
1001 self.ts_pause_timer.start(200, 1)
1004 self.unPauseService()
1006 def __seekableStatusChanged(self):
1009 print "self.isSeekable", self.isSeekable()
1010 print "self.timeshift_enabled", self.timeshift_enabled
1012 # when this service is not seekable, but timeshift
1013 # is enabled, this means we can activate
1015 if not self.isSeekable() and self.timeshift_enabled:
1018 print "timeshift activate:", enabled
1019 self["TimeshiftActivateActions"].setEnabled(enabled)
1021 def __serviceStarted(self):
1022 self.timeshift_enabled = False
1023 self.__seekableStatusChanged()
1025 from Screens.PiPSetup import PiPSetup
1027 class InfoBarExtensions:
1029 self.session.pipshown = False
1031 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1033 "extensions": (self.extensions, _("view extensions...")),
1042 def extensions(self):
1044 if self.session.pipshown == False:
1045 list.append((_("Activate Picture in Picture"), self.PIPON))
1046 elif self.session.pipshown == True:
1047 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1048 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1049 list.append((_("Swap services"), self.PIPSWAP))
1051 s = self.getCurrentServiceSubtitle()
1052 l = s and s.getSubtitleList() or [ ]
1055 list.append(("Enable Subtitles: " + x[0], self.ENABLE_SUBTITLE, x[1]))
1057 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1059 def extensionCallback(self, answer):
1060 if answer is not None:
1061 if answer[1] == self.PIPON:
1062 self.session.pip = self.session.instantiateDialog(PictureInPicture)
1063 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1064 if self.session.pip.playService(newservice):
1065 self.session.pipshown = True
1066 self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
1068 self.session.pipshown = False
1069 del self.session.pip
1070 self.session.nav.playService(newservice)
1071 elif answer[1] == self.PIPOFF:
1072 del self.session.pip
1073 self.session.pipshown = False
1074 elif answer[1] == self.PIPSWAP:
1075 swapservice = self.session.nav.getCurrentlyPlayingServiceReference()
1076 if self.session.pip.servicePath:
1077 servicepath = self.servicelist.getCurrentServicePath()
1078 ref=servicepath[len(servicepath)-1]
1079 pipref=self.session.pip.getCurrentService()
1080 self.session.pip.playService(swapservice)
1081 self.servicelist.setCurrentServicePath(self.session.pip.servicePath)
1082 if pipref.toString() != ref.toString(): # is a subservice ?
1083 self.session.nav.stopService() # stop portal
1084 self.session.nav.playService(pipref) # start subservice
1085 self.session.pip.servicePath=servicepath
1086 elif answer[1] == self.MOVEPIP:
1087 self.session.open(PiPSetup, pip = self.session.pip)
1088 elif answer[1] == self.ENABLE_SUBTITLE:
1089 self.selected_subtitle = answer[2]
1090 self.subtitles_enabled = True
1092 from RecordTimer import parseEvent
1094 class InfoBarInstantRecord:
1095 """Instant Record - handles the instantRecord action in order to
1096 start/stop instant records"""
1098 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1100 "instantRecord": (self.instantRecord, _("Instant Record...")),
1103 self["BlinkingPoint"] = BlinkingPixmapConditional()
1104 self["BlinkingPoint"].hide()
1105 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1107 def stopCurrentRecording(self, entry = -1):
1108 if entry is not None and entry != -1:
1109 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1110 self.recording.remove(self.recording[entry])
1112 def startInstantRecording(self, limitEvent = False):
1113 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1115 # try to get event info
1118 service = self.session.nav.getCurrentService()
1119 epg = eEPGCache.getInstance()
1120 event = epg.lookupEventTime(serviceref, -1, 0)
1122 info = service.info()
1123 ev = info.getEvent(0)
1129 end = time.time() + 3600 * 10
1130 name = "instant record"
1134 if event is not None:
1135 curEvent = parseEvent(event)
1137 description = curEvent[3]
1138 eventid = curEvent[4]
1143 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1145 data = (begin, end, name, description, eventid)
1147 recording = self.session.nav.recordWithTimer(serviceref, *data)
1148 recording.dontSave = True
1149 self.recording.append(recording)
1151 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1153 def isInstantRecordRunning(self):
1154 print "self.recording:", self.recording
1155 if len(self.recording) > 0:
1156 for x in self.recording:
1161 def recordQuestionCallback(self, answer):
1162 print "pre:\n", self.recording
1164 if answer is None or answer[1] == "no":
1167 recording = self.recording[:]
1169 if not x in self.session.nav.RecordTimer.timer_list:
1170 self.recording.remove(x)
1171 elif x.dontSave and x.isRunning():
1172 list.append(TimerEntryComponent(x, False))
1174 if answer[1] == "changeduration":
1175 if len(self.recording) == 1:
1176 self.changeDuration(0)
1178 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1179 elif answer[1] == "stop":
1180 if len(self.recording) == 1:
1181 self.stopCurrentRecording(0)
1183 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1184 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1186 if answer[1] == "event":
1188 if answer[1] == "manualduration":
1189 self.selectedEntry = len(self.recording)
1190 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1191 self.startInstantRecording(limitEvent = limitEvent)
1193 print "after:\n", self.recording
1195 def changeDuration(self, entry):
1196 if entry is not None:
1197 self.selectedEntry = entry
1198 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1200 def inputCallback(self, value):
1201 if value is not None:
1202 print "stopping recording after", int(value), "minutes."
1203 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1204 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1206 def instantRecord(self):
1208 stat = os.stat(resolveFilename(SCOPE_HDD))
1210 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1213 if self.isInstantRecordRunning():
1214 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")])
1216 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")])
1218 from Tools.ISO639 import LanguageCodes
1220 class InfoBarAudioSelection:
1222 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1224 "audioSelection": (self.audioSelection, _("Audio Options...")),
1227 def audioSelection(self):
1228 service = self.session.nav.getCurrentService()
1229 audio = service and service.audioTracks()
1230 self.audioTracks = audio
1231 n = audio and audio.getNumberOfTracks()
1232 keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
1234 print "tlist:", tlist
1236 self.audioChannel = service.audioChannel()
1239 i = audio.getTrackInfo(x)
1240 language = i.getLanguage()
1241 description = i.getDescription()
1243 if len(language) == 3:
1244 if language in LanguageCodes:
1245 language = LanguageCodes[language][0]
1247 if len(description):
1248 description += " (" + language + ")"
1250 description = language
1252 tlist.append((description, x))
1254 selectedAudio = tlist[0][1]
1255 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1259 if x[1] != selectedAudio:
1264 tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
1265 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
1267 del self.audioTracks
1269 def audioSelected(self, audio):
1270 if audio is not None:
1271 if isinstance(audio[1], str):
1272 if audio[1] == "mode":
1273 keys = ["red", "green", "yellow"]
1274 selection = self.audioChannel.getCurrentChannel()
1275 tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
1276 self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
1278 del self.audioChannel
1279 if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
1280 self.audioTracks.selectTrack(audio[1])
1282 del self.audioChannel
1283 del self.audioTracks
1285 def modeSelected(self, mode):
1286 if mode is not None:
1287 self.audioChannel.selectChannel(mode[1])
1288 del self.audioChannel
1290 class InfoBarSubserviceSelection:
1292 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1294 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1297 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1299 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1300 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1302 self["SubserviceQuickzapAction"].setEnabled(False)
1304 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1306 def checkSubservicesAvail(self, ev):
1307 if ev == iPlayableService.evUpdatedEventInfo:
1308 service = self.session.nav.getCurrentService()
1309 subservices = service and service.subServices()
1310 if not subservices or subservices.getNumberOfSubservices() == 0:
1311 self["SubserviceQuickzapAction"].setEnabled(False)
1313 def nextSubservice(self):
1314 self.changeSubservice(+1)
1316 def prevSubservice(self):
1317 self.changeSubservice(-1)
1319 def changeSubservice(self, direction):
1320 service = self.session.nav.getCurrentService()
1321 subservices = service and service.subServices()
1322 n = subservices and subservices.getNumberOfSubservices()
1325 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1327 if subservices.getSubservice(x).toString() == ref.toString():
1330 selection += direction
1335 newservice = subservices.getSubservice(selection)
1336 if newservice.valid():
1339 self.session.nav.playService(newservice)
1341 def subserviceSelection(self):
1342 service = self.session.nav.getCurrentService()
1343 subservices = service and service.subServices()
1345 n = subservices and subservices.getNumberOfSubservices()
1348 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1351 i = subservices.getSubservice(x)
1352 if i.toString() == ref.toString():
1354 tlist.append((i.getName(), i))
1356 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1358 def subserviceSelected(self, service):
1359 if not service is None:
1360 self["SubserviceQuickzapAction"].setEnabled(True)
1361 self.session.nav.playService(service[1])
1363 class InfoBarAdditionalInfo:
1365 self["NimA"] = Pixmap()
1366 self["NimB"] = Pixmap()
1367 self["NimA_Active"] = Pixmap()
1368 self["NimB_Active"] = Pixmap()
1370 self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0)
1371 self["TimeshiftPossible"] = self["RecordingPossible"]
1372 self["ExtensionsAvailable"] = Boolean(fixed=1)
1374 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1375 res_mgr = eDVBResourceManagerPtr()
1376 if eDVBResourceManager.getInstance(res_mgr) == 0:
1377 res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged)
1379 def tunerUseMaskChanged(self, mask):
1381 self["NimA_Active"].show()
1383 self["NimA_Active"].hide()
1385 self["NimB_Active"].show()
1387 self["NimB_Active"].hide()
1389 def checkTunerState(self, service):
1390 info = service.frontendInfo()
1391 feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber)
1392 if feNumber is None:
1402 def gotServiceEvent(self, ev):
1403 service = self.session.nav.getCurrentService()
1404 if ev == iPlayableService.evStart:
1405 self.checkTunerState(service)
1407 class InfoBarNotifications:
1409 self.onExecBegin.append(self.checkNotifications)
1410 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1411 self.onClose.append(self.__removeNotification)
1413 def __removeNotification(self):
1414 Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
1416 def checkNotificationsIfExecing(self):
1418 self.checkNotifications()
1420 def checkNotifications(self):
1421 if len(Notifications.notifications):
1422 n = Notifications.notifications[0]
1423 Notifications.notifications = Notifications.notifications[1:]
1426 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1428 self.session.open(n[1], *n[2], **n[3])
1430 class InfoBarServiceNotifications:
1432 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1434 iPlayableService.evEnd: self.serviceHasEnded
1437 def serviceHasEnded(self):
1438 print "service end!"
1441 self.setSeekState(self.SEEK_STATE_PLAY)
1445 class InfoBarCueSheetSupport:
1451 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1453 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1454 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1455 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1459 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1461 iPlayableService.evStart: self.__serviceStarted,
1464 def __serviceStarted(self):
1465 print "new service started! trying to download cuts!"
1466 self.downloadCuesheet()
1468 def __getSeekable(self):
1469 service = self.session.nav.getCurrentService()
1472 return service.seek()
1474 def cueGetCurrentPosition(self):
1475 seek = self.__getSeekable()
1478 r = seek.getPlayPosition()
1483 def jumpPreviousNextMark(self, cmp, alternative=None):
1484 current_pos = self.cueGetCurrentPosition()
1485 if current_pos is None:
1487 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1488 if mark is not None:
1490 elif alternative is not None:
1495 seekable = self.__getSeekable()
1496 if seekable is not None:
1497 seekable.seekTo(pts)
1499 def jumpPreviousMark(self):
1500 # we add 2 seconds, so if the play position is <2s after
1501 # the mark, the mark before will be used
1502 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1504 def jumpNextMark(self):
1505 self.jumpPreviousNextMark(lambda x: x)
1507 def getNearestCutPoint(self, pts, cmp=abs):
1510 for cp in self.cut_list:
1511 diff = cmp(cp[0] - pts)
1512 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1516 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1517 current_pos = self.cueGetCurrentPosition()
1518 if current_pos is None:
1519 print "not seekable"
1522 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1524 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1526 return nearest_cutpoint
1528 self.removeMark(nearest_cutpoint)
1529 elif not onlyremove and not onlyreturn:
1530 self.addMark((current_pos, self.CUT_TYPE_MARK))
1535 def addMark(self, point):
1536 bisect.insort(self.cut_list, point)
1537 self.uploadCuesheet()
1539 def removeMark(self, point):
1540 self.cut_list.remove(point)
1541 self.uploadCuesheet()
1543 def __getCuesheet(self):
1544 service = self.session.nav.getCurrentService()
1547 return service.cueSheet()
1549 def uploadCuesheet(self):
1550 cue = self.__getCuesheet()
1553 print "upload failed, no cuesheet interface"
1555 cue.setCutList(self.cut_list)
1557 def downloadCuesheet(self):
1558 cue = self.__getCuesheet()
1561 print "upload failed, no cuesheet interface"
1563 self.cut_list = cue.getCutList()
1565 class InfoBarSummary(Screen):
1567 <screen position="0,0" size="132,64">
1568 <widget source="CurrentTime" render="Label" position="50,46" size="82,18" font="Regular;16" >
1569 <convert type="ClockToText">WithSeconds</convert>
1571 <widget source="CurrentService" render="Label" position="0,4" size="132,42" font="Regular;18" >
1572 <convert type="ServiceName">Name</convert>
1576 def __init__(self, session, parent):
1577 Screen.__init__(self, session)
1578 self["CurrentService"] = CurrentService(self.session.nav)
1579 self["CurrentTime"] = Clock()
1581 class InfoBarSummarySupport:
1585 def createSummary(self):
1586 return InfoBarSummary
1588 class InfoBarTeletextPlugin:
1590 self.teletext_plugin = None
1592 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1593 self.teletext_plugin = p
1595 if self.teletext_plugin is not None:
1596 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1598 "startTeletext": (self.startTeletext, _("View teletext..."))
1601 print "no teletext plugin found!"
1603 def startTeletext(self):
1604 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())
1606 class InfoBarSubtitleSupport(object):
1608 object.__init__(self)
1609 self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
1610 self.__subtitles_enabled = False
1612 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1614 iPlayableService.evStart: self.__serviceStarted,
1617 def __serviceStarted(self):
1618 # reenable if it was enabled
1619 r = self.__subtitles_enabled
1620 self.__subtitles_enabled = False
1621 self.__selected_subtitle = None
1622 self.setSubtitlesEnable(r)
1624 def getCurrentServiceSubtitle(self):
1625 service = self.session.nav.getCurrentService()
1626 return service and service.subtitle()
1628 def setSubtitlesEnable(self, enable=True):
1629 subtitle = self.getCurrentServiceSubtitle()
1630 if enable and self.__selected_subtitle:
1631 if subtitle and not self.__subtitles_enabled:
1632 subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
1633 self.subtitle_window.show()
1634 self.__subtitles_enabled = True
1637 subtitle.disableSubtitles(self.subtitle_window.instance)
1639 self.subtitle_window.hide()
1640 self.__subtitles_enabled = False
1642 def setSelectedSubtitle(self, subtitle):
1643 if self.__selected_subtitle != subtitle and self.subtitles_enabled:
1645 self.__selected_subtitle = subtitle
1646 self.__serviceStarted()
1648 self.__selected_subtitle = subtitle
1650 subtitles_enabled = property(lambda self: self.__subtitles_enabled, setSubtitlesEnable)
1651 selected_subtitle = property(lambda self: self.__selected_subtitle, setSelectedSubtitle)