None check
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index e7c67f3b13fe3d5643ed42f0d95893fc9aeef6b1..2bc6259a2eb0b8a0b46a8e5b765d0b0e8da6bbf6 100644 (file)
@@ -1,9 +1,10 @@
 from Screen import Screen
 from Components.Button import Button
 from Components.ServiceList import ServiceList
 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 EpgSelection import EPGSelection
-from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer
+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.config import config, configElement, ConfigSubsection, configText, currentConfigSelectionElement
 from Screens.FixedMenu import FixedMenu
 from Tools.NumericalTextInput import NumericalTextInput
@@ -11,45 +12,75 @@ from Components.NimManager import nimmanager
 from Components.ServiceName import ServiceName
 from Components.Clock import Clock
 from Components.EventInfo import EventInfo
 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 re import *
+from os import remove
 
 import xml.dom.minidom
 
 
 import xml.dom.minidom
 
-class BouquetSelector(FixedMenu):
+class BouquetSelector(Screen):
        def __init__(self, session, bouquets, selectedFunc):
        def __init__(self, session, bouquets, selectedFunc):
+               Screen.__init__(self, session)
+
                self.selectedFunc=selectedFunc
                self.selectedFunc=selectedFunc
+
+               self["actions"] = ActionMap(["OkCancelActions"],
+                       {
+                               "ok": self.okbuttonClick,
+                               "cancel": self.cancelClick
+                       })
                entrys = [ ]
                for x in bouquets:
                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):
        def __init__(self, session, csel):
+               Screen.__init__(self, session)
                self.csel = csel
                self.csel = csel
+               self.bsel = None
 
 
+               self["actions"] = ActionMap(["OkCancelActions"],
+                       {
+                               "ok": self.okbuttonClick,
+                               "cancel": self.cancelClick
+                       })
                menu = [ ]
 
                menu = [ ]
 
-               inBouquetRootList = csel.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
 
                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))
 
                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))
                                        if not inBouquetRootList:
                                                if haveBouquets:
                                                        menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
@@ -65,10 +96,21 @@ class ChannelContextMenu(FixedMenu):
                                        menu.append((_("end favourites edit"), self.bouquetMarkEnd))
                                        menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
 
                                        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)
 
 
-               FixedMenu.__init__(self, session, _("Channel Selection"), menu)
-               self.skinName = "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)
+
+       def bouquetInputCallback(self, bouquet):
+               if bouquet is not None:
+                       self.csel.addBouquet(bouquet)
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
@@ -77,15 +119,31 @@ class ChannelContextMenu(FixedMenu):
                else:
                        cnt = len(bouquets)
                if cnt > 1: # show bouquet list
                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)
 
                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)
        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()
 
        def removeCurrentService(self):
                self.csel.removeCurrentService()
@@ -107,6 +165,21 @@ class ChannelContextMenu(FixedMenu):
                self.csel.endMarkedEdit(abort=True)
                self.close()
 
                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
 class ChannelSelectionEdit:
        def __init__(self):
                self.entry_marked = False
@@ -117,39 +190,149 @@ class ChannelSelectionEdit:
                self.saved_title = None
                self.saved_root = None
 
                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.getRoot()
        def getMutableList(self, root=eServiceReference()):
                if not self.mutableList is None:
                        return self.mutableList
                serviceHandler = eServiceCenter.getInstance()
                if not root.valid():
                        root=self.getRoot()
-               list = serviceHandler.list(root)
+               list = root and serviceHandler.list(root)
                if list is not None:
                        return list.startEdit()
                return None
 
                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
 #  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.getRoot()
                self.clearMarks() # this clears the internal marked set in the listboxservicecontent
                self.saved_title = self.instance.getTitle()
                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]")
                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.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.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
                        new_marked = set(self.servicelist.getMarked())
                        old_marked = set(self.__marked)
                        removed = old_marked - new_marked
@@ -166,11 +349,15 @@ class ChannelSelectionEdit:
                self.__marked = []
                self.clearMarks()
                self.bouquet_mark_edit = False
                self.__marked = []
                self.clearMarks()
                self.bouquet_mark_edit = False
-               self.bouquetRoot = None
                self.mutableList = None
                self.mutableList = None
