from Components.Label import *
from Components.ProgressBar import *
from Components.config import configfile, configsequencearg
-from Components.config import config, configElement, ConfigSubsection, configSequence
+from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean
from ChannelSelection import ChannelSelection, BouquetSelector
from Components.Pixmap import Pixmap, PixmapConditional
from Components.BlinkingPixmap import BlinkingPixmapConditional
from Components.ServiceName import ServiceName
from Components.EventInfo import EventInfo, EventInfoProgress
+from Components.Clock import Clock
+from Components.Input import Input
from ServiceReference import ServiceReference
from EpgSelection import EPGSelection
from Screens.MessageBox import MessageBox
+from Screens.ChoiceBox import ChoiceBox
+from Screens.InputBox import InputBox
from Screens.Dish import Dish
from Screens.Standby import Standby
-from Screens.EventView import EventView
+from Screens.EventView import EventViewEPGSelect, EventViewSimple
from Screens.MinuteInput import MinuteInput
from Components.Harddisk import harddiskmanager
import time
import os
+import bisect
from Components.config import config, currentConfigSelectionElement
class InfoBarDish:
def __init__(self):
self.dishDialog = self.session.instantiateDialog(Dish)
- self.onShown.append(self.dishDialog.instance.show)
+ self.onLayoutFinish.append(self.dishDialog.show)
class InfoBarShowHide:
""" InfoBar show/hide control, accepts toggleShow and hide actions, might start
"hide": self.hide,
})
- self.state = self.STATE_SHOWN
+ self.__state = self.STATE_SHOWN
+ self.__locked = 0
self.onExecBegin.append(self.show)
- self.onClose.append(self.delHideTimer)
self.hideTimer = eTimer()
self.hideTimer.timeout.get().append(self.doTimerHide)
self.hideTimer.start(5000, True)
+
+ self.onShow.append(self.__onShow)
+ self.onHide.append(self.__onHide)
- def delHideTimer(self):
- del self.hideTimer
+ def __onShow(self):
+ self.__state = self.STATE_SHOWN
+ self.startHideTimer()
+
+ def startHideTimer(self):
+ if self.__state == self.STATE_SHOWN and not self.__locked:
+ self.hideTimer.start(5000, True)
- def hide(self):
- self.instance.hide()
-
- def show(self):
- self.state = self.STATE_SHOWN
- self.hideTimer.start(5000, True)
+ def __onHide(self):
+ self.__state = self.STATE_HIDDEN
+
+ def doShow(self):
+ self.show()
+ self.startHideTimer()
def doTimerHide(self):
self.hideTimer.stop()
- if self.state == self.STATE_SHOWN:
- self.instance.hide()
- self.state = self.STATE_HIDDEN
+ if self.__state == self.STATE_SHOWN:
+ self.hide()
def toggleShow(self):
- if self.state == self.STATE_SHOWN:
- self.instance.hide()
- #pls check animation support, sorry
-# self.startHide()
+ if self.__state == self.STATE_SHOWN:
+ self.hide()
self.hideTimer.stop()
- self.state = self.STATE_HIDDEN
- elif self.state == self.STATE_HIDDEN:
- self.instance.show()
+ elif self.__state == self.STATE_HIDDEN:
self.show()
-
- def startShow(self):
- self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
- self.state = self.STATE_SHOWN
+
+ def lockShow(self):
+ self.__locked = self.__locked + 1
+ if self.execing:
+ self.show()
+ self.hideTimer.stop()
- def startHide(self):
- self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
- self.state = self.STATE_HIDDEN
+ def unlockShow(self):
+ self.__locked = self.__locked - 1
+ if self.execing:
+ self.startHideTimer()
+
+# def startShow(self):
+# self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
+# self.__state = self.STATE_SHOWN
+#
+# def startHide(self):
+# self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
+# self.__state = self.STATE_HIDDEN
class NumberZap(Screen):
def quit(self):
# print "You pressed number " + str(number)
if number == 0:
self.servicelist.recallPrevService()
- self.instance.show()
- self.show()
+ self.doShow()
else:
self.session.openWithCallback(self.numberEntered, NumberZap, number)
self.servicelist.setCurrentSelection(service) #select the service in servicelist
self.servicelist.zap()
+config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
+
class InfoBarChannelSelection:
""" ChannelSelection - handles the channelSelection dialog and the initial
channelChange actions which open the channelSelection dialog """
def __init__(self):
#instantiate forever
self.servicelist = self.session.instantiateDialog(ChannelSelection)
+
+ if config.misc.initialchannelselection.value == 1:
+ self.onShown.append(self.firstRun)
self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
{
"switchChannelUp": self.switchChannelUp,
"switchChannelDown": self.switchChannelDown,
- "zapUp": (self.zapUp, _("next channel")),
- "zapDown": (self.zapDown, _("previous channel")),
+ "zapUp": (self.zapUp, _("previous channel")),
+ "zapDown": (self.zapDown, _("next channel")),
+ "historyBack": (self.historyBack, _("previous channel in history")),
+ "historyNext": (self.historyNext, _("next channel in history"))
})
-
- def switchChannelUp(self):
+
+ def firstRun(self):
+ self.onShown.remove(self.firstRun)
+ config.misc.initialchannelselection.value = 0
+ config.misc.initialchannelselection.save()
+ self.switchChannelDown()
+
+ def historyBack(self):
+ self.servicelist.historyBack()
+
+ def historyNext(self):
+ self.servicelist.historyNext()
+
+ def switchChannelUp(self):
self.servicelist.moveUp()
self.session.execDialog(self.servicelist)
- def switchChannelDown(self):
+ def switchChannelDown(self):
self.servicelist.moveDown()
self.session.execDialog(self.servicelist)
- def zapUp(self):
+ def zapUp(self):
+ if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes":
+ if self.servicelist.inBouquet() and self.servicelist.atBegin():
+ self.servicelist.prevBouquet()
self.servicelist.moveUp()
self.servicelist.zap()
- self.instance.show()
- self.show()
+ self.doShow()
- def zapDown(self):
- self.servicelist.moveDown()
+ def zapDown(self):
+ if currentConfigSelectionElement(config.usage.quickzap_bouquet_change) == "yes" and self.servicelist.inBouquet() and self.servicelist.atEnd():
+ self.servicelist.nextBouquet()
+ else:
+ self.servicelist.moveDown()
self.servicelist.zap()
- self.instance.show()
- self.show()
-
+ self.doShow()
+
class InfoBarMenu:
""" Handles a menu action, to open the (main) menu """
def __init__(self):
assert menu.tagName == "menu", "root element in menu must be 'menu'!"
self.session.open(MainMenu, menu, menu.childNodes)
+class InfoBarSimpleEventView:
+ """ Opens the Eventview for now/next """
+ def __init__(self):
+ self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
+ {
+ "showEventInfo": (self.openEventView, _("show event details")),
+ })
+
+ def openEventView(self):
+ self.epglist = [ ]
+ service = self.session.nav.getCurrentService()
+ ref = self.session.nav.getCurrentlyPlayingServiceReference()
+ info = service.info()
+ ptr=info.getEvent(0)
+ if ptr:
+ self.epglist.append(ptr)
+ ptr=info.getEvent(1)
+ if ptr:
+ self.epglist.append(ptr)
+ if len(self.epglist) > 0:
+ self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
+
+ def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
+ if len(self.epglist) > 1:
+ tmp = self.epglist[0]
+ self.epglist[0]=self.epglist[1]
+ self.epglist[1]=tmp
+ setEvent(self.epglist[0])
+
class InfoBarEPG:
""" EPG - Opens an EPG list when the showEPGList action fires """
def __init__(self):
self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
{
- "showEPGList": (self.showEPG, _("show EPG...")),
+ "showEventInfo": (self.openEventView, _("show EPG...")),
})
- def showEPG(self):
- if currentConfigSelectionElement(config.usage.epgtoggle) == "yes":
- self.openSingleServiceEPG()
- else:
- self.showEPGList()
-
- def showEPGList(self):
- bouquets = self.servicelist.getBouquetList()
- if bouquets is None:
- cnt = 0
- else:
- cnt = len(bouquets)
- if cnt > 1: # show bouquet list
- self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
- elif cnt == 1: # add to only one existing bouquet
- self.openBouquetEPG(bouquets[0][1])
- else: #no bouquets so we open single epg
- self.openSingleEPGSelector(self.session.nav.getCurrentlyPlayingServiceReference())
-
- def bouquetEPGCallback(self, info):
- if info:
- self.openSingleServiceEPG()
-
- def singleEPGCallback(self, info):
- if info:
- self.showEPGList()
-
- def openEventView(self):
- try:
- self.epglist = [ ]
- service = self.session.nav.getCurrentService()
- info = service.info()
- ptr=info.getEvent(0)
- if ptr:
- self.epglist.append(ptr)
- ptr=info.getEvent(1)
- if ptr:
- self.epglist.append(ptr)
- if len(self.epglist) > 0:
- self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
- except:
- pass
-
- def openSingleServiceEPG(self):
- ref=self.session.nav.getCurrentlyPlayingServiceReference()
- ptr=eEPGCache.getInstance()
- if ptr.startTimeQuery(ref) != -1:
- self.session.openWithCallback(self.singleEPGCallback, EPGSelection, ref)
- else: # try to show now/next
- print 'no epg for service', ref.toString()
+ def zapToService(self, service):
+ if not service is None:
+ if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
+ self.servicelist.clearPath()
+ if self.servicelist.bouquet_root != self.epg_bouquet:
+ self.servicelist.enterPath(self.servicelist.bouquet_root)
+ self.servicelist.enterPath(self.epg_bouquet)
+ self.servicelist.setCurrentSelection(service) #select the service in servicelist
+ self.servicelist.zap()
- def openBouquetEPG(self, bouquet):
+ def openBouquetEPG(self, bouquet, withCallback=True):
ptr=eEPGCache.getInstance()
services = [ ]
servicelist = eServiceCenter.getInstance().list(bouquet)
continue
services.append(ServiceReference(service))
if len(services):
- self.session.openWithCallback(self.bouquetEPGCallback, EPGSelection, services)
+ self.epg_bouquet = bouquet
+ if withCallback:
+ self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
+ else:
+ self.session.open(EPGSelection, services, self.zapToService)
- def openSingleEPGSelector(self, ref):
+ def closed(self, ret):
+ if ret:
+ self.close(ret)
+
+ def openMultiServiceEPG(self, withCallback=True):
+ bouquets = self.servicelist.getBouquetList()
+ if bouquets is None:
+ cnt = 0
+ else:
+ cnt = len(bouquets)
+ if cnt > 1: # show bouquet list
+ if withCallback:
+ self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
+ else:
+ self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
+ elif cnt == 1:
+ self.openBouquetEPG(bouquets[0][1], withCallback)
+
+ def openSingleServiceEPG(self):
+ ref=self.session.nav.getCurrentlyPlayingServiceReference()
ptr=eEPGCache.getInstance()
- if ptr.startTimeQuery(ref) != -1:
- self.session.open(EPGSelection, ref)
- else: # try to show now/next
- print 'no epg for service', ref.toString()
- try:
- self.epglist = [ ]
- service = self.session.nav.getCurrentService()
- info = service.info()
- ptr=info.getEvent(0)
- if ptr:
- self.epglist.append(ptr)
- ptr=info.getEvent(1)
+ self.session.openWithCallback(self.closed, EPGSelection, ref)
+
+ def openEventView(self):
+ self.epglist = [ ]
+ service = self.session.nav.getCurrentService()
+ ref = self.session.nav.getCurrentlyPlayingServiceReference()
+ info = service.info()
+ ptr=info.getEvent(0)
+ if ptr:
+ self.epglist.append(ptr)
+ ptr=info.getEvent(1)
+ if ptr:
+ self.epglist.append(ptr)
+ if len(self.epglist) == 0:
+ epg = eEPGCache.getInstance()
+ ptr = epg.lookupEventTime(ref, -1)
+ if ptr:
+ self.epglist.append(ptr)
+ ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
if ptr:
self.epglist.append(ptr)
- if len(self.epglist) > 0:
- self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
- except:
- pass
+ if len(self.epglist) > 0:
+ self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
+ else:
+ print "no epg for the service avail.. so we show multiepg instead of eventinfo"
+ self.openMultiServiceEPG(False)
def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
if len(self.epglist) > 1:
self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
- self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
+ self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
class InfoBarSeek:
"""handles actions like seeking, pause"""
- # ispause, isff, issm, skip
- SEEK_STATE_PLAY = (0, 0, 0, 0)
- SEEK_STATE_PAUSE = (1, 0, 0, 0)
- SEEK_STATE_FF_2X = (0, 2, 0, 0)
- SEEK_STATE_FF_4X = (0, 4, 0, 0)
- SEEK_STATE_FF_8X = (0, 8, 0, 0)
- SEEK_STATE_FF_32X = (0, 4, 0, 32)
- SEEK_STATE_FF_64X = (0, 4, 0, 64)
- SEEK_STATE_FF_128X = (0, 4, 0, 128)
+ # ispause, isff, issm
+ SEEK_STATE_PLAY = (0, 0, 0, ">")
+ SEEK_STATE_PAUSE = (1, 0, 0, "||")
+ SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
+ SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
+ SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
+ SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
+ SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
+ SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
- SEEK_STATE_BACK_4X = (0, 0, 0, -4)
- SEEK_STATE_BACK_32X = (0, 0, 0, -32)
- SEEK_STATE_BACK_64X = (0, 0, 0, -64)
- SEEK_STATE_BACK_128X = (0, 0, 0, -128)
+ SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
+ SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
+ SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
+ SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
- SEEK_STATE_SM_HALF = (0, 0, 2, 0)
- SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
- SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
+ SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
+ SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
+ SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
def __init__(self):
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
- pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged,
- pNavigation.evNewService: self.__serviceStarted
+ iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+ iPlayableService.evStart: self.__serviceStarted,
+
+ iPlayableService.evEOF: self.__evEOF,
+ iPlayableService.evSOF: self.__evSOF,
})
- self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions",
+
+ class InfoBarSeekActionMap(HelpableActionMap):
+ def __init__(self, screen, *args, **kwargs):
+ HelpableActionMap.__init__(self, screen, *args, **kwargs)
+ self.screen = screen
+
+ def action(self, contexts, action):
+ if action[:5] == "seek:":
+ time = int(action[5:])
+ self.screen.seekRelative(time * 90000)
+ return 1
+ else:
+ return HelpableActionMap.action(self, contexts, action)
+
+ self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions",
{
"pauseService": (self.pauseService, "pause"),
"unPauseService": (self.unPauseService, "continue"),
"seekFwd": (self.seekFwd, "skip forward"),
- "seekFwdUp": (self.seekFwdUp, "skip forward"),
+ "seekFwdDown": self.seekFwdDown,
+ "seekFwdUp": self.seekFwdUp,
"seekBack": (self.seekBack, "skip backward"),
- "seekBackUp": (self.seekBackUp, "skip backward"),
+ "seekBackDown": self.seekBackDown,
+ "seekBackUp": self.seekBackUp,
}, prio=-1)
# give them a little more priority to win over color buttons
self.seekstate = self.SEEK_STATE_PLAY
- self.seekTimer = eTimer()
- self.seekTimer.timeout.get().append(self.seekTimerFired)
- self.skipinterval = 500 # 500ms skip interval
- self.onClose.append(self.delSeekTimer)
+ self.onClose.append(self.delTimer)
self.fwdtimer = False
self.fwdKeyTimer = eTimer()
self.rwdtimer = False
self.rwdKeyTimer = eTimer()
self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
+
+ self.onPlayStateChanged = [ ]
+
+ self.lockedBecauseOfSkipping = False
def up(self):
pass
def down(self):
pass
- def delSeekTimer(self):
- del self.seekTimer
+ def delTimer(self):
del self.fwdKeyTimer
del self.rwdKeyTimer
- def seekTimerFired(self):
- self.seekbase += self.skipmode * self.skipinterval
-
- # check if we bounced against the beginning of the file
- if self.seekbase < 0:
- self.seekbase = 0;
- self.setSeekState(self.SEEK_STATE_PLAY)
-
- self.doSeek(self.seekbase)
-
- def isSeekable(self):
+ def getSeek(self):
service = self.session.nav.getCurrentService()
if service is None:
return False
- if service.seek() is None:
+
+ seek = service.seek()
+
+ if seek is None or not seek.isCurrentlySeekable():
+ return None
+
+ return seek
+
+ def isSeekable(self):
+ if self.getSeek() is None:
return False
- else:
- return True
+ return True
def __seekableStatusChanged(self):
print "seekable status changed!"
def setSeekState(self, state):
service = self.session.nav.getCurrentService()
- self.seekTimer.stop()
if service is None:
return False
- if service.seek() is None:
+ if not self.isSeekable():
if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
state = self.SEEK_STATE_PLAY
oldstate = self.seekstate
self.seekstate = state
- for i in range(4):
+ for i in range(3):
if oldstate[i] != self.seekstate[i]:
- (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
+ (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
- return True
-
- def setSkipMode(self, skipmode):
- print "setskipmode", skipmode
- self.skipmode = skipmode
- if skipmode == 0:
- self.seekTimer.stop()
- else:
- self.seekTimer.start(500)
+ for c in self.onPlayStateChanged:
+ c(self.seekstate)
- service = self.session.nav.getCurrentService()
- if service is None:
- return
-
- seekable = service.seek()
- if seekable is None:
- return
+ self.checkSkipShowHideLock()
- if skipmode:
- seekable.setTrickmode(1)
- else:
- seekable.setTrickmode(0)
+ return True
- self.seekbase = seekable.getPlayPosition()[1] / 90
-
def pauseService(self):
if self.seekstate == self.SEEK_STATE_PAUSE:
print "pause, but in fact unpause"
if service is None:
return
- seekable = service.seek()
+ seekable = self.getSeek()
if seekable is None:
return
+
seekable.seekTo(90 * seektime)
- def seekFwd(self):
+ def seekFwdDown(self):
print "start fwd timer"
self.fwdtimer = True
- self.fwdKeyTimer.start(500)
+ self.fwdKeyTimer.start(1000)
- def seekBack(self):
+ def seekBackDown(self):
print "start rewind timer"
self.rwdtimer = True
- self.rwdKeyTimer.start(500)
+ self.rwdKeyTimer.start(1000)
def seekFwdUp(self):
print "seekFwdUp"
if self.fwdtimer:
self.fwdKeyTimer.stop()
self.fwdtimer = False
- lookup = {
- self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
- self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
- self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
- self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
- self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
- self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
- self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
- self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
- self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
- self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
- self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
- self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
- self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
- self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
- self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
- }
- self.setSeekState(lookup[self.seekstate]);
+ self.seekFwd()
+
+ def seekFwd(self):
+ lookup = {
+ self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
+ self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
+ self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
+ self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
+ self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
+ self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
+ self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
+ self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
+ self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
+ self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
+ self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
+ self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
+ self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
+ self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
+ self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
+ }
+ self.setSeekState(lookup[self.seekstate])
def seekBackUp(self):
print "seekBackUp"
if self.rwdtimer:
self.rwdKeyTimer.stop()
self.rwdtimer = False
+ self.seekBack()
- lookup = {
- self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
- self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
- self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
- self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
- self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
- self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
- self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
- self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
- self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
- self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
- self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
- self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
- self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
- self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
- self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
- }
- self.setSeekState(lookup[self.seekstate]);
+ def seekBack(self):
+ lookup = {
+ self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
+ self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
+ self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
+ self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
+ self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
+ self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
+ self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
+ self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
+ self.SEEK_STATE_BACK_16X: self.SEEK_STATE_BACK_32X,
+ self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
+ self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
+ self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
+ self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
+ self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
+ self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
+ }
+ self.setSeekState(lookup[self.seekstate])
+ if self.seekstate == self.SEEK_STATE_PAUSE:
+ seekable = self.getSeek()
+ if seekable is not None:
+ seekable.seekRelative(-1, 3)
+
def fwdTimerFire(self):
print "Display seek fwd"
self.fwdKeyTimer.stop()
def fwdSeekTo(self, minutes):
print "Seek", minutes, "minutes forward"
if minutes != 0:
- service = self.session.nav.getCurrentService()
- if service is None:
- return
- seekable = service.seek()
- if seekable is None:
- return
- seekable.seekRelative(1, minutes * 60 * 90000)
+ seekable = self.getSeek()
+ if seekable is not None:
+ seekable.seekRelative(1, minutes * 60 * 90000)
def rwdTimerFire(self):
print "rwdTimerFire"
def rwdSeekTo(self, minutes):
print "rwdSeekTo"
self.fwdSeekTo(0 - minutes)
+
+ def checkSkipShowHideLock(self):
+ wantlock = self.seekstate != self.SEEK_STATE_PLAY
+
+ if self.lockedBecauseOfSkipping and not wantlock:
+ self.unlockShow()
+ self.lockedBecauseOfSkipping = False
+
+ if wantlock and not self.lockedBecauseOfSkipping:
+ self.lockShow()
+ self.lockedBecauseOfSkipping = True
+
+ def __evEOF(self):
+ if self.seekstate != self.SEEK_STATE_PLAY:
+ self.setSeekState(self.SEEK_STATE_PAUSE)
+ # HACK
+ #self.getSeek().seekRelative(1, -90000)
+ self.setSeekState(self.SEEK_STATE_PLAY)
+ else:
+ self.setSeekState(self.SEEK_STATE_PAUSE)
+
+ def __evSOF(self):
+ self.setSeekState(self.SEEK_STATE_PLAY)
+ self.doSeek(0)
+
+ def seekRelative(self, diff):
+ seekable = self.getSeek()
+ if seekable is not None:
+ seekable.seekRelative(1, diff)
+
+from Screens.PVRState import PVRState, TimeshiftState
+
+class InfoBarPVRState:
+ def __init__(self, screen=PVRState):
+ self.onPlayStateChanged.append(self.__playStateChanged)
+ self.pvrStateDialog = self.session.instantiateDialog(screen)
+ self.onShow.append(self.__mayShow)
+ self.onHide.append(self.pvrStateDialog.hide)
+
+ def __mayShow(self):
+ if self.seekstate != self.SEEK_STATE_PLAY:
+ self.pvrStateDialog.show()
+
+ def __playStateChanged(self, state):
+ playstateString = state[3]
+ self.pvrStateDialog["state"].setText(playstateString)
+ self.__mayShow()
+
+class InfoBarTimeshiftState(InfoBarPVRState):
+ def __init__(self):
+ InfoBarPVRState.__init__(self, screen=TimeshiftState)
+
class InfoBarShowMovies:
{
"timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
"timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause # something like "backward key"
- })
+ }, prio=-1) # priority over record
self.timeshift_enabled = 0
self.timeshift_state = 0
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
- pNavigation.evSeekableStatusChanged: self.__seekableStatusChanged
+ iPlayableService.evStart: self.__serviceStarted,
+ iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
})
def getTimeshift(self):
return service.timeshift()
def startTimeshift(self):
- # TODO: check for harddisk! (or do this in the interface? would make
- # more sense... for example radio could be timeshifted in memory,
- # and the decision can't be made here)
print "enable timeshift"
ts = self.getTimeshift()
if ts is None:
print "hu, timeshift already enabled?"
else:
if not ts.startTimeshift():
+ import time
self.timeshift_enabled = 1
+ self.pvrStateDialog["timeshift"].setRelative(time.time())
# PAUSE.
self.setSeekState(self.SEEK_STATE_PAUSE)
else:
print "timeshift failed"
- # nyi
def stopTimeshift(self):
+ if not self.timeshift_enabled:
+ return
print "disable timeshift"
ts = self.getTimeshift()
if ts is None:
return
+ self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
+
+ def stopTimeshiftConfirmed(self, confirmed):
+ if not confirmed:
+ return
+
+ ts = self.getTimeshift()
+ if ts is None:
+ return
+
ts.stopTimeshift()
self.timeshift_enabled = 0
else:
self.setSeekState(self.SEEK_STATE_PLAY)
ts.activateTimeshift()
+ self.seekRelative(0)
# same as activateTimeshiftEnd, but pauses afterwards.
def activateTimeshiftEndAndPause(self):
print "timeshift activate:", enabled
self["TimeshiftActivateActions"].setEnabled(enabled)
+ def __serviceStarted(self):
+ self.timeshift_enabled = False
+ self.__seekableStatusChanged()
+
from RecordTimer import parseEvent
class InfoBarInstantRecord:
"instantRecord": (self.instantRecord, "Instant Record..."),
})
self.recording = None
-
self["BlinkingPoint"] = BlinkingPixmapConditional()
- self.onShown.append(self["BlinkingPoint"].hideWidget)
+ self["BlinkingPoint"].hide()
self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
-
+
def stopCurrentRecording(self):
self.session.nav.RecordTimer.removeEntry(self.recording)
self.recording = None
-
- def startInstantRecording(self):
+
+ def startInstantRecording(self, limitEvent = False):
serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
# try to get event info
event = None
try:
service = self.session.nav.getCurrentService()
- info = service.info()
- ev = info.getEvent(0)
- event = ev
+ epg = eEPGCache.getInstance()
+ event = epg.lookupEventTime(serviceref, -1, 0)
+ if event is None:
+ info = service.info()
+ ev = info.getEvent(0)
+ event = ev
except:
pass
+
+ begin = time.time()
+ end = time.time() + 3600 * 10
+ name = "instant record"
+ description = ""
+ eventid = None
if event is not None:
- data = parseEvent(event)
- begin = data[0]
- if begin < time.time():
- begin = time.time()
-
- end = data[1]
- if end < begin:
- end = begin
-
- end += 3600 * 10
-
- data = (begin, end, data[2], data[3], data[4])
+ curEvent = parseEvent(event)
+ name = curEvent[2]
+ description = curEvent[3]
+ eventid = curEvent[4]
+ if limitEvent:
+ end = curEvent[1]
else:
- data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
+ if limitEvent:
+ self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
+
+ data = (begin, end, name, description, eventid)
- # fix me, description.
self.recording = self.session.nav.recordWithTimer(serviceref, *data)
self.recording.dontSave = True
return False
def recordQuestionCallback(self, answer):
- if answer == False:
+ if answer is None or answer[1] == "no":
return
if self.isInstantRecordRunning():
- self.stopCurrentRecording()
+ if answer[1] == "manualduration":
+ self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
+ else:
+ self.stopCurrentRecording()
else:
- self.startInstantRecording()
+ limitEvent = False
+ if answer[1] == "event":
+ limitEvent = True
+ if answer[1] == "manualduration":
+ self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
+ self.startInstantRecording(limitEvent = limitEvent)
+
+ def inputCallback(self, value):
+ if value is not None:
+ print "stopping recording after", int(value), "minutes."
+ if self.recording is not None:
+ self.recording.end = time.time() + 60 * int(value)
+ self.session.nav.RecordTimer.timeChanged(self.recording)
def instantRecord(self):
try:
return
if self.isInstantRecordRunning():
- self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
+ self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("A recording is currently running.\nWhat do you want to do?"), list=[(_("stop recording"), "yes"), (_("enter recording duration"), "manualduration"), (_("do nothing"), "no")])
+# self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
else:
- self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
+ self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Start recording?"), list=[(_("record indefinitely"), "indefinitely"), (_("stop after current event"), "event"), (_("enter recording duration"), "manualduration"),(_("don't record"), "no")])
+ #self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
from Screens.AudioSelection import AudioSelection
self["ButtonRed"] = PixmapConditional(withTimer = False)
self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
- self.onShown.append(self["ButtonRed"].update)
+ self.onLayoutFinish.append(self["ButtonRed"].update)
self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
- self.onShown.append(self["ButtonRedText"].update)
+ self.onLayoutFinish.append(self["ButtonRedText"].update)
self["ButtonGreen"] = Pixmap()
self["ButtonGreenText"] = Label(_("Subservices"))
self["ButtonYellow"] = PixmapConditional(withTimer = False)
- self["ButtonYellow"].setConnect(lambda: False)
+ self["ButtonYellow"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
+ self["ButtonYellowText"] = LabelConditional(text = _("Timeshifting"), withTimer = False)
+ self["ButtonYellowText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
+ self.onLayoutFinish.append(self["ButtonYellow"].update)
+ self.onLayoutFinish.append(self["ButtonYellowText"].update)
self["ButtonBlue"] = PixmapConditional(withTimer = False)
self["ButtonBlue"].setConnect(lambda: False)
+ self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
+ self["ButtonBlueText"].setConnect(lambda: False)
+ self.onLayoutFinish.append(self["ButtonBlue"].update)
+ self.onLayoutFinish.append(self["ButtonBlueText"].update)
self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
def hideSubServiceIndication(self):
- self["ButtonGreen"].hideWidget()
+ self["ButtonGreen"].hide()
self["ButtonGreenText"].hide()
def showSubServiceIndication(self):
- self["ButtonGreen"].showWidget()
+ self["ButtonGreen"].show()
self["ButtonGreenText"].show()
def checkFormat(self, service):
if info is not None:
aspect = info.getInfo(iServiceInformation.sAspect)
if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
- self["FormatActive"].showWidget()
+ self["FormatActive"].show()
else:
- self["FormatActive"].hideWidget()
+ self["FormatActive"].hide()
def checkSubservices(self, service):
if service.subServices().getNumberOfSubservices() > 0:
dolby = True
break
if dolby:
- self["DolbyActive"].showWidget()
+ self["DolbyActive"].show()
else:
- self["DolbyActive"].hideWidget()
+ self["DolbyActive"].hide()
def checkCrypted(self, service):
info = service.info()
if info is not None:
if info.getInfo(iServiceInformation.sIsCrypted) > 0:
- self["CryptActive"].showWidget()
+ self["CryptActive"].show()
else:
- self["CryptActive"].hideWidget()
+ self["CryptActive"].hide()
def gotServiceEvent(self, ev):
service = self.session.nav.getCurrentService()
- if ev == pNavigation.evUpdatedEventInfo:
+ if ev == iPlayableService.evUpdatedEventInfo:
self.checkSubservices(service)
self.checkFormat(service)
- elif ev == pNavigation.evUpdatedInfo:
+ elif ev == iPlayableService.evUpdatedInfo:
self.checkCrypted(service)
self.checkDolby(service)
- elif ev == pNavigation.evStopService:
+ elif ev == iPlayableService.evEnd:
self.hideSubServiceIndication()
- self["CryptActive"].hideWidget()
- self["DolbyActive"].hideWidget()
- self["FormatActive"].hideWidget()
+ self["CryptActive"].hide()
+ self["DolbyActive"].hide()
+ self["FormatActive"].hide()
class InfoBarNotifications:
def __init__(self):
def __init__(self):
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
- pNavigation.evEnd: self.serviceHasEnded
+ iPlayableService.evEnd: self.serviceHasEnded
})
def serviceHasEnded(self):
self.setSeekState(self.SEEK_STATE_PLAY)
except:
pass
+
+class InfoBarCueSheetSupport:
+ CUT_TYPE_IN = 0
+ CUT_TYPE_OUT = 1
+ CUT_TYPE_MARK = 2
+
+ def __init__(self):
+ self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions",
+ {
+ "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
+ "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
+ "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
+ }, prio=1)
+
+ self.cut_list = [ ]
+ self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+ {
+ iPlayableService.evStart: self.__serviceStarted,
+ })
+
+ def __serviceStarted(self):
+ print "new service started! trying to download cuts!"
+ self.downloadCuesheet()
+
+ def __getSeekable(self):
+ service = self.session.nav.getCurrentService()
+ if service is None:
+ return None
+ return service.seek()
+
+ def cueGetCurrentPosition(self):
+ seek = self.__getSeekable()
+ if seek is None:
+ return None
+ r = seek.getPlayPosition()
+ if r[0]:
+ return None
+ return long(r[1])
+
+ def jumpPreviousNextMark(self, cmp, alternative=None):
+ current_pos = self.cueGetCurrentPosition()
+ if current_pos is None:
+ return
+ mark = self.getNearestCutPoint(current_pos, cmp=cmp)
+ if mark is not None:
+ pts = mark[0]
+ elif alternative is not None:
+ pts = alternative
+ else:
+ return
+
+ seekable = self.__getSeekable()
+ if seekable is not None:
+ seekable.seekTo(pts)
+
+ def jumpPreviousMark(self):
+ # we add 2 seconds, so if the play position is <2s after
+ # the mark, the mark before will be used
+ self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
+
+ def jumpNextMark(self):
+ self.jumpPreviousNextMark(lambda x: x)
+
+ def getNearestCutPoint(self, pts, cmp=abs):
+ # can be optimized
+ nearest = None
+ for cp in self.cut_list:
+ diff = cmp(cp[0] - pts)
+ if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
+ nearest = cp
+ return nearest
+
+ def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
+ current_pos = self.cueGetCurrentPosition()
+ if current_pos is None:
+ print "not seekable"
+ return
+
+ nearest_cutpoint = self.getNearestCutPoint(current_pos)
+
+ if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
+ if onlyreturn:
+ return nearest_cutpoint
+ if not onlyadd:
+ self.removeMark(nearest_cutpoint)
+ elif not onlyremove and not onlyreturn:
+ self.addMark((current_pos, self.CUT_TYPE_MARK))
+
+ if onlyreturn:
+ return None
+
+ def addMark(self, point):
+ bisect.insort(self.cut_list, point)
+ self.uploadCuesheet()
+
+ def removeMark(self, point):
+ self.cut_list.remove(point)
+ self.uploadCuesheet()
+
+ def __getCuesheet(self):
+ service = self.session.nav.getCurrentService()
+ if service is None:
+ return None
+ return service.cueSheet()
+
+ def uploadCuesheet(self):
+ cue = self.__getCuesheet()
+
+ if cue is None:
+ print "upload failed, no cuesheet interface"
+ return
+ cue.setCutList(self.cut_list)
+
+ def downloadCuesheet(self):
+ cue = self.__getCuesheet()
+
+ if cue is None:
+ print "upload failed, no cuesheet interface"
+ return
+ self.cut_list = cue.getCutList()
+
+class InfoBarSummary(Screen):
+ skin = """
+ <screen position="0,0" size="132,64">
+ <widget name="Clock" position="50,46" size="82,18" font="Regular;16" />
+ <widget name="CurrentService" position="0,4" size="132,42" font="Regular;18" />
+ </screen>"""
+
+ def __init__(self, session, parent):
+ Screen.__init__(self, session)
+ self["CurrentService"] = ServiceName(self.session.nav)
+ self["Clock"] = Clock()
+
+class InfoBarSummarySupport:
+ def __init__(self):
+ pass
+
+ def createSummary(self):
+ return InfoBarSummary