<div dir="ltr">This seems to be breaking regular subtitle delay (positive and negative) with keys G and H.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-05-30 22:04 GMT+02:00 Pascal Thomet <span dir="ltr"><<a href="mailto:pthomet@gmail.com" target="_blank">pthomet@gmail.com</a>></span>:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This is a follow-up to a patch I made last year<br>
(f7211d5efa4cd9ef392230d85fdf3470edefab39)<br>
When developping it I stumbled upon a prexisting bug that I could<br>
not correct at that time.<br>
<br>
I now propose a correction for this bug, as well as tooltip that better<br>
explain the use of the hotkeys introduced by f7211d5efa4cd9ef392230d85fdf3470edefab39<br>
<br>
tests passed / compile and runs correctly in debug & release modes<br>
under linux & OSX<br>
<br>
1) Bug correction info :<br>
*  *  *  *  *  *  *  *  *<br>
<br>
Bug reproduction step : *under linux* (will not happen under OSX)<br>
- launch a video that has a subtitle,<br>
- press Shift-H ("bookmark audio time"),<br>
- wait 5 seconds<br>
- press Shift-J ("bookmark subtitle time")<br>
- press Shift-K ("sync bookmarks")<br>
==> the audio is broken...<br>
(AFAIK this bug seems not to be mentioned on <a href="http://trac.videolan.org" target="_blank">trac.videolan.org</a>)<br>
<br>
The subtitle delay ("spu-delay") was previously implemented by<br>
  i) setting a variable spu-delay<br>
     (var_SetTime(... , "spu-delay", ... ))<br>
  ii) this change raised a callback that finaly lead to calling<br>
    UpdatePtsDelay().<br>
<br>
The reason UpdatePtsDelay() was called is that the subtitle delay<br>
was programed the same way as the audio delay (for which it is required<br>
to wait until the audio is actually demuxed)<br>
<br>
*However* the situation for subtitles is quite different, as they are all in memory<br>
(no need to wait until they are demuxed !)<br>
<br>
The code is now more simple (and the bug is fixed !) :<br>
- no more delay calculations inside hotkeys.c, everything is handled<br>
  inside subtitle.c through callbacks<br>
- inside subtitle.c :<br>
    * adjust_subtitle_time() receives a subtitle timestamp as input and returns<br>
      that timestamp corrected by spu-delay<br>
    * set_current_subtitle_by_time() is called when spu-delay is changed<br>
<br>
2) Tooltip<br>
*  *  *  *<br>
<br>
This adds a tooltip in the "Track Synchronization" window<br>
on the "subtitle track sycnhronization" label and widget.<br>
It explains better the use of the subtitle sync hotkeys<br>
(Shift H/J/K)<br>
<br>
Also tested under Linux & OSX.<br>
---<br>
 include/vlc_input.h                            |   2 -<br>
 modules/control/hotkeys.c                      | 113 +++++---------<br>
 modules/demux/subtitle.c                       | 205 +++++++++++++++++++++----<br>
 modules/gui/macosx/TrackSynchronization.m      |  17 +-<br>
 modules/gui/macosx/intf.m                      |   1 -<br>
 modules/gui/qt4/components/extended_panels.cpp |  16 +-<br>
 modules/gui/qt4/input_manager.cpp              |   1 -<br>
 src/input/event.c                              |  10 --<br>
 src/input/event.h                              |   1 -<br>
 src/input/input.c                              |  10 +-<br>
 src/input/input_internal.h                     |   1 -<br>
 src/input/var.c                                |   5 -<br>
 12 files changed, 250 insertions(+), 132 deletions(-)<br>
<br>
diff --git a/include/vlc_input.h b/include/vlc_input.h<br>
index 88bfe65..043414e 100644<br>
--- a/include/vlc_input.h<br>
+++ b/include/vlc_input.h<br>
@@ -380,8 +380,6 @@ typedef enum input_event_type_e<br>
<br>
     /* "audio-delay" has changed */<br>
     INPUT_EVENT_AUDIO_DELAY,<br>
-    /* "spu-delay" has changed */<br>
-    INPUT_EVENT_SUBTITLE_DELAY,<br>
<br>
     /* "bookmark" has changed */<br>
     INPUT_EVENT_BOOKMARK,<br>
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c<br>
index 1e7fcdf..eb00c57 100644<br>
--- a/modules/control/hotkeys.c<br>
+++ b/modules/control/hotkeys.c<br>
@@ -48,13 +48,6 @@ struct intf_sys_t<br>
 {<br>
     vout_thread_t      *p_last_vout;<br>
     int slider_chan;<br>
-<br>
-    /*subtitle_delaybookmarks: placeholder for storing subtitle sync timestamps*/<br>
-    struct<br>
-    {<br>
-        int64_t i_time_subtitle;<br>
-        int64_t i_time_audio;<br>
-    } subtitle_delaybookmarks;<br>
 };<br>