-               self.instance.setTitle(self.saved_title)
+               self.setTitle(self.saved_title)
                self.saved_title = None
                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()
 
        def clearMarks(self):
                self.servicelist.clearMarks()
@@ -187,37 +374,38 @@ class ChannelSelectionEdit:
                mutableList = self.getMutableList()
                if ref.valid() and mutableList is not None:
                        if not mutableList.removeService(ref):
                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.getRoot())
                                mutableList.flushChanges() #FIXME dont flush on each single removed service
                                self.setRoot(self.getRoot())
-                               self.servicelist.moveToIndex(currentIndex)
 
        def addCurrentServiceToBouquet(self, dest):
                mutableList = self.getMutableList(dest)
                if not mutableList is None:
                        if not mutableList.addService(self.servicelist.getCurrent()):
 
        def addCurrentServiceToBouquet(self, dest):
                mutableList = self.getMutableList(dest)
                if not mutableList is None:
                        if not mutableList.addService(self.servicelist.getCurrent()):
+                               self.bouquetNumOffsetCache = { }
                                mutableList.flushChanges()
                                mutableList.flushChanges()
-               self.close()
 
        def toggleMoveMode(self):
                if self.movemode:
                        if self.entry_marked:
                                self.toggleMoveMarked() # unmark current entry
                        self.movemode = False
 
        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.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
                        self.saved_title = None
+                       if self.getRoot() == self.bouquet_root:
+                               self.bouquetNumOffsetCache = { }
                else:
                        self.mutableList = self.getMutableList()
                        self.movemode = True
                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
                        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?
 
        def handleEditCancel(self):
                if self.movemode: #movemode active?
@@ -246,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)'
 
                # 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"))
 
                self["key_red"] = Button(_("All"))
                self["key_green"] = Button(_("Satellites"))
@@ -260,6 +448,33 @@ class ChannelSelectionBase(Screen):
 
                self.servicePathTV = [ ]
                self.servicePathRadio = [ ]
 
                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()
 
        def appendDVBTypes(self, ref):
                path = ref.getPath()
@@ -269,65 +484,72 @@ class ChannelSelectionBase(Screen):
                return ref
 
        def getBouquetNumOffset(self, bouquet):
                return ref
 
        def getBouquetNumOffset(self, bouquet):
-               bouquet = self.appendDVBTypes(bouquet)
                if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
                        return 0
                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":
 
        def recallBouquetMode(self):
                if self.mode == MODE_TV:
                        self.service_types = self.service_types_tv
                        if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
-                               self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
+                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
                        else:
                        else:
-                               self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types))
+                               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":
                else:
                        self.service_types = self.service_types_radio
                        if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
-                               self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet')
+                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
                        else:
                        else:
-                               self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types))
+                               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):
 
        def setTvMode(self):
+               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)"
                title = self.instance.getTitle()
                pos = title.find(" (")
                if pos != -1:
                        title = title[:pos]
                title += " (TV)"
-               self.instance.setTitle(title)
-               self.mode = MODE_TV
-               self.recallBouquetMode()
+               self.setTitle(title)
 
        def setRadioMode(self):
 
        def setRadioMode(self):
+               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)"
                title = self.instance.getTitle()
                pos = title.find(" (")
                if pos != -1:
                        title = title[:pos]
                title += " (Radio)"
-               self.instance.setTitle(title)
-               self.mode = MODE_RADIO
-               self.recallBouquetMode()
+               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')
                path = root.getPath()
                inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
                pos = path.find(' FROM BOUQUET')
@@ -340,6 +562,53 @@ class ChannelSelectionBase(Screen):
                else:
                        self.servicelist.setMode(ServiceList.MODE_NORMAL)
                self.servicelist.setRoot(root, justSet)
                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()
 
        def moveUp(self):
                self.servicelist.moveUp()
@@ -348,125 +617,147 @@ class ChannelSelectionBase(Screen):
                self.servicelist.moveDown()
 
        def clearPath(self):
                self.servicelist.moveDown()
 
        def clearPath(self):
