vlc | branch: master | Thomas Guillem <[email protected]> | Thu Jun 4 19:59:51 2020 +0200| [6f4685bedb03c81b32ac8a49873d704a5983bfab] | committer: Thomas Guillem
lib: add new player track API > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6f4685bedb03c81b32ac8a49873d704a5983bfab --- include/vlc/libvlc_media_player.h | 138 ++++++++++++++++++++++++++++++++++ lib/libvlc.sym | 6 ++ lib/media_internal.h | 19 +++++ lib/media_player.c | 153 ++++++++++++++++++++++++++++++++++++++ lib/media_player_internal.h | 1 + lib/media_track.c | 54 ++++++++++++++ 6 files changed, 371 insertions(+) diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h index a6f5fbf8e5..c067e0acc9 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_delete() + */ +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_delete(). + */ +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_delete(). + */ +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 6251d5d230..d997d79939 100644 --- a/lib/libvlc.sym +++ b/lib/libvlc.sym @@ -182,6 +182,12 @@ 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_track_from_id +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 ff6c932f69..b7b575698a 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_delete( 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_delete( 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 ); } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
