Merge branch 'bug_570_playback_skip_fixes_and_cleanup_ml_aholst'
authorghost <andreas.monzner@multimedia-labs.de>
Wed, 9 Feb 2011 14:10:03 +0000 (15:10 +0100)
committerghost <andreas.monzner@multimedia-labs.de>
Wed, 9 Feb 2011 14:10:03 +0000 (15:10 +0100)
1  2 
data/setup.xml
lib/dvb/tstools.cpp
lib/python/Components/UsageConfig.py
lib/python/Plugins/Extensions/DVDPlayer/plugin.py
lib/python/Screens/InfoBarGenerics.py

diff --combined data/setup.xml
index f5dea73,fa8ff3f..c5eb07f
mode 100755,100644..100755
                        <item level="1" text="Change bouquets in quickzap">config.usage.quickzap_bouquet_change</item>
                        <item level="1" text="Alternative radio mode">config.usage.e1like_radio_mode</item>
                        <item level="1" text="Action on long powerbutton press">config.usage.on_long_powerpress</item>
 +                      <item level="1" text="Action on short powerbutton press">config.usage.on_short_powerpress</item>
                        <item level="0" text="Infobar timeout">config.usage.infobar_timeout</item>
                        <item level="1" text="12V output" requires="12V_Output">config.usage.output_12V</item>
 +                      <item level="0" text="Show event-progress in channel selection">config.usage.show_event_progress_in_servicelist</item>
                        <item level="2" text="Show infobar on channel change">config.usage.show_infobar_on_zap</item>
                        <item level="2" text="Show infobar on skip forward/backward">config.usage.show_infobar_on_skip</item>
                        <item level="2" text="Show infobar on event change">config.usage.show_infobar_on_event_change</item>
                        <item level="2" text="Fast Forward speeds">config.seek.speeds_forward</item>
                        <item level="2" text="Rewind speeds">config.seek.speeds_backward</item>
                        <item level="2" text="Slow Motion speeds">config.seek.speeds_slowmotion</item>
- <!-- TRANSLATORS: Note that "Enter" in the two strings below should *not*
-      be interpreted as "Give speed as input". The intended meaning is
-      instead "Initial speed when starting winding", i.e. the speed at
-      which "winding mode" is entered when first pressing "rewind" or
-      "fast forward". -->  
-                       <item level="2" text="Enter Fast Forward at speed">config.seek.enter_forward</item>
-                       <item level="2" text="Enter Rewind at speed">config.seek.enter_backward</item>
- <!-- TRANSLATORS: The effect of "Non-smooth winding" is that rather
-      than using ordinary "continuous" or "smooth" winding, a fast
-      sequence of stills is shown when winding at high speeds. This
-      makes it much easier too follow when almost each frame comes from
-      a new scene. The effect is achieved by repeating each shown frame
-      a couple of times. The settings control both at which speed this
-      winding mode sets in, and how many times each frame should be
-      repeated. This was previously called "Discontinuous playback"
-      which was incomprehensible. "Non-smooth winding" may be a better
-      term, but note that there is nothing irregular about it. Synonyms
-      better suited for translation to other languages may be "stepwise
-      winding/playback", or "winding/playback using stills". -->
-                       <item level="2" text="Use non-smooth winding at speeds above">config.seek.stepwise_minspeed</item>
-                       <item level="2" text="Frame repeat count during non-smooth winding">config.seek.stepwise_repeat</item>
+ <!-- TRANSLATORS: The following is the speed you get on the first press on fast-forward.
+      It was previously called "enter fast forward at speed" which was easily misunderstood. -->  
+                       <item level="2" text="Initial Fast Forward speed">config.seek.enter_forward</item>
+                       <item level="2" text="Initial Rewind speed">config.seek.enter_backward</item>
                        <item level="2" text="Behavior of 'pause' when paused">config.seek.on_pause</item>
                        <item level="2" text="Behavior of 0 key in PiP-mode">config.usage.pip_zero_button</item>
                        <item level="2" text="Alternative services tuner priority">config.usage.alternatives_priority</item>
                        <item level="2" text="Limited character set for recording filenames">config.recording.ascii_filenames</item>
 +                      <item level="2" text="Composition of the recording filenames">config.recording.filename_composition</item>
                </setup>
                <setup key="harddisk" title="Harddisk setup" >
                        <item level="0" text="Harddisk standby after">config.usage.hdd_standby</item>