<br>
 /*****************************************************************************<br>
@@ -108,10 +101,14 @@ static int Open( vlc_object_t *p_this )<br>
     p_intf->p_sys = p_sys;<br>
<br>
     p_sys->p_last_vout = NULL;<br>
-    p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
-    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
<br>
+    /* key-osdmessage : variable to be used from external modules<br>
+     * in order to display an osd message<br>
+     * as an informative response after a hotkey press */<br>
+    var_Create (p_intf->p_libvlc, "key-osdmessage", VLC_VAR_STRING);<br>
+    var_AddCallback( p_intf->p_libvlc, "key-osdmessage", ActionEvent, p_intf );<br>
     var_AddCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );<br>
+<br>
     return VLC_SUCCESS;<br>
 }<br>
<br>
@@ -123,6 +120,8 @@ static void Close( vlc_object_t *p_this )<br>
     intf_thread_t *p_intf = (intf_thread_t *)p_this;<br>
     intf_sys_t *p_sys = p_intf->p_sys;<br>
<br>
+    var_Destroy( p_intf->p_libvlc, "key-osdmessage" );<br>
+    var_DelCallback( p_intf->p_libvlc, "key-osdmessage", ActionEvent, p_intf );<br>
     var_DelCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );<br>
<br>
     /* Destroy structure */<br>
@@ -404,76 +403,21 @@ static int PutAction( intf_thread_t *p_intf, int i_action )<br>
             break;<br>
<br>
         case ACTIONID_SUBSYNC_MARKAUDIO:<br>
-        {<br>
-            p_sys->subtitle_delaybookmarks.i_time_audio = mdate();<br>
-            DisplayMessage( p_vout, _("Sub sync: bookmarked audio time"));<br>
+            /* trigger callback in module subtitle.c */<br>
+            var_SetInteger(p_input, "spu-bookmarkaudio", mdate());<br>
             break;<br>
-        }<br>
         case ACTIONID_SUBSYNC_MARKSUB:<br>
-            if( p_input )<br>
-            {<br>
-                vlc_value_t val, list, list2;<br>
-                int i_count;<br>
-                var_Get( p_input, "spu-es", &val );<br>
-<br>
-                var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES,<br>
-                            &list, &list2 );<br>
-                i_count = list.p_list->i_count;<br>
-                if( i_count < 1 || val.i_int < 0 )<br>
-                {<br>
-                    DisplayMessage( p_vout, _("No active subtitle") );<br>
-                    var_FreeList( &list, &list2 );<br>
-                    break;<br>
-                }<br>
-                p_sys->subtitle_delaybookmarks.i_time_subtitle = mdate();<br>
-                DisplayMessage( p_vout,<br>
-                                _("Sub sync: bookmarked subtitle time"));<br>
-                var_FreeList( &list, &list2 );<br>
-            }<br>
+            /* trigger callback in module subtitle.c */<br>
+            var_SetInteger(p_input, "spu-bookmarksubtitle", mdate());<br>
             break;<br>
         case ACTIONID_SUBSYNC_APPLY:<br>
-        {<br>
-            /* Warning! Can yield a pause in the playback.<br>
-             * For example, the following succession of actions will yield a 5 second delay :<br>
-             * - Pressing Shift-H (ACTIONID_SUBSYNC_MARKAUDIO)<br>
-             * - wait 5 second<br>
-             * - Press Shift-J (ACTIONID_SUBSYNC_MARKSUB)<br>
-             * - Press Shift-K (ACTIONID_SUBSYNC_APPLY)<br>
-             * --> 5 seconds pause<br>
-             * This is due to var_SetTime() (and ultimately UpdatePtsDelay())<br>
-             * which causes the video to pause for an equivalent duration<br>
-             * (This problem is also present in the "Track synchronization" window) */<br>
-            if ( p_input )<br>
-            {<br>
-                if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )<br>
-                {<br>
-                    DisplayMessage( p_vout, _( "Sub sync: set bookmarks first!" ) );<br>
-                }<br>
-                else<br>
-                {<br>
-                    int64_t i_current_subdelay = var_GetTime( p_input, "spu-delay" );<br>
-                    int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;<br>
-                    int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;<br>
-                    var_SetTime( p_input, "spu-delay", i_total_subdelay);<br>
-                    ClearChannels( p_intf, p_vout );<br>
-                    DisplayMessage( p_vout, _( "Sub sync: corrected %i ms (total delay = %i ms)" ),<br>
-                                            (int)(i_additional_subdelay / 1000),<br>
-                                            (int)(i_total_subdelay / 1000) );<br>
-                    p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
-                    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
-                }<br>
-            }<br>
+            /* trigger callback in module subtitle.c */<br>
+            var_SetInteger(p_input, "spu-syncbookmarks", mdate());<br>
             break;<br>