-               if self.mode == MODE_RADIO:
-                       self.servicePathRadio = [ ]
-               else:
-                       self.servicePathTV = [ ]
+               del self.servicePath[:]
 
        def enterPath(self, ref, justSet=False):
 
        def enterPath(self, ref, justSet=False):
-               if self.mode == MODE_RADIO:
-                       self.servicePathRadio.append(ref)
-               else:
-                       self.servicePathTV.append(ref)
+               self.servicePath.append(ref)
                self.setRoot(ref, justSet)
 
        def pathUp(self, justSet=False):
                self.setRoot(ref, justSet)
 
        def pathUp(self, justSet=False):
-               if self.mode == MODE_TV:
-                       prev = self.servicePathTV.pop()
-                       length = len(self.servicePathTV)
-                       if length:
-                               current = self.servicePathTV[length-1]
-               else:
-                       prev = self.servicePathRadio.pop()
-                       length = len(self.servicePathRadio)
-                       if length:
-                               current = self.servicePathRadio[length-1]
-               self.setRoot(current, justSet)
-               if not justSet:
-                       self.setCurrentSelection(prev)
+               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):
                return prev
 
        def isBasePathEqual(self, ref):
-               if self.mode == MODE_RADIO and len(self.servicePathRadio) > 1 and self.servicePathRadio[0] == ref:
-                       return True
-               elif self.mode == MODE_TV and len(self.servicePathTV) > 1 and self.servicePathTV[0] == ref:
+               if len(self.servicePath) > 1 and self.servicePath[0] == ref:
                        return True
                return False
 
        def isPrevPathEqual(self, ref):
                        return True
                return False
 
        def isPrevPathEqual(self, ref):
-               path = self.servicePathRadio
-               if self.mode == MODE_TV:
-                       path = self.servicePathTV
-               length = len(path)
-               if length > 1 and path[length-2] == ref:
+               length = len(self.servicePath)
+               if length > 1 and self.servicePath[length-2] == ref:
                        return True
                return False
 
                        return True
                return False
 
+       def preEnterPath(self, refstr):
+               return False
+
        def showAllServices(self):
        def showAllServices(self):
-               ref = eServiceReference('%s ORDER BY name'%(self.service_types))
-               self.clearPath()
-               self.enterPath(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):
 
        def showSatellites(self):
-               justSet=False
-               prev = None
-               ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
-               if self.isBasePathEqual(ref):
-                       if self.isPrevPathEqual(ref):
-                               justSet=True
-                       prev = self.pathUp(justSet)
-               else:
-                       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
-                                                       service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0))
-                                               else:
-                                                       service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
-#                                      print service.toString()
-                                       self.servicelist.addService(service)
-                               self.servicelist.finishFill()
-                               if prev is not None:
-#                                      print "-->", prev.toString()
-                                       self.setCurrentSelection(prev)
+               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:
+                                       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):
 
        def showProviders(self):
-               ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
-               if self.isBasePathEqual(ref):
-                       self.pathUp()
-               else:
-                       self.clearPath()
-                       self.enterPath(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):
 
        def showFavourites(self):
-               if self.isBasePathEqual(self.bouquet_root):
-                       self.pathUp()
-               else:
-                       self.clearPath()
-                       self.enterPath(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)
 
        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)
 
                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()
 
        def getRoot(self):
                return self.servicelist.getRoot()
 
@@ -477,13 +768,13 @@ class ChannelSelectionBase(Screen):
                servicepath = service.getPath()
                pos = servicepath.find(" FROM BOUQUET")
                if pos != -1:
                servicepath = service.getPath()
                pos = servicepath.find(" FROM BOUQUET")
                if pos != -1:
-                       servicepath = '(type == 1)' + servicepath[pos:]
+                       if self.mode == MODE_TV:
+                               servicepath = '(type == 1)' + servicepath[pos:]
+                       else:
+                               servicepath = '(type == 2)' + servicepath[pos:]
                        service.setPath(servicepath)
                self.servicelist.setCurrent(service)
 
                        service.setPath(servicepath)
                self.servicelist.setCurrent(service)
 
-       def cancel(self):
-               self.close(None)
-
        def getBouquetList(self):
                serviceCount=0
                bouquets = [ ]
        def getBouquetList(self):
                serviceCount=0
                bouquets = [ ]