diff --combined lib/dvb/tstools.cpp
@@@ -7,6 -7,7 +7,6 @@@
  #include <stdio.h>
  
  eDVBTSTools::eDVBTSTools()
 -      :m_file_lock(true)
  {
        m_pid = -1;
        m_maxrange = 256*1024;
        m_futile = 0;
  }
  
 +void eDVBTSTools::closeSource()
 +{
 +      m_source = NULL;
 +}
 +
  eDVBTSTools::~eDVBTSTools()
  {
 -      closeFile();
 +      closeSource();
  }
  
  int eDVBTSTools::openFile(const char *filename, int nostreaminfo)
  {
 +      eRawFile *f = new eRawFile();
 +      ePtr<iTsSource> src = f;
 +
 +      if (f->open(filename, 1) < 0)
 +              return -1;
 +
 +      setSource(src, nostreaminfo ? NULL : filename);
 +
 +      return 0;
 +}
 +
 +void eDVBTSTools::setSource(ePtr<iTsSource> &source, const char *stream_info_filename)
 +{
        closeFile();
 -      
 -      if (!nostreaminfo)
 +
 +      m_source = source;
 +
 +      if (stream_info_filename)
        {
 -              eDebug("loading streaminfo for %s", filename);
 -              m_streaminfo.load(filename);
 +              eDebug("loading streaminfo for %s", stream_info_filename);
 +              m_streaminfo.load(stream_info_filename);
        }
        
        if (!m_streaminfo.empty())
  //            eDebug("no recorded stream information available");
                m_use_streaminfo = 0;
        }
 -      
 -      m_samples_taken = 0;
  
 -      eSingleLocker l(m_file_lock);
 -      if (m_file.open(filename, 1) < 0)
 -              return -1;
 -      return 0;
 +      m_samples_taken = 0;
  }
  
  void eDVBTSTools::closeFile()
  {
 -      eSingleLocker l(m_file_lock);
 -      m_file.close();
 +      if (m_source)
 +              closeSource();
  }
  
  void eDVBTSTools::setSyncPID(int pid)
