re-add (unused) blinking point in radio infobar to make e2 happy...
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index ff2928ecf14d1dab2f6df9cf69a29b2bf52ad636..1ccddf75ed49702cf9e1ac7281c32479340e8a45 100644 (file)
@@ -1,19 +1,24 @@
 from Screen import Screen
 from Components.Button import Button
 from Components.ServiceList import ServiceList
-from Components.ActionMap import NumberActionMap, ActionMap
+from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
 from Components.MenuList import MenuList
+from Components.ServiceEventTracker import ServiceEventTracker
 from EpgSelection import EPGSelection
-from enigma import eServiceReference, eEPGCache, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer, eDVBDB
+from enigma import eServiceReference, eEPGCache, eServiceCenter, eTimer, eDVBDB, iPlayableService, iServiceInformation
 from Components.config import config, ConfigSubsection, ConfigText
 from Screens.FixedMenu import FixedMenu
 from Tools.NumericalTextInput import NumericalTextInput
 from Components.NimManager import nimmanager
 from Components.Sources.Clock import Clock
+from Components.Sources.RdsDecoder import RdsDecoder
 from Components.Input import Input
 from Components.ParentalControl import parentalControl
+from Components.Pixmap import BlinkingPixmapConditional
 from Screens.InputBox import InputBox, PinInput
 from Screens.MessageBox import MessageBox
+from Screens.ServiceInfo import ServiceInfo
+from Screens.RdsDisplay import RassInteractive
 from ServiceReference import ServiceReference
 from Tools.BoundFunction import boundFunction
 from re import *
@@ -34,9 +39,7 @@ class BouquetSelector(Screen):
                                "ok": self.okbuttonClick,
                                "cancel": self.cancelClick
                        })
-               entrys = [ ]
-               for x in bouquets:
-                       entrys.append((x[0], x[1]))
+               entrys = [ (x[0], x[1]) for x in bouquets ]
                self["menu"] = MenuList(entrys, enableWrapAround)
 
        def getCurrent(self):
@@ -55,6 +58,15 @@ class BouquetSelector(Screen):
        def cancelClick(self):
                self.close(False)
 
+# csel.bouquet_mark_edit values
+OFF = 0
+EDIT_BOUQUET = 1
+EDIT_ALTERNATIVES = 2
+
+def apend_when_current_valid(current, menu, args):
+       if current and current.valid():
+               menu.append(args)
+
 class ChannelContextMenu(Screen):
        def __init__(self, session, csel):
                Screen.__init__(self, session)
@@ -68,58 +80,72 @@ class ChannelContextMenu(Screen):
                        })
                menu = [ ]
 
+               current = csel.getCurrentSelection()
                current_root = csel.getRoot()
-               current_sel_path = csel.getCurrentSelection().getPath()
-               current_sel_flags = csel.getCurrentSelection().flags
+               current_sel_path = current.getPath()
+               current_sel_flags = current.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
+               haveBouquets = config.usage.multibouquet.value
 
-               if not csel.bouquet_mark_edit and not csel.movemode:
+               if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
+                       apend_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
+               if csel.bouquet_mark_edit == OFF and not csel.movemode:
                        if not inBouquetRootList:
-                               if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
+                               isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
+                               if isPlayable:
                                        if config.ParentalControl.configured.value:
                                                if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
