1 from ChannelSelection import ChannelSelection, BouquetSelector
3 from Components.ActionMap import ActionMap, HelpableActionMap
4 from Components.ActionMap import NumberActionMap
5 from Components.BlinkingPixmap import BlinkingPixmapConditional
6 from Components.Harddisk import harddiskmanager
7 from Components.Input import Input
8 from Components.Label import *
9 from Components.Pixmap import Pixmap, PixmapConditional
10 from Components.PluginComponent import plugins
11 from Components.ProgressBar import *
12 from Components.ServiceEventTracker import ServiceEventTracker
13 from Components.Sources.CurrentService import CurrentService
14 from Components.Sources.EventInfo import EventInfo
15 from Components.Sources.FrontendStatus import FrontendStatus
16 from Components.Sources.Boolean import Boolean
17 from Components.Sources.Clock import Clock
18 from Components.TimerList import TimerEntryComponent
19 from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean, configSelection, configElement_nonSave, getConfigListEntry
20 from Components.config import configfile, configsequencearg
22 from EpgSelection import EPGSelection
23 from Plugins.Plugin import PluginDescriptor
25 from Screen import Screen
26 from Screens.ChoiceBox import ChoiceBox
27 from Screens.Dish import Dish
28 from Screens.EventView import EventViewEPGSelect, EventViewSimple
29 from Screens.InputBox import InputBox
30 from Screens.MessageBox import MessageBox
31 from Screens.MinuteInput import MinuteInput
32 from Screens.TimerSelection import TimerSelection
33 from Screens.PictureInPicture import PictureInPicture
34 from Screens.SubtitleDisplay import SubtitleDisplay
35 from ServiceReference import ServiceReference
37 from Tools import Notifications
38 from Tools.Directories import *
40 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
47 from Components.config import config, currentConfigSelectionElement
50 from Menu import MainMenu, mdom
54 self.dishDialog = self.session.instantiateDialog(Dish)
55 self.onLayoutFinish.append(self.dishDialog.show)
57 class InfoBarShowHide:
58 """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
66 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
68 "toggleShow": self.toggleShow,
72 self.__state = self.STATE_SHOWN
75 self.onExecBegin.append(self.show)
77 self.hideTimer = eTimer()
78 self.hideTimer.timeout.get().append(self.doTimerHide)
79 self.hideTimer.start(5000, True)
81 self.onShow.append(self.__onShow)
82 self.onHide.append(self.__onHide)
85 self.__state = self.STATE_SHOWN
88 def startHideTimer(self):
89 if self.__state == self.STATE_SHOWN and not self.__locked:
90 self.hideTimer.start(5000, True)
93 self.__state = self.STATE_HIDDEN
99 def doTimerHide(self):
100 self.hideTimer.stop()
101 if self.__state == self.STATE_SHOWN:
104 def toggleShow(self):
105 if self.__state == self.STATE_SHOWN:
107 self.hideTimer.stop()
108 elif self.__state == self.STATE_HIDDEN:
112 self.__locked = self.__locked + 1
115 self.hideTimer.stop()
117 def unlockShow(self):
118 self.__locked = self.__locked - 1
120 self.startHideTimer()
122 # def startShow(self):
123 # self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
124 # self.__state = self.STATE_SHOWN
126 # def startHide(self):
127 # self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
128 # self.__state = self.STATE_HIDDEN
130 class NumberZap(Screen):
137 self.close(int(self["number"].getText()))
139 def keyNumberGlobal(self, number):
140 self.Timer.start(3000, True) #reset timer
141 self.field = self.field + str(number)
142 self["number"].setText(self.field)
143 if len(self.field) >= 4:
146 def __init__(self, session, number):
147 Screen.__init__(self, session)
148 self.field = str(number)
150 self["channel"] = Label(_("Channel:"))
152 self["number"] = Label(self.field)
154 self["actions"] = NumberActionMap( [ "SetupActions" ],
158 "1": self.keyNumberGlobal,
159 "2": self.keyNumberGlobal,
160 "3": self.keyNumberGlobal,
161 "4": self.keyNumberGlobal,
162 "5": self.keyNumberGlobal,
163 "6": self.keyNumberGlobal,
164 "7": self.keyNumberGlobal,
165 "8": self.keyNumberGlobal,
166 "9": self.keyNumberGlobal,
167 "0": self.keyNumberGlobal
170 self.Timer = eTimer()
171 self.Timer.timeout.get().append(self.keyOK)
172 self.Timer.start(3000, True)
174 class InfoBarNumberZap:
175 """ Handles an initial number for NumberZapping """
177 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
179 "1": self.keyNumberGlobal,
180 "2": self.keyNumberGlobal,
181 "3": self.keyNumberGlobal,
182 "4": self.keyNumberGlobal,
183 "5": self.keyNumberGlobal,
184 "6": self.keyNumberGlobal,
185 "7": self.keyNumberGlobal,
186 "8": self.keyNumberGlobal,
187 "9": self.keyNumberGlobal,
188 "0": self.keyNumberGlobal,
191 def keyNumberGlobal(self, number):
192 # print "You pressed number " + str(number)
194 self.servicelist.recallPrevService()
197 self.session.openWithCallback(self.numberEntered, NumberZap, number)
199 def numberEntered(self, retval):
200 # print self.servicelist
202 self.zapToNumber(retval)
204 def searchNumberHelper(self, serviceHandler, num, bouquet):
205 servicelist = serviceHandler.list(bouquet)
206 if not servicelist is None:
208 serviceIterator = servicelist.getNext()
209 if not serviceIterator.valid(): #check end of list
211 if serviceIterator.flags: #assume normal dvb service have no flags set
214 if not num: #found service with searched number ?
215 return serviceIterator, 0
218 def zapToNumber(self, number):
219 bouquet = self.servicelist.bouquet_root
221 serviceHandler = eServiceCenter.getInstance()
222 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
223 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
225 bouquetlist = serviceHandler.list(bouquet)
226 if not bouquetlist is None:
228 bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
229 if not bouquet.valid(): #check end of list
231 if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
233 service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
234 if not service is None:
235 if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
236 self.servicelist.clearPath()
237 if self.servicelist.bouquet_root != bouquet:
238 self.servicelist.enterPath(self.servicelist.bouquet_root)
239 self.servicelist.enterPath(bouquet)
240 self.servicelist.setCurrentSelection(service) #select the service in servicelist
241 self.servicelist.zap()
243 config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
245 class InfoBarChannelSelection:
246 """ ChannelSelection - handles the channelSelection dialog and the initial
247 channelChange actions which open the channelSelection dialog """
250 self.servicelist = self.session.instantiateDialog(ChannelSelection)
252 if config.misc.initialchannelselection.value == 1:
253 self.onShown.append(self.firstRun)
255 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
257 "switchChannelUp": (self.switchChannelUp, _("open servicelist(up)")),
258 "switchChannelDown": (self.switchChannelDown, _("open servicelist(down)")),
259 "zapUp": (self.zapUp, _("previous channel")),
260 "zapDown": (self.zapDown, _("next channel")),
261 "historyBack": (self.historyBack, _("previous channel in history")),
262 "historyNext": (self.historyNext, _("next channel in history")),
263 "openServiceList": (self.openServiceList, _("open servicelist")),
266 def showTvChannelList(self, zap=False):
267 self.servicelist.setModeTv()
269 self.servicelist.zap()
270 self.session.execDialog(self.servicelist)
272 def showRadioChannelList(self, zap=False):
273 self.servicelist.setModeRadio()
275 self.servicelist.zap()
276 self.session.execDialog(self.servicelist)
279 self.onShown.remove(self.firstRun)
280 config.misc.initialchannelselection.value = 0
281 config.misc.initialchannelselection.save()
282 self.switchChannelDown()
284 def historyBack(self):
285 self.servicelist.historyBack()
287 def historyNext(self):
288 self.servicelist.historyNext()
290 def switchChannelUp(self):
291 self.servicelist.moveUp()
292 self.session.execDialog(self.servicelist)
294 def switchChannelDown(self):
295 self.servicelist.moveDown()
296 self.session.execDialog(self.servicelist)
298 def openServiceList(self):
299 self.session.execDialog(self.servicelist)
302 if self.servicelist.inBouquet():
303 prev = self.servicelist.getCurrentSelection()
305 prev = prev.toString()
307 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
308 if self.servicelist.atBegin():
309 self.servicelist.prevBouquet()
310 self.servicelist.moveUp()
311 cur = self.servicelist.getCurrentSelection()
312 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
315 self.servicelist.moveUp()
316 self.servicelist.zap()
320 if self.servicelist.inBouquet():
321 prev = self.servicelist.getCurrentSelection()
323 prev = prev.toString()
325 if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.atEnd():
326 self.servicelist.nextBouquet()
328 self.servicelist.moveDown()
329 cur = self.servicelist.getCurrentSelection()
330 if not cur or (not (cur.flags & 64)) or cur.toString() == prev:
333 self.servicelist.moveDown()
334 self.servicelist.zap()
338 """ Handles a menu action, to open the (main) menu """
340 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions",
342 "mainMenu": (self.mainMenu, _("Enter main menu...")),
346 print "loading mainmenu XML..."
347 menu = mdom.childNodes[0]
348 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
349 self.session.open(MainMenu, menu, menu.childNodes)
351 class InfoBarSimpleEventView:
352 """ Opens the Eventview for now/next """
354 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
356 "showEventInfo": (self.openEventView, _("show event details")),
359 def openEventView(self):
361 service = self.session.nav.getCurrentService()
362 ref = self.session.nav.getCurrentlyPlayingServiceReference()
363 info = service.info()
366 self.epglist.append(ptr)
369 self.epglist.append(ptr)
370 if len(self.epglist) > 0:
371 self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
373 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
374 if len(self.epglist) > 1:
375 tmp = self.epglist[0]
376 self.epglist[0]=self.epglist[1]
378 setEvent(self.epglist[0])
381 """ EPG - Opens an EPG list when the showEPGList action fires """
383 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
385 iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
388 self.is_now_next = False
390 self.bouquetSel = None
391 self.eventView = None
392 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
394 "showEventInfo": (self.openEventView, _("show EPG...")),
397 def zapToService(self, service):
398 if not service is None:
399 if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
400 self.servicelist.clearPath()
401 if self.servicelist.bouquet_root != self.epg_bouquet:
402 self.servicelist.enterPath(self.servicelist.bouquet_root)
403 self.servicelist.enterPath(self.epg_bouquet)
404 self.servicelist.setCurrentSelection(service) #select the service in servicelist
405 self.servicelist.zap()
407 def getBouquetServices(self, bouquet):
409 servicelist = eServiceCenter.getInstance().list(bouquet)
410 if not servicelist is None:
412 service = servicelist.getNext()
413 if not service.valid(): #check if end of list
415 if service.flags: #ignore non playable services
417 services.append(ServiceReference(service))
420 def openBouquetEPG(self, bouquet, withCallback=True):
421 services = self.getBouquetServices(bouquet)
423 self.epg_bouquet = bouquet
425 self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
427 self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
429 def changeBouquetCB(self, direction, epg):
432 self.bouquetSel.down()
435 bouquet = self.bouquetSel.getCurrent()
436 services = self.getBouquetServices(bouquet)
438 self.epg_bouquet = bouquet
439 epg.setServices(services)
441 def closed(self, ret=False):
442 closedScreen = self.dlg_stack.pop()
443 if self.bouquetSel and closedScreen == self.bouquetSel:
444 self.bouquetSel = None
445 elif self.eventView and closedScreen == self.eventView:
446 self.eventView = None
448 dlgs=len(self.dlg_stack)
450 self.dlg_stack[dlgs-1].close(dlgs > 1)
452 def openMultiServiceEPG(self, withCallback=True):
453 bouquets = self.servicelist.getBouquetList()
458 if cnt > 1: # show bouquet list
460 self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
461 self.dlg_stack.append(self.bouquetSel)
463 self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
465 self.openBouquetEPG(bouquets[0][1], withCallback)
467 def openSingleServiceEPG(self):
468 ref=self.session.nav.getCurrentlyPlayingServiceReference()
469 self.session.open(EPGSelection, ref)
471 def openSimilarList(self, eventid, refstr):
472 self.session.open(EPGSelection, refstr, None, eventid)
474 def getNowNext(self):
476 service = self.session.nav.getCurrentService()
477 info = service and service.info()
478 ptr = info and info.getEvent(0)
480 self.epglist.append(ptr)
481 ptr = info and info.getEvent(1)
483 self.epglist.append(ptr)
485 def __evEventInfoChanged(self):
486 if self.is_now_next and len(self.dlg_stack) == 1:
488 assert self.eventView
489 if len(self.epglist):
490 self.eventView.setEvent(self.epglist[0])
492 def openEventView(self):
493 ref = self.session.nav.getCurrentlyPlayingServiceReference()
495 if len(self.epglist) == 0:
496 self.is_now_next = False
497 epg = eEPGCache.getInstance()
498 ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
500 self.epglist.append(ptr)
501 ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
503 self.epglist.append(ptr)
505 self.is_now_next = True
506 if len(self.epglist) > 0:
507 self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
508 self.dlg_stack.append(self.eventView)
510 print "no epg for the service avail.. so we show multiepg instead of eventinfo"
511 self.openMultiServiceEPG(False)
513 def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
514 if len(self.epglist) > 1:
515 tmp = self.epglist[0]
516 self.epglist[0]=self.epglist[1]
518 setEvent(self.epglist[0])
521 """provides a snr/agc/ber display"""
523 self["FrontendStatus"] = FrontendStatus(service_source = self.session.nav.getCurrentService)
526 """provides a current/next event info display"""
528 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.NOW)
529 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.NEXT)
531 class InfoBarServiceName:
533 self["CurrentService"] = CurrentService(self.session.nav)
536 """handles actions like seeking, pause"""
538 # ispause, isff, issm
539 SEEK_STATE_PLAY = (0, 0, 0, ">")
540 SEEK_STATE_PAUSE = (1, 0, 0, "||")
541 SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
542 SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
543 SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
544 SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
545 SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
546 SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
548 SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
549 SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
550 SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
551 SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
553 SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
554 SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
555 SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
558 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
560 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
561 iPlayableService.evStart: self.__serviceStarted,
563 iPlayableService.evEOF: self.__evEOF,
564 iPlayableService.evSOF: self.__evSOF,
567 class InfoBarSeekActionMap(HelpableActionMap):
568 def __init__(self, screen, *args, **kwargs):
569 HelpableActionMap.__init__(self, screen, *args, **kwargs)
572 def action(self, contexts, action):
573 if action[:5] == "seek:":
574 time = int(action[5:])
575 self.screen.seekRelative(time * 90000)
578 return HelpableActionMap.action(self, contexts, action)
580 self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
582 "pauseService": (self.pauseService, _("pause")),
583 "unPauseService": (self.unPauseService, _("continue")),
585 "seekFwd": (self.seekFwd, _("skip forward")),
586 "seekFwdDown": self.seekFwdDown,
587 "seekFwdUp": self.seekFwdUp,
588 "seekBack": (self.seekBack, _("skip backward")),
589 "seekBackDown": self.seekBackDown,
590 "seekBackUp": self.seekBackUp,
592 # give them a little more priority to win over color buttons
594 self.seekstate = self.SEEK_STATE_PLAY
595 self.onClose.append(self.delTimer)
597 self.fwdtimer = False
598 self.fwdKeyTimer = eTimer()
599 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
601 self.rwdtimer = False
602 self.rwdKeyTimer = eTimer()
603 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
605 self.onPlayStateChanged = [ ]
607 self.lockedBecauseOfSkipping = False
620 service = self.session.nav.getCurrentService()
624 seek = service.seek()
626 if seek is None or not seek.isCurrentlySeekable():
631 def isSeekable(self):
632 if self.getSeek() is None:
636 def __seekableStatusChanged(self):
637 print "seekable status changed!"
638 if not self.isSeekable():
639 self["SeekActions"].setEnabled(False)
640 print "not seekable, return to play"
641 self.setSeekState(self.SEEK_STATE_PLAY)
643 self["SeekActions"].setEnabled(True)
646 def __serviceStarted(self):
647 self.seekstate = self.SEEK_STATE_PLAY
649 def setSeekState(self, state):
650 service = self.session.nav.getCurrentService()
655 if not self.isSeekable():
656 if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
657 state = self.SEEK_STATE_PLAY
659 pauseable = service.pause()
661 if pauseable is None:
662 print "not pauseable."
663 state = self.SEEK_STATE_PLAY
665 oldstate = self.seekstate
666 self.seekstate = state
669 if oldstate[i] != self.seekstate[i]:
670 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
672 for c in self.onPlayStateChanged:
675 self.checkSkipShowHideLock()
679 def pauseService(self):
680 if self.seekstate == self.SEEK_STATE_PAUSE:
681 print "pause, but in fact unpause"
682 self.unPauseService()
684 if self.seekstate == self.SEEK_STATE_PLAY:
685 print "yes, playing."
687 print "no", self.seekstate
689 self.setSeekState(self.SEEK_STATE_PAUSE);
691 def unPauseService(self):
693 if self.seekstate == self.SEEK_STATE_PLAY:
695 self.setSeekState(self.SEEK_STATE_PLAY);
697 def doSeek(self, seektime):
698 print "doseek", seektime
699 service = self.session.nav.getCurrentService()
703 seekable = self.getSeek()
707 seekable.seekTo(90 * seektime)
709 def seekFwdDown(self):
710 print "start fwd timer"
712 self.fwdKeyTimer.start(1000)
714 def seekBackDown(self):
715 print "start rewind timer"
717 self.rwdKeyTimer.start(1000)
722 self.fwdKeyTimer.stop()
723 self.fwdtimer = False
728 self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
729 self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
730 self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
731 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
732 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
733 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
734 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
735 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
736 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
737 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
738 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
739 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
740 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
741 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
742 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
744 self.setSeekState(lookup[self.seekstate])
746 def seekBackUp(self):
749 self.rwdKeyTimer.stop()
750 self.rwdtimer = False
755 self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
756 self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
757 self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
758 self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
759 self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
760 self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
761 self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
762 self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
763 self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
764 self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
765 self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
766 self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
767 self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
768 self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
769 self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
771 self.setSeekState(lookup[self.seekstate])
773 if self.seekstate == self.SEEK_STATE_PAUSE:
774 seekable = self.getSeek()
775 if seekable is not None:
776 seekable.seekRelative(-1, 3)
778 def fwdTimerFire(self):
779 print "Display seek fwd"
780 self.fwdKeyTimer.stop()
781 self.fwdtimer = False
782 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
784 def fwdSeekTo(self, minutes):
785 print "Seek", minutes, "minutes forward"
787 seekable = self.getSeek()
788 if seekable is not None:
789 seekable.seekRelative(1, minutes * 60 * 90000)
791 def rwdTimerFire(self):
793 self.rwdKeyTimer.stop()
794 self.rwdtimer = False
795 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
797 def rwdSeekTo(self, minutes):
799 self.fwdSeekTo(0 - minutes)
801 def checkSkipShowHideLock(self):
802 wantlock = self.seekstate != self.SEEK_STATE_PLAY
804 if self.lockedBecauseOfSkipping and not wantlock:
806 self.lockedBecauseOfSkipping = False
808 if wantlock and not self.lockedBecauseOfSkipping:
810 self.lockedBecauseOfSkipping = True
813 if self.seekstate != self.SEEK_STATE_PLAY:
814 self.setSeekState(self.SEEK_STATE_PAUSE)
816 #self.getSeek().seekRelative(1, -90000)
817 self.setSeekState(self.SEEK_STATE_PLAY)
819 self.setSeekState(self.SEEK_STATE_PAUSE)
822 self.setSeekState(self.SEEK_STATE_PLAY)
825 def seekRelative(self, diff):
826 seekable = self.getSeek()
827 if seekable is not None:
828 seekable.seekRelative(1, diff)
830 from Screens.PVRState import PVRState, TimeshiftState
832 class InfoBarPVRState:
833 def __init__(self, screen=PVRState):
834 self.onPlayStateChanged.append(self.__playStateChanged)
835 self.pvrStateDialog = self.session.instantiateDialog(screen)
836 self.onShow.append(self.__mayShow)
837 self.onHide.append(self.pvrStateDialog.hide)
840 if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
841 self.pvrStateDialog.show()
843 def __playStateChanged(self, state):
844 playstateString = state[3]
845 self.pvrStateDialog["state"].setText(playstateString)
848 class InfoBarTimeshiftState(InfoBarPVRState):
850 InfoBarPVRState.__init__(self, screen=TimeshiftState)
852 class InfoBarShowMovies:
854 # i don't really like this class.
855 # it calls a not further specified "movie list" on up/down/movieList,
856 # so this is not more than an action map
858 self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions",
860 "movieList": (self.showMovies, "movie list"),
861 "up": (self.showMovies, "movie list"),
862 "down": (self.showMovies, "movie list")
865 # InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
869 # Timeshift works the following way:
870 # demux0 demux1 "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
871 # - normal playback TUNER unused PLAY enable disable disable
872 # - user presses "yellow" button. TUNER record PAUSE enable disable enable
873 # - user presess pause again FILE record PLAY enable disable enable
874 # - user fast forwards FILE record FF enable disable enable
875 # - end of timeshift buffer reached TUNER record PLAY enable enable disable
876 # - user backwards FILE record BACK # !! enable disable enable
880 # - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
881 # freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
882 # now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
883 # - the user can now PVR around
884 # - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
885 # the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
887 # the seek actions will be disabled, but the timeshiftActivateActions will be enabled
888 # - if the user rewinds, or press pause, timeshift will be activated again
890 # note that a timeshift can be enabled ("recording") and
891 # activated (currently time-shifting).
893 class InfoBarTimeshift:
895 self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
897 "timeshiftStart": (self.startTimeshift, _("start timeshift")), # the "yellow key"
898 "timeshiftStop": (self.stopTimeshift, _("stop timeshift")) # currently undefined :), probably 'TV'
900 self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
902 "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
903 "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
904 }, prio=-1) # priority over record
906 self.timeshift_enabled = 0
907 self.timeshift_state = 0
908 self.ts_pause_timer = eTimer()
909 self.ts_pause_timer.timeout.get().append(self.pauseService)
911 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
913 iPlayableService.evStart: self.__serviceStarted,
914 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
917 def getTimeshift(self):
918 service = self.session.nav.getCurrentService()
919 return service and service.timeshift()
921 def startTimeshift(self):
922 print "enable timeshift"
923 ts = self.getTimeshift()
925 # self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
926 # print "no ts interface"
929 if self.timeshift_enabled:
930 print "hu, timeshift already enabled?"
932 if not ts.startTimeshift():
934 self.timeshift_enabled = 1
936 # we remove the "relative time" for now.
937 #self.pvrStateDialog["timeshift"].setRelative(time.time())
940 self.setSeekState(self.SEEK_STATE_PAUSE)
942 # enable the "TimeshiftEnableActions", which will override
943 # the startTimeshift actions
944 self.__seekableStatusChanged()
946 print "timeshift failed"
948 def stopTimeshift(self):
949 if not self.timeshift_enabled:
951 print "disable timeshift"
952 ts = self.getTimeshift()
955 self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
957 def stopTimeshiftConfirmed(self, confirmed):
961 ts = self.getTimeshift()
966 self.timeshift_enabled = 0
969 self.__seekableStatusChanged()
971 # activates timeshift, and seeks to (almost) the end
972 def activateTimeshiftEnd(self):
973 ts = self.getTimeshift()
978 if ts.isTimeshiftActive():
979 print "!! activate timeshift called - but shouldn't this be a normal pause?"
982 self.setSeekState(self.SEEK_STATE_PLAY)
983 ts.activateTimeshift()
986 # same as activateTimeshiftEnd, but pauses afterwards.
987 def activateTimeshiftEndAndPause(self):
988 state = self.seekstate
989 self.activateTimeshiftEnd()
991 # well, this is "andPause", but it could be pressed from pause,
992 # when pausing on the (fake-)"live" picture, so an un-pause
995 print "now, pauseService"
996 if state == self.SEEK_STATE_PLAY:
997 print "is PLAYING, start pause timer"
998 self.ts_pause_timer.start(200, 1)
1001 self.unPauseService()
1003 def __seekableStatusChanged(self):
1006 print "self.isSeekable", self.isSeekable()
1007 print "self.timeshift_enabled", self.timeshift_enabled
1009 # when this service is not seekable, but timeshift
1010 # is enabled, this means we can activate
1012 if not self.isSeekable() and self.timeshift_enabled:
1015 print "timeshift activate:", enabled
1016 self["TimeshiftActivateActions"].setEnabled(enabled)
1018 def __serviceStarted(self):
1019 self.timeshift_enabled = False
1020 self.__seekableStatusChanged()
1022 from Screens.PiPSetup import PiPSetup
1024 class InfoBarExtensions:
1026 self.session.pipshown = False
1028 self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
1030 "extensions": (self.extensions, _("view extensions...")),
1039 def extensions(self):
1041 if self.session.pipshown == False:
1042 list.append((_("Activate Picture in Picture"), self.PIPON))
1043 elif self.session.pipshown == True:
1044 list.append((_("Disable Picture in Picture"), self.PIPOFF))
1045 list.append((_("Move Picture in Picture"), self.MOVEPIP))
1046 list.append((_("Swap services"), self.PIPSWAP))
1048 s = self.getCurrentServiceSubtitle()
1049 l = s and s.getSubtitleList() or [ ]
1052 list.append(("Enable Subtitles: " + x[0], self.ENABLE_SUBTITLE, x[1]))
1054 self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
1056 def extensionCallback(self, answer):
1057 if answer is not None:
1058 if answer[1] == self.PIPON:
1059 self.session.pip = self.session.instantiateDialog(PictureInPicture)
1060 newservice = self.session.nav.getCurrentlyPlayingServiceReference()
1061 if self.session.pip.playService(newservice):
1062 self.session.pipshown = True
1063 self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
1065 self.session.pipshown = False
1066 del self.session.pip
1067 self.session.nav.playService(newservice)
1068 elif answer[1] == self.PIPOFF:
1069 del self.session.pip
1070 self.session.pipshown = False
1071 elif answer[1] == self.PIPSWAP:
1072 swapservice = self.session.nav.getCurrentlyPlayingServiceReference()
1073 if self.session.pip.servicePath:
1074 servicepath = self.servicelist.getCurrentServicePath()
1075 ref=servicepath[len(servicepath)-1]
1076 pipref=self.session.pip.getCurrentService()
1077 self.session.pip.playService(swapservice)
1078 self.servicelist.setCurrentServicePath(self.session.pip.servicePath)
1079 if pipref.toString() != ref.toString(): # is a subservice ?
1080 self.session.nav.stopService() # stop portal
1081 self.session.nav.playService(pipref) # start subservice
1082 self.session.pip.servicePath=servicepath
1083 elif answer[1] == self.MOVEPIP:
1084 self.session.open(PiPSetup, pip = self.session.pip)
1085 elif answer[1] == self.ENABLE_SUBTITLE:
1086 self.selected_subtitle = answer[2]
1087 self.subtitles_enabled = True
1089 from RecordTimer import parseEvent
1091 class InfoBarInstantRecord:
1092 """Instant Record - handles the instantRecord action in order to
1093 start/stop instant records"""
1095 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
1097 "instantRecord": (self.instantRecord, _("Instant Record...")),
1100 self["BlinkingPoint"] = BlinkingPixmapConditional()
1101 self["BlinkingPoint"].hide()
1102 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
1104 def stopCurrentRecording(self, entry = -1):
1105 if entry is not None and entry != -1:
1106 self.session.nav.RecordTimer.removeEntry(self.recording[entry])
1107 self.recording.remove(self.recording[entry])
1109 def startInstantRecording(self, limitEvent = False):
1110 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
1112 # try to get event info
1115 service = self.session.nav.getCurrentService()
1116 epg = eEPGCache.getInstance()
1117 event = epg.lookupEventTime(serviceref, -1, 0)
1119 info = service.info()
1120 ev = info.getEvent(0)
1126 end = time.time() + 3600 * 10
1127 name = "instant record"
1131 if event is not None:
1132 curEvent = parseEvent(event)
1134 description = curEvent[3]
1135 eventid = curEvent[4]
1140 self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
1142 data = (begin, end, name, description, eventid)
1144 recording = self.session.nav.recordWithTimer(serviceref, *data)
1145 recording.dontSave = True
1146 self.recording.append(recording)
1148 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
1150 def isInstantRecordRunning(self):
1151 print "self.recording:", self.recording
1152 if len(self.recording) > 0:
1153 for x in self.recording:
1158 def recordQuestionCallback(self, answer):
1159 print "pre:\n", self.recording
1161 if answer is None or answer[1] == "no":
1164 recording = self.recording[:]
1166 if not x in self.session.nav.RecordTimer.timer_list:
1167 self.recording.remove(x)
1168 elif x.dontSave and x.isRunning():
1169 list.append(TimerEntryComponent(x, False))
1171 if answer[1] == "changeduration":
1172 if len(self.recording) == 1:
1173 self.changeDuration(0)
1175 self.session.openWithCallback(self.changeDuration, TimerSelection, list)
1176 elif answer[1] == "stop":
1177 if len(self.recording) == 1:
1178 self.stopCurrentRecording(0)
1180 self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
1181 if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
1183 if answer[1] == "event":
1185 if answer[1] == "manualduration":
1186 self.selectedEntry = len(self.recording)
1187 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1188 self.startInstantRecording(limitEvent = limitEvent)
1190 print "after:\n", self.recording
1192 def changeDuration(self, entry):
1193 if entry is not None:
1194 self.selectedEntry = entry
1195 self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
1197 def inputCallback(self, value):
1198 if value is not None:
1199 print "stopping recording after", int(value), "minutes."
1200 self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
1201 self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
1203 def instantRecord(self):
1205 stat = os.stat(resolveFilename(SCOPE_HDD))
1207 self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
1210 if self.isInstantRecordRunning():
1211 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")])
1213 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")])
1215 from Tools.ISO639 import LanguageCodes
1217 class InfoBarAudioSelection:
1219 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions",
1221 "audioSelection": (self.audioSelection, _("Audio Options...")),
1224 def audioSelection(self):
1225 service = self.session.nav.getCurrentService()
1226 audio = service and service.audioTracks()
1227 self.audioTracks = audio
1228 n = audio and audio.getNumberOfTracks()
1229 keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
1231 print "tlist:", tlist
1233 self.audioChannel = service.audioChannel()
1236 i = audio.getTrackInfo(x)
1237 language = i.getLanguage()
1238 description = i.getDescription()
1240 if len(language) == 3:
1241 if language in LanguageCodes:
1242 language = LanguageCodes[language][0]
1244 if len(description):
1245 description += " (" + language + ")"
1247 description = language
1249 tlist.append((description, x))
1251 selectedAudio = tlist[0][1]
1252 tlist.sort(lambda x,y : cmp(x[0], y[0]))
1256 if x[1] != selectedAudio:
1261 tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
1262 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
1264 del self.audioTracks
1266 def audioSelected(self, audio):
1267 if audio is not None:
1268 if isinstance(audio[1], str):
1269 if audio[1] == "mode":
1270 keys = ["red", "green", "yellow"]
1271 selection = self.audioChannel.getCurrentChannel()
1272 tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
1273 self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
1275 del self.audioChannel
1276 if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
1277 self.audioTracks.selectTrack(audio[1])
1279 del self.audioChannel
1280 del self.audioTracks
1282 def modeSelected(self, mode):
1283 if mode is not None:
1284 self.audioChannel.selectChannel(mode[1])
1285 del self.audioChannel
1287 class InfoBarSubserviceSelection:
1289 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
1291 "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
1294 self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
1296 "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
1297 "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
1299 self["SubserviceQuickzapAction"].setEnabled(False)
1301 self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
1303 def checkSubservicesAvail(self, ev):
1304 if ev == iPlayableService.evUpdatedEventInfo:
1305 service = self.session.nav.getCurrentService()
1306 subservices = service and service.subServices()
1307 if not subservices or subservices.getNumberOfSubservices() == 0:
1308 self["SubserviceQuickzapAction"].setEnabled(False)
1310 def nextSubservice(self):
1311 self.changeSubservice(+1)
1313 def prevSubservice(self):
1314 self.changeSubservice(-1)
1316 def changeSubservice(self, direction):
1317 service = self.session.nav.getCurrentService()
1318 subservices = service and service.subServices()
1319 n = subservices and subservices.getNumberOfSubservices()
1322 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1324 if subservices.getSubservice(x).toString() == ref.toString():
1327 selection += direction
1332 newservice = subservices.getSubservice(selection)
1333 if newservice.valid():
1336 self.session.nav.playService(newservice)
1338 def subserviceSelection(self):
1339 service = self.session.nav.getCurrentService()
1340 subservices = service and service.subServices()
1342 n = subservices and subservices.getNumberOfSubservices()
1345 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1348 i = subservices.getSubservice(x)
1349 if i.toString() == ref.toString():
1351 tlist.append((i.getName(), i))
1353 self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
1355 def subserviceSelected(self, service):
1356 if not service is None:
1357 self["SubserviceQuickzapAction"].setEnabled(True)
1358 self.session.nav.playService(service[1])
1360 class InfoBarAdditionalInfo:
1362 self["NimA"] = Pixmap()
1363 self["NimB"] = Pixmap()
1364 self["NimA_Active"] = Pixmap()
1365 self["NimB_Active"] = Pixmap()
1367 self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0)
1368 self["TimeshiftPossible"] = self["RecordingPossible"]
1369 self["ExtensionsAvailable"] = Boolean(fixed=1)
1371 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
1372 res_mgr = eDVBResourceManagerPtr()
1373 if eDVBResourceManager.getInstance(res_mgr) == 0:
1374 res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged)
1376 def tunerUseMaskChanged(self, mask):
1378 self["NimA_Active"].show()
1380 self["NimA_Active"].hide()
1382 self["NimB_Active"].show()
1384 self["NimB_Active"].hide()
1386 def checkTunerState(self, service):
1387 info = service.frontendInfo()
1388 feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber)
1389 if feNumber is None:
1399 def gotServiceEvent(self, ev):
1400 service = self.session.nav.getCurrentService()
1401 if ev == iPlayableService.evStart:
1402 self.checkTunerState(service)
1404 class InfoBarNotifications:
1406 self.onExecBegin.append(self.checkNotifications)
1407 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
1408 self.onClose.append(self.__removeNotification)
1410 def __removeNotification(self):
1411 Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
1413 def checkNotificationsIfExecing(self):
1415 self.checkNotifications()
1417 def checkNotifications(self):
1418 if len(Notifications.notifications):
1419 n = Notifications.notifications[0]
1420 Notifications.notifications = Notifications.notifications[1:]
1423 self.session.openWithCallback(cb, n[1], *n[2], **n[3])
1425 self.session.open(n[1], *n[2], **n[3])
1427 class InfoBarServiceNotifications:
1429 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1431 iPlayableService.evEnd: self.serviceHasEnded
1434 def serviceHasEnded(self):
1435 print "service end!"
1438 self.setSeekState(self.SEEK_STATE_PLAY)
1442 class InfoBarCueSheetSupport:
1448 self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
1450 "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
1451 "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
1452 "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
1456 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1458 iPlayableService.evStart: self.__serviceStarted,
1461 def __serviceStarted(self):
1462 print "new service started! trying to download cuts!"
1463 self.downloadCuesheet()
1465 def __getSeekable(self):
1466 service = self.session.nav.getCurrentService()
1469 return service.seek()
1471 def cueGetCurrentPosition(self):
1472 seek = self.__getSeekable()
1475 r = seek.getPlayPosition()
1480 def jumpPreviousNextMark(self, cmp, alternative=None):
1481 current_pos = self.cueGetCurrentPosition()
1482 if current_pos is None:
1484 mark = self.getNearestCutPoint(current_pos, cmp=cmp)
1485 if mark is not None:
1487 elif alternative is not None:
1492 seekable = self.__getSeekable()
1493 if seekable is not None:
1494 seekable.seekTo(pts)
1496 def jumpPreviousMark(self):
1497 # we add 2 seconds, so if the play position is <2s after
1498 # the mark, the mark before will be used
1499 self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
1501 def jumpNextMark(self):
1502 self.jumpPreviousNextMark(lambda x: x)
1504 def getNearestCutPoint(self, pts, cmp=abs):
1507 for cp in self.cut_list:
1508 diff = cmp(cp[0] - pts)
1509 if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
1513 def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
1514 current_pos = self.cueGetCurrentPosition()
1515 if current_pos is None:
1516 print "not seekable"
1519 nearest_cutpoint = self.getNearestCutPoint(current_pos)
1521 if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
1523 return nearest_cutpoint
1525 self.removeMark(nearest_cutpoint)
1526 elif not onlyremove and not onlyreturn:
1527 self.addMark((current_pos, self.CUT_TYPE_MARK))
1532 def addMark(self, point):
1533 bisect.insort(self.cut_list, point)
1534 self.uploadCuesheet()
1536 def removeMark(self, point):
1537 self.cut_list.remove(point)
1538 self.uploadCuesheet()
1540 def __getCuesheet(self):
1541 service = self.session.nav.getCurrentService()
1544 return service.cueSheet()
1546 def uploadCuesheet(self):
1547 cue = self.__getCuesheet()
1550 print "upload failed, no cuesheet interface"
1552 cue.setCutList(self.cut_list)
1554 def downloadCuesheet(self):
1555 cue = self.__getCuesheet()
1558 print "upload failed, no cuesheet interface"
1560 self.cut_list = cue.getCutList()
1562 class InfoBarSummary(Screen):
1564 <screen position="0,0" size="132,64">
1565 <widget source="CurrentTime" render="Label" position="50,46" size="82,18" font="Regular;16" >
1566 <convert type="ClockToText">WithSeconds</convert>
1568 <widget source="CurrentService" render="Label" position="0,4" size="132,42" font="Regular;18" >
1569 <convert type="ServiceName">Name</convert>
1573 def __init__(self, session, parent):
1574 Screen.__init__(self, session)
1575 self["CurrentService"] = CurrentService(self.session.nav)
1576 self["CurrentTime"] = Clock()
1578 class InfoBarSummarySupport:
1582 def createSummary(self):
1583 return InfoBarSummary
1585 class InfoBarTeletextPlugin:
1587 self.teletext_plugin = None
1589 for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
1590 self.teletext_plugin = p
1592 if self.teletext_plugin is not None:
1593 self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
1595 "startTeletext": (self.startTeletext, _("View teletext..."))
1598 print "no teletext plugin found!"
1600 def startTeletext(self):
1601 self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())
1603 class InfoBarSubtitleSupport(object):
1605 object.__init__(self)
1606 self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
1607 self.__subtitles_enabled = False
1609 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1611 iPlayableService.evStart: self.__serviceStarted,
1614 def __serviceStarted(self):
1615 # reenable if it was enabled
1616 r = self.__subtitles_enabled
1617 self.__subtitles_enabled = False
1618 self.__selected_subtitle = None
1619 self.setSubtitlesEnable(r)
1621 def getCurrentServiceSubtitle(self):
1622 service = self.session.nav.getCurrentService()
1623 return service and service.subtitle()
1625 def setSubtitlesEnable(self, enable=True):
1626 subtitle = self.getCurrentServiceSubtitle()
1627 if enable and self.__selected_subtitle:
1628 if subtitle and not self.__subtitles_enabled:
1629 subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
1630 self.subtitle_window.show()
1631 self.__subtitles_enabled = True
1634 subtitle.disableSubtitles(self.subtitle_window.instance)
1636 self.subtitle_window.hide()
1637 self.__subtitles_enabled = False
1639 def setSelectedSubtitle(self, subtitle):
1640 if self.__selected_subtitle != subtitle and self.subtitles_enabled:
1642 self.__selected_subtitle = subtitle
1643 self.__serviceStarted()
1645 self.__selected_subtitle = subtitle
1647 subtitles_enabled = property(lambda self: self.__subtitles_enabled, setSubtitlesEnable)
1648 selected_subtitle = property(lambda self: self.__selected_subtitle, setSelectedSubtitle)