[vlc-devel] [PATCH 2/4] playlist: introduce playlist repository

Romain Vimont rom1v at videolabs.io
Thu Aug 20 17:44:21 CEST 2020


Store the main playlist in a "playlist repo".

This new component will be able to manage several playlists.
---
 include/vlc_playlist.h    |  39 +++++++++++
 src/Makefile.am           |   2 +
 src/interface/interface.c |  67 +-----------------
 src/libvlc.c              |  11 ++-
 src/libvlc.h              |   4 +-
 src/libvlccore.sym        |   3 +
 src/playlist/repo.c       | 142 ++++++++++++++++++++++++++++++++++++++
 src/playlist/repo.h       |  34 +++++++++
 8 files changed, 232 insertions(+), 70 deletions(-)
 create mode 100644 src/playlist/repo.c
 create mode 100644 src/playlist/repo.h

diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h
index 2c11cf8fd7..9a1c66e3dc 100644
--- a/include/vlc_playlist.h
+++ b/include/vlc_playlist.h
@@ -886,6 +886,45 @@ VLC_API int
 vlc_playlist_Export(vlc_playlist_t *playlist, const char *filename,
                     const char *type);
 
+/** Playlist repository (opaque) */
+typedef struct vlc_playlist_repo vlc_playlist_repo_t;
+
+/**
+ * Return the playlist repository.
+ *
+ * \param libvlc the libvlc instance
+ * \return the playlist repo
+ */
+VLC_API vlc_playlist_repo_t *
+libvlc_GetPlaylistRepo(libvlc_int_t *libvlc);
+
+/**
+ * Return the main playlist.
+ *
+ * This does not increment the playlist refcount. The playlist is guaranteed to
+ * exist until the libvlc instance is destroyed.
+ *
+ * \param the playlist repo
+ * \return the main playlist
+ */
+VLC_API vlc_playlist_t *
+vlc_playlist_repo_GetMainPlaylist(vlc_playlist_repo_t *repo);
+
+/**
+ * Return the main playlist from the libvlc instance.
+ *
+ * This does not increment the playlist refcount. The playlist is guaranteed to
+ * exist until the libvlc instance is destroyed.
+ *
+ * This function is provided for convenience to retrieve the main playlist
+ * directly from the libvlc_int_t instance, without handling the repo instance.
+ *
+ * \param the libvlc instance
+ * \return the main playlist
+ */
+VLC_API vlc_playlist_t *
+libvlc_GetMainPlaylist(libvlc_int_t *libvlc);
+
 /** @} */
 # ifdef __cplusplus
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 9e7c2931d2..9275ca8fff 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -239,6 +239,8 @@ libvlccore_la_SOURCES = \
 	playlist/preparse.h \
 	playlist/randomizer.c \
 	playlist/randomizer.h \
+	playlist/repo.c \
+	playlist/repo.h \
 	playlist/request.c \
 	playlist/shuffle.c \
 	playlist/sort.c \
diff --git a/src/interface/interface.c b/src/interface/interface.c
index cc490a35f2..4f182ae651 100644
--- a/src/interface/interface.c
+++ b/src/interface/interface.c
@@ -49,74 +49,11 @@
 static int AddIntfCallback( vlc_object_t *, char const *,
                             vlc_value_t , vlc_value_t , void * );
 
-static void
-PlaylistConfigureFromVariables(vlc_playlist_t *playlist, vlc_object_t *obj)
-{
-    enum vlc_playlist_playback_order order;
-    if (var_InheritBool(obj, "random"))
-        order = VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM;
-    else
-        order = VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL;
-
-    /* repeat = repeat current; loop = repeat all */
-    enum vlc_playlist_playback_repeat repeat;
-    if (var_InheritBool(obj, "repeat"))
-        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT;
-    else if (var_InheritBool(obj, "loop"))
-        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
-    else
-        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_NONE;
-
-    enum vlc_player_media_stopped_action media_stopped_action;
-    if (var_InheritBool(obj, "play-and-exit"))
-        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_EXIT;
-    else if (var_InheritBool(obj, "play-and-stop"))
-        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_STOP;
-    else if (var_InheritBool(obj, "play-and-pause"))
-        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_PAUSE;
-    else
-        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_CONTINUE;
-
-    bool start_paused = var_InheritBool(obj, "start-paused");
-    bool playlist_cork = var_InheritBool(obj, "playlist-cork");
-
-    vlc_playlist_Lock(playlist);
-    vlc_playlist_SetPlaybackOrder(playlist, order);
-    vlc_playlist_SetPlaybackRepeat(playlist, repeat);
-
-    vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
-
-    /* the playlist and the player share the same lock, and this is not an
-     * implementation detail */
-    vlc_player_SetMediaStoppedAction(player, media_stopped_action);
-    vlc_player_SetStartPaused(player, start_paused);
-    vlc_player_SetPauseOnCork(player, playlist_cork);
-
-    vlc_playlist_Unlock(playlist);
-}
-
-static vlc_playlist_t *
-libvlc_GetMainPlaylist(libvlc_int_t *libvlc)
-{
-    libvlc_priv_t *priv = libvlc_priv(libvlc);
-
-    vlc_mutex_lock(&priv->lock);
-    vlc_playlist_t *playlist = priv->main_playlist;
-    if (priv->main_playlist == NULL)
-    {
-        playlist = priv->main_playlist = vlc_playlist_New(VLC_OBJECT(libvlc));
-        if (playlist)
-            PlaylistConfigureFromVariables(playlist, VLC_OBJECT(libvlc));
-    }
-    vlc_mutex_unlock(&priv->lock);
-
-    return playlist;
-}
-
 vlc_playlist_t *
 vlc_intf_GetMainPlaylist(intf_thread_t *intf)
 {
-    vlc_playlist_t *pl = libvlc_GetMainPlaylist(vlc_object_instance(intf));
+    libvlc_int_t *libvlc = vlc_object_instance(intf);
+    vlc_playlist_t *pl = libvlc_GetMainPlaylist(libvlc);
     assert(pl);
     return pl;
 }
