fix EOF bug, display pvrstate only when seeking
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 9d610dc8ba66e3f48cfbc9e01a5ff88250c3ebbb..f1267afa0b5206a885d4dbc9e820ba56e447932b 100644 (file)
@@ -5,25 +5,27 @@ from Components.Label import *
 from Components.ProgressBar import *
 from Components.config import configfile, configsequencearg
 from Components.config import config, configElement, ConfigSubsection, configSequence
 from Components.ProgressBar import *
 from Components.config import configfile, configsequencearg
 from Components.config import config, configElement, ConfigSubsection, configSequence
-from ChannelSelection import ChannelSelection
+from ChannelSelection import ChannelSelection, BouquetSelector
 
 from Components.Pixmap import Pixmap, PixmapConditional
 from Components.BlinkingPixmap import BlinkingPixmapConditional
 from Components.ServiceName import ServiceName
 
 from Components.Pixmap import Pixmap, PixmapConditional
 from Components.BlinkingPixmap import BlinkingPixmapConditional
 from Components.ServiceName import ServiceName
-from Components.EventInfo import EventInfo
+from Components.EventInfo import EventInfo, EventInfoProgress
 
 from ServiceReference import ServiceReference
 from EpgSelection import EPGSelection
 
 from Screens.MessageBox import MessageBox
 
 from ServiceReference import ServiceReference
 from EpgSelection import EPGSelection
 
 from Screens.MessageBox import MessageBox
-from Screens.Volume import Volume
-from Screens.Mute import Mute
 from Screens.Dish import Dish
 from Screens.Standby import Standby
 from Screens.Dish import Dish
 from Screens.Standby import Standby
-from Screens.EventView import EventView
+from Screens.EventView import EventViewEPGSelect
+from Screens.MinuteInput import MinuteInput
 from Components.Harddisk import harddiskmanager
 
 from Components.Harddisk import harddiskmanager
 
+from Components.ServiceEventTracker import ServiceEventTracker
+
 from Tools import Notifications
 from Tools import Notifications
+from Tools.Directories import *
 
 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
 from enigma import *
 
 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
 from enigma import *
@@ -31,71 +33,15 @@ from enigma import *
 import time
 import os
 
 import time
 import os
 
+from Components.config import config, currentConfigSelectionElement
+
 # hack alert!
 from Menu import MainMenu, mdom
 
 # hack alert!
 from Menu import MainMenu, mdom
 
-class InfoBarVolumeControl:
-       """Volume control, handles volUp, volDown, volMute actions and display 
-       a corresponding dialog"""
-       def __init__(self):
-               config.audio = ConfigSubsection()
-               config.audio.volume = configElement("config.audio.volume", configSequence, [5], configsequencearg.get("INTEGER", (0, 100)))
-
-               self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
-                       {
-                               "volumeUp": self.volUp,
-                               "volumeDown": self.volDown,
-                               "volumeMute": self.volMute,
-                       })
-
-               self.volumeDialog = self.session.instantiateDialog(Volume)
-               self.muteDialog = self.session.instantiateDialog(Mute)
-
-               self.hideVolTimer = eTimer()
-               self.hideVolTimer.timeout.get().append(self.volHide)
-
-               vol = config.audio.volume.value[0]
-               self.volumeDialog.setValue(vol)
-               eDVBVolumecontrol.getInstance().setVolume(vol, vol)
-       
-       def volSave(self):
-               config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
-               config.audio.volume.save()
-               
-       def     volUp(self):
-               if (eDVBVolumecontrol.getInstance().isMuted()):
-                       self.volMute()
-               eDVBVolumecontrol.getInstance().volumeUp()
-               self.volumeDialog.instance.show()
-               self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
-               self.volSave()
-               self.hideVolTimer.start(3000)
-
-       def     volDown(self):
-               if (eDVBVolumecontrol.getInstance().isMuted()):
-                       self.volMute()
-               eDVBVolumecontrol.getInstance().volumeDown()
-               self.volumeDialog.instance.show()
-               self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
-               self.volSave()
-               self.hideVolTimer.start(3000)
-               
-       def volHide(self):
-               self.volumeDialog.instance.hide()
-
-       def     volMute(self):
-               eDVBVolumecontrol.getInstance().volumeToggleMute()
-               self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
-               
-               if (eDVBVolumecontrol.getInstance().isMuted()):
-                       self.muteDialog.instance.show()
-               else:
-                       self.muteDialog.instance.hide()
-
 class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
 class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
-               self.onShown.append(self.dishDialog.instance.hide)
+               self.onShown.append(self.dishDialog.show)
 
 class InfoBarShowHide:
        """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
 
 class InfoBarShowHide:
        """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
@@ -112,50 +58,59 @@ class InfoBarShowHide:
                                "hide": self.hide,
                        })
 
                                "hide": self.hide,
                        })
 
-               self.state = self.STATE_SHOWN
+               self.__state = self.STATE_SHOWN
+               self.__locked = 0
                
                self.onExecBegin.append(self.show)
                
                self.onExecBegin.append(self.show)
-               self.onClose.append(self.delHideTimer)
                
                self.hideTimer = eTimer()
                self.hideTimer.timeout.get().append(self.doTimerHide)
                
                self.hideTimer = eTimer()
                self.hideTimer.timeout.get().append(self.doTimerHide)
