[vlc-devel] [PATCH 6/9] medialib: Add bookmark support

Hugo Beauzée-Luyssen hugo at beauzee.fr
Thu Jun 18 17:40:20 CEST 2020


---
 include/vlc_media_library.h              | 74 ++++++++++++++++++-
 modules/misc/medialibrary/entities.cpp   | 11 +++
 modules/misc/medialibrary/medialib.cpp   | 93 ++++++++++++++++++++----
 modules/misc/medialibrary/medialibrary.h |  1 +
 src/libvlccore.sym                       |  2 +
 src/misc/medialibrary.c                  | 23 ++++++
 6 files changed, 188 insertions(+), 16 deletions(-)

diff --git a/include/vlc_media_library.h b/include/vlc_media_library.h
index e5ed68604e..fd82a71a23 100644
--- a/include/vlc_media_library.h
+++ b/include/vlc_media_library.h
@@ -305,6 +305,20 @@ typedef struct vlc_ml_entry_point_list_t
     vlc_ml_entry_point_t p_items[];
 } vlc_ml_entry_point_list_t;
 
+typedef struct vlc_ml_bookmark_t
+{
+    int64_t i_media_id; /**< The associated media ID */
+    int64_t i_time; /**< The bookmark time. The unit is arbitrary */
+    char* psz_name; /**< The bookmark name */
+    char* psz_description; /**< The bookmark description */
+} vlc_ml_bookmark_t;
+
+typedef struct vlc_ml_boomkmark_list_t
+{
+    size_t i_nb_items;
+    vlc_ml_bookmark_t p_items[];
+} vlc_ml_bookmark_list_t;
+
 /* Opaque medialibrary pointer, to be used by any non-medialibrary module */
 typedef struct vlc_medialibrary_t vlc_medialibrary_t;
 /* "Private" medialibrary pointer, to be used by the core & medialibrary modules */
@@ -404,6 +418,7 @@ enum vlc_ml_list_queries
     /* Media specific listings */
     VLC_ML_LIST_MEDIA_LABELS,     /**< arg1: media id;  arg2 (out): vlc_ml_label_list_t**    */
     VLC_ML_COUNT_MEDIA_LABELS,    /**< arg1: media id;  arg2 (out): size_t*              */
+    VLC_ML_LIST_MEDIA_BOOKMARKS,  /**< arg1: media id;  arg2 (out): vlc_ml_bookmark_list_t** */
 
     /* Playlist specific listings */
     VLC_ML_LIST_PLAYLIST_MEDIA,   /**< arg1: playlist id; arg2 (out): vlc_ml_media_list_t** */
@@ -465,6 +480,10 @@ enum vlc_ml_control
     VLC_ML_MEDIA_GENERATE_THUMBNAIL,        /**< arg1: media id; arg2: vlc_ml_thumbnail_size_t; arg3: width; arg4: height; arg5: position */
     VLC_ML_MEDIA_ADD_EXTERNAL_MRL,          /**< arg1: media id; arg2: const char*; arg3: type(vlc_ml_file_type_t) */
     VLC_ML_MEDIA_SET_TYPE,                  /**< arg1: media id; arg2: vlc_ml_media_type_t */