-        }<br>
         case ACTIONID_SUBSYNC_RESET:<br>
-        {<br>
-            var_SetTime( p_input, "spu-delay", 0);<br>
-            ClearChannels( p_intf, p_vout );<br>
-            DisplayMessage( p_vout, _( "Sub sync: delay reset" ) );<br>
-            p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
-            p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
+            /* trigger callback in module subtitle.c */<br>
+            var_SetInteger(p_input, "spu-syncreset", mdate());<br>
             break;<br>
-        }<br>
<br>
         case ACTIONID_SUBDELAY_DOWN:<br>
         case ACTIONID_SUBDELAY_UP:<br>
@@ -1067,7 +1011,30 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,<br>
     (void)psz_var;<br>
     (void)oldval;<br>
<br>
-    return PutAction( p_intf, newval.i_int );<br>
+    if ( strcmp( psz_var, "key-osdmessage") == 0)<br>
+    {<br>
+        if ( strlen(newval.psz_string) > 0 )<br>
+        {<br>
+            playlist_t *p_playlist = pl_Get( p_intf );<br>
+            input_thread_t *p_input = playlist_CurrentInput( p_playlist );<br>
+            if (p_input)<br>
+            {<br>
+                vout_thread_t *p_vout = p_input ? input_GetVout( p_input ) : NULL;// XXXXDZFEEGVDS<br>
+                if( p_vout )<br>
+                {<br>
+                    DisplayMessage(p_vout, "%s", newval.psz_string);<br>
+                    vlc_object_release( p_vout );<br>
+                }<br>
+                vlc_object_release(p_input);<br>
+            }<br>
+<br>
+        }<br>
+        return VLC_SUCCESS;<br>
+    }<br>
+    else<br>
+    {<br>
+        return PutAction( p_intf, newval.i_int );<br>
+    }<br>
 }<br>
<br>
 static void PlayBookmark( intf_thread_t *p_intf, int i_num )<br>
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c<br>
index 29922cc..3ed2040 100644<br>
--- a/modules/demux/subtitle.c<br>
+++ b/modules/demux/subtitle.c<br>
@@ -35,6 +35,7 @@<br>
 #include <vlc_plugin.h><br>
 #include <vlc_input.h><br>
 #include <vlc_memory.h><br>
+#include <vlc_interface.h><br>
<br>
 #include <ctype.h><br>
<br>
@@ -127,6 +128,16 @@ static void TextUnload( text_t * );<br>
<br>
 typedef struct<br>
 {<br>
+    /*<br>
+     * i_start and i_stop are the original subtitle timestamps.<br>
+     *<br>
+     * In order to take into account the subtitle delay (spu-delay),<br>
+     * please use<br>
+     *   adjust_subtitle_time(p_demux, my_subtitle_t.i_start)<br>
+     * instead of<br>
+     *   my_subtitle_t.i_start<br>
+     * (same goes for i_stop)<br>
+     */<br>
     int64_t i_start;<br>
     int64_t i_stop;<br>
<br>
@@ -141,6 +152,7 @@ struct demux_sys_t<br>
     es_out_id_t *es;<br>
<br>
     int64_t     i_next_demux_date;<br>
+    int64_t     i_last_demux_date;<br>
     int64_t     i_microsecperframe;<br>
<br>
     char        *psz_header;<br>
@@ -166,6 +178,14 @@ struct demux_sys_t<br>
         float f_total;<br>
         float f_factor;<br>
     } mpsub;<br>
+<br>
+    /*subtitle_delaybookmarks: placeholder for storing subtitle sync timestamps*/<br>
+    struct<br>
+    {<br>
+        int64_t i_time_subtitle;<br>
+        int64_t i_time_audio;<br>
+    } subtitle_delaybookmarks;<br>
+<br>
 };<br>
<br>
 static int  ParseMicroDvd   ( demux_t *, subtitle_t *, int );<br>
@@ -224,6 +244,76 @@ static int Control( demux_t *, int, va_list );<br>
<br>
 static void Fix( demux_t * );<br>
 static char * get_language_from_filename( const char * );<br>