-               self.hideTimer.start(5000)
+               self.hideTimer.start(5000, True)
+               
+               self.onShow.append(self.__onShow)
+               self.onHide.append(self.__onHide)
 
 
-       def delHideTimer(self):
-               del self.hideTimer
+       def __onShow(self):
+               self.__state = self.STATE_SHOWN
+               self.startHideTimer()
+       
+       def startHideTimer(self):
+               if self.__state == self.STATE_SHOWN and not self.__locked:
+                       self.hideTimer.start(5000, True)
 
 
-       def hide(self): 
-               self.instance.hide()
-               
-       def show(self):
-               self.state = self.STATE_SHOWN
-               self.hideTimer.stop()
-               self.hideTimer.start(5000)
+       def __onHide(self):
+               self.__state = self.STATE_HIDDEN
 
        def doTimerHide(self):
                self.hideTimer.stop()
 
        def doTimerHide(self):
                self.hideTimer.stop()
-               if self.state == self.STATE_SHOWN:
-                       self.instance.hide()
-                       self.state = self.STATE_HIDDEN
+               if self.__state == self.STATE_SHOWN:
+                       self.hide()
 
        def toggleShow(self):
 
        def toggleShow(self):
-               if self.state == self.STATE_SHOWN:
-                       self.instance.hide()
-                       #pls check animation support, sorry
-#                      self.startHide()
+               if self.__state == self.STATE_SHOWN:
+                       self.hide()
                        self.hideTimer.stop()
                        self.hideTimer.stop()
-                       self.state = self.STATE_HIDDEN
-               elif self.state == self.STATE_HIDDEN:
-                       self.instance.show()
+               elif self.__state == self.STATE_HIDDEN:
                        self.show()
                        self.show()
-                       
-       def startShow(self):
-               self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
-               self.state = self.STATE_SHOWN
+
+       def lockShow(self):
+               self.__locked = self.__locked + 1
+               if self.execing:
+                       self.show()
+                       self.hideTimer.stop()
        
        
-       def startHide(self):
-               self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
-               self.state = self.STATE_HIDDEN
+       def unlockShow(self):
+               self.__locked = self.__locked - 1
+               if self.execing:
+                       self.startHideTimer()
+
+#      def startShow(self):
+#              self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
+#              self.__state = self.STATE_SHOWN
+#      
+#      def startHide(self):
+#              self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
+#              self.__state = self.STATE_HIDDEN
 
 class NumberZap(Screen):
        def quit(self):
 
 class NumberZap(Screen):
        def quit(self):
@@ -167,7 +122,7 @@ class NumberZap(Screen):
                self.close(int(self["number"].getText()))
 
        def keyNumberGlobal(self, number):
                self.close(int(self["number"].getText()))
 
        def keyNumberGlobal(self, number):
-               self.Timer.start(3000)          #reset timer
+               self.Timer.start(3000, True)            #reset timer
                self.field = self.field + str(number)
                self["number"].setText(self.field)
                if len(self.field) >= 4:
                self.field = self.field + str(number)
                self["number"].setText(self.field)
                if len(self.field) >= 4:
@@ -199,7 +154,7 @@ class NumberZap(Screen):
 
                self.Timer = eTimer()
                self.Timer.timeout.get().append(self.keyOK)
 
                self.Timer = eTimer()
                self.Timer.timeout.get().append(self.keyOK)
-               self.Timer.start(3000)
+               self.Timer.start(3000, True)
 
 class InfoBarPowerKey:
        """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
 
 class InfoBarPowerKey:
        """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
@@ -221,7 +176,7 @@ class InfoBarPowerKey:
        
        def powerdown(self):
                self.standbyblocked = 0
        
        def powerdown(self):
                self.standbyblocked = 0
-               self.powerKeyTimer.start(3000)
+               self.powerKeyTimer.start(3000, True)
 
        def powerup(self):
                self.powerKeyTimer.stop()
 
        def powerup(self):
                self.powerKeyTimer.stop()
@@ -239,7 +194,7 @@ class InfoBarPowerKey:
 class InfoBarNumberZap:
        """ Handles an initial number for NumberZapping """
        def __init__(self):
 class InfoBarNumberZap:
        """ Handles an initial number for NumberZapping """
        def __init__(self):
