[vlc-devel] [PATCH 12/15] Add hotkey support for secondary subtitles (Part 3)
Roland Bewick
roland.bewick at gmail.com
Tue May 14 11:40:11 CEST 2019
-Secondary subtitle track cycling won't overwrite existing primary subtitle selection.
-Using the secondary subtitle control hotkey now enables dual subtitles so it doesn't have to be selected in the UI.
-Update OSD message to show secondary subtitle selection
---
include/vlc_input.h | 4 ++
include/vlc_player.h | 16 +++++++-
modules/control/hotkeys.c | 7 ++++
src/input/es_out.c | 3 ++
src/input/input.c | 3 +-
src/input/player.c | 93 ++++++++++++++++++++++++++++++++++++++++++-----
src/libvlccore.sym | 1 +
7 files changed, 116 insertions(+), 11 deletions(-)
diff --git a/include/vlc_input.h b/include/vlc_input.h
index a5f1eb8b16..20c3ea63e7 100644
--- a/include/vlc_input.h
+++ b/include/vlc_input.h
@@ -461,6 +461,10 @@ struct vlc_input_event_es {
* ES track information, can be updated after the VLC_INPUT_ES_UPDATED event.
*/
const es_format_t *fmt;
+ /**
+ * SPU ID for this ES, can be updated after the VLC_INPUT_ES_UPDATED event.
+ */
+ unsigned int spu_id;
};
struct vlc_input_event_signal {
diff --git a/include/vlc_player.h b/include/vlc_player.h
index 8a7acf63bb..22eef4745c 100644
--- a/include/vlc_player.h
+++ b/include/vlc_player.h
@@ -111,6 +111,8 @@ struct vlc_player_track
es_format_t fmt;
/** True if the track is selected */
bool selected;
+ /** SPU ID of the track if selected */
+ unsigned int i_spu_id;
};
/**
@@ -2273,7 +2275,7 @@ VLC_API float
vlc_player_GetAssociatedSubsFPS(vlc_player_t *player);
/**
- * Enable or disable the abiltity to select multiple sub tracks.
+ * Enable or disable the ability to select multiple sub tracks.
*
* @note A successful call will trigger the
* vlc_player_cbs.on_dual_subtitles_enabled_changed event.
@@ -2468,6 +2470,18 @@ VLC_API void
vlc_player_SetSubtitleMultipleSelection(vlc_player_t *player, bool multiple);
/**
+ * Cycle sub track matching the given SPU ID.
+ *
+ * @note This must be returned to SPU_ID_PRIMARY immediately after
+ * selection of the subtitle.
+ *
+ * @param player locked player instance
+ * @param select true to allow selection of multiple subtitles
+ */
+VLC_API void
+vlc_player_SetCycleSpuId(vlc_player_t *player, int spu_id);
+
+/**
* Get the signal quality and strength of the current media
*
* @param player locked player instance
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index f30a9cf695..e14f081664 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -350,6 +350,8 @@ PLAYER_ACTION_HANDLER(NavigateMedia)
PLAYER_ACTION_HANDLER(Track)
{
+ vlc_player_SetSubtitleMultipleSelection(player, i_control_spu_id > 1);
+ vlc_player_SetCycleSpuId(player, i_control_spu_id);
switch (action_id)
{
case ACTIONID_AUDIO_TRACK:
@@ -364,6 +366,8 @@ PLAYER_ACTION_HANDLER(Track)
default:
vlc_assert_unreachable();
}
+ vlc_player_SetCycleSpuId(player, SPU_ID_PRIMARY);
+ vlc_player_SetSubtitleMultipleSelection(player, false);
}
PLAYER_ACTION_HANDLER(Delay)
@@ -459,6 +463,9 @@ PLAYER_ACTION_HANDLER(ControlSubtitleSecondary)
if (++i_control_spu_id > SPU_MAX_CLOCKS)
i_control_spu_id = SPU_ID_PRIMARY;
+ if (i_control_spu_id > SPU_ID_PRIMARY)
+ vlc_player_SetDualSubtitlesEnabled(player, true);
+
vlc_player_vout_OSDMessage(player, _("%s subtitle control"),
i_control_spu_id > SPU_ID_PRIMARY ? "Secondary" : "Primary");
}
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 20631027ed..54b3884f11 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1061,6 +1061,8 @@ static void EsOutSendEsEvent(es_out_t *out, es_out_id_t *es, int action)
.id = &es->id,
.title = es->psz_title ? es->psz_title : "",
.fmt = es->fmt_out.i_cat != UNKNOWN_ES ? &es->fmt_out : &es->fmt,
+ .spu_id = es->fmt.i_cat == SPU_ES && es->p_dec ?
+ input_DecoderGetSpuId(es->p_dec) : SPU_ID_PRIMARY,
});
}
@@ -2251,6 +2253,7 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
{
input_DecoderSetSpuId( es->p_dec, EsOutCountSelected( p_sys, es->fmt.i_cat ) );
EsOutDecoderChangeDelay(out, es);
+ EsOutSendEsEvent( out, es, VLC_INPUT_ES_UPDATED );
}
}
diff --git a/src/input/input.c b/src/input/input.c
index 5fc25bed76..bdd5abd5dd 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -1062,7 +1062,8 @@ static void SetSubtitlesOptions( input_thread_t *p_input )
if( sub_delay != 0 )
{
priv->spu_delays[0] = vlc_tick_from_samples(sub_delay, 10);
- input_SendEventSubtitleDelay( p_input, priv->spu_delays[0], false );
+ input_SendEventSubtitleDelay( p_input, priv->spu_delays[0],
+ SPU_ID_PRIMARY );
/* UpdatePtsDelay will be called next by InitPrograms */
}
diff --git a/src/input/player.c b/src/input/player.c
index 2c486b9749..b59d005421 100644
--- a/src/input/player.c
+++ b/src/input/player.c
@@ -133,6 +133,9 @@ struct vlc_player_input
bool teletext_transparent;
unsigned teletext_page;
+ bool b_select_secondary_subtitle;
+ unsigned int i_cycle_spu_id;
+
struct
{
vlc_tick_t time;
@@ -432,6 +435,7 @@ vlc_player_track_New(vlc_es_id_t *id, const char *name, const es_format_t *fmt)
}
track->es_id = vlc_es_id_Hold(id);
track->selected = false;
+ track->i_spu_id = SPU_ID_PRIMARY;
return track;
}
@@ -459,7 +463,8 @@ vlc_player_track_Delete(struct vlc_player_track *track)
static int
vlc_player_track_Update(struct vlc_player_track *track,
- const char *name, const es_format_t *fmt)
+ const char *name, const es_format_t *fmt,
+ unsigned int spu_id)
{
if (strcmp(name, track->name) != 0)
{
@@ -477,6 +482,8 @@ vlc_player_track_Update(struct vlc_player_track *track,
es_format_Clean(&track->fmt);
track->fmt = fmtdup;
+
+ track->i_spu_id = spu_id;
return VLC_SUCCESS;
}
@@ -659,6 +666,9 @@ vlc_player_input_New(vlc_player_t *player, input_item_t *item)
input->subsync.audio_time =
input->subsync.subtitle_time = VLC_TICK_INVALID;
+ input->b_select_secondary_subtitle = false;
+ input->i_cycle_spu_id = SPU_ID_PRIMARY;
+
vlc_vector_init(&input->program_vector);
vlc_vector_init(&input->video_track_vector);
vlc_vector_init(&input->audio_track_vector);
@@ -1294,7 +1304,24 @@ es_format_category_to_string(enum es_format_category_e cat)
static void
vlc_player_vout_OSDTrack(vlc_player_t *player, vlc_es_id_t *id, bool select)
{
+ struct vlc_player_input *input = vlc_player_get_input_locked(player);
enum es_format_category_e cat = vlc_es_id_GetCat(id);
+ size_t spu_selected_count = 0;
+
+ if (cat == SPU_ES && input && var_GetBool(input->thread, "multiple-spus") &&
+ input->b_select_secondary_subtitle)
+ {
+ size_t count = vlc_player_GetTrackCount(player, SPU_ES);
+ for (size_t i = 0; i < count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, SPU_ES, i);
+ assert(track);
+ if (track->selected && track->es_id != id)
+ ++spu_selected_count;
+ }
+ }
+
const struct vlc_player_track *track = vlc_player_GetTrack(player, id);
if (!track && select)
return;
@@ -1302,7 +1329,10 @@ vlc_player_vout_OSDTrack(vlc_player_t *player, vlc_es_id_t *id, bool select)
const char *cat_name = es_format_category_to_string(cat);
assert(cat_name);
const char *track_name = select ? track->name : _("N/A");
- vlc_player_vout_OSDMessage(player, _("%s track: %s"), cat_name, track_name);
+ bool b_track_secondary = spu_selected_count > 0;
+ const char *track_secondary = b_track_secondary ? _("Secondary ") : _("");
+ vlc_player_vout_OSDMessage(player, _("%s%s track: %s"),
+ track_secondary, cat_name, track_name);
}
void
@@ -1320,6 +1350,9 @@ static void
vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e cat,
bool next)
{
+ struct vlc_player_input *input = vlc_player_get_input_locked(player);
+ unsigned int i_cycle_spu_id = input ? input->i_cycle_spu_id : SPU_ID_PRIMARY;
+
size_t count = vlc_player_GetTrackCount(player, cat);
if (!count)
return;
@@ -1331,12 +1364,12 @@ vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e cat,
const struct vlc_player_track *track =
vlc_player_GetTrackAt(player, cat, i);
assert(track);
- if (track->selected)
+ if (track->selected && (cat != SPU_ES || track->i_spu_id == i_cycle_spu_id))
{
if (selected)
{
/* Can't cycle through tracks if there are more than one
- * selected */
+ * selected for the same spu id */
return;
}
index = i;
@@ -1344,19 +1377,51 @@ vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e cat,
}
}
+ size_t original_index = index;
+ bool was_selected = selected;
+ bool b_check_first = false;
+
if (!selected)
{
- /* No track selected: select the first or the last track */
+ /* No track selected: try to select the first or the last track. */
index = next ? 0 : count - 1;
+ b_check_first = true;
selected = true;
}
- else
+
+ /* Search until we find an unselected track */
+ while (true)
{
/* Unselect if we reach the end of the cycle */
if ((next && index + 1 == count) || (!next && index == 0))
+ {
+ if (was_selected)
+ index = original_index;
selected = false;
- else /* Switch to the next or previous track */
- index = index + (next ? 1 : -1);
+ break;
+ }
+ else /* Switch to the next or previous unselected track */
+ {
+ if (!b_check_first)
+ index = index + (next ? 1 : -1);
+ else
+ b_check_first = false;
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, index);
+ if (!track->selected)
+ break;
+ }
+ }
+
+ if (!selected && !was_selected)
+ return; /* no track available nor selected matching request */
+
+ if (i_cycle_spu_id > SPU_ID_PRIMARY && selected && was_selected)
+ {
+ /* Deselect the old secondary sub track so we can select a new one */
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, original_index);
+ vlc_player_UnselectTrack(player, track->es_id);
}
const struct vlc_player_track *track =
@@ -1584,7 +1649,7 @@ vlc_player_input_HandleEsEvent(struct vlc_player_input *input,
track = vlc_player_track_vector_FindById(vec, ev->id, NULL);
if (!track)
break;
- if (vlc_player_track_Update(track, ev->title, ev->fmt) != 0)
+ if (vlc_player_track_Update(track, ev->title, ev->fmt, ev->spu_id) != 0)
break;
vlc_player_SendEvent(player, on_track_list_changed,
VLC_PLAYER_LIST_UPDATED, track);
@@ -2921,11 +2986,21 @@ vlc_player_SetSubtitleMultipleSelection(vlc_player_t *player, bool multiple)
struct vlc_player_input *input = vlc_player_get_input_locked(player);
if (!input)
return;
+ input->b_select_secondary_subtitle = multiple;
input_ControlPushHelper(input->thread,
INPUT_CONTROL_SET_MULTIPLE_SUBTITLE_SELECTION,
&(vlc_value_t){ .b_bool = multiple });
}
+void
+vlc_player_SetCycleSpuId(vlc_player_t *player, int spu_id)
+{
+ struct vlc_player_input *input = vlc_player_get_input_locked(player);
+ if (!input)
+ return;
+ input->i_cycle_spu_id = spu_id;
+}
+
vlc_tick_t
vlc_player_GetSubtitleDelay(vlc_player_t *player, int i_spu_id)
{
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 175d9a9639..baef0ba9dd 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -869,6 +869,7 @@ vlc_player_SetSubtitleDelay
vlc_player_SetSubtitleSync
vlc_player_SetSubtitleTextScale
vlc_player_SetSubtitleMultipleSelection
+vlc_player_SetCycleSpuId
vlc_player_SetDualSubtitlesEnabled
vlc_player_SetTeletextEnabled
vlc_player_SetTeletextTransparency
--
2.11.0
More information about the vlc-devel
mailing list