+static int64_t adjust_subtitle_time( demux_t *, int64_t);<br>
+static int set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when);<br>
+<br>
+<br>
+/*****************************************************************************<br>
+ * external callbacks<br>
+ *****************************************************************************/<br>
+int subtitle_external_callback ( vlc_object_t * ,char const *, vlc_value_t old_value, vlc_value_t new_value, void * callback_data);<br>
+int subtitle_external_callback (<br>
+        vlc_object_t * object,<br>
+        char const * variable_name,<br>
+        vlc_value_t old_value,<br>
+        vlc_value_t new_value,<br>
+        void * callback_data_p_demux)<br>
+{<br>
+    demux_t *p_demux = (demux_t*)callback_data_p_demux;<br>
+    (void)object;<br>
+    (void)old_value;<br>
+    (void)new_value;<br>
+<br>
+    demux_sys_t *p_sys = p_demux->p_sys;<br>
+<br>
+    if ( ! strcmp(variable_name, "spu-bookmarkaudio") )<br>
+    {<br>
+        p_sys->subtitle_delaybookmarks.i_time_audio = p_sys->i_last_demux_date;<br>
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: bookmarked audio time"));<br>
+    }<br>
+    if ( ! strcmp(variable_name, "spu-bookmarksubtitle") )<br>
+    {<br>
+        p_sys->subtitle_delaybookmarks.i_time_subtitle = p_sys->i_last_demux_date;<br>
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: bookmarked subtitle time"));<br>
+    }<br>
+    if ( ! strcmp(variable_name, "spu-syncbookmarks") )<br>
+    {<br>
+        if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )<br>
+        {<br>
+            var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: set bookmarks first!"));<br>
+        }<br>
+        else<br>
+        {<br>
+            int64_t i_current_subdelay = var_GetTime( p_demux->p_parent, "spu-delay" );<br>
+            int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;<br>
+            int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;<br>
+            var_SetTime( p_demux->p_parent, "spu-delay", i_total_subdelay);<br>
+            char message[150];<br>
+            snprintf(message, 150,<br>
+                    _( "Sub sync: corrected %i ms (total delay = %i ms)" ),<br>
+                                    (int)(i_additional_subdelay / 1000),<br>
+                                    (int)(i_total_subdelay / 1000) );<br>
+            var_SetString(p_demux->p_libvlc, "key-osdmessage", message);<br>
+            p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
+            p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
+        }<br>
+    }<br>
+    if ( ! strcmp(variable_name, "spu-syncreset") )<br>
+    {<br>
+        var_SetTime( p_demux->p_parent, "spu-delay", 0);<br>
+        p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
+        p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
+        var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: delay reset"));<br>
+        return VLC_SUCCESS;<br>
+    }<br>
+    if ( ! strcmp(variable_name, "spu-delau") )<br>
+    {<br>
+        set_current_subtitle_by_time(p_demux, p_sys->i_last_demux_date);<br>
+    }<br>
+    return VLC_SUCCESS;<br>
+}<br>
+<br>
+<br>
<br>
 /*****************************************************************************<br>
  * Module initializer<br>
@@ -249,7 +339,26 @@ static int Open ( vlc_object_t *p_this )<br>
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );<br>
     if( p_sys == NULL )<br>
         return VLC_ENOMEM;<br>
-<br>
+<br>
+    /* reset spu-delay at Open*/<br>
+    var_SetTime( p_demux->p_parent, "spu-delay", 0 );<br>
+<br>
+    p_sys->subtitle_delaybookmarks.i_time_audio = 0;<br>
+    p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;<br>
+<br>
+<br>
+    /* Add callbacks*/<br>
+    var_Create(p_demux->p_parent, "spu-bookmarkaudio", VLC_VAR_INTEGER);<br>
+    var_Create(p_demux->p_parent, "spu-bookmarksubtitle", VLC_VAR_INTEGER);<br>
+    var_Create(p_demux->p_parent, "spu-syncbookmarks", VLC_VAR_INTEGER);<br>
+    var_Create(p_demux->p_parent, "spu-syncreset", VLC_VAR_INTEGER);<br>
+    var_AddCallback( p_demux->p_parent, "spu-bookmarkaudio", &subtitle_external_callback, p_this );<br>
+    var_AddCallback( p_demux->p_parent, "spu-bookmarksubtitle", &subtitle_external_callback, p_this );<br>
+    var_AddCallback( p_demux->p_parent, "spu-syncbookmarks", &subtitle_external_callback, p_this );<br>
+    var_AddCallback( p_demux->p_parent, "spu-syncreset", &subtitle_external_callback, p_this );<br>
+    var_AddCallback( p_demux->p_parent, "spu-delay", &subtitle_external_callback, p_this );<br>
+<br>
+<br>
     p_sys->psz_header         = NULL;<br>
     p_sys->i_subtitle         = 0;<br>
     p_sys->i_subtitles        = 0;<br>