-               self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
+               self["NumberActions"] = NumberActionMap( [ "NumberActions"],
                        {
                                "1": self.keyNumberGlobal,
                                "2": self.keyNumberGlobal,
                        {
                                "1": self.keyNumberGlobal,
                                "2": self.keyNumberGlobal,
@@ -255,7 +210,11 @@ class InfoBarNumberZap:
 
        def keyNumberGlobal(self, number):
 #              print "You pressed number " + str(number)
 
        def keyNumberGlobal(self, number):
 #              print "You pressed number " + str(number)
-               self.session.openWithCallback(self.numberEntered, NumberZap, number)
+               if number == 0:
+                       self.servicelist.recallPrevService()
+                       self.show()
+               else:
+                       self.session.openWithCallback(self.numberEntered, NumberZap, number)
 
        def numberEntered(self, retval):
 #              print self.servicelist
 
        def numberEntered(self, retval):
 #              print self.servicelist
@@ -286,17 +245,20 @@ class InfoBarNumberZap:
                        bouquetlist = serviceHandler.list(bouquet)
                        if not bouquetlist is None:
                                while number:
                        bouquetlist = serviceHandler.list(bouquet)
                        if not bouquetlist is None:
                                while number:
-                                       bouquet = bouquetlist.getNext()
+                                       bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
                                        if not bouquet.valid(): #check end of list
                                                break
                                        if not bouquet.valid(): #check end of list
                                                break
-                                       if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
+                                       if (bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
                                                continue
                                        service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
                if not service is None:
                                                continue
                                        service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
                if not service is None:
-                       self.session.nav.playService(service) #play service
                        if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
                        if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
-                               self.servicelist.setRoot(bouquet)
+                               self.servicelist.clearPath()
+                               if self.servicelist.bouquet_root != bouquet:
+                                       self.servicelist.enterPath(self.servicelist.bouquet_root)
+                               self.servicelist.enterPath(bouquet)
                        self.servicelist.setCurrentSelection(service) #select the service in servicelist
                        self.servicelist.setCurrentSelection(service) #select the service in servicelist
+                       self.servicelist.zap()
 
 class InfoBarChannelSelection:
        """ ChannelSelection - handles the channelSelection dialog and the initial 
 
 class InfoBarChannelSelection:
        """ ChannelSelection - handles the channelSelection dialog and the initial 
@@ -312,27 +274,25 @@ class InfoBarChannelSelection:
                                "zapUp": (self.zapUp, _("next channel")),
                                "zapDown": (self.zapDown, _("previous channel")),
                        })
                                "zapUp": (self.zapUp, _("next channel")),
                                "zapDown": (self.zapDown, _("previous channel")),
                        })
-                       
-       def switchChannelUp(self):      
+
+       def switchChannelUp(self):
                self.servicelist.moveUp()
                self.session.execDialog(self.servicelist)
 
                self.servicelist.moveUp()
                self.session.execDialog(self.servicelist)
 
-       def switchChannelDown(self):    
+       def switchChannelDown(self):
                self.servicelist.moveDown()
                self.session.execDialog(self.servicelist)
 
        def     zapUp(self):
                self.servicelist.moveUp()
                self.servicelist.zap()
                self.servicelist.moveDown()
                self.session.execDialog(self.servicelist)
 
        def     zapUp(self):
                self.servicelist.moveUp()
                self.servicelist.zap()
-               self.instance.show()
                self.show()
 
        def     zapDown(self):
                self.servicelist.moveDown()
                self.servicelist.zap()
                self.show()
 
        def     zapDown(self):
                self.servicelist.moveDown()
                self.servicelist.zap()
-               self.instance.show()
                self.show()
                self.show()
-               
+
 class InfoBarMenu:
        """ Handles a menu action, to open the (main) menu """
        def __init__(self):
 class InfoBarMenu:
        """ Handles a menu action, to open the (main) menu """
        def __init__(self):
@@ -352,32 +312,81 @@ class InfoBarEPG:
        def __init__(self):
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        {
        def __init__(self):
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        {
-                               "showEPGList": (self.showEPGList, _("show EPG...")),
+                               "showEventInfo": (self.openEventView, _("show EPG...")),
                        })
 
                        })
 
-       def showEPGList(self):
+       def zapToService(self, service):
+               if not service is None:
+                       if self.servicelist.getRoot() != self.epg_bouquet: #already in correct bouquet?
+                               self.servicelist.clearPath()
+                               if self.servicelist.bouquet_root != self.epg_bouquet:
+                                       self.servicelist.enterPath(self.servicelist.bouquet_root)
+                               self.servicelist.enterPath(self.epg_bouquet)
+                       self.servicelist.setCurrentSelection(service) #select the service in servicelist
+                       self.servicelist.zap()
+
+       def openBouquetEPG(self, bouquet):
+               ptr=eEPGCache.getInstance()
+               services = [ ]
+               servicelist = eServiceCenter.getInstance().list(bouquet)
+               if not servicelist is None:
+                       while True:
+                               service = servicelist.getNext()
+                               if not service.valid(): #check if end of list
+                                       break
+                               if service.flags: #ignore non playable services
+                                       continue
+                               services.append(ServiceReference(service))
+               if len(services):
+                       self.epg_bouquet = bouquet
+                       self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
+
+       def closed(self, ret):
+               if ret:
+                       self.close(ret)
+
+       def openMultiServiceEPG(self):
+               bouquets = self.servicelist.getBouquetList()
+               if bouquets is None:
+                       cnt = 0
+               else:
+                       cnt = len(bouquets)
+               if cnt > 1: # show bouquet list
+                       self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
+               elif cnt == 1: 
+                       self.openBouquetEPG(bouquets[0][1])
+
+       def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
                ptr=eEPGCache.getInstance()
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
                ptr=eEPGCache.getInstance()
