[vlc-devel] [PATCH 4/5] Subtitle Sync : added a convenient way to adjust subtitle fps
Pascal Thomet
pthomet at gmail.com
Mon Jun 9 21:00:26 CEST 2014
Principle:
**********
* All of this is limited to *file* subtitles (DVD and DVB are not concerned)
* If the user needs to sync twice the delay, and if he does this at two different positions
in the movie (separated by at least 45 seconds), a fps ratio will be calculated and proposed
if it seems to be valid.
* The user will be asked to re-confirm the speed adjustment
* Care has been taken in order to avoid user errors:
The subtitle fps will only be adjusted if the calculated speed ratio is close to a valid one.
The only fps considered are { 23.976f, 24.f, 25.f, 30.f } (most common movies fps)
A valid ratio is under the form a / b
where a and b are members of { 23.976f, 24.f, 25.f, 30.f }
---
.../macosx/Resources/English.lproj/SyncTracks.xib | 22 +-
modules/control/hotkeys.c | 18 +-
modules/demux/subtitle.c | 358 +++++++++++++++++++--
modules/gui/qt4/components/extended_panels.cpp | 18 +-
src/input/var.c | 1 -
5 files changed, 383 insertions(+), 34 deletions(-)
diff --git a/extras/package/macosx/Resources/English.lproj/SyncTracks.xib b/extras/package/macosx/Resources/English.lproj/SyncTracks.xib
index bf0ecaa..9cb68a6 100644
--- a/extras/package/macosx/Resources/English.lproj/SyncTracks.xib
+++ b/extras/package/macosx/Resources/English.lproj/SyncTracks.xib
@@ -31,10 +31,24 @@
subsVisualSyncLayout->addWidget( buttonBookmarkAudio, 0, 0, 1, 1 );
CONNECT( buttonBookmarkAudio, pressed(), this, bookmarkAudio() ) ;
- QPushButton *buttonBookmarkSubtitle = new QPushButton(_("Bookmark subtitle"));
- buttonBookmarkSubtitle->setToolTip(_("You can also use Shift-J on the video"));
- subsVisualSyncLayout->addWidget( buttonBookmarkSubtitle, 0, 1, 1, 1 );
- CONNECT( buttonBookmarkSubtitle, pressed(), this, bookmarkSubtitle() ) ;
+ QPushButton *buttonBookmarkSync = new QPushButton(_("Sync subtitles"));
+ QString buttonBookmarkSync_Tooltip = qtr(
+ "You can also use Shift-K on the video\n"\
+ "\n"\
+ "\n"\
+ "If the subtitle has a different fps,\n"\
+ "(ie the delay varies during the movie):\n"\
+ "\n"\
+ "* sync the subtitles at the beginning of the video\n"\
+ "* fast forward a few minutes in the movie\n"\
+ "* then resync the subtitles.\n"\
+ "\n"\
+ "If applicable, you will be asked to change the fps\n"\
+ "of the subtitle.\n"\
+ );
+ buttonBookmarkSync->setToolTip( buttonBookmarkSync_Tooltip );
+ subsVisualSyncLayout->addWidget( buttonBookmarkSync, 0, 2, 1, 1 );
+ CONNECT( buttonBookmarkSync, pressed(), this, syncBookmarks() ) ;
QPushButton *buttonBookmarkSync = new QPushButton(_("Sync subtitles"));
buttonBookmarkSync->setToolTip(_("You can also use Shift-K on the video"));
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index e32c389..a45346d 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -1013,6 +1013,14 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,
if ( strcmp( psz_var, "key-osdmessage") == 0)
{
+ /* Add stars around the OSD to increase its duration (this is a hack, yes! )*/
+ int osd_duration = 1000000;
+ if ( ( strlen(newval.psz_string) > 0) && ( newval.psz_string[0] == '*' ) )
+ osd_duration *= 2;
+ if ( ( strlen(newval.psz_string) > 1) && ( newval.psz_string[1] == '*' ) )
+ osd_duration *= 2;
+ if ( ( strlen(newval.psz_string) > 2) && ( newval.psz_string[1] == '*' ) )
+ osd_duration *= 2;
if ( strlen(newval.psz_string) > 0 )
{
playlist_t *p_playlist = pl_Get( p_intf );
@@ -1022,12 +1030,18 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,
vout_thread_t *p_vout = p_input ? input_GetVout( p_input ) : NULL;// XXXXDZFEEGVDS
if( p_vout )
{
- DisplayMessage(p_vout, "%s", newval.psz_string);
+ do
+ {
+ vout_OSDText(
+ p_vout, SPU_DEFAULT_CHANNEL,
+ SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_LEFT,
+ osd_duration,
+ newval.psz_string);
+ } while(0);
vlc_object_release( p_vout );
}
vlc_object_release(p_input);
}
-
}
return VLC_SUCCESS;
}
diff --git a/modules/demux/subtitle.c b/modules/demux/subtitle.c
index 81d0a76..4d72061 100644
--- a/modules/demux/subtitle.c
+++ b/modules/demux/subtitle.c
@@ -30,7 +30,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-
+#include <math.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_input.h>
@@ -144,6 +144,23 @@ typedef struct
char *psz_text;
} subtitle_t;
+/* The only fps considered valid are : { 23.976f, 24.f, 25.f, 30.f }
+ * 13 = 1 + nb of partial permutations of 2 elements in a set of 4 := 1 + 4! / (4 - 2 ) !
+ * We add one in order to store a fps_ratio = 1.f
+ */
+#define NB_SUB_FPS_ADJUSTS 13
+typedef struct sub_fps_adjust
+{
+ float fps_ratio;
+ char sz_desc[15];
+} sub_fps_adjust;
+
+struct sub_speed_delay
+{
+ int64_t sub_delay;
+ int idx_sub_fps_adjust;
+};
+
struct demux_sys_t
{
@@ -184,8 +201,17 @@ struct demux_sys_t
{
int64_t i_time_subtitle;
int64_t i_time_audio;
+ int64_t i_time_subtitle_n_1;
+ int64_t i_time_audio_n_1;
} subtitle_delaybookmarks;
+ /*lists of possible subtitle fps adjustments*/
+ sub_fps_adjust sub_fps_adjusts[NB_SUB_FPS_ADJUSTS];
+
+ /* holds a delay + speed change that needs user confirmation*/
+ struct sub_speed_delay sub_speed_delay_user_confirm;
+ /*holds the current speed and delay*/
+ struct sub_speed_delay sub_speed_delay_current;
};
static int ParseMicroDvd ( demux_t *, subtitle_t *, int );
@@ -249,6 +275,290 @@ static int set_current_subtitle_by_time(demux_t *p_demux, int64_t i64_when);
/*****************************************************************************
+ * Compute subtitles delay and speed
+ *****************************************************************************/
+
+static float GetDemuxSubSpeed(demux_t *p_demux)
+{
+ return p_demux->p_sys->sub_fps_adjusts[ p_demux->p_sys->sub_speed_delay_current.idx_sub_fps_adjust ].fps_ratio;
+}
+
+static int64_t GetDemuxSubDelay(demux_t *p_demux)
+{
+ return p_demux->p_sys->sub_speed_delay_current.sub_delay;
+}
+
+static void SetDemuxSubDelay(demux_t *p_demux, int64_t delay)
+{
+ p_demux->p_sys->sub_speed_delay_current.sub_delay = delay;
+ var_SetTime(p_demux->p_parent, "spu-delay", delay);
+}
+
+static void LogDelays(demux_t *p_demux)
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ msg_Dbg(p_demux,
+ "ApplySubtitleDelayAndSpeed : audio0=%li sub0=%li audio1=%li sub1=%li",
+ (p_sys->subtitle_delaybookmarks.i_time_audio_n_1) / 1000,
+ (p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1) / 1000,
+ (p_sys->subtitle_delaybookmarks.i_time_audio) / 1000,
+ (p_sys->subtitle_delaybookmarks.i_time_subtitle) / 1000
+ );
+}
+static void Log_speed_delay(demux_t *p_demux)
+{
+ int64_t sub_delay = GetDemuxSubDelay(p_demux);
+ float sub_speed = GetDemuxSubSpeed(p_demux);
+ msg_Dbg(p_demux,
+ "sub_speed: %.2f spu-delay : %li",
+ sub_speed,
+ sub_delay / 1000
+ );
+}
+
+/* Fills the lists of possible subtitle fps adjustments
+ * The only fps considered valid are :
+ * { 23.976f, 24.f, 25.f, 30.f }
+ * Subtitle sync will only propose speed adjustments
+ * with valid ratios.
+ * A valid ratio is under the form a / b
+ * where a and b are members of { 23.976f, 24.f, 25.f, 30.f }
+ */
+static void fill_sub_fps_adjusts(demux_t *p_demux)
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ float fps_list[] = { 23.976f, 24.f, 25.f, 30.f };
+ int i, j;
+ float nb_fps = 4;
+
+ p_sys->sub_fps_adjusts[0].fps_ratio = 1.f;
+ p_sys->sub_fps_adjusts[0].sz_desc[0] = '\0';
+
+ int cur_id = 1;//will vary between 1 and NB_SUB_FPS_ADJUSTS - 1
+ for (i = 0; i < nb_fps; i++)
+ {
+ for (j = 0; j < nb_fps; j++)
+ {
+ if (j != i)
+ {
+ p_sys->sub_fps_adjusts[ cur_id ].fps_ratio = fps_list[i] / fps_list[j];
+ snprintf(p_sys->sub_fps_adjusts[ cur_id ].sz_desc, 15,
+ "%.6g->%.6g fps", fps_list[i], fps_list[j]);
+ cur_id ++;
+ }
+ }
+ }
+}
+
+/*
+ * Returns 1 if a change of subtitle speed (aka fps) is advisable, 0 otherwise
+ */
+static int ComputeSubSpeedAndDelay( demux_t *p_demux, struct sub_speed_delay * out_sub_speed_delay )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ /* If we do not have older bookmarks, cancel! */
+ if ( ( p_sys->subtitle_delaybookmarks.i_time_audio_n_1 <= 0 )
+ || ( p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 <= 0 ) )
+ {
+ return 0;
+ }
+
+ /*No need to do it if there is less than 45 seconds between now and the last bookmarks
+ (the user is probably readjusting the delay)*/
+ int64_t min_delay = 45 * 1000 * 1000;
+ if ( p_sys->subtitle_delaybookmarks.i_time_subtitle
+ - p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 < min_delay )
+ {
+ return 0;
+ }
+
+ /* If the speed was already adjusted, cancel,
+ * unless we have a duration > 5 minutes between the two samples, in which
+ * case, we can fine-tune the speed
+ */
+ int64_t min_delay_with_speed_already_set = 60 * 5 * 1000 * 1000;
+ if ( ( p_sys->sub_speed_delay_current.idx_sub_fps_adjust != 0 )
+ && ( p_sys->subtitle_delaybookmarks.i_time_subtitle
+ - p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 < min_delay_with_speed_already_set )
+ )
+ {
+ return 0;
+ }
+
+ float audio0 = (float)p_sys->subtitle_delaybookmarks.i_time_audio_n_1 / 1000.f;
+ float subtitle0 = p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 / 1000.f;
+ float audio1 = (float)p_sys->subtitle_delaybookmarks.i_time_audio / 1000.f;
+ float subtitle1 = p_sys->subtitle_delaybookmarks.i_time_subtitle / 1000.f;
+
+ float time0 = __MAX(audio0, subtitle0);
+ float time1 = __MAX(audio1, subtitle1);
+ int64_t i_delay0 = GetDemuxSubDelay(p_demux);
+ float delay0 = (float)i_delay0 / 1000.f;
+ int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
+ float delay1 = delay0 + (float)i_additional_subdelay / 1000.f;
+
+ float sub_speed = 1.f / ( (time1 + delay1) - (time0 + delay0) ) * (time1 - time0);
+ float sub_delay = delay0 + (0.f - time0 ) * ( delay1 - delay0 ) / (time1 - time0);
+
+ msg_Dbg(p_demux, "ComputeSubSpeedAndDelay speed=%.2f delay=%.0f",
+ sub_speed, sub_delay);
+
+ /*
+ * We now have a speed ratio candidate.
+ * We then compare it to the list of possible speed ratios,
+ * and we check if one the ratios is applicable
+ * ==> We will select the closest ratio amongst the applicable ratios
+ */
+ int i;
+ int idx_closest_ratio = -1;
+ float error_closest_ratio = 1E5;
+ /* we allow 33% of user error, i.e if the desired ratio is
+ * 24 / 25 fps = 0.96
+ * then we allow it to vary between 0.96 +/- 0.33 * (1 - 0.96)
+ * ie between 0.9468 and 0.9732
+ */
+ float max_error_applicable = 0.33;
+ for ( i = 0; i < NB_SUB_FPS_ADJUSTS; i++)
+ {
+ /* do not forget to substract 1 in order to have a usable ratio ! */
+ float ratio_ratio =
+ ( sub_speed - 1.f)
+ / ( p_sys->sub_fps_adjusts[i].fps_ratio - 1.f );
+ float error_this_ratio = fabs ( ratio_ratio - 1.f );
+
+ if ( ( error_this_ratio < max_error_applicable) && ( error_this_ratio < error_closest_ratio ) )
+ {
+ error_closest_ratio = error_this_ratio;
+ idx_closest_ratio = i;
+ }
+ }
+
+ if (idx_closest_ratio >= 0)
+ {
+ float spu_delay_applicable = delay0 + (0.f - time0 ) * ( delay1 - delay0 ) / (time1 - time0);
+ out_sub_speed_delay->sub_delay = (int64_t) (spu_delay_applicable * 1000.f );
+ out_sub_speed_delay->idx_sub_fps_adjust = idx_closest_ratio;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/* Returns 1 if a change of delay is possible, 0 otherwise*/
+static int ComputeSubDelay_Only( demux_t *p_demux, struct sub_speed_delay * out_sub_speed_delay )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )
+ {
+ char osd_message[200];
+ snprintf(osd_message, 200,
+ _("Sub sync: set bookmarks first! (delay=%li %s)"),
+ p_sys->sub_speed_delay_current.sub_delay / 1000,
+ p_sys->sub_fps_adjusts[p_sys->sub_speed_delay_current.idx_sub_fps_adjust].sz_desc
+ );
+ var_SetString(p_demux->p_libvlc, "key-osdmessage", osd_message);
+ return 0;
+ }
+
+ int64_t i_previous_subdelay = GetDemuxSubDelay(p_demux);
+ int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
+ int64_t i_current_subdelay = i_previous_subdelay + i_additional_subdelay;
+
+ out_sub_speed_delay->sub_delay = i_current_subdelay;
+ out_sub_speed_delay->idx_sub_fps_adjust = p_sys->sub_speed_delay_current.idx_sub_fps_adjust;
+ return 1;
+}
+
+static void Apply_sub_speed_delay(demux_t *p_demux, struct sub_speed_delay speed_delay,
+ int enable_osd)
+{
+ char osd_message[200];
+ demux_sys_t *p_sys = p_demux->p_sys;
+ if ( speed_delay.idx_sub_fps_adjust == 0 )
+ {
+ snprintf(
+ osd_message, 200,
+ _( "Sub sync: corrected, total delay = %li ms"),
+ speed_delay.sub_delay / 1000
+ );
+ }
+ else
+ {
+ snprintf(
+ osd_message, 200,
+ _( "Sub sync: corrected, delay = %li ms / %s"),
+ speed_delay.sub_delay / 1000,
+ p_sys->sub_fps_adjusts[speed_delay.idx_sub_fps_adjust].sz_desc
+ );
+ }
+ if (enable_osd)
+ var_SetString(p_demux->p_libvlc, "key-osdmessage", osd_message);
+
+ p_sys->sub_speed_delay_current = speed_delay;
+ SetDemuxSubDelay(p_demux, speed_delay.sub_delay);
+ set_current_subtitle_by_time(p_demux, p_sys->i_last_demux_date);
+}
+
+static void ApplySubtitleDelay(demux_t *p_demux)
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ LogDelays(p_demux);
+
+ struct sub_speed_delay speed_delay;
+
+ if (
+ ( p_sys->sub_speed_delay_user_confirm.idx_sub_fps_adjust >= 0)
+ && ( p_sys->subtitle_delaybookmarks.i_time_audio == 0 )
+ && ( p_sys->subtitle_delaybookmarks.i_time_subtitle == 0 )
+ )
+ {
+ Apply_sub_speed_delay(p_demux, p_sys->sub_speed_delay_user_confirm, 1);
+ p_sys->sub_speed_delay_user_confirm.idx_sub_fps_adjust = -1;
+ }
+ else
+ {
+ p_sys->sub_speed_delay_user_confirm.idx_sub_fps_adjust = -1;
+
+ int enable_osd = 1;
+ if ( ComputeSubSpeedAndDelay( p_demux, &speed_delay ) )
+ {
+ char osd_message[200];
+ snprintf( osd_message, 200,
+ _("** Press \"Sync subtitles\" (Shift-K) again to correct fps: %s fps **"),
+ p_sys->sub_fps_adjusts[ speed_delay.idx_sub_fps_adjust ].sz_desc
+ );
+ var_SetString(p_demux->p_libvlc, "key-osdmessage", osd_message);
+ enable_osd = 0;
+
+ p_sys->sub_speed_delay_user_confirm = speed_delay;
+ }
+
+ if ( ComputeSubDelay_Only( p_demux, &speed_delay ) )
+ Apply_sub_speed_delay(p_demux, speed_delay, enable_osd);
+ }
+
+
+ //Store old timestamps in n-1 bookmarks
+ p_sys->subtitle_delaybookmarks.i_time_audio_n_1 = p_sys->subtitle_delaybookmarks.i_time_audio;
+ p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 = p_sys->subtitle_delaybookmarks.i_time_subtitle;
+ //Clear current bookmarks
+ p_sys->subtitle_delaybookmarks.i_time_audio = 0;
+ p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+
+ Log_speed_delay(p_demux);
+}
+
+
+
+
+
+/*****************************************************************************
* external callbacks
*****************************************************************************/
int subtitle_external_callback ( vlc_object_t * ,char const *, vlc_value_t old_value, vlc_value_t new_value, void * callback_data);
@@ -278,36 +588,23 @@ int subtitle_external_callback (
}
if ( ! strcmp(variable_name, "sub-syncbookmarks") )
{
- if ( (p_sys->subtitle_delaybookmarks.i_time_audio == 0) || (p_sys->subtitle_delaybookmarks.i_time_subtitle == 0) )
- {
- var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: set bookmarks first!"));
- }
- else
- {
- int64_t i_current_subdelay = var_GetTime( p_demux->p_parent, "spu-delay" );
- int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
- int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;
- var_SetTime( p_demux->p_parent, "spu-delay", i_total_subdelay);
- char message[150];
- snprintf(message, 150,
- _( "Sub sync: corrected %i ms (total delay = %i ms)" ),
- (int)(i_additional_subdelay / 1000),
- (int)(i_total_subdelay / 1000) );
- var_SetString(p_demux->p_libvlc, "key-osdmessage", message);
- p_sys->subtitle_delaybookmarks.i_time_audio = 0;
- p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
- }
+ ApplySubtitleDelay(p_demux);
}
if ( ! strcmp(variable_name, "sub-syncreset") )
{
- var_SetTime( p_demux->p_parent, "spu-delay", 0);
+ SetDemuxSubDelay(p_demux, 0);
+ p_sys->sub_speed_delay_current.idx_sub_fps_adjust = 0;
p_sys->subtitle_delaybookmarks.i_time_audio = 0;
p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+ p_sys->subtitle_delaybookmarks.i_time_audio_n_1 = 0;
+ p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 = 0;
+ set_current_subtitle_by_time(p_demux, p_sys->i_last_demux_date);
var_SetString(p_demux->p_libvlc, "key-osdmessage", _("Sub sync: delay reset"));
return VLC_SUCCESS;
}
if ( ! strcmp(variable_name, "spu-delau") )
{
+ p_sys->sub_speed_delay_current.sub_delay = new_value.i_int;
set_current_subtitle_by_time(p_demux, p_sys->i_last_demux_date);
}
return VLC_SUCCESS;
@@ -339,15 +636,23 @@ static int Open ( vlc_object_t *p_this )
p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
if( p_sys == NULL )
return VLC_ENOMEM;
-
- /* reset spu-delay at Open*/
- var_SetTime( p_demux->p_parent, "spu-delay", 0 );
+
+ fill_sub_fps_adjusts(p_demux);
+
+ /* reset spu-delay an speed at Open*/
+ SetDemuxSubDelay(p_demux, 0);
+ p_demux->p_sys->sub_speed_delay_current.idx_sub_fps_adjust = 0;
/* this is a file subtitle*/
var_SetInteger(p_demux->p_parent, "sub-isfilesub", 1);
p_sys->subtitle_delaybookmarks.i_time_audio = 0;
p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
+ p_sys->subtitle_delaybookmarks.i_time_audio_n_1 = -1;
+ p_sys->subtitle_delaybookmarks.i_time_subtitle_n_1 = -1;
+ p_sys->sub_speed_delay_user_confirm.idx_sub_fps_adjust = -1;
+ p_sys->sub_speed_delay_current.sub_delay = 0;
+ p_sys->sub_speed_delay_current.idx_sub_fps_adjust = 0;
/* Add callbacks*/
@@ -886,8 +1191,9 @@ static int Demux( demux_t *p_demux )
*****************************************************************************/
static int64_t adjust_subtitle_time( demux_t * p_demux, int64_t i64_when)
{
- int64_t spu_delay = var_GetTime( p_demux->p_parent, "spu-delay" );
- int64_t i64_adjust = i64_when + spu_delay;
+ int64_t sub_delay = GetDemuxSubDelay( p_demux );
+ float sub_speed = GetDemuxSubSpeed( p_demux );
+ int64_t i64_adjust = (int64_t) ( (float)i64_when / sub_speed ) + sub_delay;
return i64_adjust;
}
diff --git a/modules/gui/qt4/components/extended_panels.cpp b/modules/gui/qt4/components/extended_panels.cpp
index 1f36d60..15a0656 100644
--- a/modules/gui/qt4/components/extended_panels.cpp
+++ b/modules/gui/qt4/components/extended_panels.cpp
@@ -1544,7 +1544,23 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent ) :
CONNECT( buttonBookmarkSubtitle, pressed(), this, bookmarkSubtitle() ) ;
QPushButton *buttonBookmarkSync = new QPushButton(_("Sync subtitles"));
- buttonBookmarkSync->setToolTip(_("You can also use Shift-K on the video"));
+ QString buttonBookmarkSync_Tooltip = qtr(
+ "You can also use Shift-K on the video\n"\
+ "\n"\
+ "\n"\
+ "If the subtitle has a different fps,\n"\
+ "(ie the delay varies during the movie):\n"\
+ "\n"\
+ "* sync the subtitles at the beginning of the video\n"\
+ "* fast forward a few minutes in the movie\n"\
+ "* then resync the subtitles.\n"\
+ "\n"\
+ "If applicable, you will be asked to change the fps\n"\
+ "of the subtitle.\n"\
+ );
+ buttonBookmarkSync->setToolTip( buttonBookmarkSync_Tooltip );
+ subsVisualSyncLayout->addWidget( buttonBookmarkSync, 0, 2, 1, 1 );
+
subsVisualSyncLayout->addWidget( buttonBookmarkSync, 0, 2, 1, 1 );
CONNECT( buttonBookmarkSync, pressed(), this, syncBookmarks() ) ;
diff --git a/src/input/var.c b/src/input/var.c
index be3ef2a..8e6eebc 100644
--- a/src/input/var.c
+++ b/src/input/var.c
@@ -202,7 +202,6 @@ void input_ControlVarInit ( input_thread_t *p_input )
val.i_int = 0;
var_Change( p_input, "sub-isfilesub", VLC_VAR_SETVALUE, &val, 0 );
-
/* Video ES */
var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Video Track");
--
1.9.1
More information about the vlc-devel
mailing list