-                                                       menu.append((_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
+                                                       apend_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
                                                else:
-                                                       menu.append((_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
+                                                       apend_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
                                        if haveBouquets:
-                                               menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected))
+                                               apend_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
                                        else:
-                                               menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
+                                               apend_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
                                else:
                                        if haveBouquets:
                                                if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
-                                                       menu.append((_("copy to favourites"), self.copyCurrentToBouquetList))
+                                                       apend_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
                                        if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
-                                               menu.append((_("remove all new found flags"), self.removeAllNewFoundFlags))
+                                               apend_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
                                if inBouquet:
-                                       menu.append((_("remove entry"), self.removeCurrentService))
-                               if current_root is not None and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
-                                       menu.append((_("remove new found flag"), self.removeNewFoundFlag))
+                                       apend_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
+                               if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
+                                       apend_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
                        else:
                                        menu.append((_("add bouquet"), self.showBouquetInputBox))
-                                       menu.append((_("remove entry"), self.removeBouquet))
+                                       apend_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
 
                if inBouquet: # current list is editable?
-                       if not csel.bouquet_mark_edit:
+                       if csel.bouquet_mark_edit == OFF:
                                if not csel.movemode:
-                                       menu.append((_("add marker"), self.showMarkerInputBox))
-                                       menu.append((_("enable move mode"), self.toggleMoveMode))
-                                       if not inBouquetRootList:
+                                       apend_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
+                                       if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
+                                               menu.append((_("add marker"), self.showMarkerInputBox))
                                                if haveBouquets:
-                                                       menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
+                                                       apend_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
                                                else:
-                                                       menu.append((_("enable favourite edit"), self.bouquetMarkStart))
+                                                       apend_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
+                                               if current_sel_flags & eServiceReference.isGroup:
+                                                       apend_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
+                                                       apend_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
+                                                       apend_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
+                                               elif not current_sel_flags & eServiceReference.isMarker:
+                                                       apend_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
                                else:
-                                       menu.append((_("disable move mode"), self.toggleMoveMode))
-                       elif not inBouquetRootList:
-                               if haveBouquets:
-                                       menu.append((_("end bouquet edit"), self.bouquetMarkEnd))
-                                       menu.append((_("abort bouquet edit"), self.bouquetMarkAbort))
+                                       apend_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
+                       else:
+                               if csel.bouquet_mark_edit == EDIT_BOUQUET:
+                                       if haveBouquets:
+                                               apend_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
+                                               apend_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
+                                       else:
+                                               apend_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
+                                               apend_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
                                else:
-                                       menu.append((_("end favourites edit"), self.bouquetMarkEnd))
-                                       menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
+                                               apend_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
+                                               apend_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
 
                menu.append((_("back"), self.cancelClick))
                self["menu"] = MenuList(menu)
@@ -129,7 +155,10 @@ class ChannelContextMenu(Screen):
 
        def cancelClick(self):
                self.close(False)
-               
+
+       def showServiceInformations(self):
+               self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
+
        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)
 
@@ -151,7 +180,6 @@ class ChannelContextMenu(Screen):
                        self.close()
                else:
                        self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
-               
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
@@ -163,8 +191,6 @@ class ChannelContextMenu(Screen):
                        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
@@ -188,7 +214,7 @@ class ChannelContextMenu(Screen):
                self.close()
 
        def addCurrentServiceToBouquet(self, dest):
-               self.csel.addCurrentServiceToBouquet(dest)
+               self.csel.addServiceToBouquet(dest)
                if self.bsel is not None:
                        self.bsel.close(True)
                else:
@@ -203,7 +229,7 @@ class ChannelContextMenu(Screen):
                self.close()
 
        def bouquetMarkStart(self):
-               self.csel.startMarkedEdit()
+               self.csel.startMarkedEdit(EDIT_BOUQUET)
                self.close()
 
        def bouquetMarkEnd(self):
@@ -229,6 +255,23 @@ class ChannelContextMenu(Screen):
                                eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
                self.close()
 
+       def editAlternativeServices(self):
+               self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
+               self.close()
+
+       def showAlternativeServices(self):
+               self.csel.enterPath(self.csel.getCurrentSelection())
+               self.close()
+
+       def removeAlternativeServices(self):
+               self.csel.removeAlternativeServices()
+               self.close()
+
+       def addAlternativeServices(self):
+               self.csel.addAlternativeServices()
+               self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
+               self.close()
+
 class ChannelSelectionEPG:
        def __init__(self):
                self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
@@ -248,7 +291,7 @@ class ChannelSelectionEdit:
        def __init__(self):
                self.entry_marked = False
                self.movemode = False
-               self.bouquet_mark_edit = False
+               self.bouquet_mark_edit = OFF
                self.mutableList = None
                self.__marked = [ ]
                self.saved_title = None
@@ -312,6 +355,39 @@ class ChannelSelectionEdit:
                                break
                        cnt+=1
 
+       def addAlternativeServices(self):
+               cur_service = ServiceReference(self.getCurrentSelection())
+               root = self.getRoot()
+               cur_root = root and ServiceReference(root)
+               mutableBouquet = cur_root.list().startEdit()
+               if mutableBouquet:
+                       name = cur_service.getServiceName()
+                       print "NAME", name
+                       if self.mode == MODE_TV:
+                               str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
+                       else:
+                               str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
+                       new_ref = ServiceReference(str)
+                       if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
+                               mutableBouquet.removeService(cur_service.ref)
+                               mutableBouquet.flushChanges()
+                               eDVBDB.getInstance().reloadBouquets()
+                               mutableAlternatives = new_ref.list().startEdit()
+                               if mutableAlternatives:
+                                       mutableAlternatives.setListName(name)
+                                       if mutableAlternatives.addService(cur_service.ref):
+                                               print "add", cur_service.toString(), "to new alternatives failed"
+                                       mutableAlternatives.flushChanges()
+                                       self.servicelist.addService(new_ref.ref, True)
+                                       self.servicelist.removeCurrent()
+                                       self.servicelist.moveUp()
+                               else:
+                                       print "get mutable list for new created alternatives failed"
+                       else:
+                               print "add", str, "to", cur_root.getServiceName(), "failed"
+               else:
+                       print "bouquetlist is not editable"
+
        def addBouquet(self, bName, services):
                serviceHandler = eServiceCenter.getInstance()
                mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
@@ -324,7 +400,6 @@ class ChannelSelectionEdit:
                                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()
@@ -334,13 +409,16 @@ class ChannelSelectionEdit:
                                                for service in services:
                                                        if mutableBouquet.addService(service):
                                                                print "add", service.toString(), "to new bouquet failed"
-                                                       else:
-                                                               current = self.servicelist.getCurrent()
-                                                               if current and current.toString() == self.bouquet_rootstr:
-                                                                       self.servicelist.addService(service, True)
                                        mutableBouquet.flushChanges()
                                else:
                                        print "get mutable list for new created bouquet failed"
+                               # do some voodoo to check if current_root is equal to bouquet_root
+                               cur_root = self.getRoot();
+                               str1 = cur_root and cur_root.toString()
+                               pos1 = str1 and str1.find("FROM BOUQUET") or -1
+                               pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
+                               if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
+                                       self.servicelist.addService(new_bouquet_ref)
                        else:
                                print "add", str, "to bouquets failed"
                else:
@@ -353,10 +431,32 @@ class ChannelSelectionEdit:
                services = serviceHandler.list(provider.ref)
                self.addBouquet(providerName, services and services.getContent('R', True))
 
+       def removeAlternativeServices(self):
+               cur_service = ServiceReference(self.getCurrentSelection())
+               root = self.getRoot()
+               cur_root = root and ServiceReference(root)
+               list = cur_service.list()
+               first_in_alternative = list and list.getNext()
+               if first_in_alternative:
+                       edit_root = cur_root and cur_root.list().startEdit()
+                       if edit_root:
+                               if not edit_root.addService(first_in_alternative, cur_service.ref):
+                                       self.servicelist.addService(first_in_alternative, True)
+                               else:
+                                       print "couldn't add first alternative service to current root"
+                       else:
+                               print "couldn't edit current root!!"
+               else:
+                       print "remove empty alternative list !!"
+               self.removeBouquet()
+               self.servicelist.moveUp()
+
        def removeBouquet(self):
                refstr = self.getCurrentSelection().toString()
+               print "removeBouquet", refstr
                self.bouquetNumOffsetCache = { }
                pos = refstr.find('FROM BOUQUET "')
+               filename = None
                if pos != -1:
                        refstr = refstr[pos+14:]
                        pos = refstr.find('"')
@@ -364,28 +464,35 @@ class ChannelSelectionEdit:
                                filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
                self.removeCurrentService()
                try:
-                       remove(filename)
+                       if filename is not None:
+                               remove(filename)
                except OSError:
                        print "error during remove of", filename
 
 #  multiple marked entry stuff ( edit mode, later multiepg selection )
-       def startMarkedEdit(self):
+       def startMarkedEdit(self, type):
+               self.savedPath = self.servicePath[:]
+               if type == EDIT_ALTERNATIVES:
+                       self.enterPath(self.getCurrentSelection())
                self.mutableList = self.getMutableList()
                # add all services from the current list to internal marked set in listboxservicecontent
                self.clearMarks() # this clears the internal marked set in the listboxservicecontent
                self.saved_title = self.instance.getTitle()
                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]")
