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

Roland Bewick roland.bewick at gmail.com
Mon May 27 17:35:39 CEST 2019


On 27/05/2019 2:39 PM, Thomas Guillem wrote:
> 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)

I can split the commit this time since I have to make some changes in 
the following commits anyway. Thanks for your offer.

>
>> 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.

I'll fix this, thanks.

>
>> +
>> +    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
> _______________________________________________
> 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