X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/3c79adcf97b4c2c84ede4212b6ede42c5987db83..0f1d2fd66b8a00440370f2c55aecb7819a4fa35a:/lib/python/Screens/ChannelSelection.py diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index d4a1e7ce..0e3ee2fc 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -1,54 +1,86 @@ from Screen import Screen from Components.Button import Button from Components.ServiceList import ServiceList -from Components.ActionMap import NumberActionMap +from Components.ActionMap import NumberActionMap, ActionMap +from Components.MenuList import MenuList from EpgSelection import EPGSelection -from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer -from Components.config import config, configElement, ConfigSubsection, configText +from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer, eDVBDB +from Components.config import config, configElement, ConfigSubsection, configText, currentConfigSelectionElement from Screens.FixedMenu import FixedMenu from Tools.NumericalTextInput import NumericalTextInput from Components.NimManager import nimmanager from Components.ServiceName import ServiceName from Components.Clock import Clock from Components.EventInfo import EventInfo +from Components.Input import Input +from Screens.InputBox import InputBox +from ServiceReference import ServiceReference +from re import * +from os import remove import xml.dom.minidom -class BouquetSelector(FixedMenu): +class BouquetSelector(Screen): def __init__(self, session, bouquets, selectedFunc): + Screen.__init__(self, session) + self.selectedFunc=selectedFunc + + self["actions"] = ActionMap(["OkCancelActions"], + { + "ok": self.okbuttonClick, + "cancel": self.cancelClick + }) entrys = [ ] for x in bouquets: - entrys.append((x[0], self.bouquetSelected, x[1])) - FixedMenu.__init__(self, session, "Bouquetlist", entrys) - self.skinName = "Menu" + entrys.append((x[0], x[1])) + self["menu"] = MenuList(entrys) + + def okbuttonClick(self): + self.selectedFunc(self["menu"].getCurrent()[1]) - def bouquetSelected(self): - self.selectedFunc(self["menu"].getCurrent()[2]) + def cancelClick(self): + self.close(False) -class ChannelContextMenu(FixedMenu): +class ChannelContextMenu(Screen): + def __init__(self, session, csel): + Screen.__init__(self, session) self.csel = csel + self.bsel = None + self["actions"] = ActionMap(["OkCancelActions"], + { + "ok": self.okbuttonClick, + "cancel": self.cancelClick + }) menu = [ ] - inBouquetRootList = csel.servicelist.getRoot().getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK + current_root = csel.getRoot() + inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK inBouquet = csel.getMutableList() is not None haveBouquets = csel.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1 - if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList: - if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory: - if haveBouquets: - menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected)) - else: - menu.append((_("add service to favourites"), self.addServiceToBouquetSelected)) - if inBouquet: - menu.append((_("remove service"), self.removeCurrentService)) + if not csel.bouquet_mark_edit and not csel.movemode: + if not inBouquetRootList: + if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory: + if haveBouquets: + menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected)) + else: + menu.append((_("add service to favourites"), self.addServiceToBouquetSelected)) + elif haveBouquets: + if not inBouquet and csel.getCurrentSelection().getPath().find("PROVIDERS") == -1: + menu.append((_("copy to favourites"), self.copyCurrentToBouquetList)) + if inBouquet: + menu.append((_("remove service"), self.removeCurrentService)) + elif haveBouquets: + menu.append((_("remove bouquet"), self.removeBouquet)) if inBouquet: # current list is editable? if not csel.bouquet_mark_edit: if not csel.movemode: menu.append((_("enable move mode"), self.toggleMoveMode)) + menu.append((_("add bouquet..."), self.showBouquetInputBox)) if not inBouquetRootList: if haveBouquets: menu.append((_("enable bouquet edit"), self.bouquetMarkStart)) @@ -64,10 +96,21 @@ class ChannelContextMenu(FixedMenu): menu.append((_("end favourites edit"), self.bouquetMarkEnd)) menu.append((_("abort favourites edit"), self.bouquetMarkAbort)) - menu.append((_("back"), self.close)) + menu.append((_("back"), self.cancelClick)) + self["menu"] = MenuList(menu) + + def okbuttonClick(self): + self["menu"].getCurrent()[1]() + + def cancelClick(self): + self.close(False) + + def showBouquetInputBox(self): + self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT) - FixedMenu.__init__(self, session, _("Channel Selection"), menu) - self.skinName = "Menu" + def bouquetInputCallback(self, bouquet): + if bouquet is not None: + self.csel.addBouquet(bouquet) def addServiceToBouquetSelected(self): bouquets = self.csel.getBouquetList() @@ -76,15 +119,31 @@ class ChannelContextMenu(FixedMenu): else: cnt = len(bouquets) if cnt > 1: # show bouquet list - self.session.open(BouquetSelector, bouquets, self.addCurrentServiceToBouquet) + self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet) elif cnt == 1: # add to only one existing bouquet self.addCurrentServiceToBouquet(bouquets[0][1]) else: #no bouquets in root.. so assume only one favourite list is used self.addCurrentServiceToBouquet(self.csel.bouquet_root) + def bouquetSelClosed(self, recursive): + self.bsel = None + if recursive: + self.close(False) + + def copyCurrentToBouquetList(self): + self.csel.copyCurrentToBouquetList() + self.close() + + def removeBouquet(self): + self.csel.removeBouquet() + self.close() + def addCurrentServiceToBouquet(self, dest): self.csel.addCurrentServiceToBouquet(dest) - self.close() + if self.bsel is not None: + self.bsel.close(True) + else: + self.close(True) # close bouquet selection def removeCurrentService(self): self.csel.removeCurrentService() @@ -106,6 +165,21 @@ class ChannelContextMenu(FixedMenu): self.csel.endMarkedEdit(abort=True) self.close() +class ChannelSelectionEPG: + def __init__(self): + self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"], + { + "showEPGList": self.showEPGList, + }) + + def showEPGList(self): + ref=self.getCurrentSelection() + ptr=eEPGCache.getInstance() + if ptr.startTimeQuery(ref) != -1: + self.session.open(EPGSelection, ref) + else: + print 'no epg for service', ref.toString() + class ChannelSelectionEdit: def __init__(self): self.entry_marked = False @@ -116,39 +190,149 @@ class ChannelSelectionEdit: self.saved_title = None self.saved_root = None + class ChannelSelectionEditActionMap(ActionMap): + def __init__(self, csel, contexts = [ ], actions = { }, prio=0): + ActionMap.__init__(self, contexts, actions, prio) + self.csel = csel + + def action(self, contexts, action): + if action == "cancel": + self.csel.handleEditCancel() + return 0 # fall-trough + elif action == "ok": + return 0 # fall-trough + else: + return ActionMap.action(self, contexts, action) + + self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"], + { + "contextMenu": self.doContext, + }) + def getMutableList(self, root=eServiceReference()): if not self.mutableList is None: return self.mutableList serviceHandler = eServiceCenter.getInstance() if not root.valid(): - root=self.servicelist.getRoot() + root=self.getRoot() list = serviceHandler.list(root) if list is not None: return list.startEdit() return None + def buildBouquetID(self, str): + tmp = str.lower() + name = '' + for c in tmp: + if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'): + name += c + else: + name += '_' + return name + + def addBouquet(self, providerName): + serviceHandler = eServiceCenter.getInstance() + mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit() + if mutableBouquetList: + if self.mode == MODE_TV: + providerName += " (TV)" + str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(providerName)) + else: + providerName += " (Radio)" + str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(providerName)) + new_bouquet_ref = eServiceReference(str) + if not mutableBouquetList.addService(new_bouquet_ref): + self.bouquetNumOffsetCache = { } + mutableBouquetList.flushChanges() + eDVBDB.getInstance().reloadBouquets() + mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit() + if mutableBouquet: + mutableBouquet.setListName(providerName) + mutableBouquet.flushChanges() + self.setRoot(self.getRoot()) + else: + print "get mutable list for new created bouquet failed" + else: + print "add", str, "to bouquets failed" + else: + print "bouquetlist is not editable" + + def copyCurrentToBouquetList(self): + provider = ServiceReference(self.getCurrentSelection()) + serviceHandler = eServiceCenter.getInstance() + mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit() + if mutableBouquetList: + providerName = provider.getServiceName() + if self.mode == MODE_TV: + str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(providerName)) + else: + str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(providerName)) + new_bouquet_ref = eServiceReference(str) + if not mutableBouquetList.addService(new_bouquet_ref): + self.bouquetNumOffsetCache = { } + mutableBouquetList.flushChanges() + eDVBDB.getInstance().reloadBouquets() + mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit() + if mutableBouquet: + mutableBouquet.setListName(providerName) + list = [ ] + services = serviceHandler.list(provider.ref) + if not services is None: + if not services.getContent(list, True): + for service in list: + if mutableBouquet.addService(service): + print "add", service.toString(), "to new bouquet failed" + mutableBouquet.flushChanges() + else: + print "getContent failed" + else: + print "list provider", providerName, "failed" + else: + print "get mutable list for new created bouquet failed" + else: + print "add", str, "to bouquets failed" + else: + print "bouquetlist is not editable" + + def removeBouquet(self): + refstr = self.getCurrentSelection().toString() + self.bouquetNumOffsetCache = { } + pos = refstr.find('FROM BOUQUET "') + if pos != -1: + refstr = refstr[pos+14:] + pos = refstr.find('"') + if pos != -1: + filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2 + self.removeCurrentService() + try: + remove(filename) + except OSError: + print "error during remove of", filename + eDVBDB.getInstance().reloadBouquets() + # multiple marked entry stuff ( edit mode, later multiepg selection ) def startMarkedEdit(self): self.mutableList = self.getMutableList() # add all services from the current list to internal marked set in listboxservicecontent - self.bouquetRoot = self.servicelist.getRoot() self.clearMarks() # this clears the internal marked set in the listboxservicecontent self.saved_title = self.instance.getTitle() - new_title = self.saved_title + pos = self.saved_title.find(')') + new_title = self.saved_title[:pos+1] if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1: new_title += ' ' + _("[bouquet edit]") else: new_title += ' ' + _("[favourite edit]") - self.instance.setTitle(new_title) + self.setTitle(new_title) self.bouquet_mark_edit = True self.__marked = self.servicelist.getRootServices() for x in self.__marked: self.servicelist.addMarked(eServiceReference(x)) - self.saved_root = self.getRoot() + self.savedPath = self.servicePath[:] self.showAllServices() def endMarkedEdit(self, abort): if not abort and self.mutableList is not None: + self.bouquetNumOffsetCache = { } new_marked = set(self.servicelist.getMarked()) old_marked = set(self.__marked) removed = old_marked - new_marked @@ -165,11 +349,15 @@ class ChannelSelectionEdit: self.__marked = [] self.clearMarks() self.bouquet_mark_edit = False - self.bouquetRoot = None self.mutableList = None - self.instance.setTitle(self.saved_title) + self.setTitle(self.saved_title) self.saved_title = None - self.setRoot(self.saved_root) + # self.servicePath is just a reference to servicePathTv or Radio... + # so we never ever do use the asignment operator in self.servicePath + del self.servicePath[:] # remove all elements + self.servicePath += self.savedPath # add saved elements + del self.savedPath + self.setRoot(self.servicePath[len(self.servicePath)-1]) def clearMarks(self): self.servicelist.clearMarks() @@ -186,37 +374,38 @@ class ChannelSelectionEdit: mutableList = self.getMutableList() if ref.valid() and mutableList is not None: if not mutableList.removeService(ref): - currentIndex = self.servicelist.getCurrentIndex() - self.servicelist.moveDown() - if self.servicelist.getCurrentIndex() == currentIndex: - currentIndex -= 1 + self.bouquetNumOffsetCache = { } mutableList.flushChanges() #FIXME dont flush on each single removed service - self.setRoot(self.servicelist.getRoot()) - self.servicelist.moveToIndex(currentIndex) + self.setRoot(self.getRoot()) def addCurrentServiceToBouquet(self, dest): mutableList = self.getMutableList(dest) if not mutableList is None: if not mutableList.addService(self.servicelist.getCurrent()): + self.bouquetNumOffsetCache = { } mutableList.flushChanges() - self.close() def toggleMoveMode(self): if self.movemode: if self.entry_marked: self.toggleMoveMarked() # unmark current entry self.movemode = False + self.pathChangedDisabled = False # re-enable path change self.mutableList.flushChanges() # FIXME add check if changes was made self.mutableList = None - self.instance.setTitle(self.saved_title) + self.setTitle(self.saved_title) self.saved_title = None + if self.getRoot() == self.bouquet_root: + self.bouquetNumOffsetCache = { } else: self.mutableList = self.getMutableList() self.movemode = True + self.pathChangedDisabled = True # no path change allowed in movemode self.saved_title = self.instance.getTitle() new_title = self.saved_title - new_title += ' ' + _("[move mode]"); - self.instance.setTitle(new_title); + pos = self.saved_title.find(')') + new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:] + self.setTitle(new_title); def handleEditCancel(self): if self.movemode: #movemode active? @@ -236,8 +425,6 @@ class ChannelSelectionEdit: def doContext(self): self.session.open(ChannelContextMenu, self) -USE_MULTIBOUQUETS = False - MODE_TV = 0 MODE_RADIO = 1 @@ -247,7 +434,7 @@ class ChannelSelectionBase(Screen): # this makes it much simple to implement a selectable radio or tv mode :) self.service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17)' - self.service_types_radio = '1:7:1:0:0:0:0:0:0:0:(type == 2)' + self.service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)' self["key_red"] = Button(_("All")) self["key_green"] = Button(_("Satellites")) @@ -259,6 +446,36 @@ class ChannelSelectionBase(Screen): self.numericalTextInput = NumericalTextInput() + self.servicePathTV = [ ] + self.servicePathRadio = [ ] + self.servicePath = [ ] + + self.mode = MODE_TV + + self.pathChangedDisabled = False + + self.bouquetNumOffsetCache = { } + + self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"], + { + "showFavourites": self.showFavourites, + "showAllServices": self.showAllServices, + "showProviders": self.showProviders, + "showSatellites": self.showSatellites, + "nextBouquet": self.nextBouquet, + "prevBouquet": self.prevBouquet, + "1": self.keyNumberGlobal, + "2": self.keyNumberGlobal, + "3": self.keyNumberGlobal, + "4": self.keyNumberGlobal, + "5": self.keyNumberGlobal, + "6": self.keyNumberGlobal, + "7": self.keyNumberGlobal, + "8": self.keyNumberGlobal, + "9": self.keyNumberGlobal, + "0": self.keyNumber0 + }) + def appendDVBTypes(self, ref): path = ref.getPath() pos = path.find(' FROM BOUQUET') @@ -267,59 +484,72 @@ class ChannelSelectionBase(Screen): return ref def getBouquetNumOffset(self, bouquet): - bouquet = self.appendDVBTypes(bouquet) if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK return 0 - offsetCount = 0 - serviceHandler = eServiceCenter.getInstance() - bouquetlist = serviceHandler.list(self.bouquet_root) - if not bouquetlist is None: - while True: - bouquetIterator = self.appendDVBTypes(bouquetlist.getNext()) - if not bouquetIterator.valid() or bouquetIterator == bouquet: #end of list or bouquet found - break - if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory): - continue - servicelist = serviceHandler.list(bouquetIterator) - if not servicelist is None: - while True: - serviceIterator = servicelist.getNext() - if not serviceIterator.valid(): #check if end of list - break - if serviceIterator.flags: #playable services have no flags - continue - offsetCount += 1 - return offsetCount + bouquet = self.appendDVBTypes(bouquet) + try: + return self.bouquetNumOffsetCache[bouquet.toString()] + except: + offsetCount = 0 + serviceHandler = eServiceCenter.getInstance() + bouquetlist = serviceHandler.list(self.bouquet_root) + if not bouquetlist is None: + while True: + bouquetIterator = self.appendDVBTypes(bouquetlist.getNext()) + if not bouquetIterator.valid(): #end of list + break + self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount + if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory): + continue + servicelist = serviceHandler.list(bouquetIterator) + if not servicelist is None: + while True: + serviceIterator = servicelist.getNext() + if not serviceIterator.valid(): #check if end of list + break + if serviceIterator.flags: #playable services have no flags + continue + offsetCount += 1 + return self.bouquetNumOffsetCache.get(bouquet.toString(), offsetCount) + + def recallBouquetMode(self): + if self.mode == MODE_TV: + self.service_types = self.service_types_tv + if currentConfigSelectionElement(config.usage.multibouquet) == "yes": + self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet' + else: + self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types) + else: + self.service_types = self.service_types_radio + if currentConfigSelectionElement(config.usage.multibouquet) == "yes": + self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet' + else: + self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types) + self.bouquet_root = eServiceReference(self.bouquet_rootstr) def setTvMode(self): - self.service_types = self.service_types_tv - if USE_MULTIBOUQUETS: - self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet') - else: - self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)) + self.mode = MODE_TV + self.servicePath = self.servicePathTV + self.recallBouquetMode() title = self.instance.getTitle() pos = title.find(" (") if pos != -1: title = title[:pos] title += " (TV)" - self.instance.setTitle(title) - self.mode = MODE_TV + self.setTitle(title) def setRadioMode(self): - self.service_types = self.service_types_radio - if USE_MULTIBOUQUETS: - self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet') - else: - self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)) + self.mode = MODE_RADIO + self.servicePath = self.servicePathRadio + self.recallBouquetMode() title = self.instance.getTitle() pos = title.find(" (") if pos != -1: title = title[:pos] title += " (Radio)" - self.instance.setTitle(title) - self.mode = MODE_RADIO + self.setTitle(title) - def setRootBase(self, root, justSet=False): + def setRoot(self, root, justSet=False): path = root.getPath() inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK pos = path.find(' FROM BOUQUET') @@ -332,6 +562,53 @@ class ChannelSelectionBase(Screen): else: self.servicelist.setMode(ServiceList.MODE_NORMAL) self.servicelist.setRoot(root, justSet) + self.buildTitleString() + + def removeModeStr(self, str): + if self.mode == MODE_TV: + pos = str.find(' (TV)') + else: + pos = str.find(' (Radio)') + if pos != -1: + return str[:pos] + return str + + def getServiceName(self, ref): + str = self.removeModeStr(ServiceReference(ref).getServiceName()) + if not len(str): + pathstr = ref.getPath() + if pathstr.find('FROM PROVIDERS') != -1: + return _("Provider") + if pathstr.find('FROM SATELLITES') != -1: + return _("Satellites") + if pathstr.find(') ORDER BY name') != -1: + return _("All") + return str + + def buildTitleString(self): + titleStr = self.instance.getTitle() + pos = titleStr.find(']') + if pos == -1: + pos = titleStr.find(')') + if pos != -1: + titleStr = titleStr[:pos+1] + Len = len(self.servicePath) + if Len > 0: + base_ref = self.servicePath[0] + if Len > 1: + end_ref = self.servicePath[Len-1] + else: + end_ref = None + nameStr = self.getServiceName(base_ref) + titleStr += ' ' + nameStr + if end_ref is not None: + if Len > 2: + titleStr += '/../' + else: + titleStr += '/' + nameStr = self.getServiceName(end_ref) + titleStr += nameStr + self.setTitle(titleStr) def moveUp(self): self.servicelist.moveUp() @@ -339,58 +616,148 @@ class ChannelSelectionBase(Screen): def moveDown(self): self.servicelist.moveDown() + def clearPath(self): + del self.servicePath[:] + + def enterPath(self, ref, justSet=False): + self.servicePath.append(ref) + self.setRoot(ref, justSet) + + def pathUp(self, justSet=False): + prev = self.servicePath.pop() + length = len(self.servicePath) + if length: + current = self.servicePath[length-1] + self.setRoot(current, justSet) + if not justSet: + self.setCurrentSelection(prev) + return prev + + def isBasePathEqual(self, ref): + if len(self.servicePath) > 1 and self.servicePath[0] == ref: + return True + return False + + def isPrevPathEqual(self, ref): + length = len(self.servicePath) + if length > 1 and self.servicePath[length-2] == ref: + return True + return False + + def preEnterPath(self, refstr): + return False + def showAllServices(self): - ref = eServiceReference('%s ORDER BY name'%(self.service_types)) - self.setRoot(ref) + if not self.pathChangedDisabled: + refstr = '%s ORDER BY name'%(self.service_types) + if not self.preEnterPath(refstr): + ref = eServiceReference(refstr) + currentRoot = self.getRoot() + if currentRoot is None or currentRoot != ref: + self.clearPath() + self.enterPath(ref) def showSatellites(self): - ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)) - self.setRoot(ref, True) - serviceHandler = eServiceCenter.getInstance() - servicelist = serviceHandler.list(ref) - if not servicelist is None: - while True: - service = servicelist.getNext() - if not service.valid(): #check if end of list - break - orbpos = service.getData(4) >> 16 - if service.getPath().find("FROM PROVIDER") != -1: - service_name = _("Providers") + if not self.pathChangedDisabled: + refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types) + if not self.preEnterPath(refstr): + ref = eServiceReference(refstr) + justSet=False + prev = None + + if self.isBasePathEqual(ref): + if self.isPrevPathEqual(ref): + justSet=True + prev = self.pathUp(justSet) else: - service_name = _("Services") - try: - service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos))) - service.setName(service_name) # why we need this cast? - except: - if orbpos > 1800: # west - service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0)) - else: - service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0)) - self.servicelist.addService(service) - self.servicelist.finishFill() + currentRoot = self.getRoot() + if currentRoot is None or currentRoot != ref: + justSet=True + self.clearPath() + self.enterPath(ref, True) + if justSet: + serviceHandler = eServiceCenter.getInstance() + servicelist = serviceHandler.list(ref) + if not servicelist is None: + while True: + service = servicelist.getNext() + if not service.valid(): #check if end of list + break + orbpos = service.getData(4) >> 16 + if service.getPath().find("FROM PROVIDER") != -1: + service_name = _("Providers") + else: + service_name = _("Services") + try: + service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos))) + service.setName(service_name) # why we need this cast? + except: + if orbpos > 1800: # west + orbpos = 3600 - orbpos + h = _("W") + else: + h = _("E") + n = ("%s (%d.%d" + h + ")") % (service_name, orbpos / 10, orbpos % 10) + service.setName(n) + self.servicelist.addService(service) + self.servicelist.finishFill() + if prev is not None: + self.setCurrentSelection(prev) def showProviders(self): - ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types)) - self.setRoot(ref) + if not self.pathChangedDisabled: + refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types) + if not self.preEnterPath(refstr): + ref = eServiceReference(refstr) + if self.isBasePathEqual(ref): + self.pathUp() + else: + currentRoot = self.getRoot() + if currentRoot is None or currentRoot != ref: + self.clearPath() + self.enterPath(ref) + + def changeBouquet(self, direction): + if not self.pathChangedDisabled: + if self.isBasePathEqual(self.bouquet_root): + self.pathUp() + if direction < 0: + self.moveUp() + else: + self.moveDown() + ref = self.getCurrentSelection() + self.enterPath(ref) + + def inBouquet(self): + return self.isBasePathEqual(self.bouquet_root) + + def atBegin(self): + return self.servicelist.atBegin() + + def atEnd(self): + return self.servicelist.atEnd() + + def nextBouquet(self): + self.changeBouquet(+1) + + def prevBouquet(self): + self.changeBouquet(-1) def showFavourites(self): - self.setRoot(self.bouquet_root) + if not self.pathChangedDisabled: + if not self.preEnterPath(self.bouquet_rootstr): + if self.isBasePathEqual(self.bouquet_root): + self.pathUp() + else: + currentRoot = self.getRoot() + if currentRoot is None or currentRoot != self.bouquet_root: + self.clearPath() + self.enterPath(self.bouquet_root) def keyNumberGlobal(self, number): char = self.numericalTextInput.getKey(number) - print "You pressed number " + str(number) - print "You would go to character " + str(char) self.servicelist.moveToChar(char) - def enterBouquet(self, action): - if action[:7] == "bouquet": - if action.find("FROM BOUQUET") != -1: - self.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:])) - else: - self.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:])) - return True - return False - def getRoot(self): return self.servicelist.getRoot() @@ -398,11 +765,16 @@ class ChannelSelectionBase(Screen): return self.servicelist.getCurrent() def setCurrentSelection(self, service): + servicepath = service.getPath() + pos = servicepath.find(" FROM BOUQUET") + if pos != -1: + if self.mode == MODE_TV: + servicepath = '(type == 1)' + servicepath[pos:] + else: + servicepath = '(type == 2)' + servicepath[pos:] + service.setPath(servicepath) self.servicelist.setCurrent(service) - def cancel(self): - self.close(None) - def getBouquetList(self): serviceCount=0 bouquets = [ ] @@ -426,213 +798,290 @@ class ChannelSelectionBase(Screen): return bouquets return None -class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit): + def keyNumber0(self, num): + if len(self.servicePath) > 1: + self.keyGoUp() + else: + self.keyNumberGlobal(num) + + def keyGoUp(self): + if len(self.servicePath) > 1: + if self.isBasePathEqual(self.bouquet_root): + self.showFavourites() + else: + ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)) + if self.isBasePathEqual(ref): + self.showSatellites() + else: + ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types)) + if self.isBasePathEqual(ref): + self.showProviders() + else: + self.showAllServices() + +HISTORYSIZE = 20 + +class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG): def __init__(self, session): ChannelSelectionBase.__init__(self,session) ChannelSelectionEdit.__init__(self) + ChannelSelectionEPG.__init__(self) #config for lastservice config.tv = ConfigSubsection(); config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0); config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0); - class ChannelActionMap(NumberActionMap): - def action(self, contexts, action): - if not self.csel.enterBouquet(action): - if action == "cancel": - self.csel.handleEditCancel() - NumberActionMap.action(self, contexts, action) - self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"], + self["actions"] = ActionMap(["OkCancelActions"], { "cancel": self.cancel, "ok": self.channelSelected, - "mark": self.doMark, - "contextMenu": self.doContext, - "showFavourites": self.showFavourites, - "showAllServices": self.showAllServices, - "showProviders": self.showProviders, - "showSatellites": self.showSatellites, - "showEPGList": self.showEPGList, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal }) - self["actions"].csel = self - self.onShown.append(self.onShow) + self.onShown.append(self.__onShown) self.lastChannelRootTimer = eTimer() - self.lastChannelRootTimer.timeout.get().append(self.onCreate) + self.lastChannelRootTimer.timeout.get().append(self.__onCreate) self.lastChannelRootTimer.start(100,True) - def onCreate(self): - self.setTvMode() - lastroot=eServiceReference(config.tv.lastroot.value) - if lastroot.valid(): - self.setRoot(lastroot) - else: - self.showFavourites() - self.saveRoot(self.getRoot()) + self.history = [ ] + self.history_pos = 0 + def __onCreate(self): + self.setTvMode() + self.restoreRoot() lastservice=eServiceReference(config.tv.lastservice.value) if lastservice.valid(): - self.servicelist.setCurrent(lastservice) - self.session.nav.playService(lastservice) + self.setCurrentSelection(lastservice) + self.zap() - def onShow(self): + def __onShown(self): + self.recallBouquetMode() ref = self.session.nav.getCurrentlyPlayingServiceReference() if ref is not None and ref.valid() and ref.getPath() == "": self.servicelist.setPlayableIgnoreService(ref) else: self.servicelist.setPlayableIgnoreService(eServiceReference()) - def showEPGList(self): - ref=self.getCurrentSelection() - ptr=eEPGCache.getInstance() - if ptr.startTimeQuery(ref) != -1: - self.session.open(EPGSelection, ref) - else: - print 'no epg for service', ref.toString() - def channelSelected(self): ref = self.getCurrentSelection() if self.movemode: self.toggleMoveMarked() elif (ref.flags & 7) == 7: - self.setRoot(ref) + self.enterPath(ref) elif self.bouquet_mark_edit: self.doMark() else: self.zap() self.close(ref) - def setRoot(self, root, justSet=False): - if not self.movemode: - self.setRootBase(root, justSet) - #called from infoBar and channelSelected def zap(self): - self.session.nav.playService(self.getCurrentSelection()) - self.saveRoot(self.getRoot()) + ref = self.session.nav.getCurrentlyPlayingServiceReference() + nref = self.getCurrentSelection() + if ref is None or ref != nref: + self.session.nav.playService(nref) + self.saveRoot() + self.saveChannel() + if self.servicePath is not None: + tmp=self.servicePath[:] + tmp.append(nref) + try: + del self.history[self.history_pos+1:] + except: + pass + self.history.append(tmp) + hlen = len(self.history) + if hlen > HISTORYSIZE: + del self.history[0] + hlen -= 1 + self.history_pos = hlen-1 + + def historyBack(self): + hlen = len(self.history) + if hlen > 1 and self.history_pos > 0: + self.history_pos -= 1 + self.setHistoryPath() + + def historyNext(self): + hlen = len(self.history) + if hlen > 1 and self.history_pos < (hlen-1): + self.history_pos += 1 + self.setHistoryPath() + + def setHistoryPath(self): + path = self.history[self.history_pos][:] + ref = path.pop() + del self.servicePath[:] + self.servicePath += path + self.saveRoot() + plen = len(path) + root = path[plen-1] + if self.getRoot() != root: + self.setRoot(root) + self.session.nav.playService(ref) + self.setCurrentSelection(ref) self.saveChannel() - def saveRoot(self, root): - if root is not None: - config.tv.lastroot.value = root.toString() + def saveRoot(self): + path = '' + for i in self.servicePathTV: + path += i.toString() + path += ';' + if len(path) and path != config.tv.lastroot.value: + config.tv.lastroot.value = path config.tv.lastroot.save() + def restoreRoot(self): + self.clearPath() + re = compile('.+?;') + tmp = re.findall(config.tv.lastroot.value) + cnt = 0 + for i in tmp: + self.servicePathTV.append(eServiceReference(i[:len(i)-1])) + cnt += 1 + if cnt: + path = self.servicePathTV.pop() + self.enterPath(path) + else: + self.showFavourites() + self.saveRoot() + + def preEnterPath(self, refstr): + if len(self.servicePathTV) and self.servicePathTV[0] != eServiceReference(refstr): + pathstr = config.tv.lastroot.value + if pathstr is not None and pathstr.find(refstr) == 0: + self.restoreRoot() + lastservice=eServiceReference(config.tv.lastservice.value) + if lastservice.valid(): + self.setCurrentSelection(lastservice) + return True + return False + def saveChannel(self): ref = self.session.nav.getCurrentlyPlayingServiceReference() if ref is not None: refstr = ref.toString() else: refstr = "" - config.tv.lastservice.value = refstr - config.tv.lastservice.save() + if refstr != config.tv.lastservice.value: + config.tv.lastservice.value = refstr + config.tv.lastservice.save() + + def recallPrevService(self): + hlen = len(self.history) + if hlen > 1: + if self.history_pos == hlen-1: + tmp = self.history[self.history_pos] + self.history[self.history_pos] = self.history[self.history_pos-1] + self.history[self.history_pos-1] = tmp + else: + tmp = self.history[self.history_pos+1] + self.history[self.history_pos+1] = self.history[self.history_pos] + self.history[self.history_pos] = tmp + self.setHistoryPath() def cancel(self): self.close(None) - lastroot=eServiceReference(config.tv.lastroot.value) + self.restoreRoot() lastservice=eServiceReference(config.tv.lastservice.value) - if lastroot.valid() and self.getRoot() != lastroot: - self.setRoot(lastroot) if lastservice.valid() and self.getCurrentSelection() != lastservice: - self.servicelist.setCurrent(lastservice) + self.setCurrentSelection(lastservice) + +from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord -class ServiceInfoWindow(Screen): +class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord): def __init__(self, session): Screen.__init__(self, session) - self["Service_Name"] = ServiceName(self.session.nav) + InfoBarEvent.__init__(self) + InfoBarServiceName.__init__(self) + InfoBarInstantRecord.__init__(self) self["Clock"] = Clock() - self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime) - self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime) - 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_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration) - -class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit): + +class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG): def __init__(self, session): ChannelSelectionBase.__init__(self, session) ChannelSelectionEdit.__init__(self) + ChannelSelectionEPG.__init__(self) config.radio = ConfigSubsection(); config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0); config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0); self.onLayoutFinish.append(self.onCreate) - self.info = session.instantiateDialog(ServiceInfoWindow) + self.info = session.instantiateDialog(RadioInfoBar) - class ChannelActionMap(NumberActionMap): - def action(self, contexts, action): - if not self.csel.enterBouquet(action): - NumberActionMap.action(self, contexts, action) - self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions", "TvRadioActions"], + self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"], { "keyTV": self.closeRadio, "keyRadio": self.closeRadio, - "contextMenu": self.doContext, "cancel": self.closeRadio, "ok": self.channelSelected, - "showFavourites": self.showFavourites, - "showAllServices": self.showAllServices, - "showProviders": self.showProviders, - "showSatellites": self.showSatellites, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal }) - self["actions"].csel = self - def onCreate(self): - self.setRadioMode() - lastroot=eServiceReference(config.radio.lastroot.value) - if lastroot.valid(): - self.setRoot(lastroot) + def saveRoot(self): + path = '' + for i in self.servicePathRadio: + path += i.toString() + path += ';' + if len(path) and path != config.radio.lastroot.value: + config.radio.lastroot.value = path + config.radio.lastroot.save() + + def restoreRoot(self): + self.clearPath() + re = compile('.+?;') + tmp = re.findall(config.radio.lastroot.value) + cnt = 0 + for i in tmp: + self.servicePathRadio.append(eServiceReference(i[:len(i)-1])) + cnt += 1 + if cnt: + path = self.servicePathRadio.pop() + self.enterPath(path) else: self.showFavourites() - self.saveRoot(self.getRoot()) + self.saveRoot() + + def preEnterPath(self, refstr): + if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr): + pathstr = config.radio.lastroot.value + if pathstr is not None and pathstr.find(refstr) == 0: + self.restoreRoot() + lastservice=eServiceReference(config.radio.lastservice.value) + if lastservice.valid(): + self.setCurrentSelection(lastservice) + return True + return False + + def onCreate(self): + self.setRadioMode() + self.restoreRoot() lastservice=eServiceReference(config.radio.lastservice.value) if lastservice.valid(): self.servicelist.setCurrent(lastservice) self.session.nav.playService(lastservice) self.servicelist.setPlayableIgnoreService(lastservice) - self.info.instance.show() + self.info.show() def channelSelected(self): # just return selected service ref = self.getCurrentSelection() if self.movemode: self.toggleMoveMarked() elif (ref.flags & 7) == 7: - self.setRoot(ref) + self.enterPath(ref) elif self.bouquet_mark_edit: self.doMark() else: - self.session.nav.playService(ref) - self.servicelist.setPlayableIgnoreService(ref) - config.radio.lastservice.value = ref.toString() - config.radio.lastservice.save() - config.radio.lastroot.value = self.getRoot().toString() - config.radio.lastroot.save() - - def setRoot(self, root, justSet=False): - self.setRootBase(root, justSet) + playingref = self.session.nav.getCurrentlyPlayingServiceReference() + if playingref is None or playingref != ref: + self.session.nav.playService(ref) + self.servicelist.setPlayableIgnoreService(ref) + config.radio.lastservice.value = ref.toString() + config.radio.lastservice.save() + self.saveRoot() def closeRadio(self): - self.info.instance.hide() + self.info.hide() #set previous tv service lastservice=eServiceReference(config.tv.lastservice.value) self.session.nav.playService(lastservice) @@ -642,50 +1091,28 @@ class SimpleChannelSelection(ChannelSelectionBase): def __init__(self, session, title): ChannelSelectionBase.__init__(self, session) self.title = title - self.onShown.append(self.onExecCallback) + self.onShown.append(self.__onExecCallback) - class ChannelActionMap(NumberActionMap): - def action(self, contexts, action): - if not self.csel.enterBouquet(action): - NumberActionMap.action(self, contexts, action) - self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions", "TvRadioActions"], + self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"], { - "cancel": self.cancel, + "cancel": self.close, "ok": self.channelSelected, - "showFavourites": self.showFavourites, - "showAllServices": self.showAllServices, - "showProviders": self.showProviders, - "showSatellites": self.showSatellites, "keyRadio": self.setModeRadio, "keyTV": self.setModeTv, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal }) - self["actions"].csel = self - def onExecCallback(self): - self.session.currentDialog.instance.setTitle(self.title) + def __onExecCallback(self): + self.setTitle(self.title) self.setModeTv() def channelSelected(self): # just return selected service ref = self.getCurrentSelection() if (ref.flags & 7) == 7: - self.setRoot(ref) + self.enterPath(ref) else: ref = self.getCurrentSelection() self.close(ref) - def setRoot(self, root, justSet=False): - self.setRootBase(root, justSet) - def setModeTv(self): self.setTvMode() self.showFavourites()