+               if type == EDIT_ALTERNATIVES:
+                       self.bouquet_mark_edit = EDIT_ALTERNATIVES
+                       new_title += ' ' + _("[alternative edit]")
                else:
-                       new_title += ' ' + _("[favourite edit]")
+                       self.bouquet_mark_edit = EDIT_BOUQUET
+                       if config.usage.multibouquet.value:
+                               new_title += ' ' + _("[bouquet edit]")
+                       else:
+                               new_title += ' ' + _("[favourite edit]")
                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.savedPath = self.servicePath[:]
                self.showAllServices()
 
        def endMarkedEdit(self, abort):
@@ -406,7 +513,7 @@ class ChannelSelectionEdit:
                                self.mutableList.flushChanges()
                self.__marked = []
                self.clearMarks()
-               self.bouquet_mark_edit = False
+               self.bouquet_mark_edit = OFF
                self.mutableList = None
                self.setTitle(self.saved_title)
                self.saved_title = None
@@ -436,29 +543,40 @@ class ChannelSelectionEdit:
                                mutableList.flushChanges() #FIXME dont flush on each single removed service
                                self.servicelist.removeCurrent()
 
-       def addCurrentServiceToBouquet(self, dest):
+       def addServiceToBouquet(self, dest, service=None):
                mutableList = self.getMutableList(dest)
                if not mutableList is None:
-                       if not mutableList.addService(self.servicelist.getCurrent()):
+                       if service is None: #use current selected service
+                               service = self.servicelist.getCurrent()
+                       if not mutableList.addService(service):
                                self.bouquetNumOffsetCache = { }
                                mutableList.flushChanges()
+                               # do some voodoo to check if current_root is equal to dest
+                               cur_root = self.getRoot();
+                               str1 = cur_root and cur_root.toString() or -1
+                               str2 = dest.toString()
+                               pos1 = str1.find("FROM BOUQUET")
+                               pos2 = str2.find("FROM BOUQUET")
+                               if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
+                                       self.servicelist.addService(service)
 
        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.pathChangeDisabled = False # re-enable path change
                        self.mutableList.flushChanges() # FIXME add check if changes was made
                        self.mutableList = None
                        self.setTitle(self.saved_title)
                        self.saved_title = None
-                       if self.getRoot() == self.bouquet_root:
+                       cur_root = self.getRoot()
+                       if cur_root and cur_root == self.bouquet_root:
                                self.bouquetNumOffsetCache = { }
                else:
                        self.mutableList = self.getMutableList()
                        self.movemode = True
-                       self.pathChangedDisabled = True # no path change allowed in movemode
+                       self.pathChangeDisabled = True # no path change allowed in movemode
                        self.saved_title = self.instance.getTitle()
                        new_title = self.saved_title
                        pos = self.saved_title.find(')')
@@ -469,7 +587,7 @@ class ChannelSelectionEdit:
                if self.movemode: #movemode active?
                        self.channelSelected() # unmark
                        self.toggleMoveMode() # disable move mode
-               elif self.bouquet_mark_edit:
+               elif self.bouquet_mark_edit != OFF:
                        self.endMarkedEdit(True) # abort edit mode
 
        def toggleMoveMarked(self):
@@ -511,7 +629,7 @@ class ChannelSelectionBase(Screen):
 
                self.mode = MODE_TV
 
-               self.pathChangedDisabled = False
+               self.pathChangeDisabled = False
 
                self.bouquetNumOffsetCache = { }
 
@@ -538,30 +656,21 @@ class ChannelSelectionBase(Screen):
                        })
                self.recallBouquetMode()
 
-       def appendDVBTypes(self, ref):
-               path = ref.getPath()
-               pos = path.find(' FROM BOUQUET')
-               if pos != -1:
-                       return eServiceReference(self.service_types + path[pos:])
-               return ref
-
        def getBouquetNumOffset(self, bouquet):
-               if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
+               if not config.usage.multibouquet.value:
                        return 0
-               bouquet = self.appendDVBTypes(bouquet)
-               try:
-                       return self.bouquetNumOffsetCache[bouquet.toString()]
-               except:
-                       offsetCount = 0
+               str = bouquet.toString()
+               offsetCount = 0
+               if not self.bouquetNumOffsetCache.has_key(str):
                        serviceHandler = eServiceCenter.getInstance()
                        bouquetlist = serviceHandler.list(self.bouquet_root)
                        if not bouquetlist is None:
                                while True:
