add icelandic language
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 556e76804845110b97048768f310e45b10ac8edc..8006520f41befb9bcb80c8979b846cb61456837f 100644 (file)
@@ -1,28 +1,33 @@
-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
+from Components.config import configfile, configsequencearg
 
-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
+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.Standby import Standby
+from ServiceReference import ServiceReference
 
 from Tools import Notifications
 from Tools.Directories import *
@@ -32,6 +37,7 @@ from enigma import *
 
 import time
 import os
+import bisect
 
 from Components.config import config, currentConfigSelectionElement
 
@@ -41,7 +47,7 @@ from Menu import MainMenu, mdom
 class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
-               self.onShown.append(self.dishDialog.show)
+               self.onLayoutFinish.append(self.dishDialog.show)
 
 class InfoBarShowHide:
        """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
@@ -264,21 +270,40 @@ 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",
                        {
                                "switchChannelUp": self.switchChannelUp,
                                "switchChannelDown": self.switchChannelDown,
-                               "zapUp": (self.zapUp, _("next channel")),
-                               "zapDown": (self.zapDown, _("previous channel")),
+                               "zapUp": (self.zapUp, _("previous channel")),
+                               "zapDown": (self.zapDown, _("next channel")),
+                               "historyBack": (self.historyBack, _("previous channel in history")),
+                               "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()
+
+       def historyNext(self):
+               self.servicelist.historyNext()
+
        def switchChannelUp(self):
                self.servicelist.moveUp()
                self.session.execDialog(self.servicelist)
@@ -317,6 +342,35 @@ class InfoBarMenu:
                assert menu.tagName == "menu", "root element in menu must be 'menu'!"
                self.session.open(MainMenu, menu, menu.childNodes)
 
+class InfoBarSimpleEventView:
+       """ Opens the Eventview for now/next """
+       def __init__(self):
+               self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
+                       {
+                               "showEventInfo": (self.openEventView, _("show event details")),
+                       })
+
+       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:
+                       self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
+
+       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])
+
 class InfoBarEPG:
        """ EPG - Opens an EPG list when the showEPGList action fires """
        def __init__(self):
@@ -335,7 +389,7 @@ class InfoBarEPG:
                        self.servicelist.setCurrentSelection(service) #select the service in servicelist
                        self.servicelist.zap()
 
-       def openBouquetEPG(self, bouquet):
+       def openBouquetEPG(self, bouquet, withCallback=True):
                ptr=eEPGCache.getInstance()
                services = [ ]
                servicelist = eServiceCenter.getInstance().list(bouquet)
@@ -349,22 +403,28 @@ class InfoBarEPG:
                                services.append(ServiceReference(service))
                if len(services):
                        self.epg_bouquet = bouquet
-                       self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
+                       if withCallback:
+                               self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService)
+                       else:
+                               self.session.open(EPGSelection, services, self.zapToService)
 
        def closed(self, ret):
                if ret:
                        self.close(ret)
 
-       def openMultiServiceEPG(self):
+       def openMultiServiceEPG(self, withCallback=True):
                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)
+                       if withCallback:
+                               self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG)
+                       else:
+                               self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
                elif cnt == 1: 
-                       self.openBouquetEPG(bouquets[0][1])
+                       self.openBouquetEPG(bouquets[0][1], withCallback)
 
        def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
@@ -394,7 +454,7 @@ class InfoBarEPG:
                        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()
+                       self.openMultiServiceEPG(False)
 
        def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
                if len(self.epglist) > 1:
@@ -456,7 +516,7 @@ class InfoBarEvent:
                self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
                self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
 
-               self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
+               self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Remaining)
                self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
 
                self["Now_ProgressBar"] = EventInfoProgress(self.session.nav, EventInfo.Now)
@@ -478,7 +538,7 @@ class InfoBarSeek:
        SEEK_STATE_FF_64X = (0, 64, 0, ">> 64x")
        SEEK_STATE_FF_128X = (0, 128, 0, ">> 128x")
        
-       SEEK_STATE_BACK_4X = (0, -4, 0, "<< 4x")
+       SEEK_STATE_BACK_16X = (0, -16, 0, "<< 16x")
        SEEK_STATE_BACK_32X = (0, -32, 0, "<< 32x")
        SEEK_STATE_BACK_64X = (0, -64, 0, "<< 64x")
        SEEK_STATE_BACK_128X = (0, -128, 0, "<< 128x")
@@ -496,15 +556,31 @@ 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"),
                                
                                "seekFwd": (self.seekFwd, "skip forward"),
-                               "seekFwdUp": (self.seekFwdUp, "skip forward"),
+                               "seekFwdDown": self.seekFwdDown,
+                               "seekFwdUp": self.seekFwdUp,
                                "seekBack": (self.seekBack, "skip backward"),
-                               "seekBackUp": (self.seekBackUp, "skip backward"),
+                               "seekBackDown": self.seekBackDown,
+                               "seekBackUp": self.seekBackUp,
                        }, prio=-1)
                        # give them a little more priority to win over color buttons
 
@@ -621,65 +697,75 @@ class InfoBarSeek:
                
                seekable.seekTo(90 * seektime)
 
-       def seekFwd(self):
+       def seekFwdDown(self):
                print "start fwd timer"
                self.fwdtimer = True
-               self.fwdKeyTimer.start(500)
+               self.fwdKeyTimer.start(1000)
 
-       def seekBack(self):
+       def seekBackDown(self):
                print "start rewind timer"
                self.rwdtimer = True
-               self.rwdKeyTimer.start(500)
+               self.rwdKeyTimer.start(1000)
 
        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]);
+                       self.seekFwd()
+
+       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_128X,
+                               self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
+                               self.SEEK_STATE_BACK_16X: self.SEEK_STATE_PLAY,
+                               self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_16X,
+                               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
+                       self.seekBack()
                
-                       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 seekBack(self):
+               lookup = {
+                               self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_16X,
+                               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_16X: 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])
                
+               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"
                self.fwdKeyTimer.stop()
@@ -715,7 +801,13 @@ class InfoBarSeek:
                        self.lockedBecauseOfSkipping = True
 
        def __evEOF(self):
-               self.setSeekState(self.SEEK_STATE_PAUSE)
+               if self.seekstate != self.SEEK_STATE_PLAY:
+                       self.setSeekState(self.SEEK_STATE_PAUSE)
+                       # HACK
+                       #self.getSeek().seekRelative(1, -90000)
+                       self.setSeekState(self.SEEK_STATE_PLAY)
+               else:
+                       self.setSeekState(self.SEEK_STATE_PAUSE)
        
        def __evSOF(self):
                self.setSeekState(self.SEEK_STATE_PLAY)
@@ -724,19 +816,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):
@@ -744,6 +836,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. 
@@ -805,6 +902,7 @@ class InfoBarTimeshift:
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
+                               iPlayableService.evStart: self.__serviceStarted,
                                iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
                        })
        
@@ -824,7 +922,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)
@@ -836,10 +936,22 @@ class InfoBarTimeshift:
                                print "timeshift failed"
 
        def stopTimeshift(self):
+               if not self.timeshift_enabled:
+                       return
                print "disable timeshift"
                ts = self.getTimeshift()
                if ts is None:
                        return
+               self.session.openWithCallback(self.stopTimeshiftConfirmed, MessageBox, _("Stop Timeshift?"), MessageBox.TYPE_YESNO)
+
+       def stopTimeshiftConfirmed(self, confirmed):
+               if not confirmed:
+                       return
+
+               ts = self.getTimeshift()
+               if ts is None:
+                       return
+
                ts.stopTimeshift()
                self.timeshift_enabled = 0
 
@@ -893,6 +1005,10 @@ class InfoBarTimeshift:
                print "timeshift activate:", enabled
                self["TimeshiftActivateActions"].setEnabled(enabled)
 
+       def __serviceStarted(self):
+               self.timeshift_enabled = False
+               self.__seekableStatusChanged()
+
 from RecordTimer import parseEvent
 
 class InfoBarInstantRecord:
@@ -904,38 +1020,49 @@ class InfoBarInstantRecord:
                                "instantRecord": (self.instantRecord, "Instant Record..."),
                        })
                self.recording = None
-               
                self["BlinkingPoint"] = BlinkingPixmapConditional()
-               self.onShown.append(self["BlinkingPoint"].hideWidget)
+               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 startInstantRecording(self, limitEvent = False):
                serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
                
                # try to get event info
                event = None
                try:
                        service = self.session.nav.getCurrentService()
-                       info = service.info()
-                       ev = info.getEvent(0)
-                       event = ev
+                       epg = eEPGCache.getInstance()
+                       event = epg.lookupEventTime(serviceref, -1, 0)
+                       if event is None:
+                               info = service.info()
+                               ev = info.getEvent(0)
+                               event = ev
                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
                
@@ -948,13 +1075,28 @@ class InfoBarInstantRecord:
                return False
 
        def recordQuestionCallback(self, answer):
-               if answer == False:
+               if answer is None or answer[1] == "no":
                        return
                
                if self.isInstantRecordRunning():
-                       self.stopCurrentRecording()
+                       if answer[1] == "manualduration":
+                               self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)                             
+                       else:
+                               self.stopCurrentRecording()
                else:
-                       self.startInstantRecording()
+                       limitEvent = False
+                       if answer[1] == "event":
+                               limitEvent = True
+                       if answer[1] == "manualduration":
+                               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)
+
+       def inputCallback(self, value):
+               if value is not None:
+                       print "stopping recording after", int(value), "minutes."
+                       if self.recording is not None:
+                               self.recording.end = time.time() + 60 * int(value)
+                               self.session.nav.RecordTimer.timeChanged(self.recording)
 
        def instantRecord(self):
                try:
@@ -964,9 +1106,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"), "yes"), (_("enter recording duration"), "manualduration"), (_("do nothing"), "no")])
+#                      self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
                else:
-                       self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
+                       self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Start recording?"), list=[(_("record indefinitely"), "indefinitely"), (_("stop after current event"), "event"), (_("enter recording duration"), "manualduration"),(_("don't record"), "no")])
+                       #self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
 
 from Screens.AudioSelection import AudioSelection
 
@@ -1012,28 +1156,36 @@ class InfoBarAdditionalInfo:
                
                self["ButtonRed"] = PixmapConditional(withTimer = False)
                self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
-               self.onShown.append(self["ButtonRed"].update)
+               self.onLayoutFinish.append(self["ButtonRed"].update)
                self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
                self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
-               self.onShown.append(self["ButtonRedText"].update)
+               self.onLayoutFinish.append(self["ButtonRedText"].update)
 
                self["ButtonGreen"] = Pixmap()
                self["ButtonGreenText"] = Label(_("Subservices"))
 
                self["ButtonYellow"] = PixmapConditional(withTimer = False)
-               self["ButtonYellow"].setConnect(lambda: False)
+               self["ButtonYellow"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
+               self["ButtonYellowText"] = LabelConditional(text = _("Timeshifting"), withTimer = False)
+               self["ButtonYellowText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
+               self.onLayoutFinish.append(self["ButtonYellow"].update)
+               self.onLayoutFinish.append(self["ButtonYellowText"].update)
 
                self["ButtonBlue"] = PixmapConditional(withTimer = False)
                self["ButtonBlue"].setConnect(lambda: False)
+               self["ButtonBlueText"] = LabelConditional(text = _("Extensions"), withTimer = False)
+               self["ButtonBlueText"].setConnect(lambda: False)
+               self.onLayoutFinish.append(self["ButtonBlue"].update)
+               self.onLayoutFinish.append(self["ButtonBlueText"].update)
 
                self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
 
        def hideSubServiceIndication(self):
-               self["ButtonGreen"].hideWidget()
+               self["ButtonGreen"].hide()
                self["ButtonGreenText"].hide()
 
        def showSubServiceIndication(self):
-               self["ButtonGreen"].showWidget()
+               self["ButtonGreen"].show()
                self["ButtonGreenText"].show()
 
        def checkFormat(self, service):
@@ -1041,9 +1193,9 @@ class InfoBarAdditionalInfo:
                if info is not None:
                        aspect = info.getInfo(iServiceInformation.sAspect)
                        if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
-                               self["FormatActive"].showWidget()
+                               self["FormatActive"].show()
                        else:
-                               self["FormatActive"].hideWidget()
+                               self["FormatActive"].hide()
 
        def checkSubservices(self, service):
                if service.subServices().getNumberOfSubservices() > 0:
@@ -1064,17 +1216,17 @@ class InfoBarAdditionalInfo:
                                        dolby = True
                                        break
                if dolby:
-                       self["DolbyActive"].showWidget()
+                       self["DolbyActive"].show()
                else:
-                       self["DolbyActive"].hideWidget()
+                       self["DolbyActive"].hide()
 
        def checkCrypted(self, service):
                info = service.info()
                if info is not None:
                        if info.getInfo(iServiceInformation.sIsCrypted) > 0:
-                               self["CryptActive"].showWidget()
+                               self["CryptActive"].show()
                        else:
-                               self["CryptActive"].hideWidget()
+                               self["CryptActive"].hide()
 
        def gotServiceEvent(self, ev):
                service = self.session.nav.getCurrentService()
@@ -1086,9 +1238,9 @@ class InfoBarAdditionalInfo:
                        self.checkDolby(service)
                elif ev == iPlayableService.evEnd:
                        self.hideSubServiceIndication()
-                       self["CryptActive"].hideWidget()
-                       self["DolbyActive"].hideWidget()
-                       self["FormatActive"].hideWidget()
+                       self["CryptActive"].hide()
+                       self["DolbyActive"].hide()
+                       self["FormatActive"].hide()
 
 class InfoBarNotifications:
        def __init__(self):
@@ -1124,3 +1276,160 @@ class InfoBarServiceNotifications:
                        self.setSeekState(self.SEEK_STATE_PLAY)
                except:
                        pass
+
+class InfoBarCueSheetSupport:
+       CUT_TYPE_IN = 0
+       CUT_TYPE_OUT = 1
+       CUT_TYPE_MARK = 2
+       
+       def __init__(self):
+               self["CueSheetActions"] = HelpableActionMap(self, "InfobarCueSheetActions", 
+                       {
+                               "jumpPreviousMark": (self.jumpPreviousMark, "jump to next marked position"),
+                               "jumpNextMark": (self.jumpNextMark, "jump to previous marked position"),
+                               "toggleMark": (self.toggleMark, "toggle a cut mark at the current position")
+                       }, prio=1) 
+               
+               self.cut_list = [ ]
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evStart: self.__serviceStarted,
+                       })
+
+       def __serviceStarted(self):
+               print "new service started! trying to download cuts!"
+               self.downloadCuesheet()
+
+       def __getSeekable(self):
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       return None
+               return service.seek()
+
+       def cueGetCurrentPosition(self):
+               seek = self.__getSeekable()
+               if seek is None:
+                       return None
+               r = seek.getPlayPosition()
+               if r[0]:
+                       return None
+               return long(r[1])
+
+       def jumpPreviousNextMark(self, cmp, alternative=None):
+               current_pos = self.cueGetCurrentPosition()
+               if current_pos is None:
+                       return
+               mark = self.getNearestCutPoint(current_pos, cmp=cmp)
+               if mark is not None:
+                       pts = mark[0]
+               elif alternative is not None:
+                       pts = alternative
+               else:
+                       return
+
+               seekable = self.__getSeekable()
+               if seekable is not None:
+                       seekable.seekTo(pts)
+
+       def jumpPreviousMark(self):
+               # we add 2 seconds, so if the play position is <2s after
+               # the mark, the mark before will be used
+               self.jumpPreviousNextMark(lambda x: -x-5*90000, alternative=0)
+
+       def jumpNextMark(self):
+               self.jumpPreviousNextMark(lambda x: x)
+
+       def getNearestCutPoint(self, pts, cmp=abs):
+               # can be optimized
+               nearest = None
+               for cp in self.cut_list:
+                       diff = cmp(cp[0] - pts)
+                       if diff >= 0 and (nearest is None or cmp(nearest[0] - pts) > diff):
+                               nearest = cp
+               return nearest
+
+       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
+               
+               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 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)
+               self.uploadCuesheet()
+
+       def removeMark(self, point):
+               self.cut_list.remove(point)
+               self.uploadCuesheet()
+
+       def __getCuesheet(self):
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       return None
+               return service.cueSheet()
+
+       def uploadCuesheet(self):
+               cue = self.__getCuesheet()
+
+               if cue is None:
+                       print "upload failed, no cuesheet interface"
+                       return
+               cue.setCutList(self.cut_list)
+
+       def downloadCuesheet(self):
+               cue = self.__getCuesheet()
+
+               if cue is None:
+                       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())