store and restore pathes in channellist
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 85fab2c..7a2f985 100644 (file)
@@ -2,27 +2,28 @@ from Screen import Screen
 from Components.ActionMap import ActionMap, HelpableActionMap
 from Components.ActionMap import NumberActionMap
 from Components.Label import *
 from Components.ActionMap import ActionMap, HelpableActionMap
 from Components.ActionMap import NumberActionMap
 from Components.Label import *
+from Components.ProgressBar import *
 from Components.config import configfile, configsequencearg
 from Components.config import config, configElement, ConfigSubsection, configSequence
 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.EventView import EventView
 from Screens.Dish import Dish
 from Screens.Standby import Standby
 from Screens.EventView import EventView
+from Screens.MinuteInput import MinuteInput
 from Components.Harddisk import harddiskmanager
 
 from Tools import Notifications
 from Components.Harddisk import harddiskmanager
 
 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 *
@@ -30,67 +31,11 @@ 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)
@@ -118,7 +63,7 @@ class InfoBarShowHide:
                
                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)
 
        def delHideTimer(self):
                del self.hideTimer
 
        def delHideTimer(self):
                del self.hideTimer
@@ -128,8 +73,7 @@ class InfoBarShowHide:
                
        def show(self):
                self.state = self.STATE_SHOWN
                
        def show(self):
                self.state = self.STATE_SHOWN
-               self.hideTimer.stop()
-               self.hideTimer.start(5000)
+               self.hideTimer.start(5000, True)
 
        def doTimerHide(self):
                self.hideTimer.stop()
 
        def doTimerHide(self):
                self.hideTimer.stop()