-                                       bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
+                                       bouquetIterator = bouquetlist.getNext()
                                        if not bouquetIterator.valid(): #end of list
                                                break
                                        self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
-                                       if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
+                                       if not (bouquetIterator.flags & eServiceReference.isDirectory):
                                                continue
                                        servicelist = serviceHandler.list(bouquetIterator)
                                        if not servicelist is None:
@@ -569,22 +678,22 @@ class ChannelSelectionBase(Screen):
                                                        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)
+                                                       playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
+                                                       if playable:
+                                                               offsetCount += 1
+               return self.bouquetNumOffsetCache.get(str, offsetCount)
 
        def recallBouquetMode(self):
                if self.mode == MODE_TV:
                        self.service_types = service_types_tv
                        if config.usage.multibouquet.value:
-                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
+                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0: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 = service_types_radio
                        if config.usage.multibouquet.value:
-                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
+                               self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0: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)
@@ -614,13 +723,11 @@ class ChannelSelectionBase(Screen):
        def setRoot(self, root, justSet=False):
                path = root.getPath()
                inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
-               pos = path.find(' FROM BOUQUET')
-               isBouquet = pos != -1
+               pos = path.find('FROM BOUQUET')
+               isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
                if not inBouquetRootList and isBouquet:
                        self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
                        self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
-                       refstr = self.service_types + path[pos:]
-                       root = eServiceReference(refstr)
                else:
                        self.servicelist.setMode(ServiceList.MODE_NORMAL)
                self.servicelist.setRoot(root, justSet)
@@ -710,7 +817,7 @@ class ChannelSelectionBase(Screen):
                return False
 
        def showAllServices(self):
-               if not self.pathChangedDisabled:
+               if not self.pathChangeDisabled:
                        refstr = '%s ORDER BY name'%(self.service_types)
                        if not self.preEnterPath(refstr):
                                ref = eServiceReference(refstr)
@@ -720,7 +827,7 @@ class ChannelSelectionBase(Screen):
                                        self.enterPath(ref)
 
        def showSatellites(self):
-               if not self.pathChangedDisabled:
+               if not self.pathChangeDisabled:
                        refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
                        if not self.preEnterPath(refstr):
                                ref = eServiceReference(refstr)
@@ -769,12 +876,12 @@ class ChannelSelectionBase(Screen):
                                                                        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)
+                                               self.servicelist.finishFill()
+                                               if prev is not None:
+                                                       self.setCurrentSelection(prev)
 
        def showProviders(self):
-               if not self.pathChangedDisabled:
+               if not self.pathChangeDisabled:
                        refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
                        if not self.preEnterPath(refstr):
                                ref = eServiceReference(refstr)
@@ -787,9 +894,14 @@ class ChannelSelectionBase(Screen):
                                                self.enterPath(ref)
 
        def changeBouquet(self, direction):
-               if not self.pathChangedDisabled:
-                       if self.isBasePathEqual(self.bouquet_root):
-                               self.pathUp()
+               if not self.pathChangeDisabled:
+                       if len(self.servicePath) > 1:
+                               #when enter satellite root list we must do some magic stuff..
+                               ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
+                               if self.isBasePathEqual(ref):
+                                       self.showSatellites()
+                               else:
+                                       self.pathUp()
                                if direction < 0:
                                        self.moveUp()
                                else:
@@ -813,7 +925,7 @@ class ChannelSelectionBase(Screen):
                self.changeBouquet(-1)
 
        def showFavourites(self):
-               if not self.pathChangedDisabled:
+               if not self.pathChangeDisabled:
                        if not self.preEnterPath(self.bouquet_rootstr):
                                if self.isBasePathEqual(self.bouquet_root):
                                        self.pathUp()
@@ -847,25 +959,24 @@ class ChannelSelectionBase(Screen):
                self.servicelist.setCurrent(service)
 
        def getBouquetList(self):
-               serviceCount=0
                bouquets = [ ]
                serviceHandler = eServiceCenter.getInstance()
