[vlc-devel] [RFC PATCH 6/6] lib: add a new libvlc_media_player track selection API
Thomas Guillem
thomas at gllm.fr
Tue Jun 2 22:02:10 CEST 2020
---
include/vlc/libvlc_media_player.h | 89 ++++++++++++++++++++++++++
include/vlc/libvlc_media_track.h | 4 ++
lib/media_internal.h | 19 ++++++
lib/media_player.c | 103 ++++++++++++++++++++++++++++++
lib/media_player_internal.h | 3 +
lib/media_track.c | 48 ++++++++++++++
6 files changed, 266 insertions(+)
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index a6f5fbf8e5..ad4ae7e88e 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -1284,6 +1284,95 @@ 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,
+ * the returned track can only be used to get track informations (selection is
+ * not possible) and is valid until the next call to
+ * libvlc_media_player_get_selected_track()
+ */
+LIBVLC_API const libvlc_media_track_t *
+libvlc_media_player_get_selected_track( libvlc_media_player_t *p_mi,
+ libvlc_track_type_t type );
+
+
+/**
+ * Select a track or unselect all tracks for one type
+ *
+ * \note Use libvlc_media_player_update_tracklist() for finer track selection
+ * control.
+ *
+ * \version LibVLC 4.0.0 and later.
+ *
+ * \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,
+ libvlc_media_track_t *track );
+
+/**
+ * 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/include/vlc/libvlc_media_track.h b/include/vlc/libvlc_media_track.h
index cad3822a4f..160877d539 100644
--- a/include/vlc/libvlc_media_track.h
+++ b/include/vlc/libvlc_media_track.h
@@ -139,6 +139,10 @@ typedef struct libvlc_media_track_t
char *psz_language;
char *psz_description;
+ /* Only valid if the media is attached to a mediaplayer */
+ char *psz_name;
+ bool selected;
+
} libvlc_media_track_t;
/**
diff --git a/lib/media_internal.h b/lib/media_internal.h
index 24bedfb405..e1cfc78c73 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 libvlc_media_trackpriv_t *
+libvlc_media_track_to_priv( libvlc_media_track_t *track )
+{
+ return container_of( track, 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_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_init( libvlc_media_track_t *track );
+
void
libvlc_media_track_clean( libvlc_media_track_t *track );
diff --git a/lib/media_player.c b/lib/media_player.c
index 68e6e62b1a..1f25fe758a 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -726,6 +726,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
mp->p_md = NULL;
mp->p_libvlc_instance = instance;
+ libvlc_media_track_init( &mp->selected_trackpriv.t );;
/* use a reentrant lock to allow calling libvlc functions from callbacks */
mp->player = vlc_player_New(VLC_OBJECT(mp), VLC_PLAYER_LOCK_REENTRANT,
NULL, NULL);
@@ -835,6 +836,8 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
vlc_http_cookies_destroy( cookies );
}
+ libvlc_media_track_clean( &p_mi->selected_trackpriv.t );
+
libvlc_instance_t *instance = p_mi->p_libvlc_instance;
vlc_object_delete(p_mi);
libvlc_release(instance);
@@ -1803,6 +1806,106 @@ 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;
+}
+
+const 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);
+
+ libvlc_media_track_clean( &p_mi->selected_trackpriv.t );
+
+ 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_trackpriv_from_player_track( &p_mi->selected_trackpriv, track );
+ vlc_player_Unlock(player);
+
+ return &p_mi->selected_trackpriv.t;
+}
+
+void
+libvlc_media_player_select_track( libvlc_media_player_t *p_mi,
+ libvlc_track_type_t type,
+ 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 )
+ {
+ 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_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 )
+ {
+ libvlc_media_track_t *track = libvlc_media_tracklist_at( list, i );
+ if( track->selected )
+ {
+ 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..f0fdd0f54b 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"
@@ -49,6 +50,8 @@ struct libvlc_media_player_t
struct libvlc_instance_t * p_libvlc_instance; /* Parent instance */
libvlc_media_t * p_md; /* current media descriptor */
libvlc_event_manager_t event_manager;
+
+ libvlc_media_trackpriv_t selected_trackpriv;
};
libvlc_track_description_t * libvlc_get_track_description(
diff --git a/lib/media_track.c b/lib/media_track.c
index d2c835c5fc..ba5089b510 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;
@@ -55,6 +57,8 @@ libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
track->i_bitrate = es->i_bitrate;
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_name = NULL;
+ track->selected = false;
switch( es->i_cat )
{
@@ -105,11 +109,19 @@ libvlc_media_trackpriv_from_es( libvlc_media_trackpriv_t *trackpriv,
}
}
+void
+libvlc_media_track_init( libvlc_media_track_t *track )
+{
+ track->i_type = libvlc_track_unknown;
+ track->psz_language = track->psz_description = track->psz_name = NULL;
+}
+
void
libvlc_media_track_clean( libvlc_media_track_t *track )
{
free( track->psz_language );
free( track->psz_description );
+ free( track->psz_name );
switch( track->i_type )
{
case libvlc_track_audio:
@@ -172,6 +184,39 @@ 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->t.psz_name = strdup( track->name );
+ trackpriv->t.selected = track->selected;
+}
+
+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 );
+ trackpriv->es_id = vlc_es_id_Hold( track->es_id );
+ }
+
+ return list;
+}
+
size_t
libvlc_media_tracklist_count( const libvlc_media_tracklist_t *list )
{
@@ -192,6 +237,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