diff --git a/src/libvlc.c b/src/libvlc.c
index 3e6356598b..1ff6628692 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -65,6 +65,7 @@
 #include <vlc_thumbnailer.h>
 
 #include "libvlc.h"
+#include "playlist/repo.h"
 
 #include <vlc_vlm.h>
 
@@ -92,7 +93,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
     priv = libvlc_priv (p_libvlc);
     vlc_mutex_init(&priv->lock);
     priv->interfaces = NULL;
-    priv->main_playlist = NULL;
+    priv->playlist_repo = NULL;
     priv->p_vlm = NULL;
     priv->media_source_provider = NULL;
 
@@ -222,6 +223,10 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
     if( libvlc_InternalActionsInit( p_libvlc ) != VLC_SUCCESS )
         goto error;
 
+    priv->playlist_repo = vlc_playlist_repo_New( VLC_OBJECT( p_libvlc ) );
+    if( !priv->playlist_repo )
+        goto error;
+
     /*
      * Meta data handling
      */
@@ -376,8 +381,8 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
     if (priv->parser != NULL)
         input_preparser_Delete(priv->parser);
 
-    if (priv->main_playlist)
-        vlc_playlist_Release(priv->main_playlist);
+    if (priv->playlist_repo)
+        vlc_playlist_repo_Delete(priv->playlist_repo);
 
     if ( priv->p_media_library )
         libvlc_MlRelease( priv->p_media_library );
