[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