no more bsod on adding bouquets
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index 04c3c4480ade20811c3ab8cd138d880e5d276b2c..b715ccc4f5afb13599470291995fa10f8e3a870d 100644 (file)
@@ -2,8 +2,9 @@ from Screen import Screen
 from Components.Button import Button
 from Components.ServiceList import ServiceList
 from Components.ActionMap import NumberActionMap, ActionMap
 from Components.Button import Button
 from Components.ServiceList import ServiceList
 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,93 @@ 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
+
+FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
 
 import xml.dom.minidom
 
 
 import xml.dom.minidom
 
-class BouquetSelector(FixedMenu):
-       def __init__(self, session, bouquets, selectedFunc):
+class BouquetSelector(Screen):
+       def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
+               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, enableWrapAround)
+
+       def getCurrent(self):
+               cur = self["menu"].getCurrent()
+               return cur and cur[1]
+
+       def okbuttonClick(self):
+               self.selectedFunc(self.getCurrent())
 
 
-       def bouquetSelected(self):
-               self.selectedFunc(self["menu"].getCurrent()[2])
+       def up(self):
+               self["menu"].up()
 
 
-class ChannelContextMenu(FixedMenu):
+       def down(self):
+               self["menu"].down()
+
+       def cancelClick(self):
+               self.close(False)
+
+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()
+               current_sel_path = csel.getCurrentSelection().getPath()
+               current_sel_flags = csel.getCurrentSelection().flags
+               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))
+               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))
                                else:
                                else:
-                                       menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
-                       if inBouquet:
-                               menu.append((_("remove service"), self.removeCurrentService))
+                                       if haveBouquets:
+                                               if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
+                                                       menu.append((_("copy to favourites"), self.copyCurrentToBouquetList))
+                                       if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
+                                               menu.append((_("remove all new found flags"), self.removeAllNewFoundFlags))
+                               if inBouquet:
+                                       menu.append((_("remove service"), self.removeCurrentService))
+                               if current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
+                                       menu.append((_("remove new found flag"), self.removeNewFoundFlag))
+                       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 +114,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)
+
+       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, None, True)
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
@@ -77,15 +137,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 +183,21 @@ class ChannelContextMenu(FixedMenu):
                self.csel.endMarkedEdit(abort=True)
                self.close()
 
                self.csel.endMarkedEdit(abort=True)
                self.close()
 
+       def removeNewFoundFlag(self):
+               eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
+               self.close()
+
+       def removeAllNewFoundFlags(self):
+               curpath = self.csel.getCurrentSelection().getPath()
+               idx = curpath.find("satellitePosition == ")
+               if idx != -1:
+                       tmp = curpath[idx+21:]
+                       idx = tmp.find(')')
+                       if idx != -1:
+                               satpos = int(tmp[:idx])
+                               eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
+               self.close()
+
 class ChannelSelectionEPG:
        def __init__(self):
                self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
 class ChannelSelectionEPG:
        def __init__(self):
                self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
@@ -136,11 +227,17 @@ class ChannelSelectionEdit:
                        def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
                                ActionMap.__init__(self, contexts, actions, prio)
                                self.csel = csel
                        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()
                        def action(self, contexts, action):
                                if action == "cancel":
                                        self.csel.handleEditCancel()
-                               ActionMap.action(self, contexts, action)
-               self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions"],
+                                       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,
                        })
                        {
                                "contextMenu": self.doContext,
                        })
@@ -151,33 +248,99 @@ class ChannelSelectionEdit:
                serviceHandler = eServiceCenter.getInstance()
                if not root.valid():
                        root=self.getRoot()
                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, bName, services, refresh=False):
+               serviceHandler = eServiceCenter.getInstance()
+               mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
+               if mutableBouquetList:
+                       if self.mode == MODE_TV:
+                               bName += " (TV)"
+                               str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
+                       else:
+                               bName += " (Radio)"
+                               str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
+                       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(bName)
+                                       if services is not None:
+                                               for service in services:
+                                                       if mutableBouquet.addService(service):
+                                                               print "add", service.toString(), "to new bouquet failed"
+                                       mutableBouquet.flushChanges()
+                                       if refresh:
+                                               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())
+               providerName = provider.getServiceName()
+               serviceHandler = eServiceCenter.getInstance()
+               services = serviceHandler.list(provider.ref)
+               self.addBouquet(providerName, services and services.getContent('R', True))
+
+       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
@@ -194,11 +357,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()
@@ -215,37 +382,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?
@@ -273,8 +441,8 @@ class ChannelSelectionBase(Screen):
                Screen.__init__(self, session)
 
                # this makes it much simple to implement a selectable radio or tv mode :)
                Screen.__init__(self, session)
 
                # 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_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
+               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"))
@@ -288,20 +456,22 @@ class ChannelSelectionBase(Screen):
 
                self.servicePathTV = [ ]
                self.servicePathRadio = [ ]
 
                self.servicePathTV = [ ]
                self.servicePathRadio = [ ]
+               self.servicePath = [ ]
 
 
-               class ChannelBaseActionMap(NumberActionMap):
-                       def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
-                               NumberActionMap.__init__(self, contexts, actions, prio)
-                               self.csel = csel
-                       def action(self, contexts, action):
-                               if not self.csel.enterBouquet(action):
-                                       NumberActionMap.action(self, contexts, action)
-               self["ChannelSelectBaseActions"] = ChannelBaseActionMap(self, ["ChannelSelectBaseActions"],
+               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,
                        {
                                "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,
                                "1": self.keyNumberGlobal,
                                "2": self.keyNumberGlobal,
                                "3": self.keyNumberGlobal,
@@ -311,7 +481,7 @@ class ChannelSelectionBase(Screen):
                                "7": self.keyNumberGlobal,
                                "8": self.keyNumberGlobal,
                                "9": self.keyNumberGlobal,
                                "7": self.keyNumberGlobal,
                                "8": self.keyNumberGlobal,
                                "9": self.keyNumberGlobal,
-                               "0": self.keyNumberGlobal
+                               "0": self.keyNumber0
                        })
 
        def appendDVBTypes(self, ref):
                        })
 
        def appendDVBTypes(self, ref):
