Support turbo2.
[vuplus_dvbapp] / lib / python / Screens / InfoBarGenerics.py
index 5404a4e..bc66f1f 100644 (file)
@@ -36,21 +36,26 @@ from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInform
        iPlayableService, eServiceReference, eEPGCache, eActionMap
 
 from time import time, localtime, strftime
-from os import stat as os_stat
+from os import stat as os_stat, system as os_system
 from bisect import insort
 
-from RecordTimer import RecordTimerEntry, RecordTimer
+from RecordTimer import RecordTimerEntry, RecordTimer, findSafeRecordPath
 
 # hack alert!
 from Menu import MainMenu, mdom
 
+def isStandardInfoBar(self):
+       return self.__class__.__name__ == "InfoBar"
+
 class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
+               self.dishDialog.setAnimationMode(0)
 
 class InfoBarUnhandledKey:
        def __init__(self):
                self.unhandledKeyDialog = self.session.instantiateDialog(UnhandledKey)
+               self.unhandledKeyDialog.setAnimationMode(0)
                self.hideUnhandledKeySymbolTimer = eTimer()
                self.hideUnhandledKeySymbolTimer.callback.append(self.unhandledKeyDialog.hide)
                self.checkUnusedTimer = eTimer()
@@ -233,7 +238,7 @@ class InfoBarNumberZap:
                        else:
                                self.servicelist.recallPrevService()
                else:
-                       if self.has_key("TimeshiftActions") and not self.timeshift_enabled:
+                       if not (self.has_key("TimeshiftActions") and self.timeshift_enabled):
                                self.session.openWithCallback(self.numberEntered, NumberZap, number)
 
        def numberEntered(self, retval):
@@ -487,7 +492,7 @@ class InfoBarEPG:
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show EPG...")),
-                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")),
+                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("list of EPG views...")),
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
@@ -619,6 +624,7 @@ class InfoBarEPG:
 
                if list:
                        list.append((_("show single service EPG..."), self.openSingleServiceEPG))
+                       list.append((_("Multi EPG"), self.openMultiServiceEPG))
                        self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list, skin_name = "EPGExtensionsList")
                else:
                        self.openSingleServiceEPG()
@@ -686,6 +692,7 @@ class InfoBarRdsDecoder:
        """provides RDS and Rass support/display"""
        def __init__(self):
                self.rds_display = self.session.instantiateDialog(RdsInfoDisplay)
+               self.rds_display.setAnimationMode(0)
                self.rass_interactive = None
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
@@ -737,7 +744,7 @@ class InfoBarSeek:
        SEEK_STATE_PAUSE = (1, 0, 0, "||")
        SEEK_STATE_EOF = (1, 0, 0, "END")
 
-       def __init__(self, actionmap = "InfobarSeekActions", useSeekBackHack=True):
+       def __init__(self, actionmap = "InfobarSeekActions"):
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
                                iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