diff --git a/src/libvlc.h b/src/libvlc.h
index d2d112aa56..2bc4be1075 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -174,7 +174,7 @@ void vlc_objres_remove(vlc_object_t *obj, void *data,
 typedef struct vlc_dialog_provider vlc_dialog_provider;
 typedef struct vlc_keystore vlc_keystore;
 typedef struct vlc_actions_t vlc_actions_t;
-typedef struct vlc_playlist vlc_playlist_t;
+typedef struct vlc_playlist_repo vlc_playlist_repo_t;
 typedef struct vlc_media_source_provider_t vlc_media_source_provider_t;
 typedef struct intf_thread_t intf_thread_t;
 
@@ -188,7 +188,7 @@ typedef struct libvlc_priv_t
     vlc_dialog_provider *p_dialog_provider; ///< dialog provider
     vlc_keystore      *p_memory_keystore; ///< memory keystore
     intf_thread_t *interfaces;  ///< Linked-list of interfaces
-    vlc_playlist_t *main_playlist;
+    vlc_playlist_repo_t *playlist_repo;
     struct input_preparser_t *parser; ///< Input item meta data handler
     vlc_media_source_provider_t *media_source_provider;
     vlc_actions_t *actions; ///< Hotkeys handler
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index f2aaba339d..74f47fd629 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -936,6 +936,9 @@ vlc_playlist_Pause
 vlc_playlist_Resume
 vlc_playlist_Preparse
 vlc_playlist_Export
+vlc_playlist_repo_GetMainPlaylist
+libvlc_GetPlaylistRepo
+libvlc_GetMainPlaylist
 vlc_intf_GetMainPlaylist
 vlc_media_source_Hold
 vlc_media_source_Release
diff --git a/src/playlist/repo.c b/src/playlist/repo.c
new file mode 100644
index 0000000000..b9ac59d16a
--- /dev/null
+++ b/src/playlist/repo.c
@@ -0,0 +1,142 @@
+/*****************************************************************************
+ * playlist/repo.c
+ *****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "repo.h"
+
+#include <vlc_common.h>
+#include <vlc_playlist.h>
+#include <vlc_threads.h>
+#include "libvlc.h"
+#include "player/player.h"
+
+struct vlc_playlist_repo {
+    struct vlc_object_t obj;
+    vlc_mutex_t lock;
+    vlc_playlist_t *main_playlist;
+};
+
+vlc_playlist_repo_t *
+vlc_playlist_repo_New(vlc_object_t *parent)
+{
+    vlc_playlist_repo_t *repo =
+        vlc_custom_create(parent, sizeof(*repo), "playlist-repo");
+    if (!repo)
+        return NULL;
+
+    vlc_mutex_init(&repo->lock);
+    repo->main_playlist = NULL;
+    return repo;
+}
+
+void
+vlc_playlist_repo_Delete(vlc_playlist_repo_t *repo)
+{
+    if (repo->main_playlist)
+        vlc_playlist_Release(repo->main_playlist);
+
+    vlc_object_delete(repo);
+}
+
+static void
+PlaylistConfigureFromVariables(vlc_playlist_t *playlist, vlc_object_t *obj)
+{
+    enum vlc_playlist_playback_order order;
+    if (var_InheritBool(obj, "random"))
+        order = VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM;
+    else
+        order = VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL;
+
+    /* repeat = repeat current; loop = repeat all */
+    enum vlc_playlist_playback_repeat repeat;
+    if (var_InheritBool(obj, "repeat"))
+        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT;
+    else if (var_InheritBool(obj, "loop"))
+        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_ALL;
+    else
+        repeat = VLC_PLAYLIST_PLAYBACK_REPEAT_NONE;
+
+    enum vlc_player_media_stopped_action media_stopped_action;
+    if (var_InheritBool(obj, "play-and-exit"))
+        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_EXIT;
+    else if (var_InheritBool(obj, "play-and-stop"))
+        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_STOP;
+    else if (var_InheritBool(obj, "play-and-pause"))
+        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_PAUSE;
+    else
+        media_stopped_action = VLC_PLAYER_MEDIA_STOPPED_CONTINUE;
+
+    bool start_paused = var_InheritBool(obj, "start-paused");
+    bool playlist_cork = var_InheritBool(obj, "playlist-cork");
+
+    vlc_playlist_Lock(playlist);
+    vlc_playlist_SetPlaybackOrder(playlist, order);
+    vlc_playlist_SetPlaybackRepeat(playlist, repeat);
+
+    vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
+
+    /* the playlist and the player share the same lock, and this is not an
+     * implementation detail */
+    vlc_player_SetMediaStoppedAction(player, media_stopped_action);
+    vlc_player_SetStartPaused(player, start_paused);
+    vlc_player_SetPauseOnCork(player, playlist_cork);
+
+    vlc_playlist_Unlock(playlist);
+}
+
+vlc_playlist_repo_t *
+libvlc_GetPlaylistRepo(libvlc_int_t *libvlc)
+{
+    libvlc_priv_t *priv = libvlc_priv(libvlc);
+    return priv->playlist_repo;
+}
+
+static void
+InitMainPlaylist(vlc_playlist_repo_t *repo)
+{
+    assert(!repo->main_playlist);
+
+    repo->main_playlist = vlc_playlist_New(VLC_OBJECT(repo));
+    if (!repo->main_playlist)
+        return;
+
+    PlaylistConfigureFromVariables(repo->main_playlist, VLC_OBJECT(repo));
+}
+
+vlc_playlist_t *
+vlc_playlist_repo_GetMainPlaylist(vlc_playlist_repo_t *repo)
+{
+    vlc_mutex_lock(&repo->lock);
+    if (!repo->main_playlist)
+        InitMainPlaylist(repo);
+    vlc_mutex_unlock(&repo->lock);
+
+    return repo->main_playlist;
+}
+
+vlc_playlist_t *
+libvlc_GetMainPlaylist(libvlc_int_t *libvlc)
+{
+    vlc_playlist_repo_t *repo = libvlc_GetPlaylistRepo(libvlc);
+    return vlc_playlist_repo_GetMainPlaylist(repo);
+}
diff --git a/src/playlist/repo.h b/src/playlist/repo.h
new file mode 100644
index 0000000000..b1f8e725b8
--- /dev/null
+++ b/src/playlist/repo.h
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * playlist/repo.h
+ *****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_PLAYLIST_REPO_H
+#define VLC_PLAYLIST_REPO_H
+
+#include <vlc_common.h>
+
+typedef struct vlc_playlist_repo vlc_playlist_repo_t;
+
+vlc_playlist_repo_t *
+vlc_playlist_repo_New(vlc_object_t *parent);
+
+void
+vlc_playlist_repo_Delete(vlc_playlist_repo_t *repo);
+
+#endif
-- 
2.28.0



More information about the vlc-devel mailing list