@@ -322,29 +492,33 @@ 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:
 
        def recallBouquetMode(self):
                if self.mode == MODE_TV:
@@ -362,26 +536,28 @@ class ChannelSelectionBase(Screen):
                self.bouquet_root = eServiceReference(self.bouquet_rootstr)
 
        def setTvMode(self):
                self.bouquet_root = eServiceReference(self.bouquet_rootstr)
 
        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')
@@ -394,6 +570,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()
@@ -402,47 +625,30 @@ 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
 
@@ -450,96 +656,123 @@ class ChannelSelectionBase(Screen):
                return False
 
        def showAllServices(self):
                return False
 
        def showAllServices(self):
-               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):
-               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:
+               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:
                                currentRoot = self.getRoot()
                                if currentRoot is None or currentRoot != ref:
-                                       justSet=True
                                        self.clearPath()
                                        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))
+                                       self.enterPath(ref)
+
+       def showSatellites(self):
+               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.getUnsignedData(4) >> 16
+                                                       if service.getPath().find("FROM PROVIDER") != -1:
+                                                               service_name = _("Providers")
+                                                       elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
+                                                               service_name = _("New")
                                                        else:
                                                        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)
+                                                               service_name = _("Services")
+                                                       try:
+                                                               service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
+                                                               service.setName(service_name) # why we need this cast?
+                                                       except:
+                                                               if orbpos == 0xFFFF: #Cable
+                                                                       n = ("%s (%s)") % (service_name, _("Cable"))
+                                                               elif orbpos == 0xEEEE: #Terrestrial
+                                                                       n = ("%s (%s)") % (service_name, _("Terrestrial"))
+                                                               else:
+                                                                       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):
-               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)
+               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 showFavourites(self):
-               if not self.preEnterPath(self.bouquet_rootstr):
+       def changeBouquet(self, direction):
+               if not self.pathChangedDisabled:
                        if self.isBasePathEqual(self.bouquet_root):
                                self.pathUp()
                        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)
+                               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):
+               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()
 
@@ -550,13 +783,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 = [ ]
@@ -580,6 +813,29 @@ class ChannelSelectionBase(Screen):
                        return bouquets
                return None
 
                        return bouquets
                return None
 
+       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)
 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
        def __init__(self, session):
                ChannelSelectionBase.__init__(self,session)
@@ -590,30 +846,30 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                config.tv = ConfigSubsection();
                config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
                config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
                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);
 
                self["actions"] = ActionMap(["OkCancelActions"],
                        {
                                "cancel": self.cancel,
                                "ok": self.channelSelected,
                        })
 
                self["actions"] = ActionMap(["OkCancelActions"],
                        {
                                "cancel": self.cancel,
                                "ok": self.channelSelected,
                        })
-               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() == "":
@@ -633,32 +889,68 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                        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):
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
        #called from infoBar and channelSelected
        def zap(self):
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
-               if ref is None or ref != self.getCurrentSelection():
-                       self.session.nav.playService(self.getCurrentSelection())
+               nref = self.getCurrentSelection()
+               if ref is None or ref != nref:
+                       self.session.nav.playService(nref)
                self.saveRoot()
                self.saveChannel()
                self.saveRoot()
                self.saveChannel()
+               self.addToHistory(nref)
+
+       def addToHistory(self, ref):
+               if self.servicePath is not None:
+                       tmp=self.servicePath[:]
+                       tmp.append(ref)
+                       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):
                path = ''
                for i in self.servicePathTV:
                        path += i.toString()
                        path += ';'
 
        def saveRoot(self):
                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
@@ -678,7 +970,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                        if pathstr is not None and pathstr.find(refstr) == 0:
                                self.restoreRoot()
                                lastservice=eServiceReference(config.tv.lastservice.value)
                        if pathstr is not None and pathstr.find(refstr) == 0:
                                self.restoreRoot()
                                lastservice=eServiceReference(config.tv.lastservice.value)
-                               if lastservice is not None:
+                               if lastservice.valid():
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
@@ -690,29 +982,21 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                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)
@@ -762,7 +1046,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        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
@@ -782,7 +1066,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        if pathstr is not None and pathstr.find(refstr) == 0:
                                self.restoreRoot()
                                lastservice=eServiceReference(config.radio.lastservice.value)
                        if pathstr is not None and pathstr.find(refstr) == 0:
                                self.restoreRoot()
                                lastservice=eServiceReference(config.radio.lastservice.value)
-                               if lastservice is not None:
+                               if lastservice.valid():
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
@@ -795,7 +1079,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        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()
@@ -814,11 +1098,8 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                                config.radio.lastservice.save()
                        self.saveRoot()
 
                                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)
@@ -828,18 +1109,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)
 
                self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
 
                self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
-                               "cancel": self.cancel,
+                               "cancel": self.close,
                                "ok": self.channelSelected,
                                "keyRadio": self.setModeRadio,
                                "keyTV": self.setModeTv,
                        })
 
                                "ok": self.channelSelected,
                                "keyRadio": self.setModeRadio,
                                "keyTV": self.setModeTv,
                        })
 
-       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
@@ -850,9 +1131,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()