@@ -166,7 +110,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:
@@ -198,7 +142,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"""
@@ -220,7 +164,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()
@@ -254,7 +198,12 @@ 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.instance.show()
+                       self.show()
+               else:
+                       self.session.openWithCallback(self.numberEntered, NumberZap, number)
 
        def numberEntered(self, retval):
 #              print self.servicelist
 
        def numberEntered(self, retval):
 #              print self.servicelist
@@ -285,17 +234,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 ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
                                                continue
                                        service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
                if not service is None:
                                        if not bouquet.valid(): #check end of list
                                                break
                                        if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
                                                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 
@@ -351,13 +303,79 @@ class InfoBarEPG:
        def __init__(self):
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        {
        def __init__(self):
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        {
-                               "showEPGList": (self.showEPGList, _("show EPG...")),
+                               "showEPGList": (self.showEPG, _("show EPG...")),
                        })
 
                        })
 
+       def showEPG(self):
+               if currentConfigSelectionElement(config.usage.epgtoggle) == "yes":
+                       self.openSingleServiceEPG()
+               else:
+                       self.showEPGList()
+
        def showEPGList(self):
        def showEPGList(self):
+               bouquets = self.servicelist.getBouquetList()
+               if bouquets is None:
+                       cnt = 0
+               else:
+                       cnt = len(bouquets)
+               if cnt > 1: # show bouquet list
+                       self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
+               elif cnt == 1: # add to only one existing bouquet
+                       self.openBouquetEPG(bouquets[0][1])
+               else: #no bouquets so we open single epg
+                       self.openSingleEPGSelector(self.session.nav.getCurrentlyPlayingServiceReference())
+
+       def bouquetEPGCallback(self, info):
+               if info:
+                       self.openSingleServiceEPG()
+       
+       def singleEPGCallback(self, info):
+               if info:
+                       self.showEPGList()
+                       
+       def openEventView(self):
+               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)
+                       if ptr:
+                               self.epglist.append(ptr)
+                       if len(self.epglist) > 0:
+                               self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
+               except:
+                       pass
+                       
+       def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
                ptr=eEPGCache.getInstance()
                if ptr.startTimeQuery(ref) != -1:
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
                ptr=eEPGCache.getInstance()
                if ptr.startTimeQuery(ref) != -1:
+                       self.session.openWithCallback(self.singleEPGCallback, EPGSelection, ref)
+               else: # try to show now/next
+                       print 'no epg for service', ref.toString()
+
+       
+       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.session.openWithCallback(self.bouquetEPGCallback, EPGSelection, services)
+
+       def openSingleEPGSelector(self, ref):
+               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()
                        self.session.open(EPGSelection, ref)
                else: # try to show now/next
                        print 'no epg for service', ref.toString()
@@ -376,13 +394,57 @@ class InfoBarEPG:
                        except:
                                pass
 
                        except:
                                pass
 
-       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]
                        self.epglist[1]=tmp
                        setEvent(self.epglist[0])
 
                if len(self.epglist) > 1:
                        tmp = self.epglist[0]
                        self.epglist[0]=self.epglist[1]
                        self.epglist[1]=tmp
                        setEvent(self.epglist[0])
 
+from math import log
+
+class InfoBarTuner:
+       """provides a snr/agc/ber display"""
+       def __init__(self):
+               self["snr"] = Label()
+               self["agc"] = Label()
+               self["ber"] = Label()
+               self["snr_percent"] = Label()
+               self["agc_percent"] = Label()
+               self["ber_count"] = Label()
+               self["snr_progress"] = ProgressBar()
+               self["agc_progress"] = ProgressBar()
+               self["ber_progress"] = ProgressBar()
+               self.timer = eTimer()
+               self.timer.timeout.get().append(self.updateTunerInfo)
+               self.timer.start(1000)
+
+       def calc(self,val):
+               if not val:
+                       return 0
+               if val < 2500:
+                       return (long)(log(val)/log(2))
+               return val*100/65535
+
+       def updateTunerInfo(self):
+               if self.instance.isVisible():
+                       service = self.session.nav.getCurrentService()
+                       snr=0
+                       agc=0
+                       ber=0
+                       if service is not None:
+                               feinfo = service.frontendStatusInfo()
+                               if feinfo is not None:
+                                       ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
+                                       snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
+                                       agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
+                       self["snr_percent"].setText("%d%%"%(snr))
+                       self["agc_percent"].setText("%d%%"%(agc))
+                       self["ber_count"].setText("%d"%(ber))
+                       self["snr_progress"].setValue(snr)
+                       self["agc_progress"].setValue(agc)
+                       self["ber_progress"].setValue(self.calc(ber))
+
 class InfoBarEvent:
        """provides a current/next event info display"""
        def __init__(self):
 class InfoBarEvent:
        """provides a current/next event info display"""
        def __init__(self):
@@ -395,29 +457,126 @@ 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:
-       """handles PVR specific actions like seeking, pause"""
+class InfoBarSeek:
+       """handles actions like seeking, pause"""
+       
+       # 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, 4, 0, 32)
+       SEEK_STATE_FF_64X = (0, 4, 0, 64)
+       SEEK_STATE_FF_128X = (0, 4, 0, 128)
+       
+       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_128X = (0, 0, 0, -128)
+       
+       SEEK_STATE_SM_HALF = (0, 0, 2, 0)
+       SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
+       SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
+       
        def __init__(self):
        def __init__(self):
-               self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
+               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"),
                        })
                        })
+
+               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.delSeekTimer)
+               
+               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)
+       
+       def up(self):
+               pass
+       
+       def down(self):
+               pass
+       
+       def delSeekTimer(self):
+               del self.seekTimer
+       
+       def seekTimerFired(self):
+               self.seekbase += self.skipmode * self.skipinterval
+               
+               # check if we bounced against the beginning of the file
+               if self.seekbase < 0:
+                       self.seekbase = 0;
+                       self.setSeekState(self.SEEK_STATE_PLAY)
+                       
+               self.doSeek(self.seekbase)
+
+       def setSeekState(self, state):
+               oldstate = self.seekstate
+               
+               self.seekstate = state
+
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       return
+               
+               pauseable = service.pause()
+               
+               for i in range(4):
+                       if oldstate[i] != self.seekstate[i]:
+                               (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
                
                
+       def setSkipMode(self, skipmode):
+               self.skipmode = skipmode
+               if skipmode == 0:
+                       self.seekTimer.stop()
+               else:
+                       self.seekTimer.start(500)
+               
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       return
+               
+               seekable = service.seek()
+               if seekable is None:
+                       return
+
+               if skipmode:
+                       seekable.setTrickmode(1)
+               else:
+                       seekable.setTrickmode(0)
+               
+               self.seekbase = seekable.getPlayPosition()[1] / 90
+       
        def pauseService(self):
        def pauseService(self):
-               self.session.nav.pause(1)
+               if (self.seekstate == self.SEEK_STATE_PAUSE):
+                       self.unPauseService()
+               else:
+                       self.setSeekState(self.SEEK_STATE_PAUSE);
                
        def unPauseService(self):
                
        def unPauseService(self):
-               self.session.nav.pause(0)
+               self.setSeekState(self.SEEK_STATE_PLAY);
        
        
-       def doSeek(self, dir, seektime):
+       def doSeek(self, seektime):
                service = self.session.nav.getCurrentService()
                if service is None:
                        return
                service = self.session.nav.getCurrentService()
                if service is None:
                        return
@@ -425,13 +584,144 @@ 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):
-               self.doSeek(+1, 60000)
-       
+               print "start fwd timer"
+               self.fwdtimer = True
+               self.fwdKeyTimer.start(500)
+
        def seekBack(self):
        def seekBack(self):
-               self.doSeek(-1, 60000)
+               print "start rewind timer"
+               self.rwdtimer = True
+               self.rwdKeyTimer.start(500)
+
+       def seekFwdUp(self):
+               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):
+               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):
+               self.rwdKeyTimer.stop()
+               self.rwdtimer = False
+               self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
+       
+       def rwdSeekTo(self, minutes):
+               self.fwdSeekTo(0 - minutes)
+
+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 moe 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")
+                       })
+
+class InfoBarTimeshift:
+       def __init__(self):
+               self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions", 
+                       {
+                               "timeshiftStart": (self.startTimeshift, "start timeshift "),
+                               "timeshiftStop": (self.stopTimeshift, "stop timeshift")
+                       })
+               self.tshack = 0
+       
+       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
+               print "ok, timeshift enabled"
+               if self.tshack == 0:
+                       ts.startTimeshift()
+                       self.tshack = 1
+               else:
+                       pauseable = self.session.nav.getCurrentService().pause()
+                       pauseable.pause() # switch to record
+
+       def stopTimeshift(self):
+               print "disable timeshift"
+               ts = self.getTimeshift()
+               if ts is None:
+                       return
+               ts.stopTimeshift()
+               self.tshack = 0
+               
+
+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 
@@ -453,19 +743,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())
@@ -487,9 +793,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():
@@ -535,17 +841,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)
@@ -553,18 +851,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 == pNavigation.evUpdatedEventInfo:
+                       self.checkSubservices(service)
+                       self.checkFormat(service)
+               elif ev == pNavigation.evUpdatedInfo:
+                       self.checkCrypted(service)
+                       self.checkDolby(service)
+               elif ev == pNavigation.evStopService:
+                       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)