[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