@@ -507,63 +798,63 @@ class ChannelSelectionBase(Screen):
                        return bouquets
                return None
 
                        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)
        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);
 
                #config for lastservice
                config.tv = ConfigSubsection();
                config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
                config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
-               config.tv.prevservice = configElement("config.tv.prevservice", configText, "", 0);
-               config.tv.prevroot = configElement("config.tv.prevroot", 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,
                        {
                                "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 = eTimer()
-               self.lastChannelRootTimer.timeout.get().append(self.onCreate)
+               self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
                self.lastChannelRootTimer.start(100,True)
 
                self.lastChannelRootTimer.start(100,True)
 
-       def onCreate(self):
+               self.history = [ ]
+               self.history_pos = 0
+
+       def __onCreate(self):
                self.setTvMode()
                self.setTvMode()
-               self.servicePathTV = [ ]
                self.restoreRoot()
                lastservice=eServiceReference(config.tv.lastservice.value)
                if lastservice.valid():
                        self.setCurrentSelection(lastservice)
                self.restoreRoot()
                lastservice=eServiceReference(config.tv.lastservice.value)
                if lastservice.valid():
                        self.setCurrentSelection(lastservice)
-                       self.session.nav.playService(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.recallBouquetMode()
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                if ref is not None and ref.valid() and ref.getPath() == "":
@@ -571,14 +862,6 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                else:
                        self.servicelist.setPlayableIgnoreService(eServiceReference())
 
                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:
        def channelSelected(self):
                ref = self.getCurrentSelection()
                if self.movemode:
@@ -591,15 +874,52 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                        self.zap()
                        self.close(ref)
 
                        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):
        #called from infoBar and channelSelected
        def zap(self):
-               if self.session.nav.getCurrentlyPlayingServiceReference() != self.getCurrentSelection():
-                       self.session.nav.playService(self.getCurrentSelection())
+               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()
                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):
                self.saveChannel()
 
        def saveRoot(self):
@@ -607,15 +927,12 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                for i in self.servicePathTV:
                        path += i.toString()
                        path += ';'
                for i in self.servicePathTV:
                        path += i.toString()
                        path += ';'
-               if config.tv.prevroot.value != config.tv.lastroot.value:
-                       config.tv.prevroot.value = config.tv.lastroot.value
-                       config.tv.prevroot.save()
                if len(path) and path != config.tv.lastroot.value:
                        config.tv.lastroot.value = path
                        config.tv.lastroot.save()
 
        def restoreRoot(self):
                if len(path) and path != config.tv.lastroot.value:
                        config.tv.lastroot.value = path
                        config.tv.lastroot.save()
 
        def restoreRoot(self):
-               self.servicePathTV = [ ]
+               self.clearPath()
                re = compile('.+?;')
                tmp = re.findall(config.tv.lastroot.value)
                cnt = 0
                re = compile('.+?;')
                tmp = re.findall(config.tv.lastroot.value)
                cnt = 0
@@ -629,6 +946,17 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                        self.showFavourites()
                        self.saveRoot()
 
                        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:
        def saveChannel(self):
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                if ref is not None:
@@ -636,29 +964,21 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                else:
                        refstr = ""
                if refstr != config.tv.lastservice.value:
                else:
                        refstr = ""
                if refstr != config.tv.lastservice.value:
-                       config.tv.prevservice.value = config.tv.lastservice.value
-                       config.tv.prevservice.save()
                        config.tv.lastservice.value = refstr
                        config.tv.lastservice.save()
 
        def recallPrevService(self):
                        config.tv.lastservice.value = refstr
                        config.tv.lastservice.save()
 
        def recallPrevService(self):
-               if len(config.tv.prevservice.value) and len(config.tv.prevroot.value):
-                       if config.tv.lastroot.value != config.tv.prevroot.value:
-                               tmp = config.tv.lastroot.value
-                               config.tv.lastroot.value = config.tv.prevroot.value
-                               config.tv.lastroot.save()
-                               config.tv.prevroot.value = tmp
-                               config.tv.prevroot.save()
-                               self.restoreRoot()
-                       if config.tv.lastservice.value != config.tv.prevservice.value:
-                               tmp = config.tv.lastservice.value
-                               config.tv.lastservice.value = config.tv.prevservice.value
-                               config.tv.lastservice.save()
-                               config.tv.prevservice.value = tmp
-                               config.tv.prevservice.save()
-                               lastservice=eServiceReference(config.tv.lastservice.value)
-                               self.session.nav.playService(lastservice)
-                               self.setCurrentSelection(lastservice)
+               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)
 
        def cancel(self):
                self.close(None)
