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