[vlc-devel] [PATCH 13/16] Add hotkey support for secondary subtitles (Part 3)
Roland Bewick
roland.bewick at gmail.com
Tue May 21 20:08:37 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.
---
modules/control/hotkeys.c | 136 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 133 insertions(+), 3 deletions(-)
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index f30a9cf695..1d7748326f 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -55,6 +55,10 @@ static void handle_action(intf_thread_t *, vlc_action_id_t);
/* Use standard subtitle hotkeys to control a selected sub track */
static int i_control_spu_id = SPU_ID_PRIMARY;
+/* keep track of selected SPU ES to cycle primary and secondary SPU tracks */
+static vlc_es_id_t *primary_spu_es_id = NULL;
+static vlc_es_id_t *secondary_spu_es_id = NULL;
+
/*****************************
* interface action handling *
*****************************/
@@ -348,6 +352,94 @@ PLAYER_ACTION_HANDLER(NavigateMedia)
}
}
+static void CycleSecondarySubtitles(vlc_player_t *player,
+ bool next)
+{
+ enum es_format_category_e cat = SPU_ES;
+ size_t count = vlc_player_GetTrackCount(player, cat);
+ if (!count)
+ return;
+
+ /* Check how many subtitle tracks are already selected */
+ size_t selected_count = 0;
+ for (size_t i = 0; i < count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, i);
+ assert(track);
+
+ if (track->selected)
+ {
+ ++selected_count;
+ }
+ }
+
+ if ((i_control_spu_id == SPU_ID_PRIMARY && selected_count <= 1) ||
+ selected_count == 0)
+ {
+ /* Only cycle the primary subtitle track */
+ if (next)
+ vlc_player_SelectNextTrack(player, cat);
+ else
+ vlc_player_SelectPrevTrack(player, cat);
+ }
+ else
+ {
+ vlc_es_id_t *cycle_id = i_control_spu_id == SPU_ID_PRIMARY ?
+ primary_spu_es_id : secondary_spu_es_id;
+
+ vlc_es_id_t *keep_id = i_control_spu_id == SPU_ID_PRIMARY ?
+ secondary_spu_es_id : primary_spu_es_id;
+
+ /* Find out the current selected index.
+ If no track selected, select the first or the last track */
+ size_t index = next ? 0 : count - 1;
+ for (size_t i = 0; i < count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, i);
+ assert(track);
+
+ if (track->es_id == cycle_id)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ /* Look for the next free (unselected) track */
+ while (true)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, index);
+
+ if (!track->selected)
+ {
+ cycle_id = track->es_id;
+ break;
+ }
+ /* Unselect if we reach the end of the cycle */
+ else if ((next && index + 1 == count) || (!next && index == 0))
+ {
+ cycle_id = NULL;
+ break;
+ }
+ else /* Switch to the next or previous track */
+ index = index + (next ? 1 : -1);
+ }
+
+ /* Make sure the list never contains NULL before a valid id */
+ if ( !keep_id )
+ {
+ keep_id = cycle_id;
+ cycle_id = NULL;
+ }
+
+ vlc_es_id_t *esIds[3] = { keep_id, cycle_id, NULL };
+ vlc_player_SelectTrackList(player, cat, esIds);
+ }
+}
+
PLAYER_ACTION_HANDLER(Track)
{
switch (action_id)
@@ -356,10 +448,9 @@ PLAYER_ACTION_HANDLER(Track)
vlc_player_SelectNextTrack(player, AUDIO_ES);
break;
case ACTIONID_SUBTITLE_REVERSE_TRACK:
- vlc_player_SelectPrevTrack(player, SPU_ES);
- break;
case ACTIONID_SUBTITLE_TRACK:
- vlc_player_SelectNextTrack(player, SPU_ES);
+ CycleSecondarySubtitles(player,
+ action_id == ACTIONID_SUBTITLE_TRACK);
break;
default:
vlc_assert_unreachable();
@@ -459,6 +550,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");
}
@@ -1060,6 +1154,41 @@ player_on_vout_changed(vlc_player_t *player,
vlc_assert_unreachable();
}
}
+static void
+player_on_track_selection_changed(vlc_player_t *player,
+ vlc_es_id_t *unselected_id,
+ vlc_es_id_t *selected_id, void *data)
+{
+ intf_thread_t *intf = data;
+ VLC_UNUSED(data);
+
+ /* Keep track of selected primary and secondary subtitles */
+ if (selected_id)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrack(player, selected_id);
+ if (track && track->fmt.i_cat == SPU_ES)
+ {
+ if (!primary_spu_es_id)
+ primary_spu_es_id = selected_id;
+ else
+ secondary_spu_es_id = selected_id;
+ }
+ }
+
+ if (unselected_id)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrack(player, unselected_id);
+ if (track && track->fmt.i_cat == SPU_ES)
+ {
+ if (primary_spu_es_id == unselected_id)
+ primary_spu_es_id = NULL;
+ else if (secondary_spu_es_id == unselected_id)
+ secondary_spu_es_id = NULL;
+ }
+ }
+}
static int
ActionCallback(vlc_object_t *obj, char const *var,
@@ -1086,6 +1215,7 @@ Open(vlc_object_t *this)
static struct vlc_player_cbs const player_cbs =
{
.on_vout_changed = player_on_vout_changed,
+ .on_track_selection_changed = player_on_track_selection_changed,
};
vlc_player_t *player = vlc_playlist_GetPlayer(sys->playlist);
vlc_player_Lock(player);
--
2.11.0
More information about the vlc-devel
mailing list