+    VLC_ML_MEDIA_ADD_BOOKMARK,              /**< arg1: media id; arg2: int64_t */
+    VLC_ML_MEDIA_REMOVE_BOOKMARK,           /**< arg1: media id; arg2: int64_t */
+    VLC_ML_MEDIA_REMOVE_ALL_BOOKMARKS,      /**< arg1: media id */
+    VLC_ML_MEDIA_UPDATE_BOOKMARK,           /**< arg1: media id; arg2: int64_t; arg3: const char*; arg4: const char* */
 };
 
 /**
@@ -541,6 +560,9 @@ enum vlc_ml_event_type
     VLC_ML_EVENT_GENRE_ADDED,
     VLC_ML_EVENT_GENRE_UPDATED,
     VLC_ML_EVENT_GENRE_DELETED,
+    VLC_ML_EVENT_BOOKMARKS_ADDED,
+    VLC_ML_EVENT_BOOKMARKS_UPDATED,
+    VLC_ML_EVENT_BOOKMARKS_DELETED,
     /**
      * A discovery started.
      * For each VLC_ML_EVENT_DISCOVERY_STARTED event, there will be
@@ -704,6 +726,7 @@ typedef struct vlc_ml_event_t
             const vlc_ml_album_t* p_album;
             const vlc_ml_playlist_t* p_playlist;
             const vlc_ml_genre_t* p_genre;
+            const vlc_ml_bookmark_t* p_bookmark;
         } creation;
         struct
         {
@@ -827,6 +850,8 @@ VLC_API void vlc_ml_genre_list_release( vlc_ml_genre_list_t* p_list );
 VLC_API void vlc_ml_playlist_list_release( vlc_ml_playlist_list_t* p_list );
 VLC_API void vlc_ml_entry_point_list_release( vlc_ml_entry_point_list_t* p_list );
 VLC_API void vlc_ml_playback_states_all_release( vlc_ml_playback_states_all* prefs );
+VLC_API void vlc_ml_bookmark_release( vlc_ml_bookmark_t* p_bookmark );
+VLC_API void vlc_ml_bookmark_list_release( vlc_ml_bookmark_list_t* p_list );
 
 static inline vlc_ml_query_params_t vlc_ml_query_params_create()
 {
@@ -964,6 +989,49 @@ static inline int vlc_ml_media_set_type( vlc_medialibrary_t* p_ml, int64_t i_med
     return vlc_ml_control( p_ml, VLC_ML_MEDIA_SET_TYPE, i_media_id, (int)i_type );
 }
 
+static inline vlc_ml_bookmark_list_t*
+vlc_ml_list_media_bookmarks( vlc_medialibrary_t* p_ml, const vlc_ml_query_params_t* params,
+                             int64_t i_media_id )
+{
+    assert( p_ml != NULL );
+    vlc_ml_bookmark_list_t* res;
+    if ( vlc_ml_list( p_ml, VLC_ML_LIST_MEDIA_BOOKMARKS, params, i_media_id,
+                      &res ) != VLC_SUCCESS )
+        return NULL;
+    return res;
+}
+
+static inline int
+vlc_ml_media_add_bookmark( vlc_medialibrary_t* p_ml, int64_t i_media_id, int64_t i_time )
+{
+    assert( p_ml != NULL );
+    return vlc_ml_control( p_ml, VLC_ML_MEDIA_ADD_BOOKMARK, i_media_id, i_time );
+}
+
+static inline int
+vlc_ml_media_remove_bookmark( vlc_medialibrary_t* p_ml, int64_t i_media_id, int64_t i_time )
+{
+    assert( p_ml != NULL );
+    return vlc_ml_control( p_ml, VLC_ML_MEDIA_REMOVE_BOOKMARK, i_media_id, i_time );
+}
+
+static inline int
+vlc_ml_media_update_bookmark( vlc_medialibrary_t* p_ml, int64_t i_media_id,
+                              int64_t i_time, const char* psz_name,
+                              const char* psz_desc )
+{
+    assert( p_ml != NULL );
+    return vlc_ml_control( p_ml, VLC_ML_MEDIA_UPDATE_BOOKMARK, i_media_id,
+                           i_time, psz_name, psz_desc );
+}
+
+static inline int
+vlc_ml_media_remove_all_bookmarks( vlc_medialibrary_t* p_ml, int64_t i_media_id )
+{
+    assert( p_ml != NULL );
+    return vlc_ml_control( p_ml, VLC_ML_MEDIA_REMOVE_ALL_BOOKMARKS, i_media_id );
+}
+
 static inline vlc_ml_media_t* vlc_ml_get_media( vlc_medialibrary_t* p_ml, int64_t i_media_id )
 {
     return (vlc_ml_media_t*)vlc_ml_get( p_ml, VLC_ML_GET_MEDIA, i_media_id );
@@ -1416,7 +1484,9 @@ static inline size_t vlc_ml_count_playlist_media( vlc_medialibrary_t* p_ml, cons
     vlc_ml_genre_list_t*: vlc_ml_genre_list_release, \
     vlc_ml_playlist_list_t*: vlc_ml_playlist_list_release, \
     vlc_ml_entry_point_list_t*: vlc_ml_entry_point_list_release, \
-    vlc_ml_playback_states_all*: vlc_ml_playback_states_all_release \
+    vlc_ml_playback_states_all*: vlc_ml_playback_states_all_release, \
+    vlc_ml_bookmark_t*: vlc_ml_bookmark_release, \
+    vlc_ml_bookmark_list_t*: vlc_ml_bookmark_list_release \
     )( OBJ )
 #else
 static inline void vlc_ml_release( vlc_ml_show_t* show ) { vlc_ml_show_release( show ); }
@@ -1435,6 +1505,8 @@ static inline void vlc_ml_release( vlc_ml_genre_list_t* list ) { vlc_ml_genre_li
 static inline void vlc_ml_release( vlc_ml_playlist_list_t* list ) { vlc_ml_playlist_list_release( list ); }
 static inline void vlc_ml_release( vlc_ml_entry_point_list_t* list ) { vlc_ml_entry_point_list_release( list ); }
 static inline void vlc_ml_release( vlc_ml_playback_states_all* prefs ) { vlc_ml_playback_states_all_release( prefs ); }
+static inline void vlc_ml_release( vlc_ml_bookmark_t* bookmark ) { vlc_ml_bookmark_release( bookmark ); }
+static inline void vlc_ml_release( vlc_ml_bookmark_list_t* list ) { vlc_ml_bookmark_list_release( list ); }
 #endif
 
 #endif /* VLC_MEDIA_LIBRARY_H */
