[vlc-devel] [PATCH 01/16] Add vlc_player_SelectTrackList

Thomas Guillem thomas at gllm.fr
Mon May 27 09:39:04 CEST 2019


Hi,

On Tue, May 21, 2019, at 20:09, Roland Bewick wrote:
> ---
>  include/vlc_es_out.h                          |  1 +
>  include/vlc_player.h                          | 26 ++++++++
>  modules/access/bluray.c                       |  1 +
>  modules/demux/adaptive/plumbing/FakeESOut.cpp |  1 +
>  src/input/es_out.c                            | 44 ++++++++++++++
>  src/input/es_out_timeshift.c                  |  1 +
>  src/input/input.c                             | 22 +++++++
>  src/input/input_internal.h                    |  5 ++
>  src/input/player.c                            | 85 +++++++++++++++++++++++++++
>  src/libvlccore.sym                            |  1 +
>  10 files changed, 187 insertions(+)

We could split this commit in three: es_out/input/player. I can do it myself when I actually merge it if you agree (preserving your authorship)

> 
> diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
> index b690d570e9..47e2012ab9 100644
> --- a/include/vlc_es_out.h
> +++ b/include/vlc_es_out.h
> @@ -36,6 +36,7 @@ enum es_out_query_e
>  {
>      /* set or change the selected ES in its category (audio/video/spu) */
>      ES_OUT_SET_ES,      /* arg1= es_out_id_t*                   */
> +    ES_OUT_SET_ES_LIST, /* arg1= es_out_id_t**                  */
>      ES_OUT_UNSET_ES,    /* arg1= es_out_id_t* res=can fail      */
>      ES_OUT_RESTART_ES,  /* arg1= es_out_id_t*                   */
>  
> diff --git a/include/vlc_player.h b/include/vlc_player.h
> index 1aa5f8e687..f2df800797 100644
> --- a/include/vlc_player.h
> +++ b/include/vlc_player.h
> @@ -1675,6 +1675,32 @@ vlc_player_GetSelectedTrack(vlc_player_t 
> *player, enum es_format_category_e cat)
>  VLC_API void
>  vlc_player_SelectTrack(vlc_player_t *player, vlc_es_id_t *es_id);
>  
> +
> +/**
> + * Select multiple tracks from a list of ES identifiers. Any currently
> + * selected track not referenced in the list will be unselected.
> + * 
> + * @warning there is no guarantee all requested tracks will be 
> selected.
> + * Only one audio track can be selected at a time. Two subtitle tracks
> + * can be selected simultaneously if dual subtitles are enabled.
> + * 
> + * @warning 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.
> + *
> + * @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 can be retrieved from vlc_player_cbs.on_track_list_changed 
> or
> + * vlc_player_GetTrackAt())
> + */
> +VLC_API void
> +vlc_player_SelectTrackList(vlc_player_t *player,
> +                           enum es_format_category_e cat,
> +                           vlc_es_id_t *const es_id_list[]);
> +
>  /**
>   * Select the next track
>   *
> diff --git a/modules/access/bluray.c b/modules/access/bluray.c
> index c452327aeb..cd88dcc4cf 100644
> --- a/modules/access/bluray.c
> +++ b/modules/access/bluray.c
> @@ -1546,6 +1546,7 @@ static int bluray_esOutControl(es_out_t *p_out, 
> int i_query, va_list args)
>  
>          case ES_OUT_SET_ES_DEFAULT:
>          case ES_OUT_SET_ES:
> +        case ES_OUT_SET_ES_LIST:
>          case ES_OUT_UNSET_ES:
>          case ES_OUT_SET_ES_STATE:
>              i_ret = VLC_EGENERIC;
> diff --git a/modules/demux/adaptive/plumbing/FakeESOut.cpp 
> b/modules/demux/adaptive/plumbing/FakeESOut.cpp
> index 69d00f7e7f..f1f274e0cf 100644
> --- a/modules/demux/adaptive/plumbing/FakeESOut.cpp
> +++ b/modules/demux/adaptive/plumbing/FakeESOut.cpp
> @@ -470,6 +470,7 @@ int FakeESOut::esOutControl_Callback(es_out_t 
> *fakees, int i_query, va_list args
>          }
>  
>          case ES_OUT_SET_ES:
> +        case ES_OUT_SET_ES_LIST:
>          case ES_OUT_SET_ES_DEFAULT:
>          case ES_OUT_SET_ES_STATE:
>              return VLC_SUCCESS;
> diff --git a/src/input/es_out.c b/src/input/es_out.c
> index 2026fb8c22..933249c39b 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -217,6 +217,8 @@ static void         EsOutDel    ( es_out_t *, 
> es_out_id_t * );
>  
>  static void         EsOutTerminate( es_out_t * );
>  static void         EsOutSelect( es_out_t *, es_out_id_t *es, bool 
> b_force );
> +static void         EsOutSelectList( es_out_t *, enum 
> es_format_category_e cat,
> +                                     vlc_es_id_t **es_id_list );
>  static void         EsOutUpdateInfo( es_out_t *, es_out_id_t *es, 
> const vlc_meta_t * );
>  static int          EsOutSetRecord(  es_out_t *, bool b_record );
>  
> @@ -2182,6 +2184,41 @@ static void EsOutSelect( es_out_t *out, 
> es_out_id_t *es, bool b_force )
>          p_esprops->p_main_es = es;
>  }
>  
> +static void EsOutSelectList( es_out_t *out, enum es_format_category_e 
> cat,
> +                             vlc_es_id_t **es_id_list )
> +{
> +
> +    es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> +    es_out_id_t *other;
> +
> +    foreach_es_then_es_slaves(other)
> +    {
> +        if( other->fmt.i_cat == cat )
> +        {
> +            bool select = false;
> +            for( size_t i = 0; ; i++ )
> +            {
> +                vlc_es_id_t *es_id = es_id_list[i];
> +                if( es_id == NULL )
> +                    break;
> +                else if( es_id->i_id == other->id.i_id )
> +                {
> +                    select = true;
> +                    break;
> +                }
> +            }
> +            if( !select && EsIsSelected( other ) )
> +            {
> +                EsOutUnselectEs( out, other, other->p_pgrm == 
> p_sys->p_pgrm );
> +            }
> +            else if( select && !EsIsSelected( other ) )
> +            {
> +                EsOutSelectEs( out, other );
> +            }
> +        }
> +    }
> +}
> +
>  static void EsOutCreateCCChannels( es_out_t *out, vlc_fourcc_t codec, 
> uint64_t i_bitmap,
>                                     const char *psz_descfmt, 
> es_out_id_t *parent )
>  {
> @@ -2601,6 +2638,13 @@ static int EsOutVaControlLocked( es_out_t *out, 
> int i_query, va_list args )
>          EsOutStopFreeVout( out );
>          return VLC_SUCCESS;
>      }
> +    case ES_OUT_SET_ES_LIST:
> +    {
> +        enum es_format_category_e cat = va_arg( args, enum 
> es_format_category_e );
> +        vlc_es_id_t **es_id_list = va_arg( args, vlc_es_id_t ** );
> +        EsOutSelectList( out, cat, es_id_list );
> +        return VLC_SUCCESS;
> +    }
>      case ES_OUT_UNSET_ES:
>      {
>          es_out_id_t *es = va_arg( args, es_out_id_t * ), *other;
> diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
> index 406c6f2237..21a041a1f8 100644
> --- a/src/input/es_out_timeshift.c
> +++ b/src/input/es_out_timeshift.c
> @@ -738,6 +738,7 @@ static int ControlLocked( es_out_t *p_out, int 
> i_query, va_list args )
>  
>      /* Invalid queries for this es_out level */
>      case ES_OUT_SET_ES_BY_ID:
> +    case ES_OUT_SET_ES_LIST:
>      case ES_OUT_RESTART_ES_BY_ID:
>      case ES_OUT_SET_ES_DEFAULT_BY_ID:
>      case ES_OUT_GET_ES_OBJECTS_BY_ID:
> diff --git a/src/input/input.c b/src/input/input.c
> index 381b85a9fd..eea40b59c1 100644
> --- a/src/input/input.c
> +++ b/src/input/input.c
> @@ -1712,6 +1712,18 @@ static void ControlRelease( int i_type, const 
> input_control_param_t *p_param )
>      case INPUT_CONTROL_RESTART_ES:
>          vlc_es_id_Release( p_param->id );
>          break;
> +    case INPUT_CONTROL_SET_ES_LIST:
> +    {
> +        for( size_t i = 0; ; i++ )
> +        {
> +            vlc_es_id_t *es_id = p_param->list.ids[i];
> +            if( es_id == NULL )
> +                break;
> +            vlc_es_id_Release( es_id );
> +        }
> +        free( p_param->list.ids );
> +        break;
> +    }
>  
>      default:
>          break;
> @@ -2130,6 +2142,16 @@ static bool Control( input_thread_t *p_input,
>                  demux_Control( input_priv(p_input)->master->p_demux, 
> DEMUX_SET_ES,
>                                 vlc_es_id_GetInputId( param.id ) );
>              break;
> +        case INPUT_CONTROL_SET_ES_LIST:
> +        {
> +            if( es_out_Control( input_priv(p_input)->p_es_out_display,
> +                                ES_OUT_SET_ES_LIST, param.list.cat,
> +                                param.list.ids ) == VLC_SUCCESS )
> +            {
> +                /* TODO: demux_Control(..., DEMUX_SET_ES_LIST, ... ) */
> +            }
> +            break;
> +        }
>          case INPUT_CONTROL_UNSET_ES:
>              es_out_Control( input_priv(p_input)->p_es_out_display,
>                              ES_OUT_UNSET_ES, param.id );
> diff --git a/src/input/input_internal.h b/src/input/input_internal.h
> index 18495881c2..3bcb5a9f83 100644
> --- a/src/input/input_internal.h
> +++ b/src/input/input_internal.h
> @@ -85,6 +85,10 @@ typedef union
>      vlc_viewpoint_t viewpoint;
>      vlc_es_id_t *id;
>      struct {
> +        enum es_format_category_e cat;
> +        vlc_es_id_t **ids;
> +    } list;
> +    struct {
>          bool b_fast_seek;
>          vlc_tick_t i_val;
>      } time;
> @@ -247,6 +251,7 @@ enum input_control_e
>      INPUT_CONTROL_RESTART_ES_BY_ID,
>  
>      INPUT_CONTROL_SET_ES,
> +    INPUT_CONTROL_SET_ES_LIST,  // select a list of ES atomically
>      INPUT_CONTROL_UNSET_ES,
>      INPUT_CONTROL_RESTART_ES,
>  
> diff --git a/src/input/player.c b/src/input/player.c
> index da02375a66..551b9928f1 100644
> --- a/src/input/player.c
> +++ b/src/input/player.c
> @@ -1312,6 +1312,91 @@ vlc_player_SelectTrack(vlc_player_t *player, 
> vlc_es_id_t *id)
>      vlc_player_vout_OSDTrack(player, id, true);
>  }
>  
> +void
> +vlc_player_SelectTrackList(vlc_player_t *player,
> +                           enum es_format_category_e cat,
> +                           vlc_es_id_t *const es_id_list[])
> +{
> +    struct vlc_player_input *input = 
> vlc_player_get_input_locked(player);
> +    if (!input)
> +        return;
> +
> +    /* First, count and hold all the ES Ids.
> +       Ids will be released in input.c:ControlRelease */
> +    size_t id_count;
> +    for (id_count = 0; ; id_count++)
> +    {
> +        vlc_es_id_t *es_id = es_id_list[id_count];
> +        if (es_id == NULL)
> +            break;
> +
> +        vlc_es_id_Hold( es_id );
> +    }
> +
> +    /* 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 =
> +        malloc(sizeof(vlc_es_id_t *) * (id_count + 1));

You forgot to check the malloc return.

> +
> +    for (size_t i = 0; i <= id_count; i++)
> +    {
> +        allocated_ids[i] = es_id_list[i];
> +    }
> +
> +    /* 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 */
> +    bool selected_new_track = false;
> +    for (size_t i = 0; i < id_count; i++)
> +    {
> +        vlc_es_id_t *es_id = es_id_list[i];
> +
> +        const struct vlc_player_track *track = 
> vlc_player_GetTrack(player, es_id);
> +        assert(track);
> +
> +        if (!track->selected)
> +        {
> +            vlc_player_vout_OSDTrack(player, es_id, true);
> +            selected_new_track = true;
> +        }
> +    }
> +
> +    if (!selected_new_track)
> +    {
> +        /* Display track deselection message */
> +        size_t count = vlc_player_GetTrackCount(player, cat);
> +        if (!count)
> +            return;
> +
> +        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)
> +            {
> +                bool selected = false;
> +                for (size_t j = 0; j < id_count; j++)
> +                {
> +                    if (es_id_list[j] == track->es_id)
> +                    {
> +                        selected = true;
> +                        break;
> +                    }
> +                }
> +
> +                if (!selected)
> +                    vlc_player_vout_OSDTrack(player, track->es_id, 
> false);
> +            }
> +        }
> +    }
> +}
> +
>  static void
>  vlc_player_CycleTrack(vlc_player_t *player, enum es_format_category_e 
> cat,
>                        bool next)
> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index efc07fbb25..03a503e1ea 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -856,6 +856,7 @@ vlc_player_SelectTeletextPage
>  vlc_player_SelectTitle
>  vlc_player_SelectTitleIdx
>  vlc_player_SelectTrack
> +vlc_player_SelectTrackList
>  vlc_player_SetAssociatedSubsFPS
>  vlc_player_SetAtoBLoop
>  vlc_player_SetAudioDelay
> -- 
> 2.11.0
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list