@@ -771,7 +778,7 @@ class InfoBarSeek:
 
                self["SeekActions"] = InfoBarSeekActionMap(self, actionmap,
                        {
-                               "playpauseService": self.playpauseService,
+                               "playpauseService": (self.playpauseService, _("Pause/Continue")),
                                "pauseService": (self.pauseService, _("pause")),
                                "unPauseService": (self.unPauseService, _("continue")),
 
@@ -794,20 +801,10 @@ class InfoBarSeek:
                self.__seekableStatusChanged()
 
        def makeStateForward(self, n):
-#              minspeed = config.seek.stepwise_minspeed.value
-#              repeat = int(config.seek.stepwise_repeat.value)
-#              if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
-#                      return (0, n * repeat, repeat, ">> %dx" % n)
-#              else:
-                       return (0, n, 0, ">> %dx" % n)
+               return (0, n, 0, ">> %dx" % n)
 
        def makeStateBackward(self, n):
-#              minspeed = config.seek.stepwise_minspeed.value
-#              repeat = int(config.seek.stepwise_repeat.value)
-#              if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
-#                      return (0, -n * repeat, repeat, "<< %dx" % n)
-#              else:
-                       return (0, -n, 0, "<< %dx" % n)
+               return (0, -n, 0, "<< %dx" % n)
 
        def makeStateSlowMotion(self, n):
                return (0, 0, n, "/%d" % n)
@@ -858,7 +855,7 @@ class InfoBarSeek:
                return seek
 
        def isSeekable(self):
-               if self.getSeek() is None:
+               if self.getSeek() is None or (isStandardInfoBar(self) and not self.timeshift_enabled):
                        return False
                return True
 
@@ -1114,6 +1111,7 @@ class InfoBarPVRState:
        def __init__(self, screen=PVRState, force_show = False):
                self.onPlayStateChanged.append(self.__playStateChanged)
                self.pvrStateDialog = self.session.instantiateDialog(screen)
+               self.pvrStateDialog.setAnimationMode(0)
                self.onShow.append(self._mayShow)
                self.onHide.append(self.pvrStateDialog.hide)
                self.force_show = force_show
@@ -1131,15 +1129,21 @@ class InfoBarPVRState:
                        self.pvrStateDialog.hide()
                else:
                        self._mayShow()
-                       
 
 class InfoBarTimeshiftState(InfoBarPVRState):
        def __init__(self):
                InfoBarPVRState.__init__(self, screen=TimeshiftState, force_show = True)
+               self.__hideTimer = eTimer()
+               self.__hideTimer.callback.append(self.__hideTimeshiftState)
 
        def _mayShow(self):
-               if self.execing and self.timeshift_enabled and self.seekstate != self.SEEK_STATE_PLAY:
+               if self.execing and self.timeshift_enabled:
                        self.pvrStateDialog.show()
+                       if self.seekstate == self.SEEK_STATE_PLAY and not self.shown:
+                               self.__hideTimer.start(5*1000, True)
+
+       def __hideTimeshiftState(self):
+               self.pvrStateDialog.hide()
 
 class InfoBarShowMovies:
 
@@ -1184,11 +1188,12 @@ class InfoBarShowMovies:
 
 class InfoBarTimeshift:
        def __init__(self):
-               self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
-                       {
-                               "timeshiftStart": (self.startTimeshift, _("start timeshift")),  # the "yellow key"
-                               "timeshiftStop": (self.stopTimeshift, _("stop timeshift"))      # currently undefined :), probably 'TV'
-                       }, prio=1)
+               if SystemInfo["PVRSupport"]:
+                       self["TimeshiftActions"] = HelpableActionMap(self, "InfobarTimeshiftActions",
+                               {
+                                       "timeshiftStart": (self.startTimeshift, _("start timeshift")),  # the "yellow key"
+                                       "timeshiftStop": (self.stopTimeshift, _("stop timeshift"))      # currently undefined :), probably 'TV'
+                               }, prio=1)
                self["TimeshiftActivateActions"] = ActionMap(["InfobarTimeshiftActivateActions"],
                        {
                                "timeshiftActivateEnd": self.activateTimeshiftEnd, # something like "rewind key"
@@ -1203,7 +1208,8 @@ class InfoBarTimeshift:
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
                                iPlayableService.evStart: self.__serviceStarted,
-                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
+                               iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+                               iPlayableService.evUser+3: self.__lowDiskspaceMessage
                        })
 
        def getTimeshift(self):
@@ -1221,6 +1227,13 @@ class InfoBarTimeshift:
                if self.timeshift_enabled:
                        print "hu, timeshift already enabled?"
                else:
+                       from Components import Harddisk
+                       if Harddisk.getMountPath(config.usage.timeshift_path.value) != '/' and \
+                               SystemInfo.get("DisableUsbRecord", True) and \
+                               Harddisk.isUsbStorage(config.usage.timeshift_path.value):
+                               self.session.open(MessageBox, _("Timeshift not possible on a USB storage."), MessageBox.TYPE_ERROR)
+                               return 0
+
                        if not ts.startTimeshift():
                                self.timeshift_enabled = 1
 
@@ -1307,6 +1320,9 @@ class InfoBarTimeshift:
                self.timeshift_enabled = False
                self.__seekableStatusChanged()
 
+       def __lowDiskspaceMessage(self):
+               Notifications.AddPopup(text = _("Write error. Not enough space for writing.\n"), type = MessageBox.TYPE_ERROR, timeout = 0, id = "DiskFullMessage")
+
 from Screens.PiPSetup import PiPSetup
 
 class InfoBarExtensions:
@@ -1321,6 +1337,9 @@ class InfoBarExtensions:
                                "extensions": (self.showExtensionSelection, _("view extensions...")),
                        }, 1) # lower priority
 