-               list = serviceHandler.list(self.bouquet_root)
-               if not list is None:
-                       while True:
-                               s = list.getNext()
-                               if not s.valid():
-                                       break
-                               if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
-                                       info = serviceHandler.info(s)
-                                       if not info is None:
-                                               bouquets.append((info.getName(s), s))
-                               else:
-                                       serviceCount += 1
-                       if len(bouquets) == 0 and serviceCount > 0:
-                               info = serviceHandler.info(self.bouquet_root)
-                               if not info is None:
-                                       bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
+               if config.usage.multibouquet.value:
+                       list = serviceHandler.list(self.bouquet_root)
+                       if list:
+                               while True:
+                                       s = list.getNext()
+                                       if not s.valid():
+                                               break
+                                       if s.flags & eServiceReference.isDirectory:
+                                               info = serviceHandler.info(s)
+                                               if info:
+                                                       bouquets.append((info.getName(s), s))
+                               return bouquets
+               else:
+                       info = serviceHandler.info(self.bouquet_root)
+                       if info:
+                               bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
                        return bouquets
                return None
 
@@ -922,7 +1033,11 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                                "keyTV": self.setModeTv,
                        })
 
-               self.onShown.append(self.__onShown)
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evStart: self.__evServiceStart,
+                               iPlayableService.evEnd: self.__evServiceEnd
+                       })
 
                self.lastChannelRootTimer = eTimer()
                self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
@@ -936,6 +1051,21 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                self.lastservice = config.tv.lastservice
                self.lastroot = config.tv.lastroot
                self.revertMode = None
+               config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
+
+       def multibouquet_config_changed(self, val):
+               self.recallBouquetMode()
+
+       def __evServiceStart(self):
+               service = self.session.nav.getCurrentService()
+               if service:
+                       info = service.info()
+                       if info:
+                               refstr = info.getInfoString(iServiceInformation.sServiceref)
+                               self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
+
+       def __evServiceEnd(self):
+               self.servicelist.setPlayableIgnoreService(eServiceReference())
 
        def setMode(self):
                self.restoreRoot()
@@ -976,25 +1106,20 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                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() == "":
-                       self.servicelist.setPlayableIgnoreService(ref)
-               else:
-                       self.servicelist.setPlayableIgnoreService(eServiceReference())
-
        def channelSelected(self):
                ref = self.getCurrentSelection()
                if self.movemode:
                        self.toggleMoveMarked()
                elif (ref.flags & 7) == 7:
                        self.enterPath(ref)
-               elif self.bouquet_mark_edit:
-                       self.doMark()
-               elif not (ref.flags & 64): # no marker
-                       self.zap()
-                       self.close(ref)
+               elif self.bouquet_mark_edit != OFF:
+                       if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
+                               self.doMark()
+               elif not (ref.flags & eServiceReference.isMarker): # no marker
+                       root = self.getRoot()
+                       if not root or not (root.flags & eServiceReference.isGroup):
+                               self.zap()
+                               self.close(ref)
 
        #called from infoBar and channelSelected
        def zap(self):
@@ -1004,7 +1129,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                if ref is None or ref != nref:
                        self.session.nav.playService(nref)
                        self.saveRoot()
-                       self.saveChannel()
+                       self.saveChannel(nref)
                        config.servicelist.lastmode.save()
                        self.addToHistory(nref)
 
@@ -1043,11 +1168,12 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                self.saveRoot()
                plen = len(path)
                root = path[plen-1]
-               if self.getRoot() != root:
+               cur_root = self.getRoot()
+               if cur_root and cur_root != root:
                        self.setRoot(root)
                self.session.nav.playService(ref)
                self.setCurrentSelection(ref)
-               self.saveChannel()
+               self.saveChannel(ref)
 
        def saveRoot(self):
                path = ''
@@ -1084,8 +1210,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                                return True
                return False
 
-       def saveChannel(self):
-               ref = self.session.nav.getCurrentlyPlayingServiceReference()
+       def saveChannel(self, ref):
                if ref is not None:
                        refstr = ref.toString()
                else:
@@ -1134,32 +1259,32 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                self.revertMode = None
                self.close(None)
 
-from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
+from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
 
-class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
+class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
        def __init__(self, session):
                Screen.__init__(self, session)
                InfoBarEvent.__init__(self)
                InfoBarServiceName.__init__(self)
-               InfoBarInstantRecord.__init__(self)
                self["CurrentTime"] = Clock()
