[vlc-commits] player: add multiple tracks selection support
Roland Bewick
git at videolan.org
Tue Jun 25 20:55:19 CEST 2019
vlc | branch: master | Roland Bewick <roland.bewick at gmail.com> | Thu Jun 20 13:30:08 2019 +0200| [96334761c9ed7cfcb19d0f472adb125d19cebb26] | committer: Thomas Guillem
player: add multiple tracks selection support
A new function vlc_player_SelectEsIdList() and implement
VLC_PLAYER_SELECT_SIMULTANEOUS.
vlc_player_SelectEsId() now returns the number of tracks selected for the track
category.
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=96334761c9ed7cfcb19d0f472adb125d19cebb26
---
include/vlc_player.h | 45 ++++++++++++++--
src/input/player.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/libvlccore.sym | 1 +
3 files changed, 187 insertions(+), 9 deletions(-)
diff --git a/include/vlc_player.h b/include/vlc_player.h
index 3bb13ab35e..8027983326 100644
--- a/include/vlc_player.h
+++ b/include/vlc_player.h
@@ -309,7 +309,14 @@ enum vlc_player_select_policy
* policy will disable all other tracks for the same category.
*/
VLC_PLAYER_SELECT_EXCLUSIVE,
- /* XXX VLC_PLAYER_SELECT_SIMULTANEOUS, */
+ /**
+ * Select multiple tracks for one category.
+ *
+ * Only one audio track can be selected at a time.
+ * Two subtitle tracks can be selected simultaneously.
+ * Multiple video tracks can be selected simultaneously.
+ */
+ VLC_PLAYER_SELECT_SIMULTANEOUS,
};
/**
@@ -1751,8 +1758,9 @@ vlc_player_GetSelectedTrack(vlc_player_t *player, enum es_format_category_e cat)
* @param id an ES ID (retrieved from vlc_player_cbs.on_track_list_changed or
* vlc_player_GetTrackAt())
* @param policy exclusive or simultaneous
+ * @return the number of track selected for es_id category
*/
-VLC_API void
+VLC_API unsigned
vlc_player_SelectEsId(vlc_player_t *player, vlc_es_id_t *es_id,
enum vlc_player_select_policy policy);
@@ -1760,15 +1768,42 @@ vlc_player_SelectEsId(vlc_player_t *player, vlc_es_id_t *es_id,
/**
* Helper to select a track
*/
-static inline void
+static inline unsigned
vlc_player_SelectTrack(vlc_player_t *player,
const struct vlc_player_track *track,
enum vlc_player_select_policy policy)
{
- vlc_player_SelectEsId(player, track->es_id, policy);
+ return vlc_player_SelectEsId(player, track->es_id, policy);
}
/**
+ * Select multiple tracks from a list of ES identifiers.
+ *
+ * Any tracks of the category, not referenced in the list will be unselected.
+ *
+ * @warning there is no guarantee all requested tracks will be selected. The
+ * behaviour is undefined if the list is not null-terminated.
+ *
+ * @note A successful call will trigger the
+ * vlc_player_cbs.on_track_selection_changed event for each track that has
+ * its selection state changed.
+ *
+ * @see VLC_PLAYER_SELECT_SIMULTANEOUS
+ *
+ * @param player locked player instance
+ * @param cat VIDEO_ES, AUDIO_ES or SPU_ES
+ * @param es_id_list a null-terminated list of ES identifiers. es_ids not
+ * corresponding to the category will be ignored.
+ * (ES IDs can be retrieved from vlc_player_cbs.on_track_list_changed or
+ * vlc_player_GetTrackAt())
+ * @return the number of track selected for that category
+ */
+VLC_API unsigned
+vlc_player_SelectEsIdList(vlc_player_t *player,
+ enum es_format_category_e cat,
+ vlc_es_id_t *const es_id_list[]);
+
+/**
* Select the next track
*
* If the last track is already selected, a call to this function will disable
@@ -1805,6 +1840,8 @@ vlc_player_SelectPrevTrack(vlc_player_t *player,
/**
* Unselect a track from an ES identifier
*
+ * @warning Other tracks of the same category won't be touched.
+ *
* @note A successful call will trigger the
* vlc_player_cbs.on_track_selection_changed event.
*
diff --git a/src/input/player.c b/src/input/player.c
index c49ade291e..807e1f3b2f 100644
--- a/src/input/player.c
+++ b/src/input/player.c
@@ -22,6 +22,8 @@
# include "config.h"
#endif
+#include <limits.h>
+
#include <vlc_common.h>
#include "player.h"
#include <vlc_aout.h>
@@ -32,6 +34,7 @@
#include <vlc_atomic.h>
#include <vlc_tick.h>
#include <vlc_decoder.h>
+#include <vlc_memstream.h>
#include "libvlc.h"
#include "input_internal.h"
@@ -1383,17 +1386,154 @@ vlc_player_vout_OSDTrack(vlc_player_t *player, vlc_es_id_t *id, bool select)
vlc_player_vout_OSDMessage(player, _("%s track: %s"), cat_name, track_name);
}
-void
+unsigned
+vlc_player_SelectEsIdList(vlc_player_t *player,
+ enum es_format_category_e cat,
+ vlc_es_id_t *const es_id_list[])
+{
+ static const size_t max_tracks_by_cat[] = {
+ [UNKNOWN_ES] = 0,
+ [VIDEO_ES] = UINT_MAX,
+ [AUDIO_ES] = 1,
+ [SPU_ES] = 2,
+ [DATA_ES] = 0,
+ };
+
+ struct vlc_player_input *input = vlc_player_get_input_locked(player);
+ if (!input)
+ return 0;
+
+ const size_t max_tracks = max_tracks_by_cat[cat];
+
+ if (max_tracks == 0)
+ return 0;
+
+ /* First, count and hold all the ES Ids.
+ Ids will be released in input.c:ControlRelease */
+ size_t track_count = 0;
+ for (size_t i = 0; es_id_list[i] != NULL; i++)
+ if (track_count < max_tracks && vlc_es_id_GetCat(es_id_list[i]))
+ track_count++;
+
+ /* Copy es_id_list into an allocated list so that it remains in memory until
+ selection completes. The list will be freed in input.c:ControlRelease */
+ struct vlc_es_id_t **allocated_ids =
+ vlc_alloc(track_count + 1, sizeof(vlc_es_id_t *));
+
+ if (allocated_ids == NULL)
+ return 0;
+
+ track_count = 0;
+ for (size_t i = 0; es_id_list[i] != NULL; i++)
+ {
+ vlc_es_id_t *es_id = es_id_list[i];
+ if (track_count < max_tracks && vlc_es_id_GetCat(es_id_list[i]) == cat)
+ {
+ vlc_es_id_Hold(es_id);
+ allocated_ids[track_count++] = es_id;
+ }
+ }
+ allocated_ids[track_count] = NULL;
+
+ /* Attempt to select all the requested tracks */
+ input_ControlPush(input->thread, INPUT_CONTROL_SET_ES_LIST,
+ &(input_control_param_t) {
+ .list.cat = cat,
+ .list.ids = allocated_ids,
+ });
+
+ /* Display track selection message */
+ const char *cat_name = es_format_category_to_string(cat);
+ if (track_count == 0)
+ vlc_player_vout_OSDMessage(player, _("%s track: %s"), cat_name,
+ _("N/A"));
+ else if (track_count == 1)
+ vlc_player_vout_OSDTrack(player, es_id_list[0], true);
+ else
+ {
+ struct vlc_memstream stream;
+ vlc_memstream_open(&stream);
+ for (size_t i = 0; i < track_count; i++)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrack(player, es_id_list[i]);
+
+ if (track)
+ {
+ if (i != 0)
+ vlc_memstream_puts(&stream, ", ");
+ vlc_memstream_puts(&stream, track->name);
+ }
+ }
+ if (vlc_memstream_close(&stream) == 0)
+ {
+ vlc_player_vout_OSDMessage(player, _("%s tracks: %s"), cat_name,
+ stream.ptr);
+ free(stream.ptr);
+ }
+ }
+ return track_count;
+}
+
+unsigned
vlc_player_SelectEsId(vlc_player_t *player, vlc_es_id_t *id,
enum vlc_player_select_policy policy)
{
- assert(policy == VLC_PLAYER_SELECT_EXCLUSIVE); /* TODO */
struct vlc_player_input *input = vlc_player_get_input_locked(player);
if (!input)
- return;
+ return 0;
- input_ControlPushEsHelper(input->thread, INPUT_CONTROL_SET_ES, id);
- vlc_player_vout_OSDTrack(player, id, true);
+ if (policy == VLC_PLAYER_SELECT_EXCLUSIVE)
+ {
+ input_ControlPushEsHelper(input->thread, INPUT_CONTROL_SET_ES, id);
+ vlc_player_vout_OSDTrack(player, id, true);
+ return 1;
+ }
+
+ /* VLC_PLAYER_SELECT_SIMULTANEOUS */
+ const enum es_format_category_e cat = vlc_es_id_GetCat(id);
+ const size_t track_count = vlc_player_GetTrackCount(player, cat);
+
+ if (track_count == 0)
+ return 0;
+
+ size_t selected_track_count = 1;
+ for (size_t i = 0; i < track_count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, i);
+ if (track->selected && track->es_id != id)
+ selected_track_count++;
+ }
+
+ if (selected_track_count == 1)
+ {
+ input_ControlPushEsHelper(input->thread, INPUT_CONTROL_SET_ES, id);
+ vlc_player_vout_OSDTrack(player, id, true);
+ return 1;
+ }
+
+ vlc_es_id_t **es_id_list =
+ vlc_alloc(selected_track_count + 1, sizeof(vlc_es_id_t*));
+ if (!es_id_list)
+ return 0;
+
+ size_t es_id_list_idx = 0;
+ /* Assure to select the requeste track */
+ es_id_list[es_id_list_idx++] = id;
+
+ for (size_t i = 0; i < track_count; ++i)
+ {
+ const struct vlc_player_track *track =
+ vlc_player_GetTrackAt(player, cat, i);
+ if (track->selected && track->es_id != id)
+ es_id_list[es_id_list_idx++] = track->es_id;
+ }
+ es_id_list[selected_track_count] = NULL;
+
+ unsigned ret = vlc_player_SelectEsIdList(player, cat, es_id_list);
+ free(es_id_list);
+ return ret;
}
static void
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 3e959dc21f..21401a27a5 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -835,6 +835,7 @@ vlc_player_SelectCategoryLanguage
vlc_player_SelectChapter
vlc_player_SelectChapterIdx
vlc_player_SelectEsId
+vlc_player_SelectEsIdList
vlc_player_SelectNextChapter
vlc_player_SelectNextTitle
vlc_player_SelectNextTrack
More information about the vlc-commits
mailing list