-               if ptr.startTimeQuery(ref) != -1:
-                       self.session.open(EPGSelection, ref)
-               else: # try to show now/next
-                       print 'no epg for service', ref.toString()
-                       try:
-                               self.epglist = [ ]
-                               service = self.session.nav.getCurrentService()
-                               info = service.info()
-                               ptr=info.getEvent(0)
-                               if ptr:
-                                       self.epglist.append(ptr)
-                               ptr=info.getEvent(1)
+               self.session.openWithCallback(self.closed, EPGSelection, ref)
+
+       def openEventView(self):
+               self.epglist = [ ]
+               service = self.session.nav.getCurrentService()
+               ref = self.session.nav.getCurrentlyPlayingServiceReference()
+               info = service.info()
+               ptr=info.getEvent(0)
+               if ptr:
+                       self.epglist.append(ptr)
+               ptr=info.getEvent(1)
+               if ptr:
+                       self.epglist.append(ptr)
+               if len(self.epglist) == 0:
+                       epg = eEPGCache.getInstance()
+                       ptr = epg.lookupEventTime(ref, -1)
+                       if ptr:
+                               self.epglist.append(ptr)
+                               ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
                                if ptr:
                                        self.epglist.append(ptr)
                                if ptr:
                                        self.epglist.append(ptr)
-                               if len(self.epglist) > 0:
-                                       self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
-                       except:
-                               pass
+               if len(self.epglist) > 0:
+                       self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
+               else:
+                       print "no epg for the service avail.. so we show multiepg instead of eventinfo"
+                       self.openMultiServiceEPG()
 
 
-       def eventViewCallback(self, setEvent, val): #used for now/next displaying
+       def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
                if len(self.epglist) > 1:
                        tmp = self.epglist[0]
                        self.epglist[0]=self.epglist[1]
                if len(self.epglist) > 1:
                        tmp = self.epglist[0]
                        self.epglist[0]=self.epglist[1]
@@ -400,7 +409,7 @@ class InfoBarTuner:
                self["ber_progress"] = ProgressBar()
                self.timer = eTimer()
                self.timer.timeout.get().append(self.updateTunerInfo)
                self["ber_progress"] = ProgressBar()
                self.timer = eTimer()
                self.timer.timeout.get().append(self.updateTunerInfo)
-               self.timer.start(500)
+               self.timer.start(1000)
 
        def calc(self,val):
                if not val:
 
        def calc(self,val):
                if not val:
@@ -440,80 +449,150 @@ class InfoBarEvent:
                self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
                self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
 
                self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
                self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
 
+               self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
+
 class InfoBarServiceName:
        def __init__(self):
                self["ServiceName"] = ServiceName(self.session.nav)
 
 class InfoBarServiceName:
        def __init__(self):
                self["ServiceName"] = ServiceName(self.session.nav)
 
-class InfoBarPVR:
-
-       # ispause, isff, issm, skip
-       SEEK_STATE_PLAY = (0, 0, 0, 0)
-       SEEK_STATE_PAUSE = (1, 0, 0, 0)
-       SEEK_STATE_FF_2X = (0, 2, 0, 0)
-       SEEK_STATE_FF_4X = (0, 4, 0, 0)
-       SEEK_STATE_FF_8X = (0, 8, 0, 0)
-       SEEK_STATE_FF_32X = (0, 0, 0, 32)
-       SEEK_STATE_FF_64X = (0, 0, 0, 64)
+class InfoBarSeek:
+       """handles actions like seeking, pause"""
+       
+       # ispause, isff, issm
+       SEEK_STATE_PLAY = (0, 0, 0, ">")
+       SEEK_STATE_PAUSE = (1, 0, 0, "||")
+       SEEK_STATE_FF_2X = (0, 2, 0, ">> 2x")
+       SEEK_STATE_FF_4X = (0, 4, 0, ">> 4x")
+       SEEK_STATE_FF_8X = (0, 8, 0, ">> 8x")
+       SEEK_STATE_FF_32X = (0, 32, 0, ">> 32x")
+       SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
+       SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
        
        
-       SEEK_STATE_BACK_4X = (0, 0, 0, -4)
-       SEEK_STATE_BACK_32X = (0, 0, 0, -32)
-       SEEK_STATE_BACK_64X = (0, 0, 0, -64)
+       SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
+       SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
+       SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
+       SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
        
        
-       SEEK_STATE_SM_HALF = (0, 0, 2, 0)
-       SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
-       SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
+       SEEK_STATE_SM_HALF = (0, 0, 2, "/2")
+       SEEK_STATE_SM_QUARTER = (0, 0, 4, "/4")
+       SEEK_STATE_SM_EIGHTH = (0, 0, 8, "/8")
        
        
-       """handles PVR specific actions like seeking, pause"""
        def __init__(self):
        def __init__(self):
-               self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+                               iPlayableService.evStart: self.__serviceStarted,
+                               
+                               iPlayableService.evEOF: self.__evEOF,
+                               iPlayableService.evSOF: self.__evSOF,
+                       })
+               self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions", 
                        {
                                "pauseService": (self.pauseService, "pause"),
                                "unPauseService": (self.unPauseService, "continue"),
                                
                                "seekFwd": (self.seekFwd, "skip forward"),
                        {
                                "pauseService": (self.pauseService, "pause"),
                                "unPauseService": (self.unPauseService, "continue"),
                                
                                "seekFwd": (self.seekFwd, "skip forward"),
+                               "seekFwdUp": (self.seekFwdUp, "skip forward"),
                                "seekBack": (self.seekBack, "skip backward"),
                                "seekBack": (self.seekBack, "skip backward"),
-                       })
+                               "seekBackUp": (self.seekBackUp, "skip backward"),
+                       }, prio=-1)
+                       # give them a little more priority to win over color buttons
 
                self.seekstate = self.SEEK_STATE_PLAY
 
                self.seekstate = self.SEEK_STATE_PLAY