@@ -579,8 +688,21 @@ static void Close( vlc_object_t *p_this )<br>
 {<br>
     demux_t *p_demux = (demux_t*)p_this;<br>
     demux_sys_t *p_sys = p_demux->p_sys;<br>
-    int i;<br>
<br>
+    /* Remove callbacks*/<br>
+    var_DelCallback( p_demux->p_parent, "spu-bookmarkaudio", &subtitle_external_callback, p_this );<br>
+    var_DelCallback( p_demux->p_parent, "spu-bookmarksubtitle", &subtitle_external_callback, p_this );<br>
+    var_DelCallback( p_demux->p_parent, "spu-syncbookmarks", &subtitle_external_callback, p_this );<br>
+    var_DelCallback( p_demux->p_parent, "spu-syncreset", &subtitle_external_callback, p_this );<br>
+<br>
+    var_DelCallback( p_demux->p_parent, "spu-delay", &subtitle_external_callback, p_this );<br>
+    var_Destroy(p_demux->p_parent, "spu-bookmarkaudio");<br>
+    var_Destroy(p_demux->p_parent, "spu-bookmarksubtitle");<br>
+    var_Destroy(p_demux->p_parent, "spu-syncbookmarks");<br>
+    var_Destroy(p_demux->p_parent, "spu-syncreset");<br>
+<br>
+<br>
+    int i;<br>
     for( i = 0; i < p_sys->i_subtitles; i++ )<br>
         free( p_sys->subtitle[i].psz_text );<br>
     free( p_sys->subtitle );<br>
@@ -591,6 +713,31 @@ static void Close( vlc_object_t *p_this )<br>
 /*****************************************************************************<br>
  * Control:<br>
  *****************************************************************************/<br>
+<br>
+/* Utlity function : sets the current subtitle index (p_sys->i_subtitle)<br>
+ * based on the time<br>
+ */<br>
+static int set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when)<br>
+{<br>
+    demux_sys_t *p_sys = p_demux->p_sys;<br>
+<br>
+    p_sys->i_subtitle = 0;<br>
+    while( p_sys->i_subtitle < p_sys->i_subtitles )<br>
+    {<br>
+        const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];<br>
+        if( adjust_subtitle_time(p_demux, p_subtitle->i_start) > i64_when )<br>
+            break;<br>
+        if( p_subtitle->i_stop > p_subtitle->i_start && adjust_subtitle_time(p_demux, p_subtitle->i_stop) > i64_when )<br>
+            break;<br>
+<br>
+        p_sys->i_subtitle++;<br>
+    }<br>
+<br>
+    if( p_sys->i_subtitle >= p_sys->i_subtitles )<br>
+        return VLC_EGENERIC;<br>
+    return VLC_SUCCESS;<br>
+}<br>
+<br>
 static int Control( demux_t *p_demux, int i_query, va_list args )<br>
 {<br>
     demux_sys_t *p_sys = p_demux->p_sys;<br>
@@ -608,29 +755,14 @@ static int Control( demux_t *p_demux, int i_query, va_list args )<br>
             pi64 = (int64_t*)va_arg( args, int64_t * );<br>
             if( p_sys->i_subtitle < p_sys->i_subtitles )<br>
             {<br>
-                *pi64 = p_sys->subtitle[p_sys->i_subtitle].i_start;<br>
+                *pi64 = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start);<br>
                 return VLC_SUCCESS;<br>
             }<br>
             return VLC_EGENERIC;<br>
<br>
         case DEMUX_SET_TIME:<br>
             i64 = (int64_t)va_arg( args, int64_t );<br>
-            p_sys->i_subtitle = 0;<br>
-            while( p_sys->i_subtitle < p_sys->i_subtitles )<br>
-            {<br>
-                const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];<br>
-<br>
-                if( p_subtitle->i_start > i64 )<br>
-                    break;<br>
-                if( p_subtitle->i_stop > p_subtitle->i_start && p_subtitle->i_stop > i64 )<br>
-                    break;<br>
-<br>
-                p_sys->i_subtitle++;<br>
-            }<br>
-<br>
-            if( p_sys->i_subtitle >= p_sys->i_subtitles )<br>
-                return VLC_EGENERIC;<br>
-            return VLC_SUCCESS;<br>
+            return set_current_subtitle_by_time(p_demux, i64);<br>
<br>
         case DEMUX_GET_POSITION:<br>
             pf = (double*)va_arg( args, double * );<br>
@@ -640,7 +772,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )<br>
             }<br>
             else if( p_sys->i_subtitles > 0 )<br>
             {<br>
-                *pf = (double)p_sys->subtitle[p_sys->i_subtitle].i_start /<br>
+                int64_t i_start_adjust = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start);<br>
+                *pf = (double) ( i_start_adjust ) /<br>
                       (double)p_sys->i_length;<br>
             }<br>
             else<br>
@@ -655,7 +788,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )<br>
<br>
             p_sys->i_subtitle = 0;<br>
             while( p_sys->i_subtitle < p_sys->i_subtitles &&<br>
-                   p_sys->subtitle[p_sys->i_subtitle].i_start < i64 )<br>
+                   adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) < i64 )<br>
             {<br>
                 p_sys->i_subtitle++;<br>
             }<br>
