[vlc-devel] [RFC PATCHv2 09/10] lib: add new player track API

Thomas Guillem thomas at gllm.fr
Thu Jun 4 23:23:24 CEST 2020


---
 include/vlc/libvlc_media_player.h | 138 +++++++++++++++++++++++++++
 lib/libvlc.sym                    |   5 +
 lib/media_internal.h              |  19 ++++
 lib/media_player.c                | 153 ++++++++++++++++++++++++++++++
 lib/media_player_internal.h       |   1 +
 lib/media_track.c                 |  54 +++++++++++
 6 files changed, 370 insertions(+)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index a6f5fbf8e5..c39f08ef81 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -1284,6 +1284,144 @@ LIBVLC_API void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
  */
 LIBVLC_API void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned int timeout );
 
+/**
+ * Get the track list for one type
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * \note You need to call libvlc_media_parse_with_options() or play the media
+ * at least once before calling this function.  Not doing this will result in
+ * an empty list.
+ *
+ * \note This track list is a snapshot of the current tracks when this function
+ * is called. If a track is updated after this call, the user will need to call
+ * this function again to get the updated track.
+ *
+ *
+ * The track list can be used to get track informations and to select specific
+ * tracks.
+ *
+ * \param p_mi the media player
+ * \param type type of the track list to request
+ *
+ * \return a valid libvlc_media_tracklist_t or NULL in case of error, if there
+ * is no track for a category, the returned list will have a size of 0, delete
+ * with libvlc_media_tracklist_release()
+ */
+LIBVLC_API libvlc_media_tracklist_t *
+libvlc_media_player_get_tracklist( libvlc_media_player_t *p_mi,
+                                   libvlc_track_type_t type );
+
+
+/**
+ * Get the selected track for one type
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * \warning More than one tracks can be selected for one type. In that case,
+ * libvlc_media_player_get_tracklist() should be used.
+ *
+ * \param p_mi the media player
+ * \param type type of the selected track
+ *
+ * \return a valid track or NULL if there is no selected tracks for this type,
+ * release it with libvlc_media_track_release().
+ */
+LIBVLC_API libvlc_media_track_t *
+libvlc_media_player_get_selected_track( libvlc_media_player_t *p_mi,
+                                        libvlc_track_type_t type );
+
+/*
+ * Get a track from a track id
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * This function can be used to get the last updated informations of a track.
+ *
+ * \param p_mi the media player
+ * \param psz_id valid string representing a track id (cf. psz_id from \ref
+ * libvlc_media_track_t)
+ *
+ * \return a valid track or NULL if there is currently no tracks identified by
+ * the string id, release it with libvlc_media_track_release().
+ */
+LIBVLC_API libvlc_media_track_t *
+libvlc_media_player_get_track_from_id( libvlc_media_player_t *p_mi,
+                                       const char *psz_id );
+
+
+/**
+ * Select a track or unselect all tracks for one type
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * \note Use libvlc_media_player_update_tracklist() for finer track selection
+ * control.
+ *
+ * \param p_mi the media player
+ * \param type type of the selected track
+ * \param track track to select or NULL to unselect all tracks of for this type
+ */
+LIBVLC_API void
+libvlc_media_player_select_track( libvlc_media_player_t *p_mi,
+                                  libvlc_track_type_t type,
+                                  const libvlc_media_track_t *track );
+
+/**
+ * Select tracks by their string identifier
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * This function can be used pre-select a list of tracks before starting the
+ * player. It has only effect for the current media. It can also be used when
+ * the player is already started.
+ *
+ * 'str_ids' can contain more than one track id, delimited with ','. "" or any
+ * invalid track id will cause the player to unselect all tracks of that
+ * category. NULL will disable the preference for newer tracks without
+ * unselecting any current tracks.
+ *
+ * Example:
+ * - (libvlc_track_video, "video/1,video/2") will select these 2 video tracks.
+ * If there is only one video track with the id "video/0", no tracks will be
+ * selected.
+ * - (libvlc_track_type_t, "${slave_url_md5sum}/spu/0) will select one spu
+ * added by an input slave with the corresponding url.
+ *
+ * \note The string identifier of a track can be found via psz_id from \ref
+ * libvlc_media_track_t
+ *
+ * \param p_mi the media player
+ * \param type type to select
+ * \param psz_ids list of string identifier or NULL
+ */
+LIBVLC_API void
+libvlc_media_player_select_tracks_by_ids( libvlc_media_player_t *p_mi,
+                                          libvlc_track_type_t type,
+                                          const char *psz_ids );
+
+/**
+ * Update the track selection for one type
+ *
+ * This function allow to select or unselect multiple tracks using the
+ * track list returned by libvlc_media_player_get_tracklist(). The user can
+ * iterate on all or few libvlc_media_track_t from this list and change the
+ * 'selected' boolean before calling this function.
+ *
+ * \note The internal track list can change between the calls of
+ * libvlc_media_player_get_tracklist() and
+ * libvlc_media_player_update_tracklist(). If a track selection change but the
+ * track is not present anymore, the player will just ignore it.
+ *
+ * \param p_mi the media player
+ * \param type type of the selected track
+ * \param list list returned by libvlc_media_player_get_tracklist()
+ */
+LIBVLC_API void
+libvlc_media_player_update_tracklist( libvlc_media_player_t *p_mi,
+                                      libvlc_track_type_t type,
+                                      libvlc_media_tracklist_t *list );
+
 /**
  * Add a slave to the current media player.
  *
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 4b886da753..003bb70a2c 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -182,6 +182,11 @@ libvlc_media_player_set_xwindow
 libvlc_media_player_stop_async
 libvlc_media_player_navigate
 libvlc_media_player_set_video_title_display
+libvlc_media_player_get_tracklist
+libvlc_media_player_get_selected_track
+libvlc_media_player_select_track
+libvlc_media_player_select_tracks_by_ids
+libvlc_media_player_update_tracklist
 libvlc_media_release
 libvlc_media_retain
 libvlc_media_save_meta
diff --git a/lib/media_internal.h b/lib/media_internal.h
index 24bedfb405..8acb116e8f 100644
--- a/lib/media_internal.h
+++ b/lib/media_internal.h
@@ -29,6 +29,7 @@
 
 #include <vlc_common.h>
 #include <vlc_input.h>
+#include <vlc_player.h>
 
 struct libvlc_media_t
 {
@@ -81,17 +82,35 @@ typedef struct libvlc_media_trackpriv_t
         libvlc_video_track_t video;
         libvlc_subtitle_track_t subtitle;
     };
+    vlc_es_id_t *es_id;
 } libvlc_media_trackpriv_t;
 
+static inline const libvlc_media_trackpriv_t *
+libvlc_media_track_to_priv( const libvlc_media_track_t *track )
+{
+    return container_of( track, const libvlc_media_trackpriv_t, t );
+}
+
 void
 libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
                                 const es_format_t *es  );
 
+void
+libvlc_media_trackpriv_from_player_track( libvlc_media_trackpriv_t *trackpriv,
+                                          const struct vlc_player_track *track );
+
+libvlc_media_track_t *
+libvlc_media_track_create_from_player_track( const struct vlc_player_track *track );
+
 libvlc_media_tracklist_t *
 libvlc_media_tracklist_from_es_array( es_format_t **es_array,
                                       size_t es_count,
                                       libvlc_track_type_t type );
 
+libvlc_media_tracklist_t *
+libvlc_media_tracklist_from_player( vlc_player_t *player,
+                                    libvlc_track_type_t type );
+
 void
 libvlc_media_track_clean( libvlc_media_track_t *track );
 
diff --git a/lib/media_player.c b/lib/media_player.c
index 68e6e62b1a..0ac10ba38f 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -1803,6 +1803,159 @@ void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, l
     }
 }
 
+libvlc_media_tracklist_t *
+libvlc_media_player_get_tracklist(libvlc_media_player_t *p_mi,
+                                  libvlc_track_type_t type)
+{
+    vlc_player_t *player = p_mi->player;
+
+    vlc_player_Lock(player);
+
+    libvlc_media_tracklist_t *list =
+        libvlc_media_tracklist_from_player(player, type);
+
+    vlc_player_Unlock(player);
+
+    return list;
+}
+
+libvlc_media_track_t *
+libvlc_media_player_get_selected_track(libvlc_media_player_t *p_mi,
+                                       libvlc_track_type_t type)
+{
+    vlc_player_t *player = p_mi->player;
+
+    vlc_player_Lock(player);
+
+    const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
+    const struct vlc_player_track *track =
+        vlc_player_GetSelectedTrack(player, cat);
+
+    if (track == NULL)
+    {
+        vlc_player_Unlock(player);
+        return NULL;
+    }
+
+    libvlc_media_track_t *libtrack =
+        libvlc_media_track_create_from_player_track(track);
+    vlc_player_Unlock(player);
+
+    return libtrack;
+}
+
+libvlc_media_track_t *
+libvlc_media_player_get_track_from_id( libvlc_media_player_t *p_mi,
+                                       const char *psz_id )
+{
+    vlc_player_t *player = p_mi->player;
+
+    vlc_player_Lock(player);
+
+    enum es_format_category_e cats[] = { VIDEO_ES, AUDIO_ES, SPU_ES };
+    for (size_t i = 0; i < ARRAY_SIZE(cats); ++i)
+    {
+        enum es_format_category_e cat = cats[i];
+        size_t count = vlc_player_GetTrackCount(player, VIDEO_ES);
+
+        for (size_t j = 0; j < count; ++j)
+        {
+            const struct vlc_player_track *track =
+                vlc_player_GetTrackAt(player, cat, j);
+            if (strcmp(psz_id, vlc_es_id_GetStrId(track->es_id)) == 0)
+            {
+                libvlc_media_track_t *libtrack =
+                    libvlc_media_track_create_from_player_track(track);
+                vlc_player_Unlock(player);
+                return libtrack;
+
+            }
+        }
+    }
+
+    vlc_player_Unlock(player);
+    return NULL;
+}
+
+void
+libvlc_media_player_select_track(libvlc_media_player_t *p_mi,
+                                 libvlc_track_type_t type,
+                                 const libvlc_media_track_t *track)
+{
+    assert( track == NULL || type == track->i_type );
+    vlc_player_t *player = p_mi->player;
+
+    vlc_player_Lock(player);
+
+    if (track != NULL)
+    {
+        const libvlc_media_trackpriv_t *trackpriv =
+            libvlc_media_track_to_priv(track);
+        vlc_player_SelectEsId(player, trackpriv->es_id,
+                              VLC_PLAYER_SELECT_EXCLUSIVE);
+    }
+    else
+    {
+        const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
+        vlc_player_UnselectTrackCategory(player, cat);
+    }
+
+    vlc_player_Unlock(player);
+}
+
+void
+libvlc_media_player_select_tracks_by_ids( libvlc_media_player_t *p_mi,
+                                          libvlc_track_type_t type,
+                                          const char *psz_ids )
+{
+    const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
+
+    vlc_player_t *player = p_mi->player;
+
+    vlc_player_Lock(player);
+
+    vlc_player_SelectTracksByStringIds(player, cat, psz_ids);
+
+    vlc_player_Unlock(player);
+}
+
+void
+libvlc_media_player_update_tracklist(libvlc_media_player_t *p_mi,
+                                     libvlc_track_type_t type,
+                                     libvlc_media_tracklist_t *list)
+{
+    vlc_player_t *player = p_mi->player;
+
+    size_t count = libvlc_media_tracklist_count(list);
+    vlc_es_id_t **es_id_list = vlc_alloc(count + 1, sizeof(vlc_es_id_t *));
+    size_t es_id_idx = 0;
+
+    if (es_id_list == NULL)
+        return;
+
+    const enum es_format_category_e cat = libvlc_track_type_to_escat(type);
+
+    vlc_player_Lock(player);
+
+    for (size_t i = 0; i < count; ++i)
+    {
+        const libvlc_media_track_t *track = libvlc_media_tracklist_at(list, i);
+        if (track->selected)
+        {
+            const libvlc_media_trackpriv_t *trackpriv =
+                libvlc_media_track_to_priv(track);
+            es_id_list[es_id_idx++] = trackpriv->es_id;
+        }
+    }
+    es_id_list[es_id_idx++] = NULL;
+    vlc_player_SelectEsIdList(player, cat, es_id_list);
+
+    vlc_player_Unlock(player);
+
+    free(es_id_list);
+}
+
+
 int libvlc_media_player_add_slave( libvlc_media_player_t *p_mi,
                                    libvlc_media_slave_type_t i_type,
                                    const char *psz_uri, bool b_select )
diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
index c2d5348e22..1b95fcb355 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -33,6 +33,7 @@
 #include <vlc_input.h>
 #include <vlc_player.h>
 #include <vlc_viewpoint.h>
+#include "media_internal.h"
 
 #include "../modules/audio_filter/equalizer_presets.h"
 
diff --git a/lib/media_track.c b/lib/media_track.c
index 473ea5589b..66670683ef 100644
--- a/lib/media_track.c
+++ b/lib/media_track.c
@@ -45,6 +45,8 @@ libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
 {
     libvlc_media_track_t *track = &trackpriv->t;
 
+    trackpriv->es_id = NULL;
+
     track->i_codec = es->i_codec;
     track->i_original_fourcc = es->i_original_fourcc;
     track->i_id = es->i_id;
@@ -56,6 +58,7 @@ libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
     track->psz_language = es->psz_language != NULL ? strdup(es->psz_language) : NULL;
     track->psz_description = es->psz_description != NULL ? strdup(es->psz_description) : NULL;
     track->psz_id = NULL;
+    track->id_stable = false;
     track->psz_name = NULL;
     track->selected = false;
 
@@ -135,6 +138,8 @@ libvlc_media_track_release( libvlc_media_track_t *track )
     libvlc_media_trackpriv_t *trackpriv =
         container_of( track, libvlc_media_trackpriv_t, t );
     libvlc_media_track_clean( track );
+    if( trackpriv->es_id )
+        vlc_es_id_Release( trackpriv->es_id );
     free( trackpriv );
 }
 
@@ -185,6 +190,52 @@ libvlc_media_tracklist_from_es_array( es_format_t **es_array,
     return list;
 }
 
+void
+libvlc_media_trackpriv_from_player_track( libvlc_media_trackpriv_t *trackpriv,
+                                          const struct vlc_player_track *track )
+{
+    libvlc_media_trackpriv_from_es( trackpriv, &track->fmt );
+
+    trackpriv->es_id = vlc_es_id_Hold( track->es_id );
+
+    trackpriv->t.psz_id = vlc_es_id_GetStrId( track->es_id );
+    trackpriv->t.id_stable = vlc_es_id_IsStrIdStable( track->es_id );
+    trackpriv->t.psz_name = strdup( track->name );
+    trackpriv->t.selected = track->selected;
+}
+
+libvlc_media_track_t *
+libvlc_media_track_create_from_player_track( const struct vlc_player_track *track )
+{
+    libvlc_media_trackpriv_t *trackpriv = malloc( sizeof(*trackpriv) );
+    if( trackpriv == NULL )
+        return NULL;
+    libvlc_media_trackpriv_from_player_track( trackpriv, track );
+    return &trackpriv->t;
+}
+
+libvlc_media_tracklist_t *
+libvlc_media_tracklist_from_player( vlc_player_t *player,
+                                    libvlc_track_type_t type )
+{
+    const enum es_format_category_e cat = libvlc_track_type_to_escat( type );
+
+    size_t count = vlc_player_GetTrackCount( player, cat );
+    libvlc_media_tracklist_t *list = libvlc_media_tracklist_alloc( count );
+
+    for( size_t i = 0; i < count; ++i )
+    {
+        const struct vlc_player_track *track =
+            vlc_player_GetTrackAt( player, cat, i );
+        assert( track );
+
+        libvlc_media_trackpriv_t *trackpriv = &list->tracks[i];
+        libvlc_media_trackpriv_from_player_track( trackpriv, track );
+    }
+
+    return list;
+}
+
 size_t
 libvlc_media_tracklist_count( const libvlc_media_tracklist_t *list )
 {
@@ -205,6 +256,9 @@ libvlc_media_tracklist_release( libvlc_media_tracklist_t *list )
     {
         libvlc_media_trackpriv_t *trackpriv = &list->tracks[i];
         libvlc_media_track_clean( &trackpriv->t );
+
+        if( trackpriv->es_id != NULL )
+            vlc_es_id_Release( trackpriv->es_id );
     }
     free( list );
 }
-- 
2.20.1



More information about the vlc-devel mailing list