-               self.seekTimer = eTimer()
-               self.seekTimer.timeout.get().append(self.seekTimerFired)
-               self.skipinterval = 500 # 500ms skip interval
+               self.onClose.append(self.delTimer)
+               
+               self.fwdtimer = False
+               self.fwdKeyTimer = eTimer()
+               self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
+
+               self.rwdtimer = False
+               self.rwdKeyTimer = eTimer()
+               self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
+               
+               self.onPlayStateChanged = [ ]
+               
+               self.lockedBecauseOfSkipping = False
+       
+       def up(self):
+               pass
        
        
-       def seekTimerFired(self):
-               if self.skipmode > 0:
-                       self.doSeek(+1, self.skipmode * self.skipinterval)
+       def down(self):
+               pass
+       
+       def delTimer(self):
+               del self.fwdKeyTimer
+               del self.rwdKeyTimer
+       
+       def isSeekable(self):
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       return False
+               if service.seek() is None:
+                       return False
+               else:
+                       return True
+
+       def __seekableStatusChanged(self):
+               print "seekable status changed!"
+               if not self.isSeekable():
+                       self["SeekActions"].setEnabled(False)
+                       print "not seekable, return to play"
+                       self.setSeekState(self.SEEK_STATE_PLAY)
                else:
                else:
-                       self.doSeek(-1, -self.skipmode * self.skipinterval)
+                       self["SeekActions"].setEnabled(True)
+                       print "seekable"
 
 
-       def setSeekState(self, state):
-               oldstate = self.seekstate
-               
-               self.seekstate = state
+       def __serviceStarted(self):
+               self.seekstate = self.SEEK_STATE_PLAY
 
 
+       def setSeekState(self, state):
                service = self.session.nav.getCurrentService()
                service = self.session.nav.getCurrentService()
+               
                if service is None:
                if service is None:
-                       return
+                       return False
+               
+               if service.seek() is None:
+                       if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
+                               state = self.SEEK_STATE_PLAY
                
                pauseable = service.pause()
                
                pauseable = service.pause()
+
+               if pauseable is None:
+                       print "not pauseable."
+                       state = self.SEEK_STATE_PLAY
                
                
-               for i in range(4):
+               oldstate = self.seekstate
+               self.seekstate = state
+               
+               for i in range(3):
                        if oldstate[i] != self.seekstate[i]:
                        if oldstate[i] != self.seekstate[i]:
-                               (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
+                               (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
+
+               for c in self.onPlayStateChanged:
+                       c(self.seekstate)
+               
+               self.checkSkipShowHideLock()
+
+               return True
                
                
-       def setSkipMode(self, skipmode):
-               self.skipmode = skipmode
-               if skipmode == 0:
-                       self.seekTimer.stop()
-               else:
-                       self.seekTimer.start(500)
-       
        def pauseService(self):
        def pauseService(self):
-               self.setSeekState(self.SEEK_STATE_PAUSE);
+               if self.seekstate == self.SEEK_STATE_PAUSE:
+                       print "pause, but in fact unpause"
+                       self.unPauseService()
+               else:
+                       if self.seekstate == self.SEEK_STATE_PLAY:
+                               print "yes, playing."
+                       else:
+                               print "no", self.seekstate
+                       print "pause"
+                       self.setSeekState(self.SEEK_STATE_PAUSE);
                
        def unPauseService(self):
                
        def unPauseService(self):
+               print "unpause"
                self.setSeekState(self.SEEK_STATE_PLAY);
        
                self.setSeekState(self.SEEK_STATE_PLAY);
        
-       def doSeek(self, dir, seektime):
+       def doSeek(self, seektime):
+               print "doseek", seektime
                service = self.session.nav.getCurrentService()
                if service is None:
                        return
                service = self.session.nav.getCurrentService()
                if service is None:
                        return
@@ -521,43 +600,282 @@ class InfoBarPVR:
                seekable = service.seek()
                if seekable is None:
                        return
                seekable = service.seek()
                if seekable is None:
                        return
-               seekable.seekRelative(dir, 90 * seektime)
+               seekable.seekTo(90 * seektime)
 
        def seekFwd(self):
 
        def seekFwd(self):
-               lookup = {
-                               self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
-                               self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
-                               self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
-                               self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
-                               self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
-                               self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
-                               self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_64X,
-                               self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
-                               self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
-                               self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
-                               self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
-                               self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
-                               self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
-                       }
-               self.setSeekState(lookup[self.seekstate]);
-       
+               print "start fwd timer"
+               self.fwdtimer = True
+               self.fwdKeyTimer.start(500)
+
        def seekBack(self):
        def seekBack(self):
-               lookup = {
-                               self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
-                               self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
-                               self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
-                               self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
-                               self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
-                               self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
-                               self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
-                               self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
-                               self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
-                               self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_64X,
-                               self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
-                               self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
-                               self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
-                       }
-               self.setSeekState(lookup[self.seekstate]);
+               print "start rewind timer"
+               self.rwdtimer = True
+               self.rwdKeyTimer.start(500)
+
+       def seekFwdUp(self):
+               print "seekFwdUp"
+               if self.fwdtimer:
+                       self.fwdKeyTimer.stop()
+                       self.fwdtimer = False
+                       lookup = {
+                                       self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
+                                       self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
+                                       self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
+                                       self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
+                                       self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
+                                       self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
+                                       self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
+                                       self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
+                                       self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
+                                       self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
+                                       self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
+                                       self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
+                                       self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
+                                       self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
+                                       self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
+                               }
+                       self.setSeekState(lookup[self.seekstate]);
+       
+       def seekBackUp(self):
+               print "seekBackUp"
+               if self.rwdtimer:
+                       self.rwdKeyTimer.stop()
+                       self.rwdtimer = False
+               
+                       lookup = {
+                                       self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
+                                       self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
+                                       self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
+                                       self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
+                                       self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
+                                       self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
+                                       self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
+                                       self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
+                                       self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
+                                       self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
+                                       self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
+                                       self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
+                                       self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
+                                       self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
+                                       self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
+                               }
+                       self.setSeekState(lookup[self.seekstate]);
+               
+       def fwdTimerFire(self):
+               print "Display seek fwd"
+               self.fwdKeyTimer.stop()
+               self.fwdtimer = False
+               self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
+               
+       def fwdSeekTo(self, minutes):
+               print "Seek", minutes, "minutes forward"
+               if minutes != 0:
+                       service = self.session.nav.getCurrentService()
+                       if service is None:
+                               return
+                       seekable = service.seek()
+                       if seekable is None:
+                               return
+                       seekable.seekRelative(1, minutes * 60 * 90000)
+       
+       def rwdTimerFire(self):
+               print "rwdTimerFire"
+               self.rwdKeyTimer.stop()
+               self.rwdtimer = False
+               self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
+       
+       def rwdSeekTo(self, minutes):
+               print "rwdSeekTo"
+               self.fwdSeekTo(0 - minutes)
+       
+       def checkSkipShowHideLock(self):
+               wantlock = self.seekstate != self.SEEK_STATE_PLAY
+               
+               if self.lockedBecauseOfSkipping and not wantlock:
+                       self.unlockShow()
+                       self.lockedBecauseOfSkipping = False
+               
+               if wantlock and not self.lockedBecauseOfSkipping:
+                       self.lockShow()
+                       self.lockedBecauseOfSkipping = True
+
+       def __evEOF(self):
+               self.setSeekState(self.SEEK_STATE_PAUSE)
+       
+       def __evSOF(self):
+               self.setSeekState(self.SEEK_STATE_PLAY)
+
+from Screens.PVRState import PVRState
+
+class InfoBarPVRState:
+       def __init__(self):
+               self.onPlayStateChanged.append(self.__playStateChanged)
+               self.pvrStateDialog = self.session.instantiateDialog(PVRState)
+               self.onShow.append(self.__mayShow)
+               self.onHide.append(self.pvrStateDialog.hide)
+       
+       def __mayShow(self):
+               if self.seekstate != self.SEEK_STATE_PLAY:
+                       self.pvrStateDialog.show()
+
+       def __playStateChanged(self, state):
+               playstateString = state[3]
+               self.pvrStateDialog["state"].setText(playstateString)
+               self.__mayShow()
+
+class InfoBarShowMovies:
+
+       # i don't really like this class. 
+       # it calls a not further specified "movie list" on up/down/movieList,
+       # so this is not more than an action map
+       def __init__(self):
+               self["MovieListActions"] = HelpableActionMap(self, "InfobarMovieListActions", 
+                       {
+                               "movieList": (self.showMovies, "movie list"),
+                               "up": (self.showMovies, "movie list"),
+                               "down": (self.showMovies, "movie list")
+                       })
+
+# InfoBarTimeshift requires InfoBarSeek, instantiated BEFORE!
+
+# Hrmf.
+#
+# Timeshift works the following way:
+#                                         demux0   demux1                    "TimeshiftActions" "TimeshiftActivateActions" "SeekActions"
+# - normal playback                       TUNER    unused      PLAY               enable                disable              disable
+# - user presses "yellow" button.         TUNER    record      PAUSE              enable                disable              enable
+# - user presess pause again              FILE     record      PLAY               enable                disable              enable
+# - user fast forwards                    FILE     record      FF                 enable                disable              enable
+# - end of timeshift buffer reached       TUNER    record      PLAY               enable                enable               disable
+# - user backwards                        FILE     record      BACK  # !!         enable                disable              enable
+#
+
+# in other words:
+# - when a service is playing, pressing the "timeshiftStart" button ("yellow") enables recording ("enables timeshift"),
+# freezes the picture (to indicate timeshift), sets timeshiftMode ("activates timeshift")
+# now, the service becomes seekable, so "SeekActions" are enabled, "TimeshiftEnableActions" are disabled.
+# - the user can now PVR around
+# - if it hits the end, the service goes into live mode ("deactivates timeshift", it's of course still "enabled")
+# the service looses it's "seekable" state. It can still be paused, but just to activate timeshift right
+# after!
+# the seek actions will be disabled, but the timeshiftActivateActions will be enabled
+# - if the user rewinds, or press pause, timeshift will be activated again
+
+# note that a timeshift can be enabled ("recording") and
+# activated (currently time-shifting).
+
+class InfoBarTimeshift:
+       def __init__(self):
+               self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions", 
+                       {
+                               "timeshiftStart": (self.startTimeshift, "start timeshift"),  # the "yellow key"
+                               "timeshiftStop": (self.stopTimeshift, "stop timeshift")      # currently undefined :), probably 'TV'
+                       }, prio=1)
+               self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
+                       {
+                               "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "pause key"
+                               "timeshiftActivateEndAndPause": self.activateTimeshiftEndAndPause  # something like "backward key"
+                       })
+
+               self.timeshift_enabled = 0
+               self.timeshift_state = 0
+               self.ts_pause_timer = eTimer()
+               self.ts_pause_timer.timeout.get().append(self.pauseService)
+
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
+                       })
+       
+       def getTimeshift(self):
+               service = self.session.nav.getCurrentService()
+               return service.timeshift()
+
+       def startTimeshift(self):
+               # TODO: check for harddisk! (or do this in the interface? would make
+               # more sense... for example radio could be timeshifted in memory,
+               # and the decision can't be made here)
+               print "enable timeshift"
+               ts = self.getTimeshift()
+               if ts is None:
+                       self.session.open(MessageBox, _("Timeshift not possible!"), MessageBox.TYPE_ERROR)
+                       print "no ts interface"
+                       return
+               
+               if self.timeshift_enabled:
+                       print "hu, timeshift already enabled?"
+               else:
+                       if not ts.startTimeshift():
+                               self.timeshift_enabled = 1
+                               
+                               # PAUSE.
+                               self.setSeekState(self.SEEK_STATE_PAUSE)
+                               
+                               # enable the "TimeshiftEnableActions", which will override
+                               # the startTimeshift actions
+                               self.__seekableStatusChanged()
+                       else:
+                               print "timeshift failed"
+
+       # nyi
+       def stopTimeshift(self):
+               print "disable timeshift"
+               ts = self.getTimeshift()
+               if ts is None:
+                       return
+               ts.stopTimeshift()
+               self.timeshift_enabled = 0
+
+               # disable actions
+               self.__seekableStatusChanged()
+       
+       # activates timeshift, and seeks to (almost) the end
+       def activateTimeshiftEnd(self):
+               ts = self.getTimeshift()
+               
+               if ts is None:
+                       return
+               
+               if ts.isTimeshiftActive():
+                       print "!! activate timeshift called - but shouldn't this be a normal pause?"
+                       self.pauseService()
+               else:
+                       self.setSeekState(self.SEEK_STATE_PLAY)
+                       ts.activateTimeshift()
+       
+       # same as activateTimeshiftEnd, but pauses afterwards.
+       def activateTimeshiftEndAndPause(self):
+               state = self.seekstate
+               self.activateTimeshiftEnd()
+               
+               # well, this is "andPause", but it could be pressed from pause,
+               # when pausing on the (fake-)"live" picture, so an un-pause
+               # is perfectly ok.
+               
+               print "now, pauseService"
+               if state == self.SEEK_STATE_PLAY:
+                       print "is PLAYING, start pause timer"
+                       self.ts_pause_timer.start(200, 1)
+               else:
+                       print "unpause"
+                       self.unPauseService()
+       
+       def __seekableStatusChanged(self):
+               enabled = False
+               
+               print "self.isSeekable", self.isSeekable()
+               print "self.timeshift_enabled", self.timeshift_enabled
+               
+               # when this service is not seekable, but timeshift
+               # is enabled, this means we can activate
+               # the timeshift
+               if not self.isSeekable() and self.timeshift_enabled:
+                       enabled = True
+
+               print "timeshift activate:", enabled
+               self["TimeshiftActivateActions"].setEnabled(enabled)
+
+from RecordTimer import parseEvent
 
 class InfoBarInstantRecord:
        """Instant Record - handles the instantRecord action in order to 
 
 class InfoBarInstantRecord:
        """Instant Record - handles the instantRecord action in order to 