@@ -682,6 +815,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )<br>
     }<br>
 }<br>
<br>
+<br>
 /*****************************************************************************<br>
  * Demux: Send subtitle to decoder<br>
  *****************************************************************************/<br>
@@ -693,15 +827,15 @@ static int Demux( demux_t *p_demux )<br>
     if( p_sys->i_subtitle >= p_sys->i_subtitles )<br>
         return 0;<br>
<br>
-    i_maxdate = p_sys->i_next_demux_date - var_GetTime( p_demux->p_parent, "spu-delay" );;<br>
+    i_maxdate = p_sys->i_next_demux_date;<br>
     if( i_maxdate <= 0 && p_sys->i_subtitle < p_sys->i_subtitles )<br>
     {<br>
         /* Should not happen */<br>
-        i_maxdate = p_sys->subtitle[p_sys->i_subtitle].i_start + 1;<br>
+        i_maxdate = adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) + 1;<br>
     }<br>
-<br>
+<br>
     while( p_sys->i_subtitle < p_sys->i_subtitles &&<br>
-           p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )<br>
+           adjust_subtitle_time(p_demux, p_sys->subtitle[p_sys->i_subtitle].i_start) < i_maxdate )<br>
     {<br>
         const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];<br>
<br>
@@ -721,9 +855,9 @@ static int Demux( demux_t *p_demux )<br>
         }<br>
<br>
         p_block->i_dts =<br>
-        p_block->i_pts = VLC_TS_0 + p_subtitle->i_start;<br>
+        p_block->i_pts = VLC_TS_0 + adjust_subtitle_time(p_demux, p_subtitle->i_start);<br>
         if( p_subtitle->i_stop >= 0 && p_subtitle->i_stop >= p_subtitle->i_start )<br>
-            p_block->i_length = p_subtitle->i_stop - p_subtitle->i_start;<br>
+            p_block->i_length = adjust_subtitle_time(p_demux, p_subtitle->i_stop) - adjust_subtitle_time(p_demux, p_subtitle->i_start);<br>
<br>
         memcpy( p_block->p_buffer, p_subtitle->psz_text, i_len );<br>
<br>
@@ -733,11 +867,28 @@ static int Demux( demux_t *p_demux )<br>
     }<br>
<br>
     /* */<br>
+    p_sys->i_last_demux_date = p_sys->i_next_demux_date;<br>
     p_sys->i_next_demux_date = 0;<br>
<br>
     return 1;<br>
 }<br>
<br>
+<br>
+/*****************************************************************************<br>
+ * adjust_subtitle_time : receives a subtitle timestamp as input<br>
+ *                     (p_subtitle->i_start or p_subtitle->i_stop)<br>
+ *                      and returns that timestamp corrected<br>
+ *                      by spu-delay<br>
+ *****************************************************************************/<br>
+static int64_t adjust_subtitle_time( demux_t * p_demux, int64_t i64_when)<br>
+{<br>
+    int64_t spu_delay = var_GetTime( p_demux->p_parent, "spu-delay" );<br>
+    int64_t i64_adjust = i64_when + spu_delay;<br>
+    return i64_adjust;<br>
+}<br>
+<br>
+<br>
+<br>
 /*****************************************************************************<br>
  * Fix: fix time stamp and order of subtitle<br>
  *****************************************************************************/<br>
diff --git a/modules/gui/macosx/TrackSynchronization.m b/modules/gui/macosx/TrackSynchronization.m<br>
index c0b8f3c..a5ddce3 100644<br>
--- a/modules/gui/macosx/TrackSynchronization.m<br>
+++ b/modules/gui/macosx/TrackSynchronization.m<br>
@@ -65,7 +65,22 @@ static VLCTrackSynchronization *_o_sharedInstance = nil;<br>
     [o_sv_lbl setStringValue: _NS("Subtitles/Video")];<br>
     [o_sv_advance_lbl setStringValue: _NS("Subtitle track synchronization:")];<br>
     [[o_sv_advance_value_fld formatter] setFormat:[NSString stringWithFormat:@"#,##0.000 %@", _NS("s")]];<br>
