finally use new styled skins for infobar, menu
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index fd57f4c0d651e0468677a53fee3d4a2670214c5c..cd1596816f740b83577d5f211ed38e383d8a82c6 100644 (file)
@@ -2,54 +2,103 @@ from Screen import Screen
 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 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.NimManager import nimmanager
 from Components.ServiceName import ServiceName
-from Components.Clock import Clock
+from Components.Sources.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
+
+FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
 
 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 bouquetSelected(self):
-               self.selectedFunc(self["menu"].getCurrent()[2])
+       def okbuttonClick(self):
+               self.selectedFunc(self.getCurrent())
 
-class ChannelContextMenu(FixedMenu):
+       def up(self):
+               self["menu"].up()
+
+       def down(self):
+               self["menu"].down()
+
+       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.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
 
-               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:
-                                       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))
+                                       menu.append((_("add bouquet..."), self.showBouquetInputBox))
                                        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((_("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, None, True)
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
@@ -77,15 +137,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()
@@ -107,6 +183,21 @@ class ChannelContextMenu(FixedMenu):
                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"],
@@ -136,13 +227,16 @@ class ChannelSelectionEdit:
                        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":
-                                       pass # avoid typo warning...
+                                       return 0 # fall-trough
                                else:
-                                       ActionMap.action(self, contexts, action)
+                                       return ActionMap.action(self, contexts, action)
+
                self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
                        {
                                "contextMenu": self.doContext,
@@ -154,33 +248,99 @@ class ChannelSelectionEdit:
                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
 
+       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
-               self.bouquetRoot = self.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
@@ -197,11 +357,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()
@@ -218,39 +382,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.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()):
+                               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 = True # re-enable path change
+                       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?
@@ -278,8 +441,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) || (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"))
@@ -293,15 +456,22 @@ class ChannelSelectionBase(Screen):
 
                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,
@@ -311,7 +481,7 @@ class ChannelSelectionBase(Screen):
                                "7": self.keyNumberGlobal,
                                "8": self.keyNumberGlobal,
                                "9": self.keyNumberGlobal,
-                               "0": self.keyNumberGlobal
+                               "0": self.keyNumber0
                        })
 
        def appendDVBTypes(self, ref):
@@ -322,29 +492,33 @@ 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:
@@ -362,24 +536,26 @@ class ChannelSelectionBase(Screen):
                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)"
-               self.instance.setTitle(title)
-               self.mode = MODE_TV
-               self.recallBouquetMode()
+               self.setTitle(title)
 
        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)"
-               self.instance.setTitle(title)
-               self.mode = MODE_RADIO
-               self.recallBouquetMode()
+               self.setTitle(title)
 
        def setRoot(self, root, justSet=False):
                path = root.getPath()
@@ -394,6 +570,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()
@@ -402,47 +625,30 @@ class ChannelSelectionBase(Screen):
                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):
-               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):
-               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):
-               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):
-               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
 
@@ -485,19 +691,29 @@ class ChannelSelectionBase(Screen):
                                                        service = servicelist.getNext()
                                                        if not service.valid(): #check if end of list
                                                                break
-                                                       orbpos = service.getData(4) >> 16
+                                                       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:
                                                                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))
+                                                               if orbpos == 0xFFFF: #Cable
+                                                                       n = ("%s (%s)") % (service_name, _("Cable"))
+                                                               elif orbpos == 0xEEEE: #Terrestrial
+                                                                       n = ("%s (%s)") % (service_name, _("Terrestrial"))
                                                                else:
-                                                                       service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
+                                                                       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:
@@ -516,6 +732,32 @@ class ChannelSelectionBase(Screen):
                                                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):
                if not self.pathChangedDisabled:
                        if not self.preEnterPath(self.bouquet_rootstr):
@@ -529,8 +771,6 @@ class ChannelSelectionBase(Screen):
 
        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 getRoot(self):
@@ -543,7 +783,10 @@ class ChannelSelectionBase(Screen):
                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)
 
@@ -570,40 +813,108 @@ class ChannelSelectionBase(Screen):
                        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
+
+#config for lastservice
+config.tv = ConfigSubsection()
+config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0)
+config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0)
+config.radio = ConfigSubsection()
+config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0)
+config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0)
+config.servicelist = ConfigSubsection()
+config.servicelist.lastmode = configElement("config.servicelist.lastmode", configText, "tv", 0)
+
 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);
-               config.tv.prevservice = configElement("config.tv.prevservice", configText, "", 0);
-               config.tv.prevroot = configElement("config.tv.prevroot", configText, "", 0);
-
-               self["actions"] = ActionMap(["OkCancelActions"],
+               self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
                                "cancel": self.cancel,
                                "ok": self.channelSelected,
+                               "keyRadio": self.setModeRadio,
+                               "keyTV": self.setModeTv,
                        })
-               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()
-               self.servicePathTV = [ ]
+               self.history_tv = [ ]
+               self.history_radio = [ ]
+               self.history = self.history_tv
+               self.history_pos = 0
+
+               self.lastservice = config.tv.lastservice
+               self.lastroot = config.tv.lastroot
+               self.revertMode = None
+
+       def setMode(self):
                self.restoreRoot()