diff --git a/modules/misc/medialibrary/entities.cpp b/modules/misc/medialibrary/entities.cpp
index d41fb9632c..8c567f954a 100644
--- a/modules/misc/medialibrary/entities.cpp
+++ b/modules/misc/medialibrary/entities.cpp
@@ -40,6 +40,7 @@
 #include <medialibrary/IFolder.h>
 #include <medialibrary/filesystem/IDevice.h>
 #include <medialibrary/filesystem/Errors.h>
+#include <medialibrary/IBookmark.h>
 
 #include <algorithm>
 
@@ -416,6 +417,16 @@ bool Convert( const medialibrary::IFolder* input, vlc_ml_entry_point_t& output )
     return true;
 }
 
+bool Convert( const medialibrary::IBookmark* input, vlc_ml_bookmark_t& output )
+{
+    if ( strdup_helper( input->name(), output.psz_name ) == false ||
+         strdup_helper( input->description(), output.psz_description ) == false )
+        return false;
+    output.i_media_id = input->mediaId();
+    output.i_time = input->time();
+    return true;
+}
+
 input_item_t* MediaToInputItem( const medialibrary::IMedia* media )
 {
     if ( media == nullptr )
diff --git a/modules/misc/medialibrary/medialib.cpp b/modules/misc/medialibrary/medialib.cpp
index 9239a768ef..b73cd46c55 100644
--- a/modules/misc/medialibrary/medialib.cpp
+++ b/modules/misc/medialibrary/medialib.cpp
@@ -39,6 +39,7 @@
 #include <medialibrary/IMetadata.h>
 #include <medialibrary/IShow.h>
 #include <medialibrary/IPlaylist.h>
+#include <medialibrary/IBookmark.h>
 
 #include <sstream>
 #include <initializer_list>
@@ -82,6 +83,7 @@ void assignToEvent( vlc_ml_event_t* ev, vlc_ml_artist_t* a )   { ev->creation.p_
 void assignToEvent( vlc_ml_event_t* ev, vlc_ml_album_t* a )    { ev->creation.p_album    = a; }
 void assignToEvent( vlc_ml_event_t* ev, vlc_ml_genre_t* g )    { ev->creation.p_genre    = g; }
 void assignToEvent( vlc_ml_event_t* ev, vlc_ml_playlist_t* p ) { ev->creation.p_playlist = p; }
+void assignToEvent( vlc_ml_event_t* ev, vlc_ml_bookmark_t* b ) { ev->creation.p_bookmark = b; }
 
 template <typename To, typename From>
 void wrapEntityCreatedEventCallback( vlc_medialibrary_module_t* ml,
@@ -217,19 +219,22 @@ void MediaLibrary::onMediaGroupsDeleted( std::set<int64_t> )
 {
 }
 
-void MediaLibrary::onBookmarksAdded( std::vector<medialibrary::BookmarkPtr> )
+void MediaLibrary::onBookmarksAdded( std::vector<medialibrary::BookmarkPtr> bookmarks )
 {
-
+    wrapEntityCreatedEventCallback<vlc_ml_bookmark_t>( m_vlc_ml, bookmarks,
+                                                       VLC_ML_EVENT_BOOKMARKS_ADDED );
 }
 
-void MediaLibrary::onBookmarksModified( std::set<int64_t> )
+void MediaLibrary::onBookmarksModified( std::set<int64_t> bookmarkIds )
 {
-
+    wrapEntityModifiedEventCallback( m_vlc_ml, bookmarkIds,
+                                     VLC_ML_EVENT_BOOKMARKS_UPDATED );
 }
 
-void MediaLibrary::onBookmarksDeleted( std::set<int64_t> )
+void MediaLibrary::onBookmarksDeleted( std::set<int64_t> bookmarkIds )
 {
-
+    wrapEntityDeletedEventCallback( m_vlc_ml, bookmarkIds,
+                                    VLC_ML_EVENT_BOOKMARKS_DELETED );
 }
 
 void MediaLibrary::onDiscoveryStarted( const std::string& entryPoint )
@@ -594,6 +599,10 @@ int MediaLibrary::Control( int query, va_list args )
         case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
         case VLC_ML_MEDIA_ADD_EXTERNAL_MRL:
         case VLC_ML_MEDIA_SET_TYPE:
+        case VLC_ML_MEDIA_ADD_BOOKMARK:
+        case VLC_ML_MEDIA_REMOVE_BOOKMARK:
+        case VLC_ML_MEDIA_REMOVE_ALL_BOOKMARKS:
+        case VLC_ML_MEDIA_UPDATE_BOOKMARK:
             return controlMedia( query, args );
         default:
             return VLC_EGENERIC;
@@ -795,6 +804,7 @@ int MediaLibrary::List( int listQuery, const vlc_ml_query_params_t* params, va_l
 
         case VLC_ML_LIST_MEDIA_LABELS:
         case VLC_ML_COUNT_MEDIA_LABELS:
+        case VLC_ML_LIST_MEDIA_BOOKMARKS:
             return listMedia( listQuery, paramsPtr, psz_pattern, nbItems, offset, args );
 
         case VLC_ML_LIST_SHOWS:
@@ -1232,6 +1242,43 @@ int MediaLibrary::controlMedia( int query, va_list args )
                 return VLC_EGENERIC;
             return VLC_SUCCESS;
         }
+        case VLC_ML_MEDIA_ADD_BOOKMARK:
+        {
+            auto time = va_arg( args, int64_t );
+            if ( m->addBookmark( time ) == nullptr )
+                return VLC_EGENERIC;
+            return VLC_EGENERIC;
+        }
+        case VLC_ML_MEDIA_REMOVE_BOOKMARK:
+        {
+            auto time = va_arg( args, int64_t );
+            if ( m->removeBookmark( time ) == false )
+                return VLC_EGENERIC;
+            return VLC_SUCCESS;
+        }
+        case VLC_ML_MEDIA_REMOVE_ALL_BOOKMARKS:
+        {
+            if ( m->removeAllBookmarks() == false )
+                return VLC_EGENERIC;
+            return VLC_SUCCESS;
+        }
+        case VLC_ML_MEDIA_UPDATE_BOOKMARK:
+        {
+            auto time = va_arg( args, int64_t );
+            auto name = va_arg( args, const char* );
+            auto desc = va_arg( args, const char* );
+            auto bookmark = m->bookmark( time );
+            if ( bookmark == nullptr )
+                return VLC_EGENERIC;
+            auto res = false;
+            if ( name != nullptr && desc != nullptr )
+                res = bookmark->setNameAndDescription( name, desc );
+            else if ( name != nullptr )
+                res = bookmark->setName( name );
+            else if ( desc != nullptr )
+                res = bookmark->setDescription( desc );
+            return res ? VLC_SUCCESS : VLC_EGENERIC;
+        }
         default:
             vlc_assert_unreachable();
     }
@@ -1584,26 +1631,42 @@ int MediaLibrary::listPlaylist( int listQuery, const medialibrary::QueryParamete
     }
 }
 
-int MediaLibrary::listMedia( int listQuery, const medialibrary::QueryParameters *,
+int MediaLibrary::listMedia( int listQuery, const medialibrary::QueryParameters *params,
                              const char *, uint32_t nbItems, uint32_t offset,
                              va_list args )
 {
     auto media = m_ml->media( va_arg( args, int64_t ) );
     if ( media == nullptr )
         return VLC_EGENERIC;
-    auto query = media->labels();
-    if ( query == nullptr )
-        return VLC_EGENERIC;
     switch ( listQuery )
     {
         case VLC_ML_LIST_MEDIA_LABELS:
-            *va_arg( args, vlc_ml_label_list_t**) =
-                    ml_convert_list<vlc_ml_label_list_t, vlc_ml_label_t>(
-                        query->items( nbItems, offset ) );
-            return VLC_SUCCESS;
         case VLC_ML_COUNT_MEDIA_LABELS:
-            *va_arg( args, size_t* ) = query->count();
+        {
+            auto query = media->labels();
+            if ( query == nullptr )
+                return VLC_EGENERIC;
+            switch ( listQuery )
+            {
+                case VLC_ML_LIST_MEDIA_LABELS:
+                    *va_arg( args, vlc_ml_label_list_t**) =
+                            ml_convert_list<vlc_ml_label_list_t, vlc_ml_label_t>(
+                                query->items( nbItems, offset ) );
+                    return VLC_SUCCESS;
+                case VLC_ML_COUNT_MEDIA_LABELS:
+                    *va_arg( args, size_t* ) = query->count();
+                    return VLC_SUCCESS;
+                default:
+                    vlc_assert_unreachable();
+            }
+        }
+        case VLC_ML_LIST_MEDIA_BOOKMARKS:
+        {
+            *va_arg( args, vlc_ml_bookmark_list_t** ) =
+                    ml_convert_list<vlc_ml_bookmark_list_t, vlc_ml_bookmark_t>(
+                        media->bookmarks( params )->all() );
             return VLC_SUCCESS;
+        }
         default:
             vlc_assert_unreachable();
     }
diff --git a/modules/misc/medialibrary/medialibrary.h b/modules/misc/medialibrary/medialibrary.h
index 80fcc68ac4..5fc0e28d99 100644
--- a/modules/misc/medialibrary/medialibrary.h
+++ b/modules/misc/medialibrary/medialibrary.h
@@ -220,6 +220,7 @@ bool Convert( const medialibrary::IShow* input, vlc_ml_show_t& output );
 bool Convert( const medialibrary::ILabel* input, vlc_ml_label_t& output );
 bool Convert( const medialibrary::IPlaylist* input, vlc_ml_playlist_t& output );
 bool Convert( const medialibrary::IFolder* input, vlc_ml_entry_point_t& output );
+bool Convert( const medialibrary::IBookmark* input, vlc_ml_bookmark_t& output );
 input_item_t* MediaToInputItem( const medialibrary::IMedia* media );
 
 template <typename To, typename ItemType, typename From>
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 88d558f39f..116b5d8d2b 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -575,6 +575,8 @@ vlc_ml_show_list_release
 vlc_ml_genre_list_release
 vlc_ml_playlist_list_release
 vlc_ml_entry_point_list_release
+vlc_ml_bookmark_release
+vlc_ml_bookmark_list_release
 vlc_poll_i11e
 vlc_read_i11e
 vlc_readv_i11e
diff --git a/src/misc/medialibrary.c b/src/misc/medialibrary.c
index 895f010ae9..140f055b5f 100644
--- a/src/misc/medialibrary.c
+++ b/src/misc/medialibrary.c
@@ -348,6 +348,29 @@ void vlc_ml_playback_states_all_release( vlc_ml_playback_states_all* prefs )
     free( prefs->video_filter );
 }
 
+static void vlc_ml_bookmark_release_inner( vlc_ml_bookmark_t* bookmark )
+{
+    free( bookmark->psz_name );
+    free( bookmark->psz_description );
+}
+
+void vlc_ml_bookmark_release( vlc_ml_bookmark_t* bookmark )
+{
+    if ( bookmark == NULL )
+        return;
+    vlc_ml_bookmark_release_inner( bookmark );
+    free( bookmark );
+}
+
+void vlc_ml_bookmark_list_release( vlc_ml_bookmark_list_t* list )
+{
+    if ( list == NULL )
+        return;
+    for ( size_t i = 0; i < list->i_nb_items; ++i )
+        vlc_ml_bookmark_release_inner( &list->p_items[i] );
+    free( list );
+}
+
 void* vlc_ml_get( vlc_medialibrary_t* p_ml, int i_query, ... )
 {
     assert( p_ml != NULL );
-- 
2.20.1



More information about the vlc-devel mailing list