-    [o_sv_advance_value_fld setToolTip: _NS("A positive value means that the subtitles are ahead of the video")];<br>
+    [o_sv_advance_value_fld setToolTip:<br>
+        _NS(<br>
+            "A positive value means that the subtitles are ahead of the video\n"<br>
+            "\n"\<br>
+            "In order to set the subtitle track synchronization delay easily, \n"\<br>
+            "you can use the hotkeys :\n"\<br>
+            "\n"\<br>
+            "* Shift-H (audio bookmark)\n"\<br>
+            "* Shift-J (subtitle bookmark) \n"\<br>
+            "* Shift-K (sync bookmarks)\n"\<br>
+            "\n"\<br>
+            "(Command-Shift-K resets the delay)\n"\<br>
+            "\n"\<br>
+            "(Use these hotkeys directly on the video)\n"<br>
+            )<br>
+    ];<br>
     [o_sv_speed_lbl setStringValue: _NS("Subtitle speed:")];<br>
     [[o_sv_speed_value_fld formatter] setFormat:[NSString stringWithFormat:@"#,##0.000 %@", _NS("fps")]];<br>
     [o_sv_dur_lbl setStringValue: _NS("Subtitle duration factor:")];<br>
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m<br>
index 8f46abb..26b6675 100644<br>
--- a/modules/gui/macosx/intf.m<br>
+++ b/modules/gui/macosx/intf.m<br>
@@ -358,7 +358,6 @@ static int InputEvent(vlc_object_t *p_this, const char *psz_var,<br>
             break;<br>
<br>
         case INPUT_EVENT_AUDIO_DELAY:<br>
-        case INPUT_EVENT_SUBTITLE_DELAY:<br>
             [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateDelays) withObject:nil waitUntilDone:NO];<br>
             break;<br>
<br>
diff --git a/modules/gui/qt4/components/extended_panels.cpp b/modules/gui/qt4/components/extended_panels.cpp<br>
index 84d16ae..4dd0f7d 100644<br>
--- a/modules/gui/qt4/components/extended_panels.cpp<br>
+++ b/modules/gui/qt4/components/extended_panels.cpp<br>
@@ -1475,7 +1475,21 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent ) :<br>
<br>
     subsSpin = new SyncWidget( this );<br>
     subsLayout->addWidget( subsSpin, 0, 2, 1, 1 );<br>
-<br>
+    QString subsSpin_Tooltip = qtr(<br>
+        "In order to set the subtitle track synchronization delay easily, \n"\<br>
+        "you can use the hotkeys :\n"\<br>
+        "\n"\<br>
+        "* Shift-H (audio bookmark)\n"\<br>
+        "* Shift-J (subtitle bookmark) \n"\<br>
+        "* Shift-K (sync bookmarks)\n"\<br>
+        "\n"\<br>
+        "(Ctrl-Shift-K resets the delay)\n"\<br>
+        "\n"\<br>
+        "(Use these hotkeys directly on the video)\n"<br>
+    );<br>
+    subsSpin->setToolTip(subsSpin_Tooltip);<br>
+    subsLabel->setToolTip(subsSpin_Tooltip);<br>
+<br>
     QLabel *subSpeedLabel = new QLabel;<br>
     subSpeedLabel->setText( qtr( "Subtitle speed:" ) );<br>
     subsLayout->addWidget( subSpeedLabel, 1, 0, 1, 1 );<br>
diff --git a/modules/gui/qt4/input_manager.cpp b/modules/gui/qt4/input_manager.cpp<br>
index c07f712..ef9ec66 100644<br>
--- a/modules/gui/qt4/input_manager.cpp<br>
+++ b/modules/gui/qt4/input_manager.cpp<br>
@@ -377,7 +377,6 @@ static int InputEvent( vlc_object_t *p_this, const char *,<br>
         break;<br>
<br>
     case INPUT_EVENT_AUDIO_DELAY:<br>
-    case INPUT_EVENT_SUBTITLE_DELAY:<br>
         event = new IMEvent( IMEvent::SynchroChanged );<br>
         break;<br>
<br>
diff --git a/src/input/event.c b/src/input/event.c<br>
index 453e04b..f4ca0d6 100644<br>
--- a/src/input/event.c<br>
+++ b/src/input/event.c<br>
@@ -112,16 +112,6 @@ void input_SendEventAudioDelay( input_thread_t *p_input, mtime_t i_delay )<br>
     Trigger( p_input, INPUT_EVENT_AUDIO_DELAY );<br>
 }<br>
