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, configSelection, configElement_nonSave, getConfigListEntry
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 if len(self.epglist):
452 self.eventView.setEvent(self.epglist[0])
454 def openEventView(self):
455 ref = self.session.nav.getCurrentlyPlayingServiceReference()
457 if len(self.epglist) == 0:
458 self.is_now_next = False
459 epg = eEPGCache.getInstance()
460 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
462 self.epglist.append(ptr)
463 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
465 self.epglist.append(ptr)
467 self.is_now_next = True
468 if len(self.epglist) > 0:
469 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
470 self.dlg_stack.append(self.eventView)
472 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
473 self.openMultiServiceEPG(False)
475 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
476 if len(self.epglist) > 1:
477 tmp = self.epglist[0]
478 self.epglist[0]=self.epglist[1]
480 setEvent(self.epglist[0])
483 """provides a snr/agc/ber display"""
485 self["snr"] = Label()
486 self["agc"] = Label()
487 self["ber"] = Label()
488 self["snr_percent"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
489 self["agc_percent"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
490 self["ber_count"] = TunerInfo(TunerInfo.BER_VALUE, servicefkt = self.session.nav.getCurrentService)
491 self["snr_progress"] = TunerInfo(TunerInfo.SNR_BAR, servicefkt = self.session.nav.getCurrentService)
492 self["agc_progress"] = TunerInfo(TunerInfo.AGC_BAR, servicefkt = self.session.nav.getCurrentService)
493 self["ber_progress"] = TunerInfo(TunerInfo.BER_BAR, servicefkt = self.session.nav.getCurrentService)
494 self.timer = eTimer()
495 self.timer.timeout.get().append(self.updateTunerInfo)
496 self.timer.start(1000)
498 def updateTunerInfo(self):
499 if self.instance.isVisible():
500 self["snr_percent"].update()
501 self["agc_percent"].update()
502 self["ber_count"].update()
503 self["snr_progress"].update()
504 self["agc_progress"].update()
505 self["ber_progress"].update()
508 """provides a current/next event info display"""
510 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
511 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
513 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
514 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
516 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
517 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
519 self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
521 class InfoBarServiceName:
523 self["ServiceName"] = ServiceName(self.session.nav)
526 """handles actions like seeking, pause"""
528 # ispause, isff, issm
529 SEEK_STATE_PLAY = (0, 0, 0, ">")
530 SEEK_STATE_PAUSE = (1, 0, 0, "||")
531 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
532 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
533 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
534 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
535 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
536 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
538 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
539 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
540 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
541 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
543 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
544 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
545 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
548 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
550 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
551 iPlayableService.evStart: self.__serviceStarted,
553 iPlayableService.evEOF: self.__evEOF,
554 iPlayableService.evSOF: self.__evSOF,
557 class InfoBarSeekActionMap(HelpableActionMap):
558 def __init__(self, screen, *args, **kwargs):
559 HelpableActionMap.__init__(self, screen, *args, **kwargs)
562 def action(self, contexts, action):
563 if action[:5] == "seek:":
564 time = int(action[5:])
565 self.screen.seekRelative(time * 90000)
568 return HelpableActionMap.action(self, contexts, action)
570 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
572 "pauseService": (self.pauseService, "pause"),
573 "unPauseService": (self.unPauseService, "continue"),
575 "seekFwd": (self.seekFwd, "skip forward"),
576 "seekFwdDown": self.seekFwdDown,
577 "seekFwdUp": self.seekFwdUp,
578 "seekBack": (self.seekBack, "skip backward"),
579 "seekBackDown": self.seekBackDown,
580 "seekBackUp": self.seekBackUp,
582 # give them a little more priority to win over color buttons
584 self.seekstate = self.SEEK_STATE_PLAY
585 self.onClose.append(self.delTimer)
587 self.fwdtimer = False
588 self.fwdKeyTimer = eTimer()
589 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
591 self.rwdtimer = False
592 self.rwdKeyTimer = eTimer()
593 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
595 self.onPlayStateChanged = [ ]
597 self.lockedBecauseOfSkipping = False
610 service = self.session.nav.getCurrentService()
614 seek = service.seek()
616 if seek is None or not seek.isCurrentlySeekable():
621 def isSeekable(self):
622 if self.getSeek() is None:
626 def __seekableStatusChanged(self):
627 print "seekable status changed!"
628 if not self.isSeekable():
629 self["SeekActions"].setEnabled(False)
630 print "not seekable, return to play"
631 self.setSeekState(self.SEEK_STATE_PLAY)
633 self["SeekActions"].setEnabled(True)
636 def __serviceStarted(self):
637 self.seekstate = self.SEEK_STATE_PLAY
639 def setSeekState(self, state):
640 service = self.session.nav.getCurrentService()
645 if not self.isSeekable():
646 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
647 state = self.SEEK_STATE_PLAY
649 pauseable = service.pause()
651 if pauseable is None:
652 print "not pauseable."
653 state = self.SEEK_STATE_PLAY
655 oldstate = self.seekstate
656 self.seekstate = state
659 if oldstate[i] != self.seekstate[i]:
660 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
662 for c in self.onPlayStateChanged:
665 self.checkSkipShowHideLock()
669 def pauseService(self):
670 if self.seekstate == self.SEEK_STATE_PAUSE:
671 print "pause, but in fact unpause"
672 self.unPauseService()
674 if self.seekstate == self.SEEK_STATE_PLAY:
675 print "yes, playing."
677 print "no", self.seekstate
679 self.setSeekState(self.SEEK_STATE_PAUSE);
681 def unPauseService(self):
683 self.setSeekState(self.SEEK_STATE_PLAY);
685 def doSeek(self, seektime):
686 print "doseek", seektime
687 service = self.session.nav.getCurrentService()
691 seekable = self.getSeek()
695 seekable.seekTo(90 * seektime)
697 def seekFwdDown(self):
698 print "start fwd timer"
700 self.fwdKeyTimer.start(1000)
702 def seekBackDown(self):
703 print "start rewind timer"
705 self.rwdKeyTimer.start(1000)
710 self.fwdKeyTimer.stop()
711 self.fwdtimer = False
716 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
717 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
718 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
719 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
720 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
721 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
722 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
723 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
724 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
725 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
726 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
727 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
728 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
729 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
730 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
732 self.setSeekState(lookup[self.seekstate])
734 def seekBackUp(self):
737 self.rwdKeyTimer.stop()
738 self.rwdtimer = False
743 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
744 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
745 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
746 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
747 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
748 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
749 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
750 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
751 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
752 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
753 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
754 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
755 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
756 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
757 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
759 self.setSeekState(lookup[self.seekstate])
761 if self.seekstate == self.SEEK_STATE_PAUSE:
762 seekable = self.getSeek()
763 if seekable is not None:
764 seekable.seekRelative(-1, 3)
766 def fwdTimerFire(self):
767 print "Display seek fwd"
768 self.fwdKeyTimer.stop()
769 self.fwdtimer = False
770 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
772 def fwdSeekTo(self, minutes):
773 print "Seek", minutes, "minutes forward"
775 seekable = self.getSeek()
776 if seekable is not None:
777 seekable.seekRelative(1, minutes * 60 * 90000)
779 def rwdTimerFire(self):
781 self.rwdKeyTimer.stop()
782 self.rwdtimer = False
783 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
785 def rwdSeekTo(self, minutes):
787 self.fwdSeekTo(0 - minutes)
789 def checkSkipShowHideLock(self):
790 wantlock = self.seekstate != self.SEEK_STATE_PLAY
792 if self.lockedBecauseOfSkipping and not wantlock:
794 self.lockedBecauseOfSkipping = False
796 if wantlock and not self.lockedBecauseOfSkipping:
798 self.lockedBecauseOfSkipping = True
801 if self.seekstate != self.SEEK_STATE_PLAY:
802 self.setSeekState(self.SEEK_STATE_PAUSE)
804 #self.getSeek().seekRelative(1, -90000)
805 self.setSeekState(self.SEEK_STATE_PLAY)
807 self.setSeekState(self.SEEK_STATE_PAUSE)
810 self.setSeekState(self.SEEK_STATE_PLAY)
813 def seekRelative(self, diff):
814 seekable = self.getSeek()
815 if seekable is not None:
816 seekable.seekRelative(1, diff)
818 from Screens.PVRState import PVRState, TimeshiftState
820 class InfoBarPVRState:
821 def __init__(self, screen=PVRState):
822 self.onPlayStateChanged.append(self.__playStateChanged)
823 self.pvrStateDialog = self.session.instantiateDialog(screen)
824 self.onShow.append(self.__mayShow)
825 self.onHide.append(self.pvrStateDialog.hide)
828 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
829 self.pvrStateDialog.show()
831 def __playStateChanged(self, state):
832 playstateString = state[3]
833 self.pvrStateDialog["state"].setText(playstateString)
836 class InfoBarTimeshiftState(InfoBarPVRState):
838 InfoBarPVRState.__init__(self, screen=TimeshiftState)
841 class InfoBarShowMovies:
843 # i don't really like this class.
844 # it calls a not further specified "movie list" on up/down/movieList,
845 # so this is not more than an action map
847 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
849 "movieList": (self.showMovies, "movie list"),
850 "up": (self.showMovies, "movie list"),
851 "down": (self.showMovies, "movie list")
854 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
858 # Timeshift works the following way:
859 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
860 # - normal playback TUNER unused PLAY enable disable disable
861 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
862 # - user presess pause again FILE record PLAY enable disable enable
863 # - user fast forwards FILE record FF enable disable enable
864 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
865 # - user backwards FILE record BACK # !! enable disable enable
869 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
870 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
871 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
872 # - the user can now PVR around
873 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
874 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
876 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
877 # - if the user rewinds, or press pause, timeshift will be activated again
879 # note that a timeshift can be enabled ("recording") and
880 # activated (currently time-shifting).
882 class InfoBarTimeshift:
884 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
886 "timeshiftStart": (self.startTimeshift, "start timeshift"), # the "yellow key"
887 "timeshiftStop": (self.stopTimeshift, "stop timeshift") # currently undefined :), probably 'TV'
889 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
891 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
892 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
893 }, prio=-1) # priority over record
895 self.timeshift_enabled = 0
896 self.timeshift_state = 0
897 self.ts_pause_timer = eTimer()
898 self.ts_pause_timer.timeout.get().append(self.pauseService)
900 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
902 iPlayableService.evStart: self.__serviceStarted,
903 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
906 def getTimeshift(self):
907 service = self.session.nav.getCurrentService()
908 return service and service.timeshift()
910 def startTimeshift(self):
911 print "enable timeshift"
912 ts = self.getTimeshift()
914 self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
915 print "no ts interface"
918 if self.timeshift_enabled:
919 print "hu, timeshift already enabled?"
921 if not ts.startTimeshift():
923 self.timeshift_enabled = 1
924 self.pvrStateDialog["timeshift"].setRelative(time.time())
927 self.setSeekState(self.SEEK_STATE_PAUSE)
929 # enable the "TimeshiftEnableActions", which will override
930 # the startTimeshift actions
931 self.__seekableStatusChanged()
933 print "timeshift failed"
935 def stopTimeshift(self):
936 if not self.timeshift_enabled:
938 print "disable timeshift"
939 ts = self.getTimeshift()
942 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
944 def stopTimeshiftConfirmed(self, confirmed):
948 ts = self.getTimeshift()
953 self.timeshift_enabled = 0
956 self.__seekableStatusChanged()
958 # activates timeshift, and seeks to (almost) the end
959 def activateTimeshiftEnd(self):
960 ts = self.getTimeshift()
965 if ts.isTimeshiftActive():
966 print "!! activate timeshift called - but shouldn't this be a normal pause?"
969 self.setSeekState(self.SEEK_STATE_PLAY)
970 ts.activateTimeshift()
973 # same as activateTimeshiftEnd, but pauses afterwards.
974 def activateTimeshiftEndAndPause(self):
975 state = self.seekstate
976 self.activateTimeshiftEnd()
978 # well, this is "andPause", but it could be pressed from pause,
979 # when pausing on the (fake-)"live" picture, so an un-pause
982 print "now, pauseService"
983 if state == self.SEEK_STATE_PLAY:
984 print "is PLAYING, start pause timer"
985 self.ts_pause_timer.start(200, 1)
988 self.unPauseService()
990 def __seekableStatusChanged(self):
993 print "self.isSeekable", self.isSeekable()
994 print "self.timeshift_enabled", self.timeshift_enabled
996 # when this service is not seekable, but timeshift
997 # is enabled, this means we can activate
999 if not self.isSeekable() and self.timeshift_enabled:
1002 print "timeshift activate:", enabled
1003 self["TimeshiftActivateActions"].setEnabled(enabled)
1005 def __serviceStarted(self):
1006 self.timeshift_enabled = False
1007 self.__seekableStatusChanged()
1009 from Screens.PiPSetup import PiPSetup
1011 class InfoBarExtensions:
1013 self.pipshown = False
1015 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1017 "extensions": (self.extensions, "Extensions..."),
1025 def extensions(self):
1027 if self.pipshown == False:
1028 list.append((_("Activate Picture in Picture"), self.PIPON))
1029 elif self.pipshown == True:
1030 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1031 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1032 list.append((_("Swap services"), self.PIPSWAP))
1033 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1035 def extensionCallback(self, answer):
1036 if answer is not None:
1037 if answer[1] == self.PIPON:
1038 self.pip = self.session.instantiateDialog(PictureInPicture)
1040 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1042 if self.pip.playService(newservice):
1043 self.pipshown = True
1045 self.pipshown = False
1047 self.session.nav.playService(newservice)
1048 elif answer[1] == self.PIPOFF:
1050 self.pipshown = False
1051 elif answer[1] == self.PIPSWAP:
1052 swapservice = self.pip.getCurrentService()
1053 self.pip.playService(self.session.nav.getCurrentlyPlayingServiceReference())
1054 self.session.nav.playService(swapservice)
1056 elif answer[1] == self.MOVEPIP:
1057 self.session.open(PiPSetup, pip = self.pip)
1059 from RecordTimer import parseEvent
1061 class InfoBarInstantRecord:
1062 """Instant Record - handles the instantRecord action in order to
1063 start/stop instant records"""
1065 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1067 "instantRecord": (self.instantRecord, "Instant Record..."),
1070 self["BlinkingPoint"] = BlinkingPixmapConditional()
1071 self["BlinkingPoint"].hide()
1072 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1074 def stopCurrentRecording(self, entry = -1):
1075 if entry is not None and entry != -1:
1076 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1077 self.recording.remove(self.recording[entry])
1079 def startInstantRecording(self, limitEvent = False):
1080 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1082 # try to get event info
1085 service = self.session.nav.getCurrentService()
1086 epg = eEPGCache.getInstance()
1087 event = epg.lookupEventTime(serviceref, -1, 0)
1089 info = service.info()
1090 ev = info.getEvent(0)
1096 end = time.time() + 3600 * 10
1097 name = "instant record"
1101 if event is not None:
1102 curEvent = parseEvent(event)
1104 description = curEvent[3]
1105 eventid = curEvent[4]
1110 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1112 data = (begin, end, name, description, eventid)
1114 recording = self.session.nav.recordWithTimer(serviceref, *data)
1115 recording.dontSave = True
1116 self.recording.append(recording)
1118 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1120 def isInstantRecordRunning(self):
1121 print "self.recording:", self.recording
1122 if len(self.recording) > 0:
1123 for x in self.recording:
1128 def recordQuestionCallback(self, answer):
1129 print "pre:\n", self.recording
1131 if answer is None or answer[1] == "no":
1134 recording = self.recording[:]
1136 if not x in self.session.nav.RecordTimer.timer_list:
1137 self.recording.remove(x)
1138 elif x.dontSave and x.isRunning():
1139 list.append(TimerEntryComponent(x, False))
1141 if answer[1] == "changeduration":
1142 if len(self.recording) == 1:
1143 self.changeDuration(0)
1145 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1146 elif answer[1] == "stop":
1147 if len(self.recording) == 1:
1148 self.stopCurrentRecording(0)
1150 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1151 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1153 if answer[1] == "event":
1155 if answer[1] == "manualduration":
1156 self.selectedEntry = len(self.recording)
1157 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1158 self.startInstantRecording(limitEvent = limitEvent)
1160 print "after:\n", self.recording
1162 def changeDuration(self, entry):
1163 if entry is not None:
1164 self.selectedEntry = entry
1165 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1167 def inputCallback(self, value):
1168 if value is not None:
1169 print "stopping recording after", int(value), "minutes."
1170 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1171 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1173 def instantRecord(self):
1175 stat = os.stat(resolveFilename(SCOPE_HDD))
1177 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1180 if self.isInstantRecordRunning():
1181 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")])
1183 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")])
1185 from Tools.ISO639 import LanguageCodes
1187 class InfoBarAudioSelection:
1189 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1191 "audioSelection": (self.audioSelection, "Audio Options..."),
1194 def audioSelection(self):
1195 service = self.session.nav.getCurrentService()
1196 audio = service.audioTracks()
1197 self.audioTracks = audio
1198 n = audio.getNumberOfTracks()
1200 # self.audioChannel = service.audioChannel()
1201 # config.audio.audiochannel = configElement_nonSave("config.audio.audiochannel", configSelection, self.audioChannel.getCurrentChannel(), (("left", _("Left >")), ("stereo", _("< Stereo >")), ("right", _("< Right"))))
1204 i = audio.getTrackInfo(x)
1205 language = i.getLanguage()
1206 description = i.getDescription();
1208 if len(language) == 3:
1209 if language in LanguageCodes:
1210 language = LanguageCodes[language][0]
1212 if len(description):
1213 description += " (" + language + ")"
1215 description = language
1217 tlist.append((description, x))
1219 selectedAudio = tlist[0][1]
1220 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1222 # tlist.insert(0, getConfigListEntry(_("Audio Channel"), config.audio.audiochannel))
1226 if x[1] != selectedAudio:
1231 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection)
1233 del self.audioTracks
1235 def audioSelected(self, audio):
1236 if audio is not None:
1237 self.audioTracks.selectTrack(audio[1])
1238 del self.audioTracks
1239 # del self.audioChannel
1240 # del config.audio.audiochannel
1242 class InfoBarSubserviceSelection:
1244 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1246 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1249 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1251 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1252 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1254 self["SubserviceQuickzapAction"].setEnabled(False)
1256 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1258 def checkSubservicesAvail(self, ev):
1259 if ev == iPlayableService.evUpdatedEventInfo:
1260 service = self.session.nav.getCurrentService()
1261 subservices = service.subServices()
1262 if subservices.getNumberOfSubservices() == 0:
1263 self["SubserviceQuickzapAction"].setEnabled(False)
1265 def nextSubservice(self):
1266 self.changeSubservice(+1)
1268 def prevSubservice(self):
1269 self.changeSubservice(-1)
1271 def changeSubservice(self, direction):
1272 service = self.session.nav.getCurrentService()
1273 subservices = service.subServices()
1274 n = subservices.getNumberOfSubservices()
1277 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1279 if subservices.getSubservice(x).toString() == ref.toString():
1282 selection += direction
1287 newservice = subservices.getSubservice(selection)
1288 if newservice.valid():
1291 self.session.nav.playService(newservice)
1293 def subserviceSelection(self):
1294 service = self.session.nav.getCurrentService()
1295 subservices = service.subServices()
1297 n = subservices.getNumberOfSubservices()
1300 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1303 i = subservices.getSubservice(x)
1304 if i.toString() == ref.toString():
1306 tlist.append((i.getName(), i))
1308 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1310 def subserviceSelected(self, service):
1311 if not service is None:
1312 self["SubserviceQuickzapAction"].setEnabled(True)
1313 self.session.nav.playService(service[1])
1315 class InfoBarAdditionalInfo:
1317 self["DolbyActive"] = Pixmap()
1318 self["CryptActive"] = Pixmap()
1319 self["FormatActive"] = Pixmap()
1321 self["ButtonRed"] = PixmapConditional(withTimer = False)
1322 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1323 self.onLayoutFinish.append(self["ButtonRed"].update)
1324 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
1325 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1326 self.onLayoutFinish.append(self["ButtonRedText"].update)
1328 self["ButtonGreen"] = Pixmap()
1329 self["ButtonGreenText"] = Label(_("Subservices"))
1331 self["ButtonYellow"] = PixmapConditional(withTimer = False)
1332 self["ButtonYellow"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1333 self["ButtonYellowText"] = LabelConditional(text = _("Timeshifting"), withTimer = False)
1334 self["ButtonYellowText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
1335 self.onLayoutFinish.append(self["ButtonYellow"].update)
1336 self.onLayoutFinish.append(self["ButtonYellowText"].update)
1338 self["ButtonBlue"] = PixmapConditional(withTimer = False)
1339 self["ButtonBlue"].setConnect(lambda: True)
1340 self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
1341 self["ButtonBlueText"].setConnect(lambda: True)
1342 self.onLayoutFinish.append(self["ButtonBlue"].update)
1343 self.onLayoutFinish.append(self["ButtonBlueText"].update)
1345 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1347 def hideSubServiceIndication(self):
1348 self["ButtonGreen"].hide()
1349 self["ButtonGreenText"].hide()
1351 def showSubServiceIndication(self):
1352 self["ButtonGreen"].show()
1353 self["ButtonGreenText"].show()
1355 def checkFormat(self, service):
1356 info = service.info()
1357 if info is not None:
1358 aspect = info.getInfo(iServiceInformation.sAspect)
1359 if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
1360 self["FormatActive"].show()
1362 self["FormatActive"].hide()
1364 def checkSubservices(self, service):
1365 if service.subServices().getNumberOfSubservices() > 0:
1366 self.showSubServiceIndication()
1368 self.hideSubServiceIndication()
1370 def checkDolby(self, service):
1373 audio = service.audioTracks()
1374 if audio is not None:
1375 n = audio.getNumberOfTracks()
1377 i = audio.getTrackInfo(x)
1378 description = i.getDescription();
1379 if description.find("AC3") != -1 or description.find("DTS") != -1:
1383 self["DolbyActive"].show()
1385 self["DolbyActive"].hide()
1387 def checkCrypted(self, service):
1388 info = service.info()
1389 if info is not None:
1390 if info.getInfo(iServiceInformation.sIsCrypted) > 0:
1391 self["CryptActive"].show()
1393 self["CryptActive"].hide()
1395 def gotServiceEvent(self, ev):
1396 service = self.session.nav.getCurrentService()
1397 if ev == iPlayableService.evUpdatedEventInfo:
1398 self.checkSubservices(service)
1399 self.checkFormat(service)
1400 elif ev == iPlayableService.evUpdatedInfo:
1401 self.checkCrypted(service)
1402 self.checkDolby(service)
1403 elif ev == iPlayableService.evEnd:
1404 self.hideSubServiceIndication()
1405 self["CryptActive"].hide()
1406 self["DolbyActive"].hide()
1407 self["FormatActive"].hide()
1409 class InfoBarNotifications:
1411 self.onExecBegin.append(self.checkNotifications)
1412 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1414 def checkNotificationsIfExecing(self):
1417 self.checkNotifications()
1419 print "******************************* A SEVERE ERROR HAPPENED... Someone who understands the code... please fix :) *******"
1421 def checkNotifications(self):
1422 if len(Notifications.notifications):
1423 n = Notifications.notifications[0]
1424 Notifications.notifications = Notifications.notifications[1:]
1428 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1430 self.session.open(n[1], *n[2], **n[3])
1432 class InfoBarServiceNotifications:
1434 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1436 iPlayableService.evEnd: self.serviceHasEnded
1439 def serviceHasEnded(self):
1440 print "service end!"
1443 self.setSeekState(self.SEEK_STATE_PLAY)
1447 class InfoBarCueSheetSupport:
1453 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1455 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1456 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1457 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1461 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1463 iPlayableService.evStart: self.__serviceStarted,
1466 def __serviceStarted(self):
1467 print "new service started! trying to download cuts!"
1468 self.downloadCuesheet()
1470 def __getSeekable(self):
1471 service = self.session.nav.getCurrentService()
1474 return service.seek()
1476 def cueGetCurrentPosition(self):
1477 seek = self.__getSeekable()
1480 r = seek.getPlayPosition()
1485 def jumpPreviousNextMark(self, cmp, alternative=None):
1486 current_pos = self.cueGetCurrentPosition()
1487 if current_pos is None:
1489 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1490 if mark is not None:
1492 elif alternative is not None:
1497 seekable = self.__getSeekable()
1498 if seekable is not None:
1499 seekable.seekTo(pts)
1501 def jumpPreviousMark(self):
1502 # we add 2 seconds, so if the play position is <2s after
1503 # the mark, the mark before will be used
1504 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1506 def jumpNextMark(self):
1507 self.jumpPreviousNextMark(lambda x: x)
1509 def getNearestCutPoint(self, pts, cmp=abs):
1512 for cp in self.cut_list:
1513 diff = cmp(cp[0] - pts)
1514 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1518 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1519 current_pos = self.cueGetCurrentPosition()
1520 if current_pos is None:
1521 print "not seekable"
1524 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1526 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1528 return nearest_cutpoint
1530 self.removeMark(nearest_cutpoint)
1531 elif not onlyremove and not onlyreturn:
1532 self.addMark((current_pos, self.CUT_TYPE_MARK))
1537 def addMark(self, point):
1538 bisect.insort(self.cut_list, point)
1539 self.uploadCuesheet()
1541 def removeMark(self, point):
1542 self.cut_list.remove(point)
1543 self.uploadCuesheet()
1545 def __getCuesheet(self):
1546 service = self.session.nav.getCurrentService()
1549 return service.cueSheet()
1551 def uploadCuesheet(self):
1552 cue = self.__getCuesheet()
1555 print "upload failed, no cuesheet interface"
1557 cue.setCutList(self.cut_list)
1559 def downloadCuesheet(self):
1560 cue = self.__getCuesheet()
1563 print "upload failed, no cuesheet interface"
1565 self.cut_list = cue.getCutList()
1567 class InfoBarSummary(Screen):
1569 <screen position="0,0" size="132,64">
1570 <widget name="Clock" position="50,46" size="82,18" font="Regular;16" />
1571 <widget name="CurrentService" position="0,4" size="132,42" font="Regular;18" />
1574 def __init__(self, session, parent):
1575 Screen.__init__(self, session)
1576 self["CurrentService"] = ServiceName(self.session.nav)
1577 self["Clock"] = Clock()
1579 class InfoBarSummarySupport:
1583 def createSummary(self):
1584 return InfoBarSummary
1586 class InfoBarTeletextPlugin:
1588 self.teletext_plugin = None
1590 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1591 self.teletext_plugin = p
1593 if self.teletext_plugin is not None:
1594 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1596 "startTeletext": (self.startTeletext, "View teletext...")
1599 print "no teletext plugin found!"
1601 def startTeletext(self):
1602 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())