fix notifications
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 0e186fffdd5c3560fe6bddd5eef744d3befb06c7..9e998d0571ebc272bdbac0037546967f070ef639 100644 (file)
@@ -1,28 +1,36 @@
-from Screen import Screen
+from ChannelSelection import ChannelSelection, BouquetSelector
+
 from Components.ActionMap import ActionMap, HelpableActionMap
 from Components.ActionMap import NumberActionMap
+from Components.BlinkingPixmap import BlinkingPixmapConditional
+from Components.Clock import Clock
+from Components.EventInfo import EventInfo, EventInfoProgress
+from Components.Harddisk import harddiskmanager
+from Components.Input import Input
 from Components.Label import *
-from Components.ProgressBar import *
-from Components.config import configfile, configsequencearg
-from Components.config import config, configElement, ConfigSubsection, configSequence
-from ChannelSelection import ChannelSelection, BouquetSelector
-
 from Components.Pixmap import Pixmap, PixmapConditional
-from Components.BlinkingPixmap import BlinkingPixmapConditional
+from Components.PluginComponent import plugins
+from Components.ProgressBar import *
+from Components.ServiceEventTracker import ServiceEventTracker
 from Components.ServiceName import ServiceName
-from Components.EventInfo import EventInfo, EventInfoProgress
+from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean, configSelection, configElement_nonSave, getConfigListEntry
+from Components.config import configfile, configsequencearg
+from Components.TimerList import TimerEntryComponent
+from Components.TunerInfo import TunerInfo
 
-from ServiceReference import ServiceReference
 from EpgSelection import EPGSelection
+from Plugins.Plugin import PluginDescriptor
 
-from Screens.MessageBox import MessageBox
+from Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
 from Screens.Dish import Dish
-from Screens.Standby import Standby
 from Screens.EventView import EventViewEPGSelect, EventViewSimple
+from Screens.InputBox import InputBox
+from Screens.MessageBox import MessageBox
 from Screens.MinuteInput import MinuteInput
-from Components.Harddisk import harddiskmanager
-
-from Components.ServiceEventTracker import ServiceEventTracker
+from Screens.TimerSelection import TimerSelection
+from Screens.PictureInPicture import PictureInPicture
+from ServiceReference import ServiceReference
 
 from Tools import Notifications
 from Tools.Directories import *
@@ -161,41 +169,6 @@ class NumberZap(Screen):
                self.Timer.timeout.get().append(self.keyOK)
                self.Timer.start(3000, True)
 
-class InfoBarPowerKey:
-       """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
-       
-       def __init__(self):
-               self.powerKeyTimer = eTimer()
-               self.powerKeyTimer.timeout.get().append(self.powertimer)
-               self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
-                       {
-                               "powerdown": self.powerdown,
-                               "powerup": self.powerup,
-                               "discreteStandby": (self.standby, "Go standby"),
-                               "discretePowerOff": (self.quit, "Go to deep standby"),
-                       })
-
-       def powertimer(self):   
-               print "PowerOff - Now!"
-               self.quit()
-       
-       def powerdown(self):
-               self.standbyblocked = 0
-               self.powerKeyTimer.start(3000, True)
-
-       def powerup(self):
-               self.powerKeyTimer.stop()
-               if self.standbyblocked == 0:
-                       self.standbyblocked = 1
-                       self.standby()
-
-       def standby(self):
-               self.session.open(Standby, self)
-
-       def quit(self):
-               # halt
-               quitMainloop(1)
-
 class InfoBarNumberZap:
        """ Handles an initial number for NumberZapping """
        def __init__(self):
@@ -265,12 +238,17 @@ class InfoBarNumberZap:
                        self.servicelist.setCurrentSelection(service) #select the service in servicelist
                        self.servicelist.zap()
 
+config.misc.initialchannelselection = configElementBoolean("config.misc.initialchannelselection", 1);
+
 class InfoBarChannelSelection:
        """ ChannelSelection - handles the channelSelection dialog and the initial 
        channelChange actions which open the channelSelection dialog """
        def __init__(self):
                #instantiate forever
                self.servicelist = self.session.instantiateDialog(ChannelSelection)
+               
+               if config.misc.initialchannelselection.value == 1:
+                       self.onShown.append(self.firstRun)
 
                self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
                        {
@@ -282,6 +260,12 @@ class InfoBarChannelSelection:
                                "historyNext": (self.historyNext, _("next channel in history"))
                        })
 
+       def firstRun(self):
+               self.onShown.remove(self.firstRun)
+               config.misc.initialchannelselection.value = 0
+               config.misc.initialchannelselection.save()
+               self.switchChannelDown()
+
        def historyBack(self):
                self.servicelist.historyBack()
 
@@ -358,6 +342,15 @@ class InfoBarSimpleEventView:
 class InfoBarEPG:
        """ EPG - Opens an EPG list when the showEPGList action fires """
        def __init__(self):
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
+                       })
+
+               self.is_now_next = False
+               self.dlg_stack = [ ]
+               self.bouquetSel = None
+               self.eventView = None
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
                        {
                                "showEventInfo": (self.openEventView, _("show EPG...")),
@@ -373,8 +366,7 @@ class InfoBarEPG:
                        self.servicelist.setCurrentSelection(service) #select the service in servicelist
                        self.servicelist.zap()
 
-       def openBouquetEPG(self, bouquet, withCallback=True):
-               ptr=eEPGCache.getInstance()
+       def getBouquetServices(self, bouquet):
                services = [ ]
                servicelist = eServiceCenter.getInstance().list(bouquet)
                if not servicelist is None:
@@ -385,16 +377,39 @@ class InfoBarEPG:
                                if service.flags: #ignore non playable services
                                        continue
                                services.append(ServiceReference(service))
+               return services
+
+       def openBouquetEPG(self, bouquet, withCallback=True):
+               services = self.getBouquetServices(bouquet)
                if len(services):
                        self.epg_bouquet = bouquet
                        if withCallback:
-                               self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
+                               self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
                        else:
-                               self.session.open(EPGSelection, services, self.zapToService)
+                               self.session.open(EPGSelection, services, self.zapToService, None, self.changeBouquetCB)
 
-       def closed(self, ret):
+       def changeBouquetCB(self, direction, epg):
+               if self.bouquetSel:
+                       if direction > 0:
+                               self.bouquetSel.down()
+                       else:
+                               self.bouquetSel.up()
+                       bouquet = self.bouquetSel.getCurrent()
+                       services = self.getBouquetServices(bouquet)
+                       if len(services):
+                               self.epg_bouquet = bouquet
+                               epg.setServices(services)
+
+       def closed(self, ret=False):
+               closedScreen = self.dlg_stack.pop()
+               if self.bouquetSel and closedScreen == self.bouquetSel:
+                       self.bouquetSel = None
+               elif self.eventView and closedScreen == self.eventView:
+                       self.eventView = None
                if ret:
-                       self.close(ret)
+                       dlgs=len(self.dlg_stack)
+                       if dlgs > 0:
+                               self.dlg_stack[dlgs-1].close(dlgs > 1)
 
        def openMultiServiceEPG(self, withCallback=True):
                bouquets = self.servicelist.getBouquetList()
@@ -404,38 +419,55 @@ class InfoBarEPG:
                        cnt = len(bouquets)
                if cnt > 1: # show bouquet list
                        if withCallback:
-                               self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
+                               self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
+                               self.dlg_stack.append(self.bouquetSel)
                        else:
-                               self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
+                               self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
                elif cnt == 1: 
                        self.openBouquetEPG(bouquets[0][1], withCallback)
 
        def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
-               ptr=eEPGCache.getInstance()
-               self.session.openWithCallback(self.closed, EPGSelection, ref)
+               self.session.open(EPGSelection, ref)
 
-       def openEventView(self):
+       def openSimilarList(self, eventid, refstr):
+               self.session.open(EPGSelection, refstr, None, eventid)
+
+       def getNowNext(self):
                self.epglist = [ ]
                service = self.session.nav.getCurrentService()
-               ref = self.session.nav.getCurrentlyPlayingServiceReference()
-               info = service.info()
-               ptr=info.getEvent(0)
+               info = service and service.info()
+               ptr = info and info.getEvent(0)
                if ptr:
                        self.epglist.append(ptr)
-               ptr=info.getEvent(1)
+               ptr = info and info.getEvent(1)
                if ptr:
                        self.epglist.append(ptr)
+
+       def __evEventInfoChanged(self):
+               if self.is_now_next and len(self.dlg_stack) == 1:
+                       self.getNowNext()
+                       assert self.eventView
+                       if len(self.epglist):
+                               self.eventView.setEvent(self.epglist[0])
+
+       def openEventView(self):
+               ref = self.session.nav.getCurrentlyPlayingServiceReference()
+               self.getNowNext()
                if len(self.epglist) == 0:
+                       self.is_now_next = False
                        epg = eEPGCache.getInstance()
-                       ptr = epg.lookupEventTime(ref, -1)
+                       ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
                        if ptr:
                                self.epglist.append(ptr)
                                ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
                                if ptr:
                                        self.epglist.append(ptr)
+               else:
+                       self.is_now_next = True
                if len(self.epglist) > 0:
-                       self.session.open(EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG)
+                       self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
+                       self.dlg_stack.append(self.eventView)
                else:
                        print "no epg for the service avail.. so we show multiepg instead of eventinfo"
                        self.openMultiServiceEPG(False)
@@ -447,49 +479,30 @@ class InfoBarEPG:
                        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["snr_percent"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
+               self["agc_percent"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, servicefkt = self.session.nav.getCurrentService)
+               self["ber_count"] = TunerInfo(TunerInfo.BER_VALUE, servicefkt = self.session.nav.getCurrentService)
+               self["snr_progress"] = TunerInfo(TunerInfo.SNR_BAR, servicefkt = self.session.nav.getCurrentService)
+               self["agc_progress"] = TunerInfo(TunerInfo.AGC_BAR, servicefkt = self.session.nav.getCurrentService)
+               self["ber_progress"] = TunerInfo(TunerInfo.BER_BAR, servicefkt = self.session.nav.getCurrentService)
                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))
+                       self["snr_percent"].update()
+                       self["agc_percent"].update()
+                       self["ber_count"].update()
+                       self["snr_progress"].update()
+                       self["agc_progress"].update()
+                       self["ber_progress"].update()
 
 class InfoBarEvent:
        """provides a current/next event info display"""
@@ -540,7 +553,21 @@ class InfoBarSeek:
                                iPlayableService.evEOF: self.__evEOF,
                                iPlayableService.evSOF: self.__evSOF,
                        })
-               self["SeekActions"] = HelpableActionMap(self, "InfobarSeekActions", 
+
+               class InfoBarSeekActionMap(HelpableActionMap):
+                       def __init__(self, screen, *args, **kwargs):
+                               HelpableActionMap.__init__(self, screen, *args, **kwargs)
+                               self.screen = screen
+                               
+                       def action(self, contexts, action):
+                               if action[:5] == "seek:":
+                                       time = int(action[5:])
+                                       self.screen.seekRelative(time * 90000)
+                                       return 1
+                               else:
+                                       return HelpableActionMap.action(self, contexts, action)
+
+               self["SeekActions"] = InfoBarSeekActionMap(self, "InfobarSeekActions", 
                        {
                                "pauseService": (self.pauseService, "pause"),
                                "unPauseService": (self.unPauseService, "continue"),
@@ -582,7 +609,7 @@ class InfoBarSeek:
        def getSeek(self):
                service = self.session.nav.getCurrentService()
                if service is None:
-                       return False
+                       return None
 
                seek = service.seek()
 
@@ -638,7 +665,7 @@ class InfoBarSeek:
                self.checkSkipShowHideLock()
 
                return True
-               
+
        def pauseService(self):
                if self.seekstate == self.SEEK_STATE_PAUSE:
                        print "pause, but in fact unpause"
@@ -730,6 +757,11 @@ class InfoBarSeek:
                                self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
                        }
                self.setSeekState(lookup[self.seekstate])
+               
+               if self.seekstate == self.SEEK_STATE_PAUSE:
+                       seekable = self.getSeek()
+                       if seekable is not None:
+                               seekable.seekRelative(-1, 3)
 
        def fwdTimerFire(self):
                print "Display seek fwd"
@@ -781,19 +813,19 @@ class InfoBarSeek:
        def seekRelative(self, diff):
                seekable = self.getSeek()
                if seekable is not None:
-                       seekable.seekRelative(0, diff)
+                       seekable.seekRelative(1, diff)
 
-from Screens.PVRState import PVRState
+from Screens.PVRState import PVRState, TimeshiftState
 
 class InfoBarPVRState:
-       def __init__(self):
+       def __init__(self, screen=PVRState):
                self.onPlayStateChanged.append(self.__playStateChanged)
-               self.pvrStateDialog = self.session.instantiateDialog(PVRState)
+               self.pvrStateDialog = self.session.instantiateDialog(screen)
                self.onShow.append(self.__mayShow)
                self.onHide.append(self.pvrStateDialog.hide)
        
        def __mayShow(self):
-               if self.seekstate != self.SEEK_STATE_PLAY:
+               if self.seekstate != self.SEEK_STATE_PLAY and self.execing:
                        self.pvrStateDialog.show()
 
        def __playStateChanged(self, state):
@@ -801,6 +833,11 @@ class InfoBarPVRState:
                self.pvrStateDialog["state"].setText(playstateString)
                self.__mayShow()
 
+class InfoBarTimeshiftState(InfoBarPVRState):
+       def __init__(self):
+               InfoBarPVRState.__init__(self, screen=TimeshiftState)
+
+
 class InfoBarShowMovies:
 
        # i don't really like this class. 
@@ -862,12 +899,13 @@ class InfoBarTimeshift:
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
+                               iPlayableService.evStart: self.__serviceStarted,
                                iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
                        })
        
        def getTimeshift(self):
                service = self.session.nav.getCurrentService()
-               return service.timeshift()
+               return service and service.timeshift()
 
        def startTimeshift(self):
                print "enable timeshift"
@@ -881,7 +919,9 @@ class InfoBarTimeshift:
                        print "hu, timeshift already enabled?"
                else:
                        if not ts.startTimeshift():
+                               import time
                                self.timeshift_enabled = 1
+                               self.pvrStateDialog["timeshift"].setRelative(time.time())
                                
                                # PAUSE.
                                self.setSeekState(self.SEEK_STATE_PAUSE)
@@ -962,6 +1002,60 @@ class InfoBarTimeshift:
                print "timeshift activate:", enabled
                self["TimeshiftActivateActions"].setEnabled(enabled)
 
+       def __serviceStarted(self):
+               self.timeshift_enabled = False
+               self.__seekableStatusChanged()
+
+from Screens.PiPSetup import PiPSetup
+
+class InfoBarExtensions:
+       def __init__(self):
+               self.pipshown = False
+               
+               self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
+                       {
+                               "extensions": (self.extensions, "Extensions..."),
+                       })
+
+       PIPON = 0
+       PIPOFF = 1
+       MOVEPIP = 2
+       PIPSWAP = 3
+
+       def extensions(self):
+               list = []
+               if self.pipshown == False:
+                       list.append((_("Activate Picture in Picture"), self.PIPON))
+               elif self.pipshown == True:
+                       list.append((_("Disable Picture in Picture"), self.PIPOFF))
+                       list.append((_("Move Picture in Picture"), self.MOVEPIP))
+                       list.append((_("Swap services"), self.PIPSWAP))
+               self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list)
+
+       def extensionCallback(self, answer):
+               if answer is not None:
+                       if answer[1] == self.PIPON:
+                               self.pip = self.session.instantiateDialog(PictureInPicture)
+                               
+                               newservice = self.session.nav.getCurrentlyPlayingServiceReference()
+                               
+                               if self.pip.playService(newservice):
+                                       self.pipshown = True
+                               else:
+                                       self.pipshown = False
+                                       del self.pip
+                               self.session.nav.playService(newservice)
+                       elif answer[1] == self.PIPOFF:
+                               del self.pip
+                               self.pipshown = False
+                       elif answer[1] == self.PIPSWAP:
+                               swapservice = self.pip.getCurrentService()
+                               self.pip.playService(self.session.nav.getCurrentlyPlayingServiceReference())
+                               self.session.nav.playService(swapservice)
+                               
+                       elif answer[1] == self.MOVEPIP:
+                               self.session.open(PiPSetup, pip = self.pip)
+
 from RecordTimer import parseEvent
 
 class InfoBarInstantRecord:
@@ -972,16 +1066,17 @@ class InfoBarInstantRecord:
                        {
                                "instantRecord": (self.instantRecord, "Instant Record..."),
                        })
-               self.recording = None
+               self.recording = []
                self["BlinkingPoint"] = BlinkingPixmapConditional()
                self["BlinkingPoint"].hide()
                self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
 
-       def stopCurrentRecording(self): 
-               self.session.nav.RecordTimer.removeEntry(self.recording)
-               self.recording = None
-
-       def startInstantRecording(self):
+       def stopCurrentRecording(self, entry = -1):     
+               if entry is not None and entry != -1:
+                       self.session.nav.RecordTimer.removeEntry(self.recording[entry])
+                       self.recording.remove(self.recording[entry])
+                       
+       def startInstantRecording(self, limitEvent = False):
                serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
                
                # try to get event info
@@ -997,34 +1092,83 @@ class InfoBarInstantRecord:
                except:
                        pass
 
+               begin = time.time()
+               end = time.time() + 3600 * 10
+               name = "instant record"
+               description = ""
+               eventid = None
+               
                if event is not None:
-                       data = parseEvent(event)
-                       begin = time.time()
-                       end = begin + 3600 * 10
-                       data = (begin, end, data[2], data[3], data[4])
+                       curEvent = parseEvent(event)
+                       name = curEvent[2]
+                       description = curEvent[3]
+                       eventid = curEvent[4]
+                       if limitEvent:
+                               end = curEvent[1]
                else:
-                       data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
+                       if limitEvent:
+                               self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
+                               
+               data = (begin, end, name, description, eventid)
                
-               # fix me, description. 
-               self.recording = self.session.nav.recordWithTimer(serviceref, *data)
-               self.recording.dontSave = True
+               recording = self.session.nav.recordWithTimer(serviceref, *data)
+               recording.dontSave = True
+               self.recording.append(recording)
                
                #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
                
        def isInstantRecordRunning(self):
-               if self.recording != None:
-                       if self.recording.isRunning():
-                               return True
+               print "self.recording:", self.recording
+               if len(self.recording) > 0:
+                       for x in self.recording:
+                               if x.isRunning():
+                                       return True
                return False
 
        def recordQuestionCallback(self, answer):
-               if answer == False:
-                       return
+               print "pre:\n", self.recording
                
-               if self.isInstantRecordRunning():
-                       self.stopCurrentRecording()
-               else:
-                       self.startInstantRecording()
+               if answer is None or answer[1] == "no":
+                       return
+               list = []
+               recording = self.recording[:]
+               for x in recording:
+                       if not x in self.session.nav.RecordTimer.timer_list:
+                               self.recording.remove(x)
+                       elif x.dontSave and x.isRunning():
+                               list.append(TimerEntryComponent(x, False))              
+
+               if answer[1] == "changeduration":
+                       if len(self.recording) == 1:
+                               self.changeDuration(0)
+                       else:
+                               self.session.openWithCallback(self.changeDuration, TimerSelection, list)
+               elif answer[1] == "stop":
+                       if len(self.recording) == 1:
+                               self.stopCurrentRecording(0)
+                       else:
+                               self.session.openWithCallback(self.stopCurrentRecording, TimerSelection, list)
+               if answer[1] == "indefinitely" or answer[1] == "manualduration" or answer[1] == "event":
+                       limitEvent = False
+                       if answer[1] == "event":
+                               limitEvent = True
+                       if answer[1] == "manualduration":
+                               self.selectedEntry = len(self.recording)
+                               self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
+                       self.startInstantRecording(limitEvent = limitEvent)
+                       
+               print "after:\n", self.recording
+
+       def changeDuration(self, entry):
+               if entry is not None:
+                       self.selectedEntry = entry
+                       self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
+
+       def inputCallback(self, value):
+               if value is not None:
+                       print "stopping recording after", int(value), "minutes."
+                       self.recording[self.selectedEntry].end = time.time() + 60 * int(value)
+                       self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
 
        def instantRecord(self):
                try:
@@ -1034,11 +1178,11 @@ class InfoBarInstantRecord:
                        return
        
                if self.isInstantRecordRunning():
-                       self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
+                       self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("A recording is currently running.\nWhat do you want to do?"), list=[(_("stop recording"), "stop"), (_("change recording (duration)"), "changeduration"), (_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"), (_("do nothing"), "no")])
                else:
-                       self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
+                       self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Start recording?"), list=[(_("add recording (indefinitely)"), "indefinitely"), (_("add recording (stop after current event)"), "event"), (_("add recording (enter recording duration)"), "manualduration"),(_("don't record"), "no")])
 
-from Screens.AudioSelection import AudioSelection
+from Tools.ISO639 import LanguageCodes
 
 class InfoBarAudioSelection:
        def __init__(self):
@@ -1050,29 +1194,123 @@ class InfoBarAudioSelection:
        def audioSelection(self):
                service = self.session.nav.getCurrentService()
                audio = service.audioTracks()
+               self.audioTracks = audio
                n = audio.getNumberOfTracks()
                if n > 0:
-                       self.session.open(AudioSelection, audio)
+#                      self.audioChannel = service.audioChannel()
+#                      config.audio.audiochannel = configElement_nonSave("config.audio.audiochannel", configSelection, self.audioChannel.getCurrentChannel(), (("left", _("Left  >")), ("stereo", _("<  Stereo  >")), ("right", _("<  Right"))))
+                       tlist = []
+                       for x in range(n):
+                               i = audio.getTrackInfo(x)
+                               language = i.getLanguage()
+                               description = i.getDescription();
+       
+                               if len(language) == 3:
+                                       if language in LanguageCodes:
+                                               language = LanguageCodes[language][0]
+       
+                               if len(description):
+                                       description += " (" + language + ")"
+                               else:
+                                       description = language
+       
+                               tlist.append((description, x))
+                       
+                       selectedAudio = tlist[0][1]
+                       tlist.sort(lambda x,y : cmp(x[0], y[0]))
+
+#                      tlist.insert(0, getConfigListEntry(_("Audio Channel"), config.audio.audiochannel))
+
+                       selection = 0
+                       for x in tlist:
+                               if x[1] != selectedAudio:
+                                       selection += 1
+                               else:
+                                       break
+                       
+                       self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection)
+               else:
+                       del self.audioTracks
 
-from Screens.SubserviceSelection import SubserviceSelection
+       def audioSelected(self, audio):
+               if audio is not None:
+                       self.audioTracks.selectTrack(audio[1])
+               del self.audioTracks
+#              del self.audioChannel
+#              del config.audio.audiochannel
 
 class InfoBarSubserviceSelection:
        def __init__(self):
                self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
                        {
-                               "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
+                               "subserviceSelection": (self.subserviceSelection, _("Subservice list...")),
                        })
 
+               self["SubserviceQuickzapAction"] = HelpableActionMap(self, "InfobarSubserviceQuickzapActions",
+                       {
+                               "nextSubservice": (self.nextSubservice, _("Switch to next subservice")),
+                               "prevSubservice": (self.prevSubservice, _("Switch to previous subservice"))
+                       }, -1)
+               self["SubserviceQuickzapAction"].setEnabled(False)
+
+               self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
+
+       def checkSubservicesAvail(self, ev):
+               if ev == iPlayableService.evUpdatedEventInfo:
+                       service = self.session.nav.getCurrentService()
+                       subservices = service.subServices()
+                       if subservices.getNumberOfSubservices() == 0:
+                               self["SubserviceQuickzapAction"].setEnabled(False)
+
+       def nextSubservice(self):
+               self.changeSubservice(+1)
+
+       def prevSubservice(self):
+               self.changeSubservice(-1)
+
+       def changeSubservice(self, direction):
+               service = self.session.nav.getCurrentService()
+               subservices = service.subServices()
+               n = subservices.getNumberOfSubservices()
+               if n > 0:
+                       selection = -1
+                       ref = self.session.nav.getCurrentlyPlayingServiceReference()
+                       for x in range(n):
+                               if subservices.getSubservice(x).toString() == ref.toString():
+                                       selection = x
+                       if selection != -1:
+                               selection += direction
+                               if selection >= n:
+                                       selection=0
+                               elif selection < 0:
+                                       selection=n-1
+                               newservice = subservices.getSubservice(selection)
+                               if newservice.valid():
+                                       del subservices
+                                       del service
+                                       self.session.nav.playService(newservice)
+
        def subserviceSelection(self):
                service = self.session.nav.getCurrentService()
                subservices = service.subServices()
+               
                n = subservices.getNumberOfSubservices()
+               selection = 0
                if n > 0:
-                       self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
+                       ref = self.session.nav.getCurrentlyPlayingServiceReference()
+                       tlist = []
+                       for x in range(n):
+                               i = subservices.getSubservice(x)
+                               if i.toString() == ref.toString():
+                                       selection = x
+                               tlist.append((i.getName(), i))
+
+                       self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection)
 
        def subserviceSelected(self, service):
                if not service is None:
-                       self.session.nav.playService(service)
+                       self["SubserviceQuickzapAction"].setEnabled(True)
+                       self.session.nav.playService(service[1])
 
 class InfoBarAdditionalInfo:
        def __init__(self):
@@ -1098,9 +1336,9 @@ class InfoBarAdditionalInfo:
                self.onLayoutFinish.append(self["ButtonYellowText"].update)
 
                self["ButtonBlue"] = PixmapConditional(withTimer = False)
-               self["ButtonBlue"].setConnect(lambda: False)
+               self["ButtonBlue"].setConnect(lambda: True)
                self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
-               self["ButtonBlueText"].setConnect(lambda: False)
+               self["ButtonBlueText"].setConnect(lambda: True)
                self.onLayoutFinish.append(self["ButtonBlue"].update)
                self.onLayoutFinish.append(self["ButtonBlueText"].update)
 
@@ -1172,6 +1410,10 @@ class InfoBarNotifications:
        def __init__(self):
                self.onExecBegin.append(self.checkNotifications)
                Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
+               self.onClose.append(self.__removeNotification)
+       
+       def __removeNotification(self):
+               Notifications.notificationAdded.remove(self.checkNotificationsIfExecing)
        
        def checkNotificationsIfExecing(self):
                if self.execing:
@@ -1181,12 +1423,11 @@ class InfoBarNotifications:
                if len(Notifications.notifications):
                        n = Notifications.notifications[0]
                        Notifications.notifications = Notifications.notifications[1:]
-                       print "open",n
                        cb = n[0]
                        if cb is not None:
-                               self.session.openWithCallback(cb, *n[1:])
+                               self.session.openWithCallback(cb, n[1], *n[2], **n[3])
                        else:
-                               self.session.open(*n[1:])
+                               self.session.open(n[1], *n[2], **n[3])
 
 class InfoBarServiceNotifications:
        def __init__(self):
@@ -1232,7 +1473,7 @@ class InfoBarCueSheetSupport:
                        return None
                return service.seek()
 
-       def __getCurrentPosition(self):
+       def cueGetCurrentPosition(self):
                seek = self.__getSeekable()
                if seek is None:
                        return None
@@ -1242,7 +1483,7 @@ class InfoBarCueSheetSupport:
                return long(r[1])
 
        def jumpPreviousNextMark(self, cmp, alternative=None):
-               current_pos = self.__getCurrentPosition()
+               current_pos = self.cueGetCurrentPosition()
                if current_pos is None:
                        return
                mark = self.getNearestCutPoint(current_pos, cmp=cmp)
@@ -1274,8 +1515,8 @@ class InfoBarCueSheetSupport:
                                nearest = cp
                return nearest
 
-       def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000):
-               current_pos = self.__getCurrentPosition()
+       def toggleMark(self, onlyremove=False, onlyadd=False, tolerance=5*90000, onlyreturn=False):
+               current_pos = self.cueGetCurrentPosition()
                if current_pos is None:
                        print "not seekable"
                        return
@@ -1283,10 +1524,15 @@ class InfoBarCueSheetSupport:
                nearest_cutpoint = self.getNearestCutPoint(current_pos)
                
                if nearest_cutpoint is not None and abs(nearest_cutpoint[0] - current_pos) < tolerance:
+                       if onlyreturn:
+                               return nearest_cutpoint
                        if not onlyadd:
                                self.removeMark(nearest_cutpoint)
-               elif not onlyremove:
+               elif not onlyremove and not onlyreturn:
                        self.addMark((current_pos, self.CUT_TYPE_MARK))
+               
+               if onlyreturn:
+                       return None
 
        def addMark(self, point):
                bisect.insort(self.cut_list, point)
@@ -1317,3 +1563,40 @@ class InfoBarCueSheetSupport:
                        print "upload failed, no cuesheet interface"
                        return
                self.cut_list = cue.getCutList()
+
+class InfoBarSummary(Screen):
+       skin = """
+       <screen position="0,0" size="132,64">
+               <widget name="Clock" position="50,46" size="82,18" font="Regular;16" />
+               <widget name="CurrentService" position="0,4" size="132,42" font="Regular;18" />
+       </screen>"""
+
+       def __init__(self, session, parent):
+               Screen.__init__(self, session)
+               self["CurrentService"] = ServiceName(self.session.nav)
+               self["Clock"] = Clock()
+
+class InfoBarSummarySupport:
+       def __init__(self):
+               pass
+       
+       def createSummary(self):
+               return InfoBarSummary
+
+class InfoBarTeletextPlugin:
+       def __init__(self):
+               self.teletext_plugin = None
+               
+               for p in plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT):
+                       self.teletext_plugin = p
+               
+               if self.teletext_plugin is not None:
+                       self["TeletextActions"] = HelpableActionMap(self, "InfobarTeletextActions",
+                               {
+                                       "startTeletext": (self.startTeletext, "View teletext...")
+                               })
+               else:
+                       print "no teletext plugin found!"
+
+       def startTeletext(self):
+               self.teletext_plugin(session=self.session, service=self.session.nav.getCurrentService())