X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/24dab815808d6be2758f3e63f93b7c171190059e..7f5aa3b85debad0a5642cc5c57cc5b967093ff3e:/lib/python/Screens/InfoBarGenerics.py diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index f05c4eae..84d04f92 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -18,7 +18,7 @@ from EpgSelection import EPGSelection from Screens.MessageBox import MessageBox from Screens.Dish import Dish from Screens.Standby import Standby -from Screens.EventView import EventViewEPGSelect +from Screens.EventView import EventViewEPGSelect, EventViewSimple from Screens.MinuteInput import MinuteInput from Components.Harddisk import harddiskmanager @@ -32,6 +32,7 @@ from enigma import * import time import os +import bisect from Components.config import config, currentConfigSelectionElement @@ -275,10 +276,18 @@ class 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 historyBack(self): + self.servicelist.historyBack() + + def historyNext(self): + self.servicelist.historyNext() + def switchChannelUp(self): self.servicelist.moveUp() self.session.execDialog(self.servicelist) @@ -317,6 +326,35 @@ class InfoBarMenu: 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): @@ -335,7 +373,7 @@ class InfoBarEPG: 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) @@ -349,22 +387,28 @@ class InfoBarEPG: services.append(ServiceReference(service)) if len(services): self.epg_bouquet = bouquet - self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService) + if withCallback: + self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService) + else: + self.session.open(EPGSelection, services, self.zapToService) def closed(self, ret): if ret: self.close(ret) - def openMultiServiceEPG(self): + 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 - self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG) + 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]) + self.openBouquetEPG(bouquets[0][1], withCallback) def openSingleServiceEPG(self): ref=self.session.nav.getCurrentlyPlayingServiceReference() @@ -394,7 +438,7 @@ class InfoBarEPG: 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() + self.openMultiServiceEPG(False) def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying if len(self.epglist) > 1: @@ -478,7 +522,7 @@ class InfoBarSeek: SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x") SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x") - SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x") + 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") @@ -496,15 +540,30 @@ class InfoBarSeek: 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) + else: + 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 @@ -621,65 +680,70 @@ class InfoBarSeek: 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]) + def fwdTimerFire(self): print "Display seek fwd" self.fwdKeyTimer.stop() @@ -715,7 +779,13 @@ class InfoBarSeek: self.lockedBecauseOfSkipping = True def __evEOF(self): - self.setSeekState(self.SEEK_STATE_PAUSE) + 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) @@ -724,7 +794,7 @@ class InfoBarSeek: def seekRelative(self, diff): seekable = self.getSeek() if seekable is not None: - seekable.seekRelative(0, diff) + seekable.seekRelative(1, diff) from Screens.PVRState import PVRState @@ -836,6 +906,8 @@ class InfoBarTimeshift: print "timeshift failed" def stopTimeshift(self): + if not self.timeshift_enabled: + return print "disable timeshift" ts = self.getTimeshift() if ts is None: @@ -915,7 +987,7 @@ class InfoBarInstantRecord: }) self.recording = None self["BlinkingPoint"] = BlinkingPixmapConditional() - self.onLayoutFinish.append(self["BlinkingPoint"].hideWidget) + self["BlinkingPoint"].hide() self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording) def stopCurrentRecording(self): @@ -929,17 +1001,19 @@ class InfoBarInstantRecord: 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 - + if event is not None: data = parseEvent(event) begin = time.time() end = begin + 3600 * 10 - data = (begin, end, data[2], data[3], data[4]) else: data = (time.time(), time.time() + 3600 * 10, "instant record", "", None) @@ -1021,28 +1095,36 @@ class InfoBarAdditionalInfo: 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): @@ -1050,9 +1132,9 @@ class InfoBarAdditionalInfo: 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: @@ -1073,17 +1155,17 @@ class InfoBarAdditionalInfo: 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() @@ -1095,9 +1177,9 @@ class InfoBarAdditionalInfo: self.checkDolby(service) 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): @@ -1133,3 +1215,118 @@ class InfoBarServiceNotifications: 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): + 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 not onlyadd: + self.removeMark(nearest_cutpoint) + elif not onlyremove: + self.addMark((current_pos, self.CUT_TYPE_MARK)) + + 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()