+               self["RdsDecoder"] = RdsDecoder(self.session.nav)
+               self["BlinkingPoint"] = BlinkingPixmapConditional()
+               self["BlinkingPoint"].hide()
 
-class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
-
+class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
        ALLOW_SUSPEND = True
 
-       def __init__(self, session):
+       def __init__(self, session, infobar):
                ChannelSelectionBase.__init__(self, session)
                ChannelSelectionEdit.__init__(self)
                ChannelSelectionEPG.__init__(self)
-               InfoBarRadioText.__init__(self)
-
+               self.infobar = infobar
                config.radio = ConfigSubsection();
                config.radio.lastservice = ConfigText()
                config.radio.lastroot = ConfigText()
                self.onLayoutFinish.append(self.onCreate)
 
-               self.info = session.instantiateDialog(RadioInfoBar)
+               self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
 
                self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
@@ -1169,6 +1294,54 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                                "ok": self.channelSelected,
                        })
 
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evStart: self.__evServiceStart,
+                               iPlayableService.evEnd: self.__evServiceEnd
+                       })
+
+########## RDS Radiotext / Rass Support BEGIN
+               self.infobar = infobar # reference to real infobar (the one and only)
+               self["RdsDecoder"] = self.info["RdsDecoder"]
+               self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
+               {
+                       "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
+               },-1)
+               self["RdsActions"].setEnabled(False)
+               infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
+
+       def startRassInteractive(self):
+               self.info.hide();
+               self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
+
+       def RassInteractiveClosed(self):
+               self.info.show()
+               self.infobar.rass_interactive = None
+               self.infobar.RassSlidePicChanged()
+
+       def RassInteractivePossibilityChanged(self, state):
+               self["RdsActions"].setEnabled(state)
+########## RDS Radiotext / Rass Support END
+
+       def closeRadio(self):
+               self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
+               self.info.hide()
+               #set previous tv service
+               lastservice=eServiceReference(config.tv.lastservice.value)
+               self.session.nav.playService(lastservice)
+               self.close(None)
+
+       def __evServiceStart(self):
+               service = self.session.nav.getCurrentService()
+               if service:
+                       info = service.info()
+                       if info:
+                               refstr = info.getInfoString(iServiceInformation.sServiceref)
+                               self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
+
+       def __evServiceEnd(self):
+               self.servicelist.setPlayableIgnoreService(eServiceReference())
+
        def saveRoot(self):
                path = ''
                for i in self.servicePathRadio:
@@ -1211,7 +1384,6 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                if lastservice.valid():
                        self.servicelist.setCurrent(lastservice)
                        self.session.nav.playService(lastservice)
-                       self.servicelist.setPlayableIgnoreService(lastservice)
                self.info.show()
 
        def channelSelected(self): # just return selected service
@@ -1220,23 +1392,18 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
                        self.toggleMoveMarked()
                elif (ref.flags & 7) == 7:
                        self.enterPath(ref)
-               elif self.bouquet_mark_edit:
-                       self.doMark()
-               elif not (ref.flags & 64): # no marker
-                       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.hide()
-               #set previous tv service
-               lastservice=eServiceReference(config.tv.lastservice.value)
-               self.session.nav.playService(lastservice)
-               self.close(None)
+               elif self.bouquet_mark_edit != OFF:
+                       if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
+                               self.doMark()
+               elif not (ref.flags & eServiceReference.isMarker): # no marker
+                       cur_root = self.getRoot()
+                       if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
+                               playingref = self.session.nav.getCurrentlyPlayingServiceReference()
+                               if playingref is None or playingref != ref:
+                                       self.session.nav.playService(ref)
+                                       config.radio.lastservice.value = ref.toString()
+                                       config.radio.lastservice.save()
+                               self.saveRoot()
 
 class SimpleChannelSelection(ChannelSelectionBase):
        def __init__(self, session, title):
@@ -1260,7 +1427,7 @@ class SimpleChannelSelection(ChannelSelectionBase):
                ref = self.getCurrentSelection()
                if (ref.flags & 7) == 7:
                        self.enterPath(ref)
-               elif not (ref.flags & 64):
+               elif not (ref.flags & eServiceReference.isMarker):
                        ref = self.getCurrentSelection()
                        self.close(ref)