-               lastservice=eServiceReference(config.tv.lastservice.value)
+               lastservice=eServiceReference(self.lastservice.value)
                if lastservice.valid():
                        self.setCurrentSelection(lastservice)
-                       self.session.nav.playService(lastservice)
 
-       def onShow(self):
+       def setModeTv(self):
+               if self.revertMode is None and config.servicelist.lastmode.value == "radio":
+                       self.revertMode = MODE_RADIO
+               self.history = self.history_tv
+               self.lastservice = config.tv.lastservice
+               self.lastroot = config.tv.lastroot
+               config.servicelist.lastmode.value = "tv"
+               self.setTvMode()
+               self.setMode()
+
+       def setModeRadio(self):
+               if self.revertMode is None and config.servicelist.lastmode.value == "tv":
+                       self.revertMode = MODE_TV
+               if currentConfigSelectionElement(config.usage.e1like_radio_mode) == "yes":
+                       self.history = self.history_radio
+                       self.lastservice = config.radio.lastservice
+                       self.lastroot = config.radio.lastroot
+                       config.servicelist.lastmode.value = "radio"
+                       self.setRadioMode()
+                       self.setMode()
+
+       def __onCreate(self):
+               if currentConfigSelectionElement(config.usage.e1like_radio_mode) == "yes":
+                       if config.servicelist.lastmode.value == "tv":
+                               self.setModeTv()
+                       else:
+                               self.setModeRadio()
+               else:
+                       self.setModeTv()
+               lastservice=eServiceReference(self.lastservice.value)
+               if lastservice.valid():
+                       self.zap()
+
+       def __onShown(self):
                self.recallBouquetMode()
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                if ref is not None and ref.valid() and ref.getPath() == "":
@@ -625,46 +936,88 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
 
        #called from infoBar and channelSelected
        def zap(self):
+               self.revertMode=None
                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()
+                       config.servicelist.lastmode.save()
+                       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:
+               for i in self.servicePath:
                        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()
+               if len(path) and path != self.lastroot.value:
+                       self.lastroot.value = path
+                       self.lastroot.save()
 
        def restoreRoot(self):
-               self.servicePathTV = [ ]
+               self.clearPath()
                re = compile('.+?;')
-               tmp = re.findall(config.tv.lastroot.value)
+               tmp = re.findall(self.lastroot.value)
                cnt = 0
                for i in tmp:
-                       self.servicePathTV.append(eServiceReference(i[:len(i)-1]))
+                       self.servicePath.append(eServiceReference(i[:len(i)-1]))
                        cnt += 1
                if cnt:
-                       path = self.servicePathTV.pop()
+                       path = self.servicePath.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 len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
+                       pathstr = self.lastroot.value
                        if pathstr is not None and pathstr.find(refstr) == 0:
                                self.restoreRoot()
-                               lastservice=eServiceReference(config.tv.lastservice.value)
-                               if lastservice is not None:
+                               lastservice=eServiceReference(self.lastservice.value)
+                               if lastservice.valid():
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
@@ -675,37 +1028,49 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                        refstr = ref.toString()
                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()
+               if refstr != self.lastservice.value:
+                       self.lastservice.value = refstr
+                       self.lastservice.save()
+
+       def setCurrentServicePath(self, path):
+               hlen = len(self.history)
+               if hlen > 0:
+                       self.history[self.history_pos] = path
+               else:
+                       self.history.append(path)
+               self.setHistoryPath()
+
+       def getCurrentServicePath(self):
+               hlen = len(self.history)
+               if hlen > 0:
+                       return self.history[self.history_pos]
+               return None
 
        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):
+               if self.revertMode is None:
+                       self.restoreRoot()
+                       lastservice=eServiceReference(self.lastservice.value)
+                       if lastservice.valid() and self.getCurrentSelection() != lastservice:
+                               self.setCurrentSelection(lastservice)
+               elif self.revertMode == MODE_TV:
+                       self.setModeTv()
+               elif self.revertMode == MODE_RADIO:
+                       self.setModeRadio()
+               self.revertMode = None
                self.close(None)
-               self.restoreRoot()
-               lastservice=eServiceReference(config.tv.lastservice.value)
-               if lastservice.valid() and self.getCurrentSelection() != lastservice:
-                       self.setCurrentSelection(lastservice)
 
 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord
 
@@ -715,7 +1080,7 @@ class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecor
                InfoBarEvent.__init__(self)
                InfoBarServiceName.__init__(self)
                InfoBarInstantRecord.__init__(self)
-               self["Clock"] = Clock()
+               self["CurrentTime"] = Clock()
 
 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
        def __init__(self, session):
@@ -748,7 +1113,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        config.radio.lastroot.save()
 
        def restoreRoot(self):
-               self.servicePathRadio = [ ]
+               self.clearPath()
                re = compile('.+?;')
                tmp = re.findall(config.radio.lastroot.value)
                cnt = 0
@@ -768,7 +1133,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 lastservice is not None:
+                               if lastservice.valid():
                                        self.setCurrentSelection(lastservice)
                                return True
                return False
@@ -781,7 +1146,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        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()
@@ -801,7 +1166,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        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)
@@ -811,18 +1176,18 @@ 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)
 
                self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
-                               "cancel": self.cancel,
+                               "cancel": self.close,
                                "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