<br>
-void input_SendEventSubtitleDelay( input_thread_t *p_input, mtime_t i_delay )<br>
-{<br>
-    vlc_value_t val;<br>
-<br>
-    val.i_time = i_delay;<br>
-    var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );<br>
-<br>
-    Trigger( p_input, INPUT_EVENT_SUBTITLE_DELAY );<br>
-}<br>
-<br>
 /* TODO and file name ? */<br>
 void input_SendEventRecord( input_thread_t *p_input, bool b_recording )<br>
 {<br>
diff --git a/src/input/event.h b/src/input/event.h<br>
index c8f1071..b3c4b56 100644<br>
--- a/src/input/event.h<br>
+++ b/src/input/event.h<br>
@@ -36,7 +36,6 @@ void input_SendEventLength( input_thread_t *p_input, mtime_t i_length );<br>
 void input_SendEventStatistics( input_thread_t *p_input );<br>
 void input_SendEventRate( input_thread_t *p_input, int i_rate );<br>
 void input_SendEventAudioDelay( input_thread_t *p_input, mtime_t i_delay );<br>
-void input_SendEventSubtitleDelay( input_thread_t *p_input, mtime_t i_delay );<br>
 void input_SendEventRecord( input_thread_t *p_input, bool b_recording );<br>
 void input_SendEventTitle( input_thread_t *p_input, int i_title );<br>
 void input_SendEventSeekpoint( input_thread_t *p_input, int i_title, int i_seekpoint );<br>
diff --git a/src/input/input.c b/src/input/input.c<br>
index 7e71d4e..6d4bc4a 100644<br>
--- a/src/input/input.c<br>
+++ b/src/input/input.c<br>
@@ -1102,8 +1102,7 @@ static void UpdatePtsDelay( input_thread_t *p_input )<br>
<br>
     /* Take care of audio/spu delay */<br>
     const mtime_t i_audio_delay = var_GetTime( p_input, "audio-delay" );<br>
-    const mtime_t i_spu_delay   = var_GetTime( p_input, "spu-delay" );<br>
-    const mtime_t i_extra_delay = __MIN( i_audio_delay, i_spu_delay );<br>
+    const mtime_t i_extra_delay = i_audio_delay;<br>
     if( i_extra_delay < 0 )<br>
         i_pts_delay -= i_extra_delay;<br>
<br>
@@ -1112,7 +1111,6 @@ static void UpdatePtsDelay( input_thread_t *p_input )<br>
<br>
     /* */<br>
     es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, i_audio_delay );<br>
-    es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, i_spu_delay );<br>
     es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, 0, i_cr_average );<br>
 }<br>
<br>
@@ -1871,12 +1869,6 @@ static bool Control( input_thread_t *p_input,<br>
             input_SendEventAudioDelay( p_input, val.i_time );<br>
             UpdatePtsDelay( p_input );<br>
             break;<br>
-<br>
-        case INPUT_CONTROL_SET_SPU_DELAY:<br>
-            input_SendEventSubtitleDelay( p_input, val.i_time );<br>
-            UpdatePtsDelay( p_input );<br>
-            break;<br>
-<br>
         case INPUT_CONTROL_SET_TITLE:<br>
         case INPUT_CONTROL_SET_TITLE_NEXT:<br>
         case INPUT_CONTROL_SET_TITLE_PREV:<br>
diff --git a/src/input/input_internal.h b/src/input/input_internal.h<br>
index 9f71294..9e534d9 100644<br>
--- a/src/input/input_internal.h<br>
+++ b/src/input/input_internal.h<br>
@@ -202,7 +202,6 @@ enum input_control_e<br>
     INPUT_CONTROL_RESTART_ES,<br>
<br>
     INPUT_CONTROL_SET_AUDIO_DELAY,<br>
-    INPUT_CONTROL_SET_SPU_DELAY,<br>
<br>
     INPUT_CONTROL_ADD_SLAVE,<br>
<br>
diff --git a/src/input/var.c b/src/input/var.c<br>
index 3e722f4..293babd 100644<br>
--- a/src/input/var.c<br>
+++ b/src/input/var.c<br>
@@ -97,7 +97,6 @@ static const vlc_input_callback_t p_input_callbacks[] =<br>
     CALLBACK( "title", TitleCallback ),<br>
     CALLBACK( "chapter", SeekpointCallback ),<br>
     CALLBACK( "audio-delay", EsDelayCallback ),<br>
-    CALLBACK( "spu-delay", EsDelayCallback ),<br>
     CALLBACK( "video-es", ESCallback ),<br>
     CALLBACK( "audio-es", ESCallback ),<br>
     CALLBACK( "spu-es", ESCallback ),<br>
@@ -787,10 +786,6 @@ static int EsDelayCallback ( vlc_object_t *p_this, char const *psz_cmd,<br>
     {<br>
         input_ControlPush( p_input, INPUT_CONTROL_SET_AUDIO_DELAY, &newval );<br>
     }<br>
-    else if( !strcmp( psz_cmd, "spu-delay" ) )<br>
-    {<br>
-        input_ControlPush( p_input, INPUT_CONTROL_SET_SPU_DELAY, &newval );<br>
-    }<br>
     return VLC_SUCCESS;<br>
 }<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
1.9.1<br>
<br>
_______________________________________________<br>
vlc-devel mailing list<br>
To unsubscribe or modify your subscription options:<br>
<a href="https://mailman.videolan.org/listinfo/vlc-devel" target="_blank">https://mailman.videolan.org/listinfo/vlc-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Félix Abecassis<div><a href="http://felix.abecassis.me" target="_blank">http://felix.abecassis.me</a></div>
</div>