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.Clock import Clock
7 from Components.EventInfo import EventInfo, EventInfoProgress
8 from Components.Harddisk import harddiskmanager
9 from Components.Input import Input
10 from Components.Label import *
11 from Components.Pixmap import Pixmap, PixmapConditional
12 from Components.PluginComponent import plugins
13 from Components.ProgressBar import *
14 from Components.ServiceEventTracker import ServiceEventTracker
15 from Components.ServiceName import ServiceName
16 from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean
17 from Components.config import configfile, configsequencearg
18 from Components.TimerList import TimerEntryComponent
19 from Components.TunerInfo import TunerInfo
21 from EpgSelection import EPGSelection
22 from Plugins.Plugin import PluginDescriptor
24 from Screen import Screen
25 from Screens.ChoiceBox import ChoiceBox
26 from Screens.Dish import Dish
27 from Screens.EventView import EventViewEPGSelect, EventViewSimple
28 from Screens.InputBox import InputBox
29 from Screens.MessageBox import MessageBox
30 from Screens.MinuteInput import MinuteInput
31 from Screens.TimerSelection import TimerSelection
32 from Screens.PictureInPicture import PictureInPicture
33 from ServiceReference import ServiceReference
35 from Tools import Notifications
36 from Tools.Directories import *
38 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
45 from Components.config import config, currentConfigSelectionElement
48 from Menu import MainMenu, mdom
52 self.dishDialog = self.session.instantiateDialog(Dish)
53 self.onLayoutFinish.append(self.dishDialog.show)
55 class InfoBarShowHide:
56 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
64 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
66 "toggleShow": self.toggleShow,
70 self.__state = self.STATE_SHOWN
73 self.onExecBegin.append(self.show)
75 self.hideTimer = eTimer()
76 self.hideTimer.timeout.get().append(self.doTimerHide)
77 self.hideTimer.start(5000, True)
79 self.onShow.append(self.__onShow)
80 self.onHide.append(self.__onHide)
83 self.__state = self.STATE_SHOWN
86 def startHideTimer(self):
87 if self.__state == self.STATE_SHOWN and not self.__locked:
88 self.hideTimer.start(5000, True)
91 self.__state = self.STATE_HIDDEN
97 def doTimerHide(self):
99 if self.__state == self.STATE_SHOWN:
102 def toggleShow(self):
103 if self.__state == self.STATE_SHOWN:
105 self.hideTimer.stop()
106 elif self.__state == self.STATE_HIDDEN:
110 self.__locked = self.__locked + 1
113 self.hideTimer.stop()
115 def unlockShow(self):
116 self.__locked = self.__locked - 1
118 self.startHideTimer()
120 # def startShow(self):
121 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
122 # self.__state = self.STATE_SHOWN
124 # def startHide(self):
125 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
126 # self.__state = self.STATE_HIDDEN
128 class NumberZap(Screen):
135 self.close(int(self["number"].getText()))
137 def keyNumberGlobal(self, number):
138 self.Timer.start(3000, True) #reset timer
139 self.field = self.field + str(number)
140 self["number"].setText(self.field)
141 if len(self.field) >= 4:
144 def __init__(self, session, number):
145 Screen.__init__(self, session)
146 self.field = str(number)
148 self["channel"] = Label(_("Channel:"))
150 self["number"] = Label(self.field)
152 self["actions"] = NumberActionMap( [ "SetupActions" ],
156 "1": self.keyNumberGlobal,
157 "2": self.keyNumberGlobal,
158 "3": self.keyNumberGlobal,
159 "4": self.keyNumberGlobal,
160 "5": self.keyNumberGlobal,
161 "6": self.keyNumberGlobal,
162 "7": self.keyNumberGlobal,
163 "8": self.keyNumberGlobal,
164 "9": self.keyNumberGlobal,
165 "0": self.keyNumberGlobal
168 self.Timer = eTimer()
169 self.Timer.timeout.get().append(self.keyOK)
170 self.Timer.start(3000, True)
172 class InfoBarNumberZap:
173 """ Handles an initial number for NumberZapping """
175 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
177 "1": self.keyNumberGlobal,
178 "2": self.keyNumberGlobal,
179 "3": self.keyNumberGlobal,
180 "4": self.keyNumberGlobal,
181 "5": self.keyNumberGlobal,
182 "6": self.keyNumberGlobal,
183 "7": self.keyNumberGlobal,
184 "8": self.keyNumberGlobal,
185 "9": self.keyNumberGlobal,
186 "0": self.keyNumberGlobal,
189 def keyNumberGlobal(self, number):
190 # print "You pressed number " + str(number)
192 self.servicelist.recallPrevService()
195 self.session.openWithCallback(self.numberEntered, NumberZap, number)
197 def numberEntered(self, retval):
198 # print self.servicelist
200 self.zapToNumber(retval)
202 def searchNumberHelper(self, serviceHandler, num, bouquet):
203 servicelist = serviceHandler.list(bouquet)
204 if not servicelist is None:
206 serviceIterator = servicelist.getNext()
207 if not serviceIterator.valid(): #check end of list
209 if serviceIterator.flags: #assume normal dvb service have no flags set
212 if not num: #found service with searched number ?
213 return serviceIterator, 0
216 def zapToNumber(self, number):
217 bouquet = self.servicelist.bouquet_root
219 serviceHandler = eServiceCenter.getInstance()
220 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
221 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
223 bouquetlist = serviceHandler.list(bouquet)
224 if not bouquetlist is None:
226 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
227 if not bouquet.valid(): #check end of list
229 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
231 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
232 if not service is None:
233 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
234 self.servicelist.clearPath()
235 if self.servicelist.bouquet_root != bouquet:
236 self.servicelist.enterPath(self.servicelist.bouquet_root)
237 self.servicelist.enterPath(bouquet)
238 self.servicelist.setCurrentSelection(service) #select the service in servicelist
239 self.servicelist.zap()
241 config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
243 class InfoBarChannelSelection:
244 """ ChannelSelection - handles the channelSelection dialog and the initial
245 channelChange actions which open the channelSelection dialog """
248 self.servicelist = self.session.instantiateDialog(ChannelSelection)
250 if config.misc.initialchannelselection.value == 1:
251 self.onShown.append(self.firstRun)
253 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
255 "switchChannelUp": self.switchChannelUp,
256 "switchChannelDown": self.switchChannelDown,
257 "zapUp": (self.zapUp, _("previous channel")),
258 "zapDown": (self.zapDown, _("next channel")),
259 "historyBack": (self.historyBack, _("previous channel in history")),
260 "historyNext": (self.historyNext, _("next channel in history"))
264 self.onShown.remove(self.firstRun)
265 config.misc.initialchannelselection.value = 0
266 config.misc.initialchannelselection.save()
267 self.switchChannelDown()
269 def historyBack(self):
270 self.servicelist.historyBack()
272 def historyNext(self):
273 self.servicelist.historyNext()
275 def switchChannelUp(self):
276 self.servicelist.moveUp()
277 self.session.execDialog(self.servicelist)
279 def switchChannelDown(self):
280 self.servicelist.moveDown()
281 self.session.execDialog(self.servicelist)
284 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
285 if self.servicelist.inBouquet() and self.servicelist.atBegin():
286 self.servicelist.prevBouquet()
287 self.servicelist.moveUp()
288 self.servicelist.zap()
292 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
293 self.servicelist.nextBouquet()
295 self.servicelist.moveDown()
296 self.servicelist.zap()
300 """ Handles a menu action, to open the (main) menu """
302 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
304 "mainMenu": (self.mainMenu, "Enter main menu..."),
308 print "loading mainmenu XML..."
309 menu = mdom.childNodes[0]
310 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
311 self.session.open(MainMenu, menu, menu.childNodes)
313 class InfoBarSimpleEventView:
314 """ Opens the Eventview for now/next """
316 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
318 "showEventInfo": (self.openEventView, _("show event details")),
321 def openEventView(self):
323 service = self.session.nav.getCurrentService()
324 ref = self.session.nav.getCurrentlyPlayingServiceReference()
325 info = service.info()
328 self.epglist.append(ptr)
331 self.epglist.append(ptr)
332 if len(self.epglist) > 0:
333 self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
335 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
336 if len(self.epglist) > 1:
337 tmp = self.epglist[0]
338 self.epglist[0]=self.epglist[1]
340 setEvent(self.epglist[0])
343 """ EPG - Opens an EPG list when the showEPGList action fires """
345 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
347 iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
350 self.is_now_next = False
352 self.bouquetSel = None
353 self.eventView = None
354 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
356 "showEventInfo": (self.openEventView, _("show EPG...")),
359 def zapToService(self, service):
360 if not service is None:
361 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
362 self.servicelist.clearPath()
363 if self.servicelist.bouquet_root != self.epg_bouquet:
364 self.servicelist.enterPath(self.servicelist.bouquet_root)
365 self.servicelist.enterPath(self.epg_bouquet)
366 self.servicelist.setCurrentSelection(service) #select the service in servicelist
367 self.servicelist.zap()
369 def getBouquetServices(self, bouquet):
371 servicelist = eServiceCenter.getInstance().list(bouquet)
372 if not servicelist is None:
374 service = servicelist.getNext()
375 if not service.valid(): #check if end of list
377 if service.flags: #ignore non playable services
379 services.append(ServiceReference(service))
382 def openBouquetEPG(self, bouquet, withCallback=True):
383 services = self.getBouquetServices(bouquet)
385 self.epg_bouquet = bouquet
387 self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
389 self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
391 def changeBouquetCB(self, direction, epg):
394 self.bouquetSel.down()
397 bouquet = self.bouquetSel.getCurrent()
398 services = self.getBouquetServices(bouquet)
400 self.epg_bouquet = bouquet
401 epg.setServices(services)
403 def closed(self, ret=False):
404 closedScreen = self.dlg_stack.pop()
405 if self.bouquetSel and closedScreen == self.bouquetSel:
406 self.bouquetSel = None
407 elif self.eventView and closedScreen == self.eventView:
408 self.eventView = None
410 dlgs=len(self.dlg_stack)
412 self.dlg_stack[dlgs-1].close(dlgs > 1)
414 def openMultiServiceEPG(self, withCallback=True):
415 bouquets = self.servicelist.getBouquetList()
420 if cnt > 1: # show bouquet list
422 self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
423 self.dlg_stack.append(self.bouquetSel)
425 self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
427 self.openBouquetEPG(bouquets[0][1], withCallback)
429 def openSingleServiceEPG(self):
430 ref=self.session.nav.getCurrentlyPlayingServiceReference()
431 self.session.open(EPGSelection, ref)
433 def openSimilarList(self, eventid, refstr):
434 self.session.open(EPGSelection, refstr, None, eventid)
436 def getNowNext(self):
438 service = self.session.nav.getCurrentService()
439 info = service and service.info()
440 ptr = info and info.getEvent(0)
442 self.epglist.append(ptr)
443 ptr = info and info.getEvent(1)
445 self.epglist.append(ptr)
447 def __evEventInfoChanged(self):
448 if self.is_now_next and len(self.dlg_stack) == 1:
450 assert self.eventView
451 self.eventView.setEvent(self.epglist[0])
453 def openEventView(self):
454 ref = self.session.nav.getCurrentlyPlayingServiceReference()
456 if len(self.epglist) == 0:
457 self.is_now_next = False
458 epg = eEPGCache.getInstance()
459 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
461 self.epglist.append(ptr)
462 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
464 self.epglist.append(ptr)
466 self.is_now_next = True
467 if len(self.epglist) > 0:
468 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
469 self.dlg_stack.append(self.eventView)
471 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
472 self.openMultiServiceEPG(False)
474 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
475 if len(self.epglist) > 1:
476 tmp = self.epglist[0]
477 self.epglist[0]=self.epglist[1]
479 setEvent(self.epglist[0])
482 """provides a snr/agc/ber display"""
484 self["snr"] = Label()
485 self["agc"] = Label()
486 self["ber"] = Label()
487 self["snr_percent"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
488 self["agc_percent"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
489 self["ber_count"] = TunerInfo(TunerInfo.BER_VALUE, servicefkt = self.session.nav.getCurrentService)
490 self["snr_progress"] = TunerInfo(TunerInfo.SNR_BAR, servicefkt = self.session.nav.getCurrentService)
491 self["agc_progress"] = TunerInfo(TunerInfo.AGC_BAR, servicefkt = self.session.nav.getCurrentService)
492 self["ber_progress"] = TunerInfo(TunerInfo.BER_BAR, servicefkt = self.session.nav.getCurrentService)
493 self.timer = eTimer()
494 self.timer.timeout.get().append(self.updateTunerInfo)
495 self.timer.start(1000)
497 def updateTunerInfo(self):
498 if self.instance.isVisible():
499 self["snr_percent"].update()
500 self["agc_percent"].update()
501 self["ber_count"].update()
502 self["snr_progress"].update()
503 self["agc_progress"].update()
504 self["ber_progress"].update()
507 """provides a current/next event info display"""
509 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
510 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
512 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
513 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
515 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
516 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
518 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
520 class InfoBarServiceName:
522 self["ServiceName"] = ServiceName(self.session.nav)
525 """handles actions like seeking, pause"""
527 # ispause, isff, issm
528 SEEK_STATE_PLAY = (0, 0, 0, ">")
529 SEEK_STATE_PAUSE = (1, 0, 0, "||")
530 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
531 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
532 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
533 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
534 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
535 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
537 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
538 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
539 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
540 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
542 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
543 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
544 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
547 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
549 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
550 iPlayableService.evStart: self.__serviceStarted,
552 iPlayableService.evEOF: self.__evEOF,
553 iPlayableService.evSOF: self.__evSOF,
556 class InfoBarSeekActionMap(HelpableActionMap):
557 def __init__(self, screen, *args, **kwargs):
558 HelpableActionMap.__init__(self, screen, *args, **kwargs)
561 def action(self, contexts, action):
562 if action[:5] == "seek:":
563 time = int(action[5:])
564 self.screen.seekRelative(time * 90000)
567 return HelpableActionMap.action(self, contexts, action)
569 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
571 "pauseService": (self.pauseService, "pause"),
572 "unPauseService": (self.unPauseService, "continue"),
574 "seekFwd": (self.seekFwd, "skip forward"),
575 "seekFwdDown": self.seekFwdDown,
576 "seekFwdUp": self.seekFwdUp,
577 "seekBack": (self.seekBack, "skip backward"),
578 "seekBackDown": self.seekBackDown,
579 "seekBackUp": self.seekBackUp,
581 # give them a little more priority to win over color buttons
583 self.seekstate = self.SEEK_STATE_PLAY
584 self.onClose.append(self.delTimer)
586 self.fwdtimer = False
587 self.fwdKeyTimer = eTimer()
588 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
590 self.rwdtimer = False
591 self.rwdKeyTimer = eTimer()
592 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
594 self.onPlayStateChanged = [ ]
596 self.lockedBecauseOfSkipping = False
609 service = self.session.nav.getCurrentService()
613 seek = service.seek()
615 if seek is None or not seek.isCurrentlySeekable():
620 def isSeekable(self):
621 if self.getSeek() is None:
625 def __seekableStatusChanged(self):
626 print "seekable status changed!"
627 if not self.isSeekable():
628 self["SeekActions"].setEnabled(False)
629 print "not seekable, return to play"
630 self.setSeekState(self.SEEK_STATE_PLAY)
632 self["SeekActions"].setEnabled(True)
635 def __serviceStarted(self):
636 self.seekstate = self.SEEK_STATE_PLAY
638 def setSeekState(self, state):
639 service = self.session.nav.getCurrentService()
644 if not self.isSeekable():
645 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
646 state = self.SEEK_STATE_PLAY
648 pauseable = service.pause()
650 if pauseable is None:
651 print "not pauseable."
652 state = self.SEEK_STATE_PLAY
654 oldstate = self.seekstate
655 self.seekstate = state
658 if oldstate[i] != self.seekstate[i]:
659 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
661 for c in self.onPlayStateChanged:
664 self.checkSkipShowHideLock()
668 def pauseService(self):
669 if self.seekstate == self.SEEK_STATE_PAUSE:
670 print "pause, but in fact unpause"
671 self.unPauseService()
673 if self.seekstate == self.SEEK_STATE_PLAY:
674 print "yes, playing."
676 print "no", self.seekstate
678 self.setSeekState(self.SEEK_STATE_PAUSE);
680 def unPauseService(self):
682 self.setSeekState(self.SEEK_STATE_PLAY);
684 def doSeek(self, seektime):
685 print "doseek", seektime
686 service = self.session.nav.getCurrentService()
690 seekable = self.getSeek()
694 seekable.seekTo(90 * seektime)
696 def seekFwdDown(self):
697 print "start fwd timer"
699 self.fwdKeyTimer.start(1000)
701 def seekBackDown(self):
702 print "start rewind timer"
704 self.rwdKeyTimer.start(1000)
709 self.fwdKeyTimer.stop()
710 self.fwdtimer = False
715 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
716 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
717 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
718 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
719 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
720 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
721 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
722 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
723 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
724 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
725 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
726 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
727 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
728 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
729 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
731 self.setSeekState(lookup[self.seekstate])
733 def seekBackUp(self):
736 self.rwdKeyTimer.stop()
737 self.rwdtimer = False
742 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
743 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
744 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
745 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
746 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
747 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
748 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
749 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
750 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
751 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
752 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
753 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
754 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
755 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
756 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
758 self.setSeekState(lookup[self.seekstate])
760 if self.seekstate == self.SEEK_STATE_PAUSE:
761 seekable = self.getSeek()
762 if seekable is not None:
763 seekable.seekRelative(-1, 3)
765 def fwdTimerFire(self):
766 print "Display seek fwd"
767 self.fwdKeyTimer.stop()
768 self.fwdtimer = False
769 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
771 def fwdSeekTo(self, minutes):
772 print "Seek", minutes, "minutes forward"
774 seekable = self.getSeek()
775 if seekable is not None:
776 seekable.seekRelative(1, minutes * 60 * 90000)
778 def rwdTimerFire(self):
780 self.rwdKeyTimer.stop()
781 self.rwdtimer = False
782 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
784 def rwdSeekTo(self, minutes):
786 self.fwdSeekTo(0 - minutes)
788 def checkSkipShowHideLock(self):
789 wantlock = self.seekstate != self.SEEK_STATE_PLAY
791 if self.lockedBecauseOfSkipping and not wantlock:
793 self.lockedBecauseOfSkipping = False
795 if wantlock and not self.lockedBecauseOfSkipping:
797 self.lockedBecauseOfSkipping = True
800 if self.seekstate != self.SEEK_STATE_PLAY:
801 self.setSeekState(self.SEEK_STATE_PAUSE)
803 #self.getSeek().seekRelative(1, -90000)
804 self.setSeekState(self.SEEK_STATE_PLAY)
806 self.setSeekState(self.SEEK_STATE_PAUSE)
809 self.setSeekState(self.SEEK_STATE_PLAY)
812 def seekRelative(self, diff):
813 seekable = self.getSeek()
814 if seekable is not None:
815 seekable.seekRelative(1, diff)
817 from Screens.PVRState import PVRState, TimeshiftState
819 class InfoBarPVRState:
820 def __init__(self, screen=PVRState):
821 self.onPlayStateChanged.append(self.__playStateChanged)
822 self.pvrStateDialog = self.session.instantiateDialog(screen)
823 self.onShow.append(self.__mayShow)
824 self.onHide.append(self.pvrStateDialog.hide)
827 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
828 self.pvrStateDialog.show()
830 def __playStateChanged(self, state):
831 playstateString = state[3]
832 self.pvrStateDialog["state"].setText(playstateString)
835 class InfoBarTimeshiftState(InfoBarPVRState):
837 InfoBarPVRState.__init__(self, screen=TimeshiftState)
840 class InfoBarShowMovies:
842 # i don't really like this class.
843 # it calls a not further specified "movie list" on up/down/movieList,
844 # so this is not more than an action map
846 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
848 "movieList": (self.showMovies, "movie list"),
849 "up": (self.showMovies, "movie list"),
850 "down": (self.showMovies, "movie list")
853 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
857 # Timeshift works the following way:
858 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
859 # - normal playback TUNER unused PLAY enable disable disable
860 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
861 # - user presess pause again FILE record PLAY enable disable enable
862 # - user fast forwards FILE record FF enable disable enable
863 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
864 # - user backwards FILE record BACK # !! enable disable enable
868 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
869 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
870 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
871 # - the user can now PVR around
872 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
873 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
875 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
876 # - if the user rewinds, or press pause, timeshift will be activated again
878 # note that a timeshift can be enabled ("recording") and
879 # activated (currently time-shifting).
881 class InfoBarTimeshift:
883 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
885 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
886 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
888 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
890 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
891 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
892 }, prio=-1) # priority over record
894 self.timeshift_enabled = 0
895 self.timeshift_state = 0
896 self.ts_pause_timer = eTimer()
897 self.ts_pause_timer.timeout.get().append(self.pauseService)
899 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
901 iPlayableService.evStart: self.__serviceStarted,
902 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
905 def getTimeshift(self):
906 service = self.session.nav.getCurrentService()
907 return service and service.timeshift()
909 def startTimeshift(self):
910 print "enable timeshift"
911 ts = self.getTimeshift()
913 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
914 print "no ts interface"
917 if self.timeshift_enabled:
918 print "hu, timeshift already enabled?"
920 if not ts.startTimeshift():
922 self.timeshift_enabled = 1
923 self.pvrStateDialog["timeshift"].setRelative(time.time())
926 self.setSeekState(self.SEEK_STATE_PAUSE)
928 # enable the "TimeshiftEnableActions", which will override
929 # the startTimeshift actions
930 self.__seekableStatusChanged()
932 print "timeshift failed"
934 def stopTimeshift(self):
935 if not self.timeshift_enabled:
937 print "disable timeshift"
938 ts = self.getTimeshift()
941 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
943 def stopTimeshiftConfirmed(self, confirmed):
947 ts = self.getTimeshift()
952 self.timeshift_enabled = 0
955 self.__seekableStatusChanged()
957 # activates timeshift, and seeks to (almost) the end
958 def activateTimeshiftEnd(self):
959 ts = self.getTimeshift()
964 if ts.isTimeshiftActive():
965 print "!! activate timeshift called - but shouldn't this be a normal pause?"
968 self.setSeekState(self.SEEK_STATE_PLAY)
969 ts.activateTimeshift()
972 # same as activateTimeshiftEnd, but pauses afterwards.
973 def activateTimeshiftEndAndPause(self):
974 state = self.seekstate
975 self.activateTimeshiftEnd()
977 # well, this is "andPause", but it could be pressed from pause,
978 # when pausing on the (fake-)"live" picture, so an un-pause
981 print "now, pauseService"
982 if state == self.SEEK_STATE_PLAY:
983 print "is PLAYING, start pause timer"
984 self.ts_pause_timer.start(200, 1)
987 self.unPauseService()
989 def __seekableStatusChanged(self):
992 print "self.isSeekable", self.isSeekable()
993 print "self.timeshift_enabled", self.timeshift_enabled
995 # when this service is not seekable, but timeshift
996 # is enabled, this means we can activate
998 if not self.isSeekable() and self.timeshift_enabled:
1001 print "timeshift activate:", enabled
1002 self["TimeshiftActivateActions"].setEnabled(enabled)
1004 def __serviceStarted(self):
1005 self.timeshift_enabled = False
1006 self.__seekableStatusChanged()
1008 from Screens.PiPSetup import PiPSetup
1010 class InfoBarExtensions:
1012 self.pipshown = False
1014 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1016 "extensions": (self.extensions, "Extensions..."),
1023 def extensions(self):
1025 if self.pipshown == False:
1026 list.append((_("Activate Picture in Picture"), self.PIPON))
1027 elif self.pipshown == True:
1028 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1029 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1030 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1032 def extensionCallback(self, answer):
1033 if answer is not None:
1034 if answer[1] == self.PIPON:
1035 # self.session.nav.stopService()
1036 self.pip = self.session.instantiateDialog(PictureInPicture)
1039 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1040 self.pipservice = eServiceCenter.getInstance().play(newservice)
1041 if self.pipservice and not self.pipservice.setTarget(1):
1042 self.pipservice.start()
1043 self.pipshown = True
1045 self.pipservice = None
1047 self.session.nav.playService(newservice)
1048 elif answer[1] == self.PIPOFF:
1050 self.pipservice = None
1052 self.pipshown = False
1053 elif answer[1] == self.MOVEPIP:
1054 self.session.open(PiPSetup, pip = self.pip)
1056 from RecordTimer import parseEvent
1058 class InfoBarInstantRecord:
1059 """Instant Record - handles the instantRecord action in order to
1060 start/stop instant records"""
1062 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1064 "instantRecord": (self.instantRecord, "Instant Record..."),
1067 self["BlinkingPoint"] = BlinkingPixmapConditional()
1068 self["BlinkingPoint"].hide()
1069 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1071 def stopCurrentRecording(self, entry = -1):
1072 if entry is not None and entry != -1:
1073 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1074 self.recording.remove(self.recording[entry])
1076 def startInstantRecording(self, limitEvent = False):
1077 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1079 # try to get event info
1082 service = self.session.nav.getCurrentService()
1083 epg = eEPGCache.getInstance()
1084 event = epg.lookupEventTime(serviceref, -1, 0)
1086 info = service.info()
1087 ev = info.getEvent(0)
1093 end = time.time() + 3600 * 10
1094 name = "instant record"
1098 if event is not None:
1099 curEvent = parseEvent(event)
1101 description = curEvent[3]
1102 eventid = curEvent[4]
1107 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1109 data = (begin, end, name, description, eventid)
1111 recording = self.session.nav.recordWithTimer(serviceref, *data)
1112 recording.dontSave = True
1113 self.recording.append(recording)
1115 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1117 def isInstantRecordRunning(self):
1118 print "self.recording:", self.recording
1119 if len(self.recording) > 0:
1120 for x in self.recording:
1125 def recordQuestionCallback(self, answer):
1126 print "pre:\n", self.recording
1128 if answer is None or answer[1] == "no":
1131 recording = self.recording[:]
1133 if not x in self.session.nav.RecordTimer.timer_list:
1134 self.recording.remove(x)
1135 elif x.dontSave and x.isRunning():
1136 list.append(TimerEntryComponent(x, False))
1138 if answer[1] == "changeduration":
1139 if len(self.recording) == 1:
1140 self.changeDuration(0)
1142 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1143 elif answer[1] == "stop":
1144 if len(self.recording) == 1:
1145 self.stopCurrentRecording(0)
1147 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1148 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1150 if answer[1] == "event":
1152 if answer[1] == "manualduration":
1153 self.selectedEntry = len(self.recording)
1154 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1155 self.startInstantRecording(limitEvent = limitEvent)
1157 print "after:\n", self.recording
1159 def changeDuration(self, entry):
1160 if entry is not None:
1161 self.selectedEntry = entry
1162 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1164 def inputCallback(self, value):
1165 if value is not None:
1166 print "stopping recording after", int(value), "minutes."
1167 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1168 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1170 def instantRecord(self):
1172 stat = os.stat(resolveFilename(SCOPE_HDD))
1174 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1177 if self.isInstantRecordRunning():
1178 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")])
1180 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")])
1182 from Tools.ISO639 import LanguageCodes
1184 class InfoBarAudioSelection:
1186 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1188 "audioSelection": (self.audioSelection, "Audio Options..."),
1191 def audioSelection(self):
1192 service = self.session.nav.getCurrentService()
1193 audio = service.audioTracks()
1195 n = audio.getNumberOfTracks()
1199 i = audio.getTrackInfo(x)
1200 language = i.getLanguage()
1201 description = i.getDescription();
1203 if len(language) == 3:
1204 if language in LanguageCodes:
1205 language = LanguageCodes[language][0]
1207 if len(description):
1208 description += " (" + language + ")"
1210 description = language
1212 tlist.append((description, x))
1214 selectedAudio = tlist[0][1]
1215 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1218 if x[1] != selectedAudio:
1223 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection)
1225 def audioSelected(self, audio):
1226 if audio is not None:
1227 self.audio.selectTrack(audio[1])
1230 class InfoBarSubserviceSelection:
1232 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1234 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1237 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1239 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1240 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1242 self["SubserviceQuickzapAction"].setEnabled(False)
1244 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1246 def checkSubservicesAvail(self, ev):
1247 if ev == iPlayableService.evUpdatedEventInfo:
1248 service = self.session.nav.getCurrentService()
1249 subservices = service.subServices()
1250 if subservices.getNumberOfSubservices() == 0:
1251 self["SubserviceQuickzapAction"].setEnabled(False)
1253 def nextSubservice(self):
1254 self.changeSubservice(+1)
1256 def prevSubservice(self):
1257 self.changeSubservice(-1)
1259 def changeSubservice(self, direction):
1260 service = self.session.nav.getCurrentService()
1261 subservices = service.subServices()
1262 n = subservices.getNumberOfSubservices()
1265 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1267 if subservices.getSubservice(x).toString() == ref.toString():
1270 selection += direction
1275 newservice = subservices.getSubservice(selection)
1276 if newservice.valid():
1279 self.session.nav.playService(newservice)
1281 def subserviceSelection(self):
1282 service = self.session.nav.getCurrentService()
1283 subservices = service.subServices()
1285 n = subservices.getNumberOfSubservices()
1288 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1291 i = subservices.getSubservice(x)
1292 if i.toString() == ref.toString():
1294 tlist.append((i.getName(), i))
1296 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1298 def subserviceSelected(self, service):
1299 if not service is None:
1300 self["SubserviceQuickzapAction"].setEnabled(True)
1301 self.session.nav.playService(service[1])
1303 class InfoBarAdditionalInfo:
1305 self["DolbyActive"] = Pixmap()
1306 self["CryptActive"] = Pixmap()
1307 self["FormatActive"] = Pixmap()
1309 self["ButtonRed"] = PixmapConditional(withTimer = False)
1310 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1311 self.onLayoutFinish.append(self["ButtonRed"].update)
1312 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1313 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1314 self.onLayoutFinish.append(self["ButtonRedText"].update)
1316 self["ButtonGreen"] = Pixmap()
1317 self["ButtonGreenText"] = Label(_("Subservices"))
1319 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1320 self["ButtonYellow"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1321 self["ButtonYellowText"] = LabelConditional(text = _("Timeshifting"), withTimer = False)
1322 self["ButtonYellowText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1323 self.onLayoutFinish.append(self["ButtonYellow"].update)
1324 self.onLayoutFinish.append(self["ButtonYellowText"].update)
1326 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1327 self["ButtonBlue"].setConnect(lambda: True)
1328 self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
1329 self["ButtonBlueText"].setConnect(lambda: True)
1330 self.onLayoutFinish.append(self["ButtonBlue"].update)
1331 self.onLayoutFinish.append(self["ButtonBlueText"].update)
1333 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1335 def hideSubServiceIndication(self):
1336 self["ButtonGreen"].hide()
1337 self["ButtonGreenText"].hide()
1339 def showSubServiceIndication(self):
1340 self["ButtonGreen"].show()
1341 self["ButtonGreenText"].show()
1343 def checkFormat(self, service):
1344 info = service.info()
1345 if info is not None:
1346 aspect = info.getInfo(iServiceInformation.sAspect)
1347 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1348 self["FormatActive"].show()
1350 self["FormatActive"].hide()
1352 def checkSubservices(self, service):
1353 if service.subServices().getNumberOfSubservices() > 0:
1354 self.showSubServiceIndication()
1356 self.hideSubServiceIndication()
1358 def checkDolby(self, service):
1361 audio = service.audioTracks()
1362 if audio is not None:
1363 n = audio.getNumberOfTracks()
1365 i = audio.getTrackInfo(x)
1366 description = i.getDescription();
1367 if description.find("AC3") != -1 or description.find("DTS") != -1:
1371 self["DolbyActive"].show()
1373 self["DolbyActive"].hide()
1375 def checkCrypted(self, service):
1376 info = service.info()
1377 if info is not None:
1378 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1379 self["CryptActive"].show()
1381 self["CryptActive"].hide()
1383 def gotServiceEvent(self, ev):
1384 service = self.session.nav.getCurrentService()
1385 if ev == iPlayableService.evUpdatedEventInfo:
1386 self.checkSubservices(service)
1387 self.checkFormat(service)
1388 elif ev == iPlayableService.evUpdatedInfo:
1389 self.checkCrypted(service)
1390 self.checkDolby(service)
1391 elif ev == iPlayableService.evEnd:
1392 self.hideSubServiceIndication()
1393 self["CryptActive"].hide()
1394 self["DolbyActive"].hide()
1395 self["FormatActive"].hide()
1397 class InfoBarNotifications:
1399 self.onExecBegin.append(self.checkNotifications)
1400 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1402 def checkNotificationsIfExecing(self):
1404 self.checkNotifications()
1406 def checkNotifications(self):
1407 if len(Notifications.notifications):
1408 n = Notifications.notifications[0]
1409 Notifications.notifications = Notifications.notifications[1:]
1413 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1415 self.session.open(n[1], *n[2], **n[3])
1417 class InfoBarServiceNotifications:
1419 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1421 iPlayableService.evEnd: self.serviceHasEnded
1424 def serviceHasEnded(self):
1425 print "service end!"
1428 self.setSeekState(self.SEEK_STATE_PLAY)
1432 class InfoBarCueSheetSupport:
1438 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1440 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1441 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1442 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1446 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1448 iPlayableService.evStart: self.__serviceStarted,
1451 def __serviceStarted(self):
1452 print "new service started! trying to download cuts!"
1453 self.downloadCuesheet()
1455 def __getSeekable(self):
1456 service = self.session.nav.getCurrentService()
1459 return service.seek()
1461 def cueGetCurrentPosition(self):
1462 seek = self.__getSeekable()
1465 r = seek.getPlayPosition()
1470 def jumpPreviousNextMark(self, cmp, alternative=None):
1471 current_pos = self.cueGetCurrentPosition()
1472 if current_pos is None:
1474 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1475 if mark is not None:
1477 elif alternative is not None:
1482 seekable = self.__getSeekable()
1483 if seekable is not None:
1484 seekable.seekTo(pts)
1486 def jumpPreviousMark(self):
1487 # we add 2 seconds, so if the play position is <2s after
1488 # the mark, the mark before will be used
1489 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1491 def jumpNextMark(self):
1492 self.jumpPreviousNextMark(lambda x: x)
1494 def getNearestCutPoint(self, pts, cmp=abs):
1497 for cp in self.cut_list:
1498 diff = cmp(cp[0] - pts)
1499 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1503 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1504 current_pos = self.cueGetCurrentPosition()
1505 if current_pos is None:
1506 print "not seekable"
1509 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1511 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1513 return nearest_cutpoint
1515 self.removeMark(nearest_cutpoint)
1516 elif not onlyremove and not onlyreturn:
1517 self.addMark((current_pos, self.CUT_TYPE_MARK))
1522 def addMark(self, point):
1523 bisect.insort(self.cut_list, point)
1524 self.uploadCuesheet()
1526 def removeMark(self, point):
1527 self.cut_list.remove(point)
1528 self.uploadCuesheet()
1530 def __getCuesheet(self):
1531 service = self.session.nav.getCurrentService()
1534 return service.cueSheet()
1536 def uploadCuesheet(self):
1537 cue = self.__getCuesheet()
1540 print "upload failed, no cuesheet interface"
1542 cue.setCutList(self.cut_list)
1544 def downloadCuesheet(self):
1545 cue = self.__getCuesheet()
1548 print "upload failed, no cuesheet interface"
1550 self.cut_list = cue.getCutList()
1552 class InfoBarSummary(Screen):
1554 <screen position="0,0" size="132,64">
1555 <widget name="Clock" position="50,46" size="82,18" font="Regular;16" />
1556 <widget name="CurrentService" position="0,4" size="132,42" font="Regular;18" />
1559 def __init__(self, session, parent):
1560 Screen.__init__(self, session)
1561 self["CurrentService"] = ServiceName(self.session.nav)
1562 self["Clock"] = Clock()
1564 class InfoBarSummarySupport:
1568 def createSummary(self):
1569 return InfoBarSummary
1571 class InfoBarTeletextPlugin:
1573 self.teletext_plugin = None
1575 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1576 self.teletext_plugin = p
1578 if self.teletext_plugin is not None:
1579 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1581 "startTeletext": (self.startTeletext, "View teletext...")
1584 print "no teletext plugin found!"
1586 def startTeletext(self):
1587 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())