X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/5e942862b2017443ec34831f649f890f8215a534..a9589a258f6173fc8af17d802def10d0d918bc16:/lib/python/Screens/InfoBarGenerics.py diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 3bc8a419..1594b3a5 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -2,16 +2,14 @@ from ChannelSelection import ChannelSelection, BouquetSelector from Components.ActionMap import ActionMap, HelpableActionMap from Components.ActionMap import NumberActionMap -from Components.BlinkingPixmap import BlinkingPixmapConditional from Components.Harddisk import harddiskmanager from Components.Input import Input from Components.Label import Label -from Components.Pixmap import Pixmap from Components.PluginComponent import plugins from Components.ServiceEventTracker import ServiceEventTracker -from Components.Sources.Source import ObsoleteSource from Components.Sources.Boolean import Boolean from Components.config import config, ConfigBoolean, ConfigClock +from Components.SystemInfo import SystemInfo from EpgSelection import EPGSelection from Plugins.Plugin import PluginDescriptor @@ -31,15 +29,17 @@ from Screens.TimeDateInput import TimeDateInput from ServiceReference import ServiceReference from Tools import Notifications -from Tools.Directories import SCOPE_HDD, resolveFilename +from Tools.Directories import SCOPE_HDD, resolveFilename, fileExists from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \ - iPlayableService, eServiceReference, eDVBResourceManager, iFrontendInformation, eEPGCache + iPlayableService, eServiceReference, eEPGCache from time import time, localtime, strftime from os import stat as os_stat from bisect import insort +from RecordTimer import RecordTimerEntry, RecordTimer + # hack alert! from Menu import MainMenu, mdom @@ -348,14 +348,14 @@ class InfoBarMenu: def mainMenu(self): print "loading mainmenu XML..." - menu = mdom.childNodes[0] - assert menu.tagName == "menu", "root element in menu must be 'menu'!" + menu = mdom.getroot() + assert menu.tag == "menu", "root element in menu must be 'menu'!" self.session.infobar = self # so we can access the currently active infobar from screens opened from within the mainmenu # at the moment used from the SubserviceSelection - self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu, menu.childNodes) + self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu) def mainMenuClosed(self, *val): self.session.infobar = None @@ -369,25 +369,53 @@ class InfoBarSimpleEventView: }) def openEventView(self): - self.epglist = [ ] + epglist = [ ] + self.epglist = epglist service = self.session.nav.getCurrentService() ref = self.session.nav.getCurrentlyPlayingServiceReference() info = service.info() ptr=info.getEvent(0) if ptr: - self.epglist.append(ptr) + 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) + epglist.append(ptr) + if epglist: + self.session.open(EventViewSimple, 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]) + epglist = self.epglist + if len(epglist) > 1: + tmp = epglist[0] + epglist[0] = epglist[1] + epglist[1] = tmp + setEvent(epglist[0]) + +class SimpleServicelist: + def __init__(self, services): + self.services = services + self.length = len(services) + self.current = 0 + + def selectService(self, service): + self.current = 0 + while self.services[self.current].ref != service: + self.current += 1 + + def nextService(self): + if self.current+1 < self.length: + self.current += 1 + else: + self.current = 0 + + def prevService(self): + if self.current-1 > -1: + self.current -= 1 + else: + self.current = self.length - 1 + + def currentService(self): + return self.services[self.current] class InfoBarEPG: """ EPG - Opens an EPG list when the showEPGList action fires """ @@ -404,7 +432,7 @@ class InfoBarEPG: self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", { "showEventInfo": (self.openEventView, _("show EPG...")), - "showSingleServiceEPG": (self.openSingleServiceEPG, _("show single service EPG...")), + "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")), "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible, }) @@ -440,7 +468,7 @@ class InfoBarEPG: def openBouquetEPG(self, bouquet, withCallback=True): services = self.getBouquetServices(bouquet) - if len(services): + if services: self.epg_bouquet = bouquet if withCallback: self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB)) @@ -455,7 +483,7 @@ class InfoBarEPG: self.bouquetSel.up() bouquet = self.bouquetSel.getCurrent() services = self.getBouquetServices(bouquet) - if len(services): + if services: self.epg_bouquet = bouquet epg.setServices(services) @@ -485,46 +513,83 @@ class InfoBarEPG: elif cnt == 1: self.openBouquetEPG(bouquets[0][1], withCallback) + def changeServiceCB(self, direction, epg): + if self.serviceSel: + if direction > 0: + self.serviceSel.nextService() + else: + self.serviceSel.prevService() + epg.setService(self.serviceSel.currentService()) + + def SingleServiceEPGClosed(self, ret=False): + self.serviceSel = None + def openSingleServiceEPG(self): ref=self.session.nav.getCurrentlyPlayingServiceReference() - self.session.open(EPGSelection, ref) + if ref: + if self.servicelist.getMutableList() is not None: # bouquet in channellist + current_path = self.servicelist.getRoot() + services = self.getBouquetServices(current_path) + self.serviceSel = SimpleServicelist(services) + self.serviceSel.selectService(ref) + self.session.openWithCallback(self.SingleServiceEPGClosed, EPGSelection, ref, serviceChangeCB = self.changeServiceCB) + else: + self.session.open(EPGSelection, ref) + + def showEventInfoPlugins(self): + list = [(p.name, boundFunction(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO)] + + if list: + list.append((_("show single service EPG..."), self.openSingleServiceEPG)) + self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list) + else: + self.openSingleServiceEPG() + + def runPlugin(self, plugin): + plugin(session = self.session, servicelist = self.servicelist) + + def EventInfoPluginChosen(self, answer): + if answer is not None: + answer[1]() def openSimilarList(self, eventid, refstr): self.session.open(EPGSelection, refstr, None, eventid) def getNowNext(self): - self.epglist = [ ] + epglist = [ ] service = self.session.nav.getCurrentService() info = service and service.info() ptr = info and info.getEvent(0) if ptr: - self.epglist.append(ptr) + epglist.append(ptr) ptr = info and info.getEvent(1) if ptr: - self.epglist.append(ptr) + epglist.append(ptr) + self.epglist = epglist def __evEventInfoChanged(self): if self.is_now_next and len(self.dlg_stack) == 1: self.getNowNext() assert self.eventView - if len(self.epglist): + if self.epglist: self.eventView.setEvent(self.epglist[0]) def openEventView(self): ref = self.session.nav.getCurrentlyPlayingServiceReference() self.getNowNext() - if len(self.epglist) == 0: + epglist = self.epglist + if not epglist: self.is_now_next = False epg = eEPGCache.getInstance() ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1) if ptr: - self.epglist.append(ptr) + epglist.append(ptr) ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1) if ptr: - self.epglist.append(ptr) + epglist.append(ptr) else: self.is_now_next = True - if len(self.epglist) > 0: + if epglist: self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList) self.dlg_stack.append(self.eventView) else: @@ -532,22 +597,12 @@ class InfoBarEPG: self.openMultiServiceEPG(False) 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 InfoBarTuner: - """provides a snr/agc/ber display""" - def __init__(self): - self["FrontendStatus"] = ObsoleteSource(new_source = "session.FrontendStatus", removal_date = "2008-01") - -class InfoBarEvent: - """provides a current/next event info display""" - def __init__(self): - self["Event_Now"] = ObsoleteSource(new_source = "session.Event_Now", removal_date = "2008-01") - self["Event_Next"] = ObsoleteSource(new_source = "session.Event_Next", removal_date = "2008-01") + epglist = self.epglist + if len(epglist) > 1: + tmp = epglist[0] + epglist[0]=epglist[1] + epglist[1]=tmp + setEvent(epglist[0]) class InfoBarRdsDecoder: """provides RDS and Rass support/display""" @@ -597,10 +652,6 @@ class InfoBarRdsDecoder: self.RassSlidePicChanged() self.rds_display.show() -class InfoBarServiceName: - def __init__(self): - self["CurrentService"] = ObsoleteSource(new_source = "session.CurrentService", removal_date = "2008-01") - class InfoBarSeek: """handles actions like seeking, pause""" @@ -608,7 +659,7 @@ class InfoBarSeek: SEEK_STATE_PAUSE = (1, 0, 0, "||") SEEK_STATE_EOF = (1, 0, 0, "END") - def __init__(self, actionmap = "InfobarSeekActions"): + def __init__(self, actionmap = "InfobarSeekActions", useSeekBackHack=True): self.__event_tracker = ServiceEventTracker(screen=self, eventmap= { iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged, @@ -623,7 +674,7 @@ class InfoBarSeek: self.eofInhibitTimer = eTimer() self.eofInhibitTimer.timeout.get().append(self.inhibitEof) - self.minSpeedBackward = 16 + self.minSpeedBackward = useSeekBackHack and 16 or 0 class InfoBarSeekActionMap(HelpableActionMap): def __init__(self, screen, *args, **kwargs): @@ -638,9 +689,9 @@ class InfoBarSeek: return 1 elif action[:8] == "seekdef:": key = int(action[8:]) - time = [-config.seek.selfdefined_13.value, False, config.seek.selfdefined_13.value, + time = (-config.seek.selfdefined_13.value, False, config.seek.selfdefined_13.value, -config.seek.selfdefined_46.value, False, config.seek.selfdefined_46.value, - -config.seek.selfdefined_79.value, False, config.seek.selfdefined_79.value][key-1] + -config.seek.selfdefined_79.value, False, config.seek.selfdefined_79.value)[key-1] self.screen.doSeekRelative(time * 90000) return 1 else: @@ -681,7 +732,7 @@ class InfoBarSeek: def makeStateBackward(self, n): minspeed = config.seek.stepwise_minspeed.value repeat = int(config.seek.stepwise_repeat.value) - if n < self.minSpeedBackward: + if self.minSpeedBackward and n < self.minSpeedBackward: r = (self.minSpeedBackward - 1)/ n + 1 if minspeed != "Never" and n >= int(minspeed) and repeat > 1: r = max(r, repeat) @@ -710,7 +761,7 @@ class InfoBarSeek: return False def getLower(self, n, lst): - lst = lst+[] + lst = lst[:] lst.reverse() for x in lst: if x < n: @@ -745,14 +796,14 @@ class InfoBarSeek: return True def __seekableStatusChanged(self): - print "seekable status changed!" +# print "seekable status changed!" if not self.isSeekable(): self["SeekActions"].setEnabled(False) - print "not seekable, return to play" +# print "not seekable, return to play" self.setSeekState(self.SEEK_STATE_PLAY) else: self["SeekActions"].setEnabled(True) - print "seekable" +# print "seekable" def __serviceStarted(self): self.seekstate = self.SEEK_STATE_PLAY @@ -768,7 +819,7 @@ class InfoBarSeek: return False if not self.isSeekable(): - if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]: + if state not in (self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE): state = self.SEEK_STATE_PLAY pauseable = service.pause() @@ -780,7 +831,7 @@ class InfoBarSeek: oldstate = self.seekstate self.seekstate = state - for i in range(3): + for i in (0, 1, 2): if oldstate[i] != self.seekstate[i]: (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i]) @@ -855,7 +906,7 @@ class InfoBarSeek: if self.seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value))) elif self.seekstate == self.SEEK_STATE_PAUSE: - if config.seek.speeds_slowmotion: + if len(config.seek.speeds_slowmotion.value): self.setSeekState(self.makeStateSlowMotion(config.seek.speeds_slowmotion.value[-1])) else: self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value))) @@ -881,30 +932,31 @@ class InfoBarSeek: self.setSeekState(self.makeStateSlowMotion(speed)) def seekBack(self): - if self.seekstate == self.SEEK_STATE_PLAY: + seekstate = self.seekstate + if seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) - elif self.seekstate == self.SEEK_STATE_EOF: + elif seekstate == self.SEEK_STATE_EOF: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) self.doSeekRelative(-6) - elif self.seekstate == self.SEEK_STATE_PAUSE: + elif seekstate == self.SEEK_STATE_PAUSE: self.doSeekRelative(-3) - elif self.isStateForward(self.seekstate): - speed = self.seekstate[1] - if self.seekstate[2]: - speed /= self.seekstate[2] + elif self.isStateForward(seekstate): + speed = seekstate[1] + if seekstate[2]: + speed /= seekstate[2] speed = self.getLower(speed, config.seek.speeds_forward.value) if speed: self.setSeekState(self.makeStateForward(speed)) else: self.setSeekState(self.SEEK_STATE_PLAY) - elif self.isStateBackward(self.seekstate): - speed = -self.seekstate[1] - if self.seekstate[2]: - speed /= self.seekstate[2] + elif self.isStateBackward(seekstate): + speed = -seekstate[1] + if seekstate[2]: + speed /= seekstate[2] speed = self.getHigher(speed, config.seek.speeds_backward.value) or config.seek.speeds_backward.value[-1] self.setSeekState(self.makeStateBackward(speed)) - elif self.isStateSlowMotion(self.seekstate): - speed = self.getHigher(self.seekstate[2], config.seek.speeds_slowmotion.value) + elif self.isStateSlowMotion(seekstate): + speed = self.getHigher(seekstate[2], config.seek.speeds_slowmotion.value) if speed: self.setSeekState(self.makeStateSlowMotion(speed)) else: @@ -990,7 +1042,7 @@ class InfoBarSeek: self.eofState = 0 if not self.seekstate == self.SEEK_STATE_PAUSE: self.setSeekState(self.SEEK_STATE_EOF) - if eofstate == -1 or not seekstate in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]: + if eofstate == -1 or not seekstate in (self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE): seekable = self.getSeek() if seekable is not None: seekable.seekTo(-1) @@ -1009,11 +1061,12 @@ class InfoBarSeek: from Screens.PVRState import PVRState, TimeshiftState class InfoBarPVRState: - def __init__(self, screen=PVRState): + def __init__(self, screen=PVRState, force_show = False): self.onPlayStateChanged.append(self.__playStateChanged) self.pvrStateDialog = self.session.instantiateDialog(screen) self.onShow.append(self._mayShow) self.onHide.append(self.pvrStateDialog.hide) + self.force_show = force_show def _mayShow(self): if self.execing and self.seekstate != self.SEEK_STATE_PLAY: @@ -1022,14 +1075,20 @@ class InfoBarPVRState: def __playStateChanged(self, state): playstateString = state[3] self.pvrStateDialog["state"].setText(playstateString) - self._mayShow() + + # if we return into "PLAY" state, ensure that the dialog gets hidden if there will be no infobar displayed + if not config.usage.show_infobar_on_skip.value and self.seekstate == self.SEEK_STATE_PLAY and not self.force_show: + self.pvrStateDialog.hide() + else: + self._mayShow() + class InfoBarTimeshiftState(InfoBarPVRState): def __init__(self): - InfoBarPVRState.__init__(self, screen=TimeshiftState) + InfoBarPVRState.__init__(self, screen=TimeshiftState, force_show = True) def _mayShow(self): - if self.execing and self.timeshift_enabled: + if self.execing and self.timeshift_enabled and self.seekstate != self.SEEK_STATE_PLAY: self.pvrStateDialog.show() class InfoBarShowMovies: @@ -1185,8 +1244,8 @@ class InfoBarTimeshift: def __seekableStatusChanged(self): enabled = False - print "self.isSeekable", self.isSeekable() - print "self.timeshift_enabled", self.timeshift_enabled +# print "self.isSeekable", self.isSeekable() +# print "self.timeshift_enabled", self.timeshift_enabled # when this service is not seekable, but timeshift # is enabled, this means we can activate @@ -1194,7 +1253,7 @@ class InfoBarTimeshift: if not self.isSeekable() and self.timeshift_enabled: enabled = True - print "timeshift activate:", enabled +# print "timeshift activate:", enabled self["TimeshiftActivateActions"].setEnabled(enabled) def __serviceStarted(self): @@ -1213,7 +1272,7 @@ class InfoBarExtensions: self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions", { "extensions": (self.showExtensionSelection, _("view extensions...")), - }) + }, 1) # lower priority def addExtension(self, extension, key = None, type = EXTENSION_SINGLE): self.list.append((type, extension, key)) @@ -1261,8 +1320,8 @@ class InfoBarExtensions: extensionsList.remove(extension) else: extensionsList.remove(extension) - for x in extensionsList: - list.append((x[0](), x)) + list.extend([(x[0](), x) for x in extensionsList]) + keys += [""] * len(extensionsList) self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list, keys = keys) @@ -1273,7 +1332,6 @@ class InfoBarExtensions: from Tools.BoundFunction import boundFunction # depends on InfoBarExtensions -from Components.PluginComponent import plugins class InfoBarPlugins: def __init__(self): @@ -1283,21 +1341,37 @@ class InfoBarPlugins: return name def getPluginList(self): - list = [] - for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU): - list.append(((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None)) - return list + return [((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU)] def runPlugin(self, plugin): - plugin(session = self.session, servicelist = self.servicelist) + if isinstance(self, InfoBarChannelSelection): + plugin(session = self.session, servicelist = self.servicelist) + else: + plugin(session = self.session) + +from Components.Task import job_manager +class InfoBarJobman: + def __init__(self): + self.addExtension(extension = self.getJobList, type = InfoBarExtensions.EXTENSION_LIST) + + def getJobList(self): + return [((boundFunction(self.getJobName, job), boundFunction(self.showJobView, job), lambda: True), None) for job in job_manager.getPendingJobs()] + + def getJobName(self, job): + return "%s: %s (%d%%)" % (job.getStatustext(), job.name, int(100*job.progress/float(job.end))) + + def showJobView(self, job): + from Screens.TaskView import JobView + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, job) + + def JobViewCB(self, in_background): + job_manager.in_background = in_background # depends on InfoBarExtensions class InfoBarSleepTimer: def __init__(self): - self.addExtension((self.getSleepTimerName, self.showSleepTimerSetup, self.available), "1") - - def available(self): - return True + self.addExtension((self.getSleepTimerName, self.showSleepTimerSetup, lambda: True), "1") def getSleepTimerName(self): return _("Sleep Timer") @@ -1309,13 +1383,10 @@ class InfoBarSleepTimer: class InfoBarPiP: def __init__(self): self.session.pipshown = False - - self.addExtension((self.getShowHideName, self.showPiP, self.available), "blue") - self.addExtension((self.getMoveName, self.movePiP, self.pipShown), "green") - self.addExtension((self.getSwapName, self.swapPiP, self.pipShown), "yellow") - - def available(self): - return True + if SystemInfo.get("NumVideoDecoders", 1) > 1: + self.addExtension((self.getShowHideName, self.showPiP, lambda: True), "blue") + self.addExtension((self.getMoveName, self.movePiP, self.pipShown), "green") + self.addExtension((self.getSwapName, self.swapPiP, self.pipShown), "yellow") def pipShown(self): return self.session.pipshown @@ -1377,7 +1448,7 @@ class InfoBarPiP: elif "stop" == use: self.showPiP() -from RecordTimer import parseEvent +from RecordTimer import parseEvent, RecordTimerEntry class InfoBarInstantRecord: """Instant Record - handles the instantRecord action in order to @@ -1388,13 +1459,6 @@ class InfoBarInstantRecord: "instantRecord": (self.instantRecord, _("Instant Record...")), }) self.recording = [] -#### DEPRECATED CODE #### - self["BlinkingPoint"] = BlinkingPixmapConditional() - self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording) - self["BlinkingPoint"].deprecationInfo = ( - "session.RecordState source, Pixmap renderer and " - "ConditionalShowHide/Blink Converter", "2008-02") -######################### def stopCurrentRecording(self, entry = -1): if entry is not None and entry != -1: @@ -1417,8 +1481,8 @@ class InfoBarInstantRecord: except: pass - begin = time() - end = time() + 3600 * 10 + begin = int(time()) + end = begin + 3600 # dummy name = "instant record" description = "" eventid = None @@ -1434,19 +1498,37 @@ class InfoBarInstantRecord: if limitEvent: self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO) - data = (begin, end, name, description, eventid) + if isinstance(serviceref, eServiceReference): + serviceref = ServiceReference(serviceref) - recording = self.session.nav.recordWithTimer(serviceref, *data) + recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = config.movielist.last_videodir.value) recording.dontSave = True - self.recording.append(recording) - -#### DEPRECATED CODE #### - self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning()) -######################### + + if event is None or limitEvent == False: + recording.autoincrease = True + if recording.setAutoincreaseEnd(): + self.session.nav.RecordTimer.record(recording) + self.recording.append(recording) + else: + simulTimerList = self.session.nav.RecordTimer.record(recording) + if simulTimerList is not None: # conflict with other recording + name = simulTimerList[1].name + name_date = ' '.join((name, strftime('%c', localtime(simulTimerList[1].begin)))) + print "[TIMER] conflicts with", name_date + recording.autoincrease = True # start with max available length, then increment + if recording.setAutoincreaseEnd(): + self.session.nav.RecordTimer.record(recording) + self.recording.append(recording) + self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO) + else: + self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO) + recording.autoincrease = False + else: + self.recording.append(recording) def isInstantRecordRunning(self): print "self.recording:", self.recording - if len(self.recording) > 0: + if self.recording: for x in self.recording: if x.isRunning(): return True @@ -1500,6 +1582,8 @@ class InfoBarInstantRecord: if ret[0]: localendtime = localtime(ret[1]) print "stopping recording at", strftime("%c", localendtime) + if self.recording[self.selectedEntry].end != ret[1]: + self.recording[self.selectedEntry].autoincrease = False self.recording[self.selectedEntry].end = ret[1] self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry]) @@ -1511,35 +1595,42 @@ class InfoBarInstantRecord: def inputCallback(self, value): if value is not None: print "stopping recording after", int(value), "minutes." - self.recording[self.selectedEntry].end = time() + 60 * int(value) - self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry]) + entry = self.recording[self.selectedEntry] + if int(value) != 0: + entry.autoincrease = False + entry.end = int(time()) + 60 * int(value) + self.session.nav.RecordTimer.timeChanged(entry) def instantRecord(self): + dir = config.movielist.last_videodir.value + if not fileExists(dir, 'w'): + dir = resolveFilename(SCOPE_HDD) try: - stat = os_stat(resolveFilename(SCOPE_HDD)) + stat = os_stat(dir) except: + # XXX: this message is a little odd as we might be recording to a remote device self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR) return if self.isInstantRecordRunning(): 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"), \ - (_("change recording (endtime)"), "changeendtime"), \ - (_("add recording (indefinitely)"), "indefinitely"), \ - (_("add recording (stop after current event)"), "event"), \ + list=((_("add recording (stop after current event)"), "event"), \ (_("add recording (enter recording duration)"), "manualduration"), \ (_("add recording (enter recording endtime)"), "manualendtime"), \ - (_("do nothing"), "no")]) + (_("add recording (indefinitely)"), "indefinitely"), \ + (_("change recording (duration)"), "changeduration"), \ + (_("change recording (endtime)"), "changeendtime"), \ + (_("stop recording"), "stop"), \ + (_("do nothing"), "no"))) else: self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \ title=_("Start recording?"), \ - list=[(_("add recording (indefinitely)"), "indefinitely"), \ - (_("add recording (stop after current event)"), "event"), \ + list=((_("add recording (stop after current event)"), "event"), \ (_("add recording (enter recording duration)"), "manualduration"), \ (_("add recording (enter recording endtime)"), "manualendtime"), \ - (_("don't record"), "no")]) + (_("add recording (indefinitely)"), "indefinitely"), \ + (_("don't record"), "no"))) from Tools.ISO639 import LanguageCodes @@ -1552,16 +1643,15 @@ class InfoBarAudioSelection: def audioSelection(self): service = self.session.nav.getCurrentService() - audio = service and service.audioTracks() - self.audioTracks = audio + self.audioTracks = audio = service and service.audioTracks() n = audio and audio.getNumberOfTracks() or 0 - keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n tlist = [] if n > 0: self.audioChannel = service.audioChannel() - for x in range(n): - i = audio.getTrackInfo(x) + idx = 0 + while idx < n: + i = audio.getTrackInfo(idx) language = i.getLanguage() description = i.getDescription() @@ -1573,30 +1663,55 @@ class InfoBarAudioSelection: else: description = language - tlist.append((description, x)) + tlist.append((description, idx)) + idx += 1 - selectedAudio = audio.getCurrentTrack() tlist.sort(key=lambda x: x[0]) - selection = 2 + selectedAudio = self.audioTracks.getCurrentTrack() + + selection = 0 + for x in tlist: if x[1] != selectedAudio: selection += 1 else: break - tlist = [([_("Left"), _("Stereo"), _("Right")][self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist + if SystemInfo["CanDownmixAC3"]: + tlist = [(_("AC3 downmix") + " - " +(_("Off"), _("On"))[config.av.downmix_ac3.value and 1 or 0], "CALLFUNC", self.changeAC3Downmix), + ((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode"), + ("--", "")] + tlist + keys = [ "red", "green", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n + selection += 3 + else: + tlist = [((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist + keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n + selection += 2 self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys) else: del self.audioTracks + def changeAC3Downmix(self, arg): + choicelist = self.session.current_dialog["list"] + list = choicelist.list + t = list[0][1] + list[0][1]=(t[0], t[1], t[2], t[3], t[4], t[5], t[6], + _("AC3 downmix") + " - " + (_("On"), _("Off"))[config.av.downmix_ac3.value and 1 or 0]) + choicelist.setList(list) + if config.av.downmix_ac3.value: + config.av.downmix_ac3.value = False + else: + config.av.downmix_ac3.value = True + config.av.downmix_ac3.save() + def audioSelected(self, audio): if audio is not None: if isinstance(audio[1], str): if audio[1] == "mode": keys = ["red", "green", "yellow"] selection = self.audioChannel.getCurrentChannel() - tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)] + tlist = ((_("left"), 0), (_("stereo"), 1), (_("right"), 2)) self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys) else: del self.audioChannel @@ -1625,16 +1740,18 @@ class InfoBarSubserviceSelection: }, -1) self["SubserviceQuickzapAction"].setEnabled(False) - self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events + self.__event_tracker = ServiceEventTracker(screen=self, eventmap= + { + iPlayableService.evUpdatedEventInfo: self.checkSubservicesAvail + }) self.bsel = None - def checkSubservicesAvail(self, ev): - if ev == iPlayableService.evUpdatedEventInfo: - service = self.session.nav.getCurrentService() - subservices = service and service.subServices() - if not subservices or subservices.getNumberOfSubservices() == 0: - self["SubserviceQuickzapAction"].setEnabled(False) + def checkSubservicesAvail(self): + service = self.session.nav.getCurrentService() + subservices = service and service.subServices() + if not subservices or subservices.getNumberOfSubservices() == 0: + self["SubserviceQuickzapAction"].setEnabled(False) def nextSubservice(self): self.changeSubservice(+1) @@ -1649,9 +1766,12 @@ class InfoBarSubserviceSelection: if n and n > 0: selection = -1 ref = self.session.nav.getCurrentlyPlayingServiceReference() - for x in range(n): - if subservices.getSubservice(x).toString() == ref.toString(): - selection = x + idx = 0 + while idx < n: + if subservices.getSubservice(idx).toString() == ref.toString(): + selection = idx + break + idx += 1 if selection != -1: selection += direction if selection >= n: @@ -1662,7 +1782,7 @@ class InfoBarSubserviceSelection: if newservice.valid(): del subservices del service - self.session.nav.playService(newservice) + self.session.nav.playService(newservice, False) def subserviceSelection(self): service = self.session.nav.getCurrentService() @@ -1673,14 +1793,16 @@ class InfoBarSubserviceSelection: if n and n > 0: ref = self.session.nav.getCurrentlyPlayingServiceReference() tlist = [] - for x in range(n): - i = subservices.getSubservice(x) + idx = 0 + while idx < n: + i = subservices.getSubservice(idx) if i.toString() == ref.toString(): - selection = x + selection = idx tlist.append((i.getName(), i)) + idx += 1 if self.bouquets and len(self.bouquets): - keys = ["red", "green", "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n + keys = ["red", "blue", "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n if config.usage.multibouquet.value: tlist = [(_("Quickzap"), "quickzap", service.subServices()), (_("Add to bouquet"), "CALLFUNC", self.addSubserviceToBouquetCallback), ("--", "")] + tlist else: @@ -1702,7 +1824,7 @@ class InfoBarSubserviceSelection: self.session.open(SubservicesQuickzap, service[2]) else: self["SubserviceQuickzapAction"].setEnabled(True) - self.session.nav.playService(service[1]) + self.session.nav.playService(service[1], False) def addSubserviceToBouquetCallback(self, service): if len(service) > 1 and isinstance(service[1], eServiceReference): @@ -1733,63 +1855,13 @@ class InfoBarSubserviceSelection: class InfoBarAdditionalInfo: def __init__(self): - self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0) + self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0 and config.misc.rcused.value == 1) self["TimeshiftPossible"] = self["RecordingPossible"] + self["ShowTimeshiftOnYellow"] = Boolean(fixed=(not config.misc.rcused.value == 0)) + self["ShowAudioOnYellow"] = Boolean(fixed=config.misc.rcused.value == 0) + self["ShowRecordOnRed"] = Boolean(fixed=config.misc.rcused.value == 1) self["ExtensionsAvailable"] = Boolean(fixed=1) -######### DEPRECATED CODE ########## - self["NimA"] = Pixmap() - self["NimA"].deprecationInfo = ( - "session.TunerInfo source, Pixmap renderer, TunerInfo/UseMask Converter" - ", ValueBitTest(1) Converter and ConditionalShowHide Converter", "2008-02") - self["NimB"] = Pixmap() - self["NimB"].deprecationInfo = ( - "session.TunerInfo source, Pixmap renderer, TunerInfo/UseMask Converter" - ", ValueBitTest(2) Converter and ConditionalShowHide Converter", "2008-02") - self["NimA_Active"] = Pixmap() - self["NimA_Active"].deprecationInfo = ( - "session.FrontendInfo source, Pixmap renderer, FrontendInfo/NUMBER Converter" - ", ValueRange(1,1) Converter and ConditionalShowHide Converter", "2008-02") - self["NimB_Active"] = Pixmap() - self["NimB_Active"].deprecationInfo = ( - "session.FrontendInfo source, Pixmap renderer, FrontendInfo/NUMBER Converter" - ", ValueRange(1,1) Converter and ConditionalShowHide Converter", "2008-02") - - res_mgr = eDVBResourceManager.getInstance() - if res_mgr: - res_mgr.frontendUseMaskChanged.get().append(self.tunerUseMaskChanged) - - self.session.nav.event.append(self.gotServiceEvent) # we like to get service events - - def tunerUseMaskChanged(self, mask): - if mask&1: - self["NimA_Active"].show() - else: - self["NimA_Active"].hide() - if mask&2: - self["NimB_Active"].show() - else: - self["NimB_Active"].hide() - - def checkTunerState(self, service): - info = service and service.frontendInfo() - feNumber = info and info.getFrontendInfo(iFrontendInformation.frontendNumber) - if feNumber is None: - self["NimA"].hide() - self["NimB"].hide() - elif feNumber == 0: - self["NimB"].hide() - self["NimA"].show() - elif feNumber == 1: - self["NimA"].hide() - self["NimB"].show() - - def gotServiceEvent(self, ev): - service = self.session.nav.getCurrentService() - if ev == iPlayableService.evUpdatedInfo or ev == iPlayableService.evEnd: - self.checkTunerState(service) -#################################### - class InfoBarNotifications: def __init__(self): self.onExecBegin.append(self.checkNotifications) @@ -1804,10 +1876,11 @@ class InfoBarNotifications: self.checkNotifications() def checkNotifications(self): - if len(Notifications.notifications): - n = Notifications.notifications[0] + notifications = Notifications.notifications + if notifications: + n = notifications[0] - Notifications.notifications = Notifications.notifications[1:] + del notifications[0] cb = n[0] if n[3].has_key("onSessionOpenCallback"): @@ -1883,6 +1956,13 @@ class InfoBarCueSheetSupport: if config.usage.on_movie_start.value == "ask": Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Do you want to resume this playback?"), timeout=10) elif config.usage.on_movie_start.value == "resume": +# TRANSLATORS: The string "Resuming playback" flashes for a moment +# TRANSLATORS: at the start of a movie, when the user has selected +# TRANSLATORS: "Resume from last position" as start behavior. +# TRANSLATORS: The purpose is to notify the user that the movie starts +# TRANSLATORS: in the middle somewhere and not from the beginning. +# TRANSLATORS: (Some translators seem to have interpreted it as a +# TRANSLATORS: question or a choice, but it is a statement.) Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Resuming playback"), timeout=2, type=MessageBox.TYPE_INFO) def playLastCB(self, answer): @@ -1953,7 +2033,7 @@ class InfoBarCueSheetSupport: if bestdiff >= 0: nearest = [0, False] for cp in self.cut_list: - if beforecut and cp[1] in [self.CUT_TYPE_IN, self.CUT_TYPE_OUT]: + if beforecut and cp[1] in (self.CUT_TYPE_IN, self.CUT_TYPE_OUT): beforecut = False if cp[1] == self.CUT_TYPE_IN: # Start is here, disregard previous marks diff = cmp(cp[0] - pts) @@ -1962,7 +2042,7 @@ class InfoBarCueSheetSupport: bestdiff = diff else: nearest = None - if cp[1] in [self.CUT_TYPE_MARK, self.CUT_TYPE_LAST]: + if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST): diff = cmp(cp[0] - pts) if diff >= 0 and (nearest is None or bestdiff > diff): nearest = cp @@ -2048,9 +2128,6 @@ class InfoBarSummary(Screen): # Reference # - def __init__(self, session, parent): - Screen.__init__(self, session, parent = parent) - class InfoBarSummarySupport: def __init__(self): pass @@ -2076,9 +2153,6 @@ class InfoBarMoviePlayerSummary(Screen): """ - def __init__(self, session, parent): - Screen.__init__(self, session) - class InfoBarMoviePlayerSummarySupport: def __init__(self): pass @@ -2179,7 +2253,7 @@ class InfoBarServiceErrorPopupSupport: else: self.last_error = error - errors = { + error = { eDVBServicePMTHandler.eventNoResources: _("No free tuner!"), eDVBServicePMTHandler.eventTuneFailed: _("Tune failed!"), eDVBServicePMTHandler.eventNoPAT: _("No data on transponder!\n(Timeout reading PAT)"), @@ -2190,9 +2264,7 @@ class InfoBarServiceErrorPopupSupport: eDVBServicePMTHandler.eventSOF: None, eDVBServicePMTHandler.eventEOF: None, eDVBServicePMTHandler.eventMisconfiguration: _("Service unavailable!\nCheck tuner configuration!"), - } - - error = errors.get(error) #this returns None when the key not exist in the dict + }.get(error) #this returns None when the key not exist in the dict if error is not None: Notifications.AddPopup(text = error, type = MessageBox.TYPE_ERROR, timeout = 5, id = "ZapError")