@@ -579,19 +897,35 @@ class InfoBarInstantRecord:
                        
        def startInstantRecording(self):
                serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
                        
        def startInstantRecording(self):
                serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
-                       
+               
                # try to get event info
                # try to get event info
-               epg = None
+               event = None
                try:
                        service = self.session.nav.getCurrentService()
                        info = service.info()
                        ev = info.getEvent(0)
                try:
                        service = self.session.nav.getCurrentService()
                        info = service.info()
                        ev = info.getEvent(0)
-                       epg = ev
+                       event = ev
                except:
                        pass
                
                except:
                        pass
                
+               if event is not None:
+                       data = parseEvent(event)
+                       begin = data[0]
+                       if begin < time.time():
+                               begin = time.time()
+                       
+                       end = data[1]
+                       if end < begin:
+                               end = begin
+                       
+                       end += 3600 * 10
+                       
+                       data = (begin, end, data[2], data[3], data[4])
+               else:
+                       data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
+               
                # fix me, description. 
                # fix me, description. 
-               self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600, serviceref, epg, "instant record")
+               self.recording = self.session.nav.recordWithTimer(serviceref, *data)
                self.recording.dontSave = True
                
                #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
                self.recording.dontSave = True
                
                #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
@@ -613,9 +947,9 @@ class InfoBarInstantRecord:
 
        def instantRecord(self):
                try:
 
        def instantRecord(self):
                try:
-                       stat = os.stat("/hdd/movies")
+                       stat = os.stat(resolveFilename(SCOPE_HDD))
                except:
                except:
-                       self.session.open(MessageBox, "No HDD found!")
+                       self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
                        return
        
                if self.isInstantRecordRunning():
                        return
        
                if self.isInstantRecordRunning():
@@ -661,17 +995,9 @@ class InfoBarSubserviceSelection:
 
 class InfoBarAdditionalInfo:
        def __init__(self):
 
 class InfoBarAdditionalInfo:
        def __init__(self):
-               self["DolbyActive"] = PixmapConditional()
-               # TODO: get the info from c++ somehow
-               self["DolbyActive"].setConnect(lambda: False)
-               
-               self["CryptActive"] = PixmapConditional()
-               # TODO: get the info from c++ somehow
-               self["CryptActive"].setConnect(lambda: False)
-               
-               self["FormatActive"] = PixmapConditional()
-               # TODO: get the info from c++ somehow
-               self["FormatActive"].setConnect(lambda: False)
+               self["DolbyActive"] = Pixmap()
+               self["CryptActive"] = Pixmap()
+               self["FormatActive"] = Pixmap()
                
                self["ButtonRed"] = PixmapConditional(withTimer = False)
                self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
                
                self["ButtonRed"] = PixmapConditional(withTimer = False)
                self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
@@ -679,18 +1005,80 @@ class InfoBarAdditionalInfo:
                self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
                self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
                self.onShown.append(self["ButtonRedText"].update)
                self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
                self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
                self.onShown.append(self["ButtonRedText"].update)
-                               
-               self["ButtonGreen"] = PixmapConditional()
-               self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
-               self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
-               self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
 
 
-               self["ButtonYellow"] = PixmapConditional()
+               self["ButtonGreen"] = Pixmap()
+               self["ButtonGreenText"] = Label(_("Subservices"))
+
+               self["ButtonYellow"] = PixmapConditional(withTimer = False)
                self["ButtonYellow"].setConnect(lambda: False)
 
                self["ButtonYellow"].setConnect(lambda: False)
 
-               self["ButtonBlue"] = PixmapConditional()
+               self["ButtonBlue"] = PixmapConditional(withTimer = False)
                self["ButtonBlue"].setConnect(lambda: False)
 
                self["ButtonBlue"].setConnect(lambda: False)
 
+               self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
+
+       def hideSubServiceIndication(self):
+               self["ButtonGreen"].hideWidget()
+               self["ButtonGreenText"].hide()
+
+       def showSubServiceIndication(self):
+               self["ButtonGreen"].showWidget()
+               self["ButtonGreenText"].show()
+
+       def checkFormat(self, service):
+               info = service.info()
+               if info is not None:
+                       aspect = info.getInfo(iServiceInformation.sAspect)
+                       if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
+                               self["FormatActive"].showWidget()
+                       else:
+                               self["FormatActive"].hideWidget()
+
+       def checkSubservices(self, service):
+               if service.subServices().getNumberOfSubservices() > 0:
+                       self.showSubServiceIndication()
+               else:
+                       self.hideSubServiceIndication()
+
+       def checkDolby(self, service):
+               # FIXME
+               dolby = False
+               audio = service.audioTracks()
+               if audio is not None:
+                       n = audio.getNumberOfTracks()
+                       for x in range(n):
+                               i = audio.getTrackInfo(x)
+                               description = i.getDescription();
+                               if description.find("AC3") != -1 or description.find("DTS") != -1:
+                                       dolby = True
+                                       break
+               if dolby:
+                       self["DolbyActive"].showWidget()
+               else:
+                       self["DolbyActive"].hideWidget()
+
+       def checkCrypted(self, service):
+               info = service.info()
+               if info is not None:
+                       if info.getInfo(iServiceInformation.sIsCrypted) > 0:
+                               self["CryptActive"].showWidget()
+                       else:
+                               self["CryptActive"].hideWidget()
+
+       def gotServiceEvent(self, ev):
+               service = self.session.nav.getCurrentService()
+               if ev == iPlayableService.evUpdatedEventInfo:
+                       self.checkSubservices(service)
+                       self.checkFormat(service)
+               elif ev == iPlayableService.evUpdatedInfo:
+                       self.checkCrypted(service)
+                       self.checkDolby(service)
+               elif ev == iPlayableService.evEnd:
+                       self.hideSubServiceIndication()
+                       self["CryptActive"].hideWidget()
+                       self["DolbyActive"].hideWidget()
+                       self["FormatActive"].hideWidget()
+
 class InfoBarNotifications:
        def __init__(self):
                self.onExecBegin.append(self.checkNotifications)
 class InfoBarNotifications:
        def __init__(self):
                self.onExecBegin.append(self.checkNotifications)
@@ -710,3 +1098,18 @@ class InfoBarNotifications:
                                self.session.openWithCallback(cb, *n[1:])
                        else:
                                self.session.open(*n[1:])
                                self.session.openWithCallback(cb, *n[1:])
                        else:
                                self.session.open(*n[1:])
+
+class InfoBarServiceNotifications:
+       def __init__(self):
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evEnd: self.serviceHasEnded
+                       })
+
+       def serviceHasEnded(self):
+               print "service end!"
+
+               try:
+                       self.setSeekState(self.SEEK_STATE_PLAY)
+               except:
+                       pass