@@ -667,57 +987,36 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
                if lastservice.valid() and self.getCurrentSelection() != lastservice:
                        self.setCurrentSelection(lastservice)
 
                if lastservice.valid() and self.getCurrentSelection() != lastservice:
                        self.setCurrentSelection(lastservice)
 
-class ServiceInfoWindow(Screen):
+from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord
+
+class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
        def __init__(self, session):
                Screen.__init__(self, session)
        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["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)
        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)
 
 
                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,
                        {
                                "keyTV": self.closeRadio,
                                "keyRadio": self.closeRadio,
-                               "contextMenu": self.doContext,
                                "cancel": self.closeRadio,
                                "ok": self.channelSelected,
                                "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 saveRoot(self):
                path = ''
 
        def saveRoot(self):
                path = ''
@@ -729,7 +1028,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
                        config.radio.lastroot.save()
 
        def restoreRoot(self):
                        config.radio.lastroot.save()
 
        def restoreRoot(self):
-               self.servicePathRadio = [ ]
+               self.clearPath()
                re = compile('.+?;')
                tmp = re.findall(config.radio.lastroot.value)
                cnt = 0
                re = compile('.+?;')
                tmp = re.findall(config.radio.lastroot.value)
                cnt = 0
@@ -743,6 +1042,17 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
                        self.showFavourites()
                        self.saveRoot()
 
                        self.showFavourites()
                        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()
        def onCreate(self):
                self.setRadioMode()
                self.restoreRoot()
@@ -751,7 +1061,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
                        self.servicelist.setCurrent(lastservice)
                        self.session.nav.playService(lastservice)
                        self.servicelist.setPlayableIgnoreService(lastservice)
                        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()
 
        def channelSelected(self): # just return selected service
                ref = self.getCurrentSelection()
@@ -762,18 +1072,16 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
                elif self.bouquet_mark_edit:
                        self.doMark()
                else:
                elif self.bouquet_mark_edit:
                        self.doMark()
                else:
-                       if self.session.nav.getCurrentlyPlayingServiceReference() != ref:
+                       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()
 
                                self.session.nav.playService(ref)
                                self.servicelist.setPlayableIgnoreService(ref)
                                config.radio.lastservice.value = ref.toString()
                                config.radio.lastservice.save()
                        self.saveRoot()
 
-       def setRoot(self, root, justSet=False):
-               self.setRootBase(root, justSet)
-
        def closeRadio(self):
        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)
                #set previous tv service
                lastservice=eServiceReference(config.tv.lastservice.value)
                self.session.nav.playService(lastservice)
@@ -783,37 +1091,18 @@ class SimpleChannelSelection(ChannelSelectionBase):
        def __init__(self, session, title):
                ChannelSelectionBase.__init__(self, session)
                self.title = title
        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,
                                "ok": self.channelSelected,
-                               "showFavourites": self.showFavourites,
-                               "showAllServices": self.showAllServices,
-                               "showProviders": self.showProviders,
-                               "showSatellites": self.showSatellites,
                                "keyRadio": self.setModeRadio,
                                "keyTV": self.setModeTv,
                                "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
                self.setModeTv()
 
        def channelSelected(self): # just return selected service
@@ -824,9 +1113,6 @@ class SimpleChannelSelection(ChannelSelectionBase):
                        ref = self.getCurrentSelection()
                        self.close(ref)
 
                        ref = self.getCurrentSelection()
                        self.close(ref)
 
-       def setRoot(self, root, justSet=False):
-               self.setRootBase(root, justSet)
-
        def setModeTv(self):
                self.setTvMode()
                self.showFavourites()
        def setModeTv(self):
                self.setTvMode()
                self.showFavourites()