[vlc-devel] [PATCH 08/12] core: playlist: notify on AddListener()

Romain Vimont rom1v at videolabs.io
Thu Oct 11 23:14:46 CEST 2018


When a client registers a listener, it may optionally receive the
current state of the playlist via callbacks. This provides a convenient
way to initialize clients automatically.
---
 include/vlc_playlist_new.h |  16 +++--
 src/playlist/playlist.c    | 133 +++++++++++++++++++++++++++++--------
 2 files changed, 116 insertions(+), 33 deletions(-)

diff --git a/include/vlc_playlist_new.h b/include/vlc_playlist_new.h
index ea5c908c4c..102d7f8e79 100644
--- a/include/vlc_playlist_new.h
+++ b/include/vlc_playlist_new.h
@@ -356,15 +356,23 @@ vlc_playlist_Unlock(vlc_playlist_t *);
  * Return an opaque listener identifier, to be passed to
  * vlc_player_RemoveListener().
  *
- * \param playlist the playlist
- * \param cbs      the callbacks (must be valid until the listener is removed)
- * \param userdata userdata provided as a parameter in callbacks
+ * If notify_current_state is true, the callbacks are called once with the
+ * current state of the playlist. This is useful because when a client
+ * registers to the playlist, it may already contain items. Calling callbacks
+ * is a convenient way to initialize the client automatically.
+ *
+ * \param playlist             the playlist
+ * \param cbs                  the callbacks (must be valid until the listener
+ *                             is removed)
+ * \param userdata             userdata provided as a parameter in callbacks
+ * \param notify_current_state true to notify the current state immediately via
+ *                             callbacks
  * \return a listener identifier, or NULL if an error occurred
  */
 VLC_API VLC_USED vlc_playlist_listener_id *
 vlc_playlist_AddListener(vlc_playlist_t *playlist,
                          const struct vlc_playlist_callbacks *cbs,
-                         void *userdata);
+                         void *userdata, bool notify_current_state);
 
 /**
  * Remove a player listener.
diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c
index a4c08b028e..0d9af6938f 100644
--- a/src/playlist/playlist.c
+++ b/src/playlist/playlist.c
@@ -770,10 +770,28 @@ vlc_playlist_Unlock(vlc_playlist_t *playlist)
     vlc_player_Unlock(playlist->player);
 }
 
+static void
+vlc_playlist_NotifyCurrentState(vlc_playlist_t *playlist,
+                                vlc_playlist_listener_id *listener)
+{
+    PlaylistNotifyListener(playlist, listener, on_items_reset,
+                           playlist->items.data, playlist->items.size);
+    PlaylistNotifyListener(playlist, listener, on_playback_repeat_changed,
+                           playlist->repeat);
+    PlaylistNotifyListener(playlist, listener, on_playback_order_changed,
+                           playlist->order);
+    PlaylistNotifyListener(playlist, listener, on_current_index_changed,
+                           playlist->current);
+    PlaylistNotifyListener(playlist, listener, on_has_prev_changed,
+                           playlist->has_prev);
+    PlaylistNotifyListener(playlist, listener, on_has_next_changed,
+                           playlist->has_next);
+}
+
 vlc_playlist_listener_id *
 vlc_playlist_AddListener(vlc_playlist_t *playlist,
                          const struct vlc_playlist_callbacks *cbs,
-                         void *userdata)
+                         void *userdata, bool notify_current_state)
 {
     PlaylistAssertLocked(playlist);
 
@@ -785,6 +803,9 @@ vlc_playlist_AddListener(vlc_playlist_t *playlist,
     listener->userdata = userdata;
     vlc_list_append(&listener->node, &playlist->listeners);
 
+    if (notify_current_state)
+        vlc_playlist_NotifyCurrentState(playlist, listener);
+
     return listener;
 }
 
@@ -2145,7 +2166,7 @@ test_items_added_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     int ret = vlc_playlist_AppendOne(playlist, media[0]);
@@ -2243,7 +2264,7 @@ test_items_moved_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_Move(playlist, 2, 3, 5);
@@ -2335,7 +2356,7 @@ test_items_removed_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_RemoveOne(playlist, 4);
@@ -2426,7 +2447,7 @@ test_items_reset_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     callback_ctx_reset(&ctx);
@@ -2472,7 +2493,7 @@ test_playback_repeat_changed_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_SetPlaybackRepeat(playlist, VLC_PLAYLIST_PLAYBACK_REPEAT_ALL);
@@ -2503,7 +2524,7 @@ test_playback_order_changed_callbacks(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_SetPlaybackOrder(playlist, VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM);
@@ -2520,6 +2541,65 @@ test_playback_order_changed_callbacks(void)
     vlc_playlist_Delete(playlist);
 }
 
+static void
+test_callbacks_on_add_listener(void)
+{
+    vlc_playlist_t *playlist = vlc_playlist_New(NULL);
+    assert(playlist);
+
+    input_item_t *media[10];
+    CreateDummyMediaArray(media, 10);
+
+    /* initial playlist with 10 items */
+    int ret = vlc_playlist_Append(playlist, media, 10);
+    assert(ret == VLC_SUCCESS);
+
+    vlc_playlist_SetPlaybackRepeat(playlist, VLC_PLAYLIST_PLAYBACK_REPEAT_ALL);
+    vlc_playlist_SetPlaybackOrder(playlist, VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL);
+
+    ret = vlc_playlist_GoTo(playlist, 5);
+    assert(ret == VLC_SUCCESS);
+
+    struct vlc_playlist_callbacks cbs = {
+        .on_items_reset = callback_on_items_reset,
+        .on_playback_repeat_changed = callback_on_playback_repeat_changed,
+        .on_playback_order_changed = callback_on_playback_order_changed,
+        .on_current_index_changed = callback_on_current_index_changed,
+        .on_has_prev_changed = callback_on_has_prev_changed,
+        .on_has_next_changed = callback_on_has_next_changed,
+    };
+
+    struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
+    vlc_playlist_listener_id *listener =
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, true);
+    assert(listener);
+
+    assert(ctx.vec_items_reset.size == 1);
+    assert(ctx.vec_items_reset.data[0].count == 10);
+
+    assert(ctx.vec_playback_repeat_changed.size == 1);
+    assert(ctx.vec_playback_repeat_changed.data[0].repeat ==
+                                            VLC_PLAYLIST_PLAYBACK_REPEAT_ALL);
+
+    assert(ctx.vec_playback_order_changed.size == 1);
+    assert(ctx.vec_playback_order_changed.data[0].order ==
+                                            VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL);
+
+    assert(ctx.vec_current_index_changed.size == 1);
+    assert(ctx.vec_current_index_changed.data[0].current == 5);
+
+    assert(ctx.vec_has_prev_changed.size == 1);
+    assert(ctx.vec_has_prev_changed.data[0].has_prev);
+
+    assert(ctx.vec_has_next_changed.size == 1);
+    assert(ctx.vec_has_next_changed.data[0].has_next);
+
+    callback_ctx_destroy(&ctx);
+    vlc_playlist_RemoveListener(playlist, listener);
+    DestroyMediaArray(media, 10);
+    vlc_playlist_Delete(playlist);
+}
+
 static void
 test_index_of(void)
 {
@@ -2570,7 +2650,7 @@ test_prev(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     playlist->current = 2; /* last item */
@@ -2646,7 +2726,7 @@ test_next(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     playlist->current = 0; /* first item */
@@ -2722,7 +2802,7 @@ test_goto(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     /* go to an item in the middle */
@@ -2836,7 +2916,7 @@ test_request_insert(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     /* insert 5 items at index 10 (out-of-bounds) */
@@ -2881,7 +2961,7 @@ test_request_remove_with_matching_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *items_to_remove[] = {
@@ -2933,7 +3013,7 @@ test_request_remove_without_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *items_to_remove[] = {
@@ -2985,7 +3065,7 @@ test_request_remove_adapt(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *dummy = vlc_playlist_item_New(media[10]);
@@ -3057,7 +3137,7 @@ test_request_move_with_matching_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *items_to_move[] = {
@@ -3113,7 +3193,7 @@ test_request_move_without_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *items_to_move[] = {
@@ -3183,7 +3263,7 @@ test_request_move_adapt(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     vlc_playlist_item_t *dummy = vlc_playlist_item_New(media[15]);
@@ -3286,7 +3366,7 @@ test_request_goto_with_matching_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     /* go to an item in the middle, with incorrect index_hint */
@@ -3333,7 +3413,7 @@ test_request_goto_without_hint(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     /* go to an item in the middle, with incorrect index_hint */
@@ -3379,7 +3459,7 @@ test_request_goto_adapt(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     /* go to an item in the middle, with incorrect index_hint */
@@ -3428,7 +3508,7 @@ test_random(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
     assert(!vlc_playlist_HasPrev(playlist));
@@ -3555,12 +3635,9 @@ test_shuffle(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
-    /* on_items_reset is called once during AddListener() */
-    callback_ctx_reset(&ctx);
-
     playlist->current = 4;
     playlist->has_prev = true;
     playlist->has_next = true;
@@ -3647,12 +3724,9 @@ test_sort(void)
 
     struct callback_ctx ctx = CALLBACK_CTX_INITIALIZER;
     vlc_playlist_listener_id *listener =
-            vlc_playlist_AddListener(playlist, &cbs, &ctx);
+            vlc_playlist_AddListener(playlist, &cbs, &ctx, false);
     assert(listener);
 
-    /* on_items_reset is called once during AddListener() */
-    callback_ctx_reset(&ctx);
-
     playlist->current = 0;
     playlist->has_prev = false;
     playlist->has_next = true;
@@ -3739,6 +3813,7 @@ int main(void)
     test_items_reset_callbacks();
     test_playback_repeat_changed_callbacks();
     test_playback_order_changed_callbacks();
+    test_callbacks_on_add_listener();
     test_index_of();
     test_prev();
     test_next();
-- 
2.19.1



More information about the vlc-devel mailing list