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

Hugo Beauzée-Luyssen hugo at beauzee.fr
Wed Jul 31 11:20:38 CEST 2019


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)
+{
+    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);
+    }
+    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);
+    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) \
+    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");
+
+#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;
+
+    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();
-- 
2.20.1



More information about the vlc-devel mailing list