@@@ -91,24 -77,31 +91,24 @@@ int eDVBTSTools::getPTS(off_t &offset, 
                if (!m_streaminfo.getPTS(offset, pts))
                        return 0;
        
 -      if (!m_file.valid())
 +      if (!m_source || !m_source->valid())
                return -1;
  
        offset -= offset % 188;
  
 -      eSingleLocker l(m_file_lock);
 -      if (m_file.lseek(offset, SEEK_SET) < 0)
 -      {
 -              eDebug("lseek failed");
 -              return -1;
 -      }
 -      
        int left = m_maxrange;
        
        while (left >= 188)
        {
                unsigned char packet[188];
 -              if (m_file.read(packet, 188) != 188)
 +              if (m_source->read(offset, packet, 188) != 188)
                {
                        eDebug("read error");
                        break;
                }
                left -= 188;
                offset += 188;
 -              
 +
                if (packet[0] != 0x47)
                {
                        eDebug("resync");
                                if (packet[i] == 0x47)
                                        break;
                                ++i;
 +                              --offset;
                        }
 -                      offset = m_file.lseek(i - 188, SEEK_CUR);
                        continue;
                }
                
@@@ -411,7 -404,7 +411,7 @@@ int eDVBTSTools::getNextAccessPoint(pts
  
  void eDVBTSTools::calcBegin()
  {
 -      if (!m_file.valid())
 +      if (!m_source || !m_source->valid())
                return;
  
        if (!(m_begin_valid || m_futile))
  
  void eDVBTSTools::calcEnd()
  {
 -      if (!m_file.valid())
 +      if (!m_source || !m_source->valid())
                return;
  
 -      eSingleLocker l(m_file_lock);
 -      off_t end = m_file.lseek(0, SEEK_END);
 +      off_t end = m_source->lseek(0, SEEK_END);
        
        if (llabs(end - m_last_filelength) > 1*1024*1024)
        {
@@@ -579,28 -573,31 +579,28 @@@ int eDVBTSTools::takeSample(off_t off, 
  int eDVBTSTools::findPMT(int &pmt_pid, int &service_id)
  {
                /* FIXME: this will be factored out soon! */
 -      if (!m_file.valid())
 +      if (!m_source || !m_source->valid())
        {
                eDebug(" file not valid");
                return -1;
        }
  
 -      eSingleLocker l(m_file_lock);
 -      if (m_file.lseek(0, SEEK_SET) < 0)
 -      {
 -              eDebug("seek failed");
 -              return -1;
 -      }
 +      off_t position=0;
  
        int left = 5*1024*1024;
        
        while (left >= 188)
        {
                unsigned char packet[188];
 -              if (m_file.read(packet, 188) != 188)
 +              int ret = m_source->read(position, packet, 188);
 +              if (ret != 188)
                {
                        eDebug("read error");
                        break;
                }
                left -= 188;
 -              
 +              position += 188;
 +
                if (packet[0] != 0x47)
                {
                        int i = 0;
                        {
                                if (packet[i] == 0x47)
                                        break;
 +                              --position;
                                ++i;
                        }
 -                      m_file.lseek(i - 188, SEEK_CUR);
                        continue;
                }
 -              
                int pid = ((packet[1] << 8) | packet[2]) & 0x1FFF;
                
                int pusi = !!(packet[1] & 0x40);
@@@ -700,9 -698,26 +700,26 @@@ int eDVBTSTools::findFrame(off_t &_offs
                else if (direction == +1)
                        direction = 0;
        }
-                       /* let's find the next frame after the given offset */
        off_t start = offset;
  
+ #if 0
+                       /* backtrack to find the previous sequence start, in case of MPEG2 */
+       if ((data & 0xFF) == 0x00) {
+               do {
+                       --start;
+                       if (m_streaminfo.getStructureEntry(start, data, 0))
+                       {
+                               eDebug("get previous failed");
+                               return -1;
+                       }
+               } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00) && ((data & 0xFF) != 0xB3)); /* sequence start or previous frame */
+               if ((data & 0xFF) != 0xB3)
+                       start = offset;  /* Failed to find corresponding sequence start, so never mind */
+       }
+ #endif
+                       /* let's find the next frame after the given offset */
        do {
                if (m_streaminfo.getStructureEntry(offset, data, 1))
                {
  //            eDebug("%08llx@%llx (next)", data, offset);
        } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */
  
+ #if 0
                        /* align to TS pkt start */
- //    start = start - (start % 188);
- //    offset = offset - (offset % 188);
+       start = start - (start % 188);
+       offset = offset - (offset % 188);
+ #endif
  
        len = offset - start;
        _offset = start;
@@@ -1,7 -1,7 +1,7 @@@
  from Components.Harddisk import harddiskmanager
  from config import ConfigSubsection, ConfigYesNo, config, ConfigSelection, ConfigText, ConfigNumber, ConfigSet, ConfigLocations
  from Tools.Directories import resolveFilename, SCOPE_HDD
 -from enigma import Misc_Options, setTunerTypePriorityOrder;
 +from enigma import Misc_Options, setTunerTypePriorityOrder, eEnv;
  from SystemInfo import SystemInfo
  import os
  
@@@ -51,14 -51,7 +51,14 @@@ def InitUsageConfig()
  
        config.usage.on_long_powerpress = ConfigSelection(default = "show_menu", choices = [
                ("show_menu", _("show shutdown menu")),
 -              ("shutdown", _("immediate shutdown")) ] )
 +              ("shutdown", _("immediate shutdown")),
 +              ("standby", _("Standby")) ] )
 +      
 +      config.usage.on_short_powerpress = ConfigSelection(default = "standby", choices = [
 +              ("show_menu", _("show shutdown menu")),
 +              ("shutdown", _("immediate shutdown")),
 +              ("standby", _("Standby")) ] )
 +
  
        config.usage.alternatives_priority = ConfigSelection(default = "0", choices = [
                ("0", "DVB-S/-C/-T"),
@@@ -68,8 -61,6 +68,8 @@@
                ("4", "DVB-T/-C/-S"),
                ("5", "DVB-T/-S/-C") ])
  
 +      config.usage.show_event_progress_in_servicelist = ConfigYesNo(default = False)
 +
        config.usage.blinking_display_clock_during_recording = ConfigYesNo(default = False)
  
        config.usage.show_message_when_recording_starts = ConfigYesNo(default = True)
@@@ -94,7 -85,7 +94,7 @@@
  
        SystemInfo["12V_Output"] = Misc_Options.getInstance().detected_12V_output()
  
 -      config.usage.keymap = ConfigText(default = "/usr/share/enigma2/keymap.xml")
 +      config.usage.keymap = ConfigText(default = eEnv.resolve("${datadir}/enigma2/keymap.xml"))
  
        config.seek = ConfigSubsection()
        config.seek.selfdefined_13 = ConfigNumber(default=15)
        config.seek.selfdefined_79 = ConfigNumber(default=300)
  
        config.seek.speeds_forward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128])
-       config.seek.speeds_backward = ConfigSet(default=[8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128])
+       config.seek.speeds_backward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128])
        config.seek.speeds_slowmotion = ConfigSet(default=[2, 4, 8], choices=[2, 4, 6, 8, 12, 16, 25])
  
        config.seek.enter_forward = ConfigSelection(default = "2", choices = ["2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"])
        config.seek.enter_backward = ConfigSelection(default = "1", choices = ["1", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"])
-       config.seek.stepwise_minspeed = ConfigSelection(default = "16", choices = ["Never", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"])
-       config.seek.stepwise_repeat = ConfigSelection(default = "3", choices = ["2", "3", "4", "5", "6"])
  
        config.seek.on_pause = ConfigSelection(default = "play", choices = [
                ("play", _("Play")),
@@@ -4,7 -4,7 +4,7 @@@ from Screens.Screen import Scree
  from Screens.MessageBox import MessageBox
  from Screens.ChoiceBox import ChoiceBox
  from Screens.HelpMenu import HelpableScreen
 -from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
 +from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications, InfoBarAudioSelection, InfoBarSubtitleSupport
  from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
  from Components.Label import Label
  from Components.Sources.StaticText import StaticText
@@@ -39,11 -39,8 +39,11 @@@ class FileBrowser(Screen)
                                currDir = "/media/dvd/"
                        if not pathExists(currDir):
                                currDir = "/"
 +                      if lastpath == "":  # 'None' is magic to start at the list of mountpoints
 +                              currDir = None
  
 -                      self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
 +                      inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
 +                      self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso|img)", useServiceRef = True)
                        self["filelist"] = self.filelist
  
                self["FilelistActions"] = ActionMap(["SetupActions"],
                                        lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
                                        print "lastpath video_ts.ifo=", lastpath
                                        self.close(pathname)
 +                              if fileExists(pathname+"VIDEO_TS/VIDEO_TS.IFO"):
 +                                      print "dvd structure found, trying to open..."
 +                                      lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
 +                                      print "lastpath video_ts.ifo=", lastpath
 +                                      pathname += "VIDEO_TS"
 +                                      self.close(pathname)
                        else:
                                lastpath = filename[0:filename.rfind("/")]
                                print "lastpath directory=", lastpath
@@@ -97,8 -88,8 +97,8 @@@
                self.close(None)
  
  class DVDSummary(Screen):
 -      skin = """
 -      <screen position="0,0" size="132,64">
 +      skin = (
 +      """<screen name="DVDSummary" position="0,0" size="132,64" id="1">
                <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
                        <convert type="ServiceName">Name</convert>
                </widget>
                <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
                        <convert type="ServicePosition">Position</convert>
                </widget>
 -      </screen>"""
 +      </screen>""",
 +      """<screen name="DVDSummary" position="0,0" size="96,64" id="2">
 +              <widget source="session.CurrentService" render="Label" position="0,0" size="96,25" font="Regular;12" transparent="1" >
 +                      <convert type="ServiceName">Name</convert>
 +              </widget>
 +              <widget name="DVDPlayer" position="0,26" size="96,12" font="Regular;10" transparent="1" />
 +              <widget name="Chapter" position="0,40" size="66,12" font="Regular;10" transparent="1" halign="left" />
 +              <widget source="session.CurrentService" render="Label" position="66,40" size="30,12" font="Regular;10" transparent="1" halign="right" >
 +                      <convert type="ServicePosition">Position</convert>
 +              </widget>
 +              <widget source="session.CurrentService" render="Progress" position="0,52" size="96,12" borderWidth="1" >
 +                      <convert type="ServicePosition">Position</convert>
 +              </widget>
 +      </screen>""")
  
        def __init__(self, session, parent):
                Screen.__init__(self, session, parent)
@@@ -195,7 -173,7 +195,7 @@@ class ChapterZap(Screen)
                self.Timer.callback.append(self.keyOK)
                self.Timer.start(3000, True)
  
 -class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport):
 +class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport, InfoBarAudioSelection, InfoBarSubtitleSupport):
        ALLOW_SUSPEND = Screen.SUSPEND_PAUSES
        ENABLE_RESUME_SUPPORT = True
        
                self.saved_config_speeds_backward = config.seek.speeds_backward.value
                self.saved_config_enter_forward = config.seek.enter_forward.value
                self.saved_config_enter_backward = config.seek.enter_backward.value
-               self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
-               self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
                self.saved_config_seek_on_pause = config.seek.on_pause.value
                self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
  
                config.seek.speeds_slowmotion.value = [ ]
                config.seek.enter_forward.value = "2"
                config.seek.enter_backward.value = "2"
-               config.seek.stepwise_minspeed.value = "Never"
-               config.seek.stepwise_repeat.value = "3"
                config.seek.on_pause.value = "play"
  
        def restore_infobar_seek_config(self):
                config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
                config.seek.enter_forward.value = self.saved_config_enter_forward
                config.seek.enter_backward.value = self.saved_config_enter_backward
-               config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
-               config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
                config.seek.on_pause.value = self.saved_config_seek_on_pause
  
        def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None):
                InfoBarNotifications.__init__(self)
                InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
                InfoBarShowHide.__init__(self)
 +              InfoBarAudioSelection.__init__(self)
 +              InfoBarSubtitleSupport.__init__(self)
                HelpableScreen.__init__(self)
                self.save_infobar_seek_config()
                self.change_infobar_seek_config()
-               InfoBarSeek.__init__(self, useSeekBackHack=False)
+               InfoBarSeek.__init__(self)
                InfoBarPVRState.__init__(self)
                self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
  
                                "prevTitle": (self.prevTitle, _("jump back to the previous title")),
                                "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
                                "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
 +                              "AudioSelection": (self.enterAudioSelection, _("Select audio track")),
                                "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
                                "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
                                "nextAngle": (self.nextAngle, _("switch to the next angle")),
                        keys.keyPressed(key)
                return keys
  
 +      def enterAudioSelection(self):
 +              self.audioSelection()
 +
        def nextAudioTrack(self):
                self.sendKey(iServiceKeys.keyUser)
  
                        newref = eServiceReference(4369, 0, val)
                        print "play", newref.toString()
                        if curref is None or curref != newref:
 +                              if newref.toString().endswith("/VIDEO_TS") or newref.toString().endswith("/"):
 +                                      names = newref.toString().rsplit("/",3)
 +                                      if names[2].startswith("Disk ") or names[2].startswith("DVD "):
 +                                              name = str(names[1]) + " - " + str(names[2])
 +                                      else:
 +                                              name = names[2]
 +                                      print "setting name to: ", self.service
 +                                      newref.setName(str(name))
                                self.session.nav.playService(newref)
                                self.service = self.session.nav.getCurrentService()
                                print "self.service", self.service
@@@ -598,7 -598,6 +598,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()
@@@ -717,7 -716,7 +717,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,
                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)
@@@ -1673,11 -1662,126 +1663,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):
@@@ -1970,20 -2074,21 +1960,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]
                                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