[vlc-devel] [PATCH 09/12] player: Save & restore playback states

Thomas Guillem thomas at gllm.fr
Wed Jul 31 16:17:56 CEST 2019



On Wed, Jul 31, 2019, at 11:20, Hugo Beauzée-Luyssen wrote:
> Refs #22524
> ---
>  src/input/player.c | 171 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 171 insertions(+)
> 
> diff --git a/src/input/player.c b/src/input/player.c
> index e53849dc21..411456dfd8 100644
> --- a/src/input/player.c
> +++ b/src/input/player.c
> @@ -35,6 +35,7 @@
>  #include <vlc_tick.h>
>  #include <vlc_decoder.h>
>  #include <vlc_memstream.h>
> +#include <vlc_media_library.h>
>  
>  #include "libvlc.h"
>  #include "input_internal.h"
> @@ -145,6 +146,8 @@ struct vlc_player_input
>          float pos;
>          bool set;
>      } abloop_state[2];
> +
> +    vlc_ml_playback_states_all prefs;
>  };
>  
>  struct vlc_player_t
> @@ -649,6 +652,43 @@ vlc_player_title_list_GetCount(struct 
> vlc_player_title_list *titles)
>      return titles->count;
>  }
>  
> +static void
> +vlc_player_input_restore_ml_prefs(struct vlc_player_input* input,
> +                                  const input_item_t* item)

NIT: vlc_player_input_RestoreMlPrefs

> +{
> +    vlc_player_t* player = input->player;
> +    vlc_player_assert_locked(player);
> +
> +    vlc_medialibrary_t* ml = vlc_ml_instance_get(input->player);
> +    if (!ml)
> +        return;
> +    vlc_ml_media_t* media = vlc_ml_get_media_by_mrl( ml, 
> item->psz_uri);
> +    if (!media)
> +        return;
> +    if (vlc_ml_media_get_all_playback_pref(ml, media->i_id, 
> &input->prefs) != VLC_SUCCESS)
> +        return;
> +    if (input->prefs.current_title >= 0)
> +    {
> +        /* If we are aiming at a specific title, wait for it to be 
> added, and
> +         * only then select it & set the position
> +         * If we're not aiming at a title, just set the position.
> +         */
> +        if (input->prefs.progress > .0f)
> +            input_SetPosition(input->thread, input->prefs.progress, 
> false);

This doesn't seem to match the comment. YOu want to set position here only if current_title == -1, right ?

> +    }
> +    if (input->prefs.rate != .0f)
> +        vlc_player_ChangeRate(player, input->prefs.rate);
> +    if (input->prefs.aspect_ratio)
> +        var_SetString(input->thread, "aspect-ratio", 
> input->prefs.aspect_ratio);
> +    if (input->prefs.zoom)
> +        var_SetString(input->thread, "zoom", input->prefs.zoom);
> +    if (input->prefs.zoom)
> +        var_SetString(input->thread, "deinterlace", input->prefs.zoom);
> +    if (input->prefs.video_filter)
> +        var_SetString(input->thread, "video-filter", 
> input->prefs.video_filter);

The vout is likely already created, so it won't inherit these variables.

> +    vlc_ml_release(media);
> +}
> +
>  static struct vlc_player_input *
>  vlc_player_input_New(vlc_player_t *player, input_item_t *item)
>  {
> @@ -687,6 +727,14 @@ vlc_player_input_New(vlc_player_t *player, 
> input_item_t *item)
>  
>      input->abloop_state[0].set = input->abloop_state[1].set = false;
>  
> +    memset(&input->prefs, 0, sizeof(input->prefs));
> +    input->prefs.aspect_ratio = input->prefs.zoom = input->prefs.crop =
> +        input->prefs.deinterlace = input->prefs.video_filter = NULL;
> +    input->prefs.current_title = input->prefs.current_video_track =
> +        input->prefs.current_audio_track =
> +        input->prefs.current_subtitle_track = -1;
> +    input->prefs.progress = -1.f;
> +
>      input->thread = input_Create(player, input_thread_Events, input, 
> item,
>                                   player->resource, player->renderer);
>      if (!input->thread)
> @@ -695,6 +743,8 @@ vlc_player_input_New(vlc_player_t *player, 
> input_item_t *item)
>          return NULL;
>      }
>  
> +    vlc_player_input_restore_ml_prefs(input, item);
> +
>      /* Initial sub/audio delay */
>      const vlc_tick_t cat_delays[DATA_ES] = {
>          [AUDIO_ES] =
> @@ -892,6 +942,87 @@ static int vlc_player_selected_track( const 
> vlc_player_track_vector* tracks )
>      return 0;
>  }
>  
> +static void vlc_player_UpdateML(vlc_player_t *player,
> +                                struct vlc_player_input* input)
> +{
> +    vlc_medialibrary_t* ml = vlc_ml_instance_get(player);
> +    if (!ml)
> +        return;
> +    input_item_t* item = input_GetItem(input->thread);
> +    if (!item)
> +        return;
> +    vlc_ml_media_t* media = vlc_ml_get_media_by_mrl(ml, item->psz_uri);
> +    if (!media)
> +    {
> +        /* We don't know this media yet, let's add it as an external 
> media so
> +         * we can still store its playback preferences
> +         */
> +        media = vlc_ml_new_external_media(ml, item->psz_uri);
> +        if (media == NULL)
> +            return;
> +    }
> +
> +    input->prefs.progress = input->position;
> +    input->prefs.current_title = input->title_selected;
> +    if (input->rate != input->prefs.rate)
> +        input->prefs.rate = input->rate;
> +    else
> +        input->prefs.rate = -1.f;
> +
> +#define COMPARE_ASSIGN_STR(field, var) \

You could add a little comment to explain what this macro is doing

> +    char* field = var_GetNonEmptyString(player, var); \
> +    if ( ( field != NULL && input->prefs.field != NULL && 
> strcmp(field, input->prefs.field)) || \
> +         ( field == NULL && input->prefs.field != NULL ) || \
> +         ( field != NULL && input->prefs.field == NULL ) ) \
> +    { \
> +        free(input->prefs.field); \
> +        input->prefs.field = field; \
> +        field = NULL; \
> +    } \
> +    else \
> +    { \
> +        free(input->prefs.field); \
> +        input->prefs.field = NULL; \
> +    }
> +
> +    COMPARE_ASSIGN_STR(aspect_ratio, "aspect-ratio" );
> +    COMPARE_ASSIGN_STR(zoom, "zoom");
> +    COMPARE_ASSIGN_STR(crop, "crop");
> +    COMPARE_ASSIGN_STR(deinterlace, "deinterlace");
> +    COMPARE_ASSIGN_STR(video_filter, "video-filter");

These variables could be on the player, yes but they won't be up to date. Player users have to change these variables on vouts. So maybe you should query the vout, but the good one, cf. vlc_player_GetEsIdVout

> +
> +#undef COMPARE_ASSIGN_STR
> +
> +    int current_video_track = 
> vlc_player_selected_track(&input->video_track_vector);
> +    int current_audio_track = 
> vlc_player_selected_track(&input->audio_track_vector);
> +    int current_subtitle_track = 
> vlc_player_selected_track(&input->spu_track_vector);
> +
> +    if (input->prefs.current_video_track != current_video_track)
> +        input->prefs.current_video_track = current_video_track;
> +    else
> +        input->prefs.current_video_track = -1;

I don't understand why you would set it to -1 if tracks are equal.

> +
> +    if (input->prefs.current_audio_track != current_audio_track)
> +        input->prefs.current_audio_track = current_audio_track;
> +    else
> +        input->prefs.current_audio_track = -1;
> +
> +    if (input->prefs.current_subtitle_track != current_subtitle_track)
> +        input->prefs.current_subtitle_track = current_subtitle_track;
> +    else
> +        input->prefs.current_subtitle_track = -1;
> +
> +    vlc_ml_media_set_all_playback_states(ml, media->i_id, 
> &input->prefs);
> +    vlc_ml_release(&input->prefs);
> +    vlc_ml_release(media);
> +
> +    free(video_filter);
> +    free(deinterlace);
> +    free(crop);
> +    free(zoom);
> +    free(aspect_ratio);
> +}
> +
>  static void *
>  vlc_player_destructor_Thread(void *data)
>  {
> @@ -916,6 +1047,7 @@ vlc_player_destructor_Thread(void *data)
>              vlc_player_input_HandleState(input, 
> VLC_PLAYER_STATE_STOPPING);
>              vlc_player_destructor_AddStoppingInput(player, input);
>  
> +            vlc_player_UpdateML(player, input);
>              input_Stop(input->thread);
>          }
>  
> @@ -1840,6 +1972,28 @@ vlc_player_input_HandleEsEvent(struct 
> vlc_player_input *input,
>              }
>              vlc_player_SendEvent(player, on_track_list_changed,
>                                   VLC_PLAYER_LIST_ADDED, &trackpriv->t);
> +            switch(ev->fmt->i_cat)
> +            {
> +                case VIDEO_ES:
> +                    if (input->prefs.current_video_track != -1 &&
> +                        input->prefs.current_video_track == 
> ev->fmt->i_id)
> +                        vlc_player_SelectTrack(input->player, 
> &trackpriv->t,
> +                                               
> VLC_PLAYER_SELECT_EXCLUSIVE);
> +                    break;
> +                case AUDIO_ES:
> +                    if (input->prefs.current_audio_track != -1 &&
> +                        input->prefs.current_audio_track == 
> ev->fmt->i_id)
> +                        vlc_player_SelectTrack(input->player, 
> &trackpriv->t,
> +                                               
> VLC_PLAYER_SELECT_EXCLUSIVE);
> +                    break;
> +                case SPU_ES:
> +                    if (input->prefs.current_subtitle_track != -1 &&
> +                        input->prefs.current_subtitle_track == 
> ev->fmt->i_id)
> +                        vlc_player_SelectTrack(input->player, 
> &trackpriv->t,
> +                                               
> VLC_PLAYER_SELECT_EXCLUSIVE);
> +                default:
> +                    break;
> +            }
>              break;
>          case VLC_INPUT_ES_DELETED:
>          {
> @@ -1907,8 +2061,15 @@ vlc_player_input_HandleTitleEvent(struct 
> vlc_player_input *input,
>                                               title_offset, 
> chapter_offset);
>              vlc_player_SendEvent(player, on_titles_changed, 
> input->titles);
>              if (input->titles)
> +            {
>                  vlc_player_SendEvent(player, 
> on_title_selection_changed,
>                                       &input->titles->array[0], 0);
> +                if (input->prefs.current_title >= 0 &&
> +                    (size_t)input->prefs.current_title < 
> ev->list.count)
> +                {
> +                    vlc_player_SelectTitleIdx(player, 
> input->prefs.current_title);
> +                }
> +            }
>              break;
>          }
>          case VLC_INPUT_TITLE_SELECTED:
> @@ -1919,6 +2080,16 @@ vlc_player_input_HandleTitleEvent(struct 
> vlc_player_input *input,
>              vlc_player_SendEvent(player, on_title_selection_changed,
>                                   
> &input->titles->array[input->title_selected],
>                                   input->title_selected);
> +            if (input->prefs.current_title >= 0 &&
> +                (size_t)input->prefs.current_title == ev->selected_idx 
> &&
> +                input->prefs.progress > .0f)
> +            {
> +                input_SetPosition(input->thread, 
> input->prefs.progress, false);
> +                /* Reset the wanted title to avoid forcing it or the 
> position
> +                 * again during the next title change
> +                 */
> +                input->prefs.current_title = 0;
> +            }
>              break;
>          default:
>              vlc_assert_unreachable();
> -- 

There can be several players instances. I think only the main one, owned by the main playlist should play with the medialibrary.

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