+               for p in plugins.getPlugins(PluginDescriptor.WHERE_EXTENSIONSINGLE):
+                       p(self)
+
        def addExtension(self, extension, key = None, type = EXTENSION_SINGLE):
                self.list.append((type, extension, key))
 
@@ -1377,6 +1396,7 @@ class InfoBarExtensions:
                        answer[1][1]()
 
 from Tools.BoundFunction import boundFunction
+import inspect
 
 # depends on InfoBarExtensions
 
@@ -1388,9 +1408,13 @@ class InfoBarPlugins:
                return name
 
        def getPluginList(self):
-               list = [((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None, p.name) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU)]
-               list.sort(key = lambda e: e[2]) # sort by name
-               return list
+               l = []
+               for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU):
+                 args = inspect.getargspec(p.__call__)[0]
+                 if len(args) == 1 or len(args) == 2 and isinstance(self, InfoBarChannelSelection):
+                         l.append(((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None, p.name))
+               l.sort(key = lambda e: e[2]) # sort by name
+               return l
 
        def runPlugin(self, plugin):
                if isinstance(self, InfoBarChannelSelection):
@@ -1457,6 +1481,7 @@ class InfoBarPiP:
                        self.session.pipshown = False
                else:
                        self.session.pip = self.session.instantiateDialog(PictureInPicture)
+                       self.session.pip.setAnimationMode(0)
                        self.session.pip.show()
                        newservice = self.session.nav.getCurrentlyPlayingServiceReference()
                        if self.session.pip.playService(newservice):
@@ -1499,10 +1524,11 @@ class InfoBarInstantRecord:
        """Instant Record - handles the instantRecord action in order to
        start/stop instant records"""
        def __init__(self):
-               self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
-                       {
-                               "instantRecord": (self.instantRecord, _("Instant Record...")),
-                       })
+               if SystemInfo["PVRSupport"]:
+                       self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
+                               {
+                                       "instantRecord": (self.instantRecord, _("Instant Record...")),
+                               })
                self.recording = []
 
        def stopCurrentRecording(self, entry = -1):
@@ -1548,28 +1574,30 @@ class InfoBarInstantRecord:
 
                recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = preferredInstantRecordPath())
                recording.dontSave = True
-               
+
                if event is None or limitEvent == False:
                        recording.autoincrease = True
-                       if recording.setAutoincreaseEnd():
-                               self.session.nav.RecordTimer.record(recording)
-                               self.recording.append(recording)
+                       recording.setAutoincreaseEnd()
+
+               simulTimerList = self.session.nav.RecordTimer.record(recording)
+
+               if simulTimerList is None:      # no conflict
+                       self.recording.append(recording)
                else:
-                               simulTimerList = self.session.nav.RecordTimer.record(recording)
-                               if simulTimerList is not None:  # conflict with other recording
-                                       name = simulTimerList[1].name
-                                       name_date = ' '.join((name, strftime('%c', localtime(simulTimerList[1].begin))))
-                                       print "[TIMER] conflicts with", name_date
-                                       recording.autoincrease = True   # start with max available length, then increment
-                                       if recording.setAutoincreaseEnd():
-                                               self.session.nav.RecordTimer.record(recording)
-                                               self.recording.append(recording)
-                                               self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO)
-                                       else:
-                                               self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO)
-                                       recording.autoincrease = False
-                               else:
+                       if len(simulTimerList) > 1: # with other recording
+                               name = simulTimerList[1].name
+                               name_date = ' '.join((name, strftime('%c', localtime(simulTimerList[1].begin))))
+                               print "[TIMER] conflicts with", name_date
+                               recording.autoincrease = True   # start with max available length, then increment
+                               if recording.setAutoincreaseEnd():
+                                       self.session.nav.RecordTimer.record(recording)
                                        self.recording.append(recording)
+                                       self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO)
+                               else:
+                                       self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO)
+                       else:
+                               self.session.open(MessageBox, _("Couldn't record due to invalid service %s") % serviceref, MessageBox.TYPE_INFO)
+                       recording.autoincrease = False
 
        def isInstantRecordRunning(self):
                print "self.recording:", self.recording
@@ -1647,13 +1675,14 @@ class InfoBarInstantRecord:
                        self.session.nav.RecordTimer.timeChanged(entry)
 
        def instantRecord(self):
-               dir = preferredInstantRecordPath()
-               if not dir or not fileExists(dir, 'w'):
-                       dir = defaultMoviePath()
-               try:
-                       stat = os_stat(dir)
-               except:
-                       # XXX: this message is a little odd as we might be recording to a remote device
+               if not fileExists("/hdd", 0):
+                       print "not found /hdd"
+                       os_system("ln -s /media/hdd /hdd")
+
+               recPath = preferredInstantRecordPath()
+               if not findSafeRecordPath(recPath) and not findSafeRecordPath(defaultMoviePath()):
+                       if not recPath:
+                               recPath = ""
                        self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
                        return
 
@@ -1687,126 +1716,11 @@ class InfoBarAudioSelection:
                        })
 
        def audioSelection(self):
-               service = self.session.nav.getCurrentService()
-               self.audioTracks = audio = service and service.audioTracks()
-               n = audio and audio.getNumberOfTracks() or 0
-               tlist = []
-               if n > 0:
-                       self.audioChannel = service.audioChannel()
-
-                       idx = 0
-                       while idx < n:
-                               cnt = 0
-                               i = audio.getTrackInfo(idx)
-                               languages = i.getLanguage().split('/')
-                               description = i.getDescription()
-                               language = ""
-
-                               for lang in languages:
-                                       if cnt:
-                                               language += ' / '
-                                       if LanguageCodes.has_key(lang):
-                                               language += LanguageCodes[lang][0]
-                                       else:
-                                               language += lang
-                                       cnt += 1
-
-                               if len(description):
-                                       description += " (" + language + ")"
-                               else:
-                                       description = language
-
-                               tlist.append((description, idx))
-                               idx += 1
-
-                       tlist.sort(key=lambda x: x[0])
-
-                       selectedAudio = self.audioTracks.getCurrentTrack()
-
-                       selection = 0
-
-                       for x in tlist:
-                               if x[1] != selectedAudio:
-                                       selection += 1
-                               else:
-                                       break
-
-                       availableKeys = []
-                       usedKeys = []
-
-                       if SystemInfo["CanDownmixAC3"]:
-                               flist = [(_("AC3 downmix") + " - " +(_("Off"), _("On"))[config.av.downmix_ac3.value and 1 or 0], "CALLFUNC", self.changeAC3Downmix),
-                                       ((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
-                               usedKeys.extend(["red", "green"])
-                               availableKeys.extend(["yellow", "blue"])
-                               selection += 2
-                       else:
-                               flist = [((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
-                               usedKeys.extend(["red"])
-                               availableKeys.extend(["green", "yellow", "blue"])
-                               selection += 1
-
-                       if hasattr(self, "runPlugin"):
-                               class PluginCaller:
-                                       def __init__(self, fnc, *args):
-                                               self.fnc = fnc
-                                               self.args = args
-                                       def __call__(self, *args, **kwargs):
-                                               self.fnc(*self.args)
-
-                               Plugins = [ (p.name, PluginCaller(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_AUDIOMENU) ]
-
-                               for p in Plugins:
-                                       selection += 1
-                                       flist.append((p[0], "CALLFUNC", p[1]))
-                                       if availableKeys:
-                                               usedKeys.append(availableKeys[0])
-                                               del availableKeys[0]
-                                       else:
-                                               usedKeys.append("")
-
-                       flist.append(("--", ""))
-                       usedKeys.append("")
-                       selection += 1
-
-                       keys = usedKeys + [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" ] + [""] * n
-                       self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = flist + tlist, selection = selection, keys = keys, skin_name = "AudioTrackSelection")
-               else:
-                       del self.audioTracks
-
-       def changeAC3Downmix(self, arg):
-               choicelist = self.session.current_dialog["list"]
-               list = choicelist.list
-               t = list[0][1]
-               list[0][1]=(t[0], t[1], t[2], t[3], t[4], t[5], t[6],
-                       _("AC3 downmix") + " - " + (_("On"), _("Off"))[config.av.downmix_ac3.value and 1 or 0])
-               choicelist.setList(list)
-               if config.av.downmix_ac3.value:
-                       config.av.downmix_ac3.value = False
-               else:
-                       config.av.downmix_ac3.value = True
-               config.av.downmix_ac3.save()
-
-       def audioSelected(self, audio):
-               if audio is not None:
-                       if isinstance(audio[1], str):
-                               if audio[1] == "mode":
-                                       keys = ["red", "green", "yellow"]
-                                       selection = self.audioChannel.getCurrentChannel()
-                                       tlist = ((_("left"), 0), (_("stereo"), 1), (_("right"), 2))
-                                       self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys, skin_name ="AudioModeSelection")
-                       else:
-                               del self.audioChannel
-                               if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
-                                       self.audioTracks.selectTrack(audio[1])
-               else:
-                       del self.audioChannel
-               del self.audioTracks
-
-       def modeSelected(self, mode):
-               if mode is not None:
-                       self.audioChannel.selectChannel(mode[1])
-               del self.audioChannel
+               from Screens.AudioSelection import AudioSelection
+               self.session.openWithCallback(self.audioSelected, AudioSelection, infobar=self)
+               
+       def audioSelected(self, ret=None):
+               print "[infobar::audioSelected]", ret
 
 class InfoBarSubserviceSelection:
        def __init__(self):
@@ -1934,13 +1848,74 @@ class InfoBarSubserviceSelection:
                else:
                        del self.selectedSubservice
 
+from Components.Sources.HbbtvApplication import HbbtvApplication
+gHbbtvApplication = HbbtvApplication()
+class InfoBarRedButton:
+       def __init__(self):
+               if not (config.misc.rcused.value == 1):
+                       self["RedButtonActions"] = HelpableActionMap(self, "InfobarRedButtonActions",
+                               {
+                                       "activateRedButton": (self.activateRedButton, _("Red button...")),
+                               })
+                       self["HbbtvApplication"] = gHbbtvApplication
+               else:
+                       self["HbbtvApplication"] = Boolean(fixed=0)
+                       self["HbbtvApplication"].name = "" #is this a hack?
+                       
+               self.onHBBTVActivation = [ ]
+               self.onRedButtonActivation = [ ]
+               self.onReadyForAIT = [ ]
+               self.__et = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evHBBTVInfo: self.detectedHbbtvApplication,
+                               iPlayableService.evUpdatedInfo: self.updateInfomation
+                       })
+
+       def updateAIT(self, orgId=0):
+               for x in self.onReadyForAIT:
+                       try:
+                               x(orgId)
+                       except Exception, ErrMsg: 
+                               print ErrMsg
+                               #self.onReadyForAIT.remove(x)
+
+       def updateInfomation(self):
+               try:
+                       self["HbbtvApplication"].setApplicationName("")
+                       self.updateAIT()
+               except Exception, ErrMsg:
+                       pass
+               
+       def detectedHbbtvApplication(self):
+               service = self.session.nav.getCurrentService()
+               info = service and service.info()
+               try:
+                       for x in info.getInfoObject(iServiceInformation.sHBBTVUrl):
+                               print x
+                               if x[0] in (-1, 1):
+                                       self.updateAIT(x[3])
+                                       self["HbbtvApplication"].setApplicationName(x[1])
+                                       break
+               except Exception, ErrMsg:
+                       pass
+
+       def activateRedButton(self):
+               service = self.session.nav.getCurrentService()
+               info = service and service.info()
+               if info and info.getInfoString(iServiceInformation.sHBBTVUrl) != "":
+                       for x in self.onHBBTVActivation:
+                               x()
+               elif False: # TODO: other red button services
+                       for x in self.onRedButtonActivation:
+                               x()
+
 class InfoBarAdditionalInfo:
        def __init__(self):
 
                self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0 and config.misc.rcused.value == 1)
                self["TimeshiftPossible"] = self["RecordingPossible"]
-               self["ShowTimeshiftOnYellow"] = Boolean(fixed=(not config.misc.rcused.value == 0))
-               self["ShowAudioOnYellow"] = Boolean(fixed=config.misc.rcused.value == 0)
+               self["ShowTimeshiftOnYellow"] = Boolean(fixed=(config.misc.rcused.value == 1))
+               self["ShowAudioOnYellow"] = Boolean(fixed=config.misc.rcused.value != 1)
                self["ShowRecordOnRed"] = Boolean(fixed=config.misc.rcused.value == 1)
                self["ExtensionsAvailable"] = Boolean(fixed=1)
 
@@ -2099,20 +2074,21 @@ class InfoBarCueSheetSupport:
                return True
 
        def jumpPreviousMark(self):
-               # we add 2 seconds, so if the play position is <2s after
+               # we add 5 seconds, so if the play position is <5s after
                # the mark, the mark before will be used
                self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True)
 
        def jumpNextMark(self):
-               if not self.jumpPreviousNextMark(lambda x: x):
+               if not self.jumpPreviousNextMark(lambda x: x-90000):
                        self.doSeek(-1)
 
        def getNearestCutPoint(self, pts, cmp=abs, start=False):
                # can be optimized
-               beforecut = False
+               beforecut = True
                nearest = None
+               bestdiff = -1
+               instate = True
                if start:
-                       beforecut = True
                        bestdiff = cmp(0 - pts)
                        if bestdiff >= 0:
                                nearest = [0, False]
@@ -2121,14 +2097,19 @@ class InfoBarCueSheetSupport:
                                beforecut = False
                                if cp[1] == self.CUT_TYPE_IN:  # Start is here, disregard previous marks
                                        diff = cmp(cp[0] - pts)
-                                       if diff >= 0:
+                                       if start and diff >= 0:
                                                nearest = cp
                                                bestdiff = diff
                                        else:
                                                nearest = None
-                       if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST):
+                                               bestdiff = -1
+                       if cp[1] == self.CUT_TYPE_IN:
+                               instate = True
+                       elif cp[1] == self.CUT_TYPE_OUT:
+                               instate = False
+                       elif cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST):
                                diff = cmp(cp[0] - pts)
-                               if diff >= 0 and (nearest is None or bestdiff > diff):
+                               if instate and diff >= 0 and (nearest is None or bestdiff > diff):
                                        nearest = cp
                                        bestdiff = diff
                return nearest
@@ -2266,6 +2247,7 @@ class InfoBarSubtitleSupport(object):
        def __init__(self):
                object.__init__(self)
                self.subtitle_window = self.session.instantiateDialog(SubtitleDisplay)
+               self.subtitle_window.setAnimationMode(0)
                self.__subtitles_enabled = False
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
@@ -2284,8 +2266,7 @@ class InfoBarSubtitleSupport(object):
                        self.__selected_subtitle = None
 
        def __updatedInfo(self):
-               if not self.cached_subtitle_checked:
-                       self.cached_subtitle_checked = True
+               if not self.__selected_subtitle:
                        subtitle = self.getCurrentServiceSubtitle()
                        self.setSelectedSubtitle(subtitle and subtitle.getCachedSubtitle())
                        if self.__selected_subtitle:
@@ -2306,7 +2287,7 @@ class InfoBarSubtitleSupport(object):
                else:
                        if subtitle:
                                subtitle.disableSubtitles(self.subtitle_window.instance)
-                       self.__selected_subtitle = False
+                       self.__selected_subtitle = None
                        self.__subtitles_enabled = False
                        self.subtitle_window.hide()
 
@@ -2356,3 +2337,67 @@ class InfoBarServiceErrorPopupSupport:
                        Notifications.AddPopup(text = error, type = MessageBox.TYPE_ERROR, timeout = 5, id = "ZapError")
                else:
                        Notifications.RemovePopup(id = "ZapError")
+
+class InfoBarHDMI:
+       def __init__(self):
+               self.hdmiInServiceRef = eServiceReference('8192:0:1:0:0:0:0:0:0:0:')
+
+               if SystemInfo.get("HdmiInSupport", False):
+                       self.addExtension((self.getShowHdmiInName, self.HDMIIn, lambda: True), None)
+                       self.addExtension((self.getShowHdmiInPIPName, self.HDMIInPIP, self.showHDMIPIPMenu), None)
+
+       def getShowHdmiInName(self):
+               curref = self.session.nav.getCurrentlyPlayingServiceReference()
+               if curref and curref.type == 8192:
+                       name = _("Disable HDMI-IN on Main Screen")
+               else:
+                       name = _("Enable HDMI-IN on Main Screen")
+
+               return name
+
+       def getShowHdmiInPIPName(self):
+               return _("Enable HDMI-IN on PIP")
+
+       def showHDMIPIPMenu(self):
+               _pipAvailable = SystemInfo.get("NumVideoDecoders", 1) > 1
+
+               hdmiin_enabled = False
+               curref = self.session.nav.getCurrentlyPlayingServiceReference()
+               if curref and curref.type == 8192:
+                       hdmiin_enabled = True
+
+               hdmiin_pip_shown = False
+               if self.session.pipshown:
+                       pipref=self.session.pip.getCurrentService()
+                       if pipref and pipref.type == 8192:
+                               hdmiin_pip_shown = True
+
+               return _pipAvailable and not hdmiin_enabled and not hdmiin_pip_shown
+
+       def getCurrentServiceRef(self):
+               slist = self.servicelist
+               currentServiceSref = slist.servicelist.getCurrent()
+               return currentServiceSref
+
+       def HDMIIn(self):
+               curref = self.session.nav.getCurrentlyPlayingServiceReference()
+               if curref and curref.type == 8192:
+                       self.session.nav.playService(self.getCurrentServiceRef())
+               else:
+                       self.session.nav.playService(self.hdmiInServiceRef)
+
+       def HDMIInPIP(self):
+               if self.session.pipshown:
+                       del self.session.pip
+
+               self.session.pip = self.session.instantiateDialog(PictureInPicture)
+               self.session.pip.setAnimationMode(0)
+               self.session.pip.show()
+               newservice = self.hdmiInServiceRef
+               if self.session.pip.playService(newservice):
+                       self.session.pipshown = True
+                       self.session.pip.servicePath = self.servicelist.getCurrentServicePath()
+               else:
+                       self.session.pipshown = False
+                       del self.session.pip
+                       self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR)