[vlc-devel] [PATCH 3/5] core: medialibrary: Add an event API
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Thu Aug 16 17:59:32 CEST 2018
On Thu, Aug 16, 2018, at 5:55 PM, Hugo Beauzée-Luyssen wrote:
> ---
> include/vlc_media_library.h | 149 ++++++++++++++++++++++++++++++++++++
> src/libvlccore.sym | 2 +
> src/misc/medialibrary.c | 61 +++++++++++++++
> 3 files changed, 212 insertions(+)
>
> diff --git a/include/vlc_media_library.h b/include/vlc_media_library.h
> index e1e08203f0..5928602144 100644
> --- a/include/vlc_media_library.h
> +++ b/include/vlc_media_library.h
> @@ -460,6 +460,139 @@ enum vlc_ml_playback_pref
> VLC_ML_PLAYBACK_PREF_APP_SPECIFIC,
> };
>
> +enum vlc_ml_event_type
> +{
> + /**
> + * Entity modification callbacks. The affected entity ID will be
> passed in
> + * vlc_ml_event_t::i_entity_id
> + * When _DELETED callbacks get invoked, the entity will already
> have been
> + * deleted from the database, and cannot be retrieved anymore
> + */
> + VLC_ML_EVENT_MEDIA_ADDED,
> + VLC_ML_EVENT_MEDIA_UPDATED,
> + VLC_ML_EVENT_MEDIA_DELETED,
> + VLC_ML_EVENT_ARTIST_ADDED,
> + VLC_ML_EVENT_ARTIST_UPDATED,
> + VLC_ML_EVENT_ARTIST_DELETED,
> + VLC_ML_EVENT_ALBUM_ADDED,
> + VLC_ML_EVENT_ALBUM_UPDATED,
> + VLC_ML_EVENT_ALBUM_DELETED,
> + VLC_ML_EVENT_PLAYLIST_ADDED,
> + VLC_ML_EVENT_PLAYLIST_UPDATED,
> + VLC_ML_EVENT_PLAYLIST_DELETED,
> + VLC_ML_EVENT_GENRE_ADDED,
> + VLC_ML_EVENT_GENRE_UPDATED,
> + VLC_ML_EVENT_GENRE_DELETED,
> + /**
> + * A discovery started.
> + * For each VLC_ML_EVENT_DISCOVERY_STARTED event, there will be
> + * 1 VLC_ML_EVENT_DISCOVERY_COMPLETED event, and N
> + * VLC_ML_EVENT_DISCOVERY_COMPLETED events.
> + * The entry point being discovered is stored in
> + * vlc_ml_event_t::psz_entry_point.
> + */
> + VLC_ML_EVENT_DISCOVERY_STARTED,
> + /**
> + * Sent when a discovery or reload operation starts analyzing a new
> folder.
> + * The discovered entry point is stored in
> vlc_ml_event_t::psz_entry_point.
> + */
> + VLC_ML_EVENT_DISCOVERY_PROGRESS,
> + /**
> + * Sent when an entry point discovery is completed.
> + * The entry point that was being discovered is stored in
> + * vlc_ml_event_t::psz_entry_point.
> + */
> + VLC_ML_EVENT_DISCOVERY_COMPLETED,
> + /**
> + * An entry point reload operation started.
> + * For all the entry points being reloaded, N
> VLC_EVENT_DISCOVERY_PROGRESS
> + * and 1 VLC_EVENT_RELOAD_COMPLETED event will be sent.
> + * The entry point being reloaded is stored in
> + * vlc_ml_event_t::psz_entry_point.
> + */
> + VLC_ML_EVENT_RELOAD_STARTED,
> + /**
> + * Sent when an entry point reload is completed.
> + * The entry point that was being reloaded is stored in
> + * vlc_ml_event_t::psz_entry_point.
> + * The success state is stored in vlc_ml_event::b_success.
> + */
> + VLC_ML_EVENT_RELOAD_COMPLETED,
> + /**
> + * Sent when an entry point removal request has been processed.
> + * The removed entry point is stored in
> vlc_ml_event_t::psz_entry_point and
> + * the operation success is stored in vlc_ml_event_t::b_success
> + */
> + VLC_ML_EVENT_ENTRY_POINT_REMOVED,
> + /**
> + * Sent when an entry point ban request has been processed.
> + * The banned entry point is stored in
> vlc_ml_event_t::psz_entry_point and
> + * the operation success is stored in vlc_ml_event_t::b_success
> + */
> + VLC_ML_EVENT_ENTRY_POINT_BANNED,
> + /**
> + * Sent when an entry point unban request has been processed.
> + * The unbanned entry point is stored in
> vlc_ml_event_t::psz_entry_point and
> + * the operation success is stored in vlc_ml_event_t::b_success
> + */
> + VLC_ML_EVENT_ENTRY_POINT_UNBANNED,
> + /**
> + * Sent when a discoverer or parser threads changes its idle state.
> + * The idle state is stored in vlc_ml_event_t::b_idle.
> + * False means at least one background thread is in running, true
> means
> + * both discoverer & parser threads are paused.
> + */
> + VLC_ML_EVENT_BACKGROUND_IDLE_CHANGED,
> + /**
> + * Sent when the parsing progress percentage gets updated.
> + * The percentage is stored as a [0;100] integer, in
> + * vlc_ml_event_t::i_progress
> + * This value might decrease as more media get discovered, but it
> will only
> + * increase once all discovery operations are completed.
> + */
> + VLC_ML_EVENT_PARSING_PROGRESS_UPDATED,
> +};
> +
> +typedef struct vlc_ml_event_t
> +{
> + int i_type;
> + union
> + {
> + struct
> + {
> + const char* psz_entry_point;
> + bool b_success;
> + } discovery;
> + struct
> + {
> + uint8_t i_progress;
> + } parser;
> + union
> + {
> + const vlc_ml_media_t* p_media;
> + const vlc_ml_artist_t* p_artist;
> + const vlc_ml_album_t* p_album;
> + const vlc_ml_playlist_t* p_playlist;
> + const vlc_ml_genre_t* p_genre;
> + } modification;
> + struct
> + {
> + int64_t i_entity_id;
> + } deletion;
> + struct
> + {
> + bool b_idle;
> + } background_tasks;
> + };
> +} vlc_ml_event_t;
> +
> +typedef void (*vlc_ml_callback_t)( void* p_data, const vlc_ml_event_t*
> p_event );
> +
> +typedef struct vlc_medialibrary_callbacks_t
> +{
> + void (*pf_send_event)( vlc_medialibrary_module_t* p_ml, const
> vlc_ml_event_t* p_event );
> +} vlc_medialibrary_callbacks_t;
> +
> struct vlc_medialibrary_module_t
> {
> struct vlc_common_members obj;
> @@ -493,6 +626,8 @@ struct vlc_medialibrary_module_t
> * Refer to the list of queries for the specific return type
> */
> void* (*pf_get)( struct vlc_medialibrary_module_t* p_ml, int
> i_query, int64_t i_id );
> +
> + const vlc_medialibrary_callbacks_t* cbs;
> };
>
> vlc_medialibrary_t* libvlc_MlCreate( libvlc_int_t* p_libvlc );
> @@ -505,6 +640,20 @@ VLC_API void* vlc_ml_get( vlc_medialibrary_t* p_ml,
> int i_query, int64_t i_id )
> VLC_API int vlc_ml_control( vlc_medialibrary_t* p_ml, int
> i_query, ... ) VLC_USED;
> VLC_API int vlc_ml_list( vlc_medialibrary_t* p_ml, int i_query,
> const vlc_ml_query_params_t*
> p_params, ... );
> +
> +/**
> + * \brief Registers a medialibrary callback.
> + * \returns A handle to the callback, to be passed to
> vlc_ml_unregister_callback
> + */
> +VLC_API void* vlc_ml_event_register_callback( vlc_medialibrary_t* p_ml,
> vlc_ml_callback_t cb, void* p_data );
> +
> +/**
> + * \brief Unregisters a medialibrary callback
> + * \param p_handle The handled returned by vlc_ml_register_callback
> + */
> +VLC_API void vlc_ml_event_unregister_callback( vlc_medialibrary_t*
> p_ml, void* p_handle );
> +
> +
> VLC_API void vlc_ml_entrypoints_release( vlc_ml_entrypoint_t* p_list,
> size_t i_nb_items );
>
> VLC_API void vlc_ml_show_release( vlc_ml_show_t* p_show );
> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index 63293849d6..19fb6d492e 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -596,6 +596,8 @@ vlc_ml_instance_get
> vlc_ml_get
> vlc_ml_control
> vlc_ml_list
> +vlc_ml_event_register_callback
> +vlc_ml_event_unregister_callback
> vlc_ml_entrypoints_release
> vlc_ml_show_release
> vlc_ml_artist_release
> diff --git a/src/misc/medialibrary.c b/src/misc/medialibrary.c
> index 78ba661034..f9d842218c 100644
> --- a/src/misc/medialibrary.c
> +++ b/src/misc/medialibrary.c
> @@ -25,15 +25,32 @@
> #include <vlc_common.h>
> #include <vlc_media_library.h>
> #include <vlc_modules.h>
> +#include <vlc_list.h>
> +#include <vlc_threads.h>
> #include <libvlc.h>
>
> #include <assert.h>
>
> +struct ml_callback_t
> +{
> + vlc_ml_callback_t pf_cb;
> + void* p_data;
> + struct vlc_list node;
> +};
> +
> struct vlc_medialibrary_t
> {
> vlc_medialibrary_module_t m;
> +
> + vlc_mutex_t lock;
> + struct vlc_list cbs;
> };
>
> +static vlc_medialibrary_t* ml_priv( vlc_medialibrary_module_t* p_ml )
> +{
> + return container_of( p_ml, struct vlc_medialibrary_t, m );
> +}
> +
> void vlc_ml_entrypoints_release( vlc_ml_entrypoint_t* p_list, size_t
> i_nb_items )
> {
> for ( size_t i = 0; i < i_nb_items; ++i )
> @@ -43,16 +60,58 @@ void
> vlc_ml_entrypoints_release( vlc_ml_entrypoint_t* p_list, size_t
> i_nb_items
> free( p_list );
> }
>
> +static void vlc_ml_event_send( vlc_medialibrary_module_t* p_ml, const
> vlc_ml_event_t* p_event )
> +{
> + vlc_medialibrary_t* p_priv = ml_priv( p_ml );
> + vlc_mutex_lock( &p_priv->lock );
> + struct ml_callback_t* p_cb;
> + vlc_list_foreach( p_cb, &p_priv->cbs, node )
> + {
> + p_cb->pf_cb( p_cb->p_data, p_event );
> + }
> + vlc_mutex_unlock( &p_priv->lock );
> +}
> +
> +void* vlc_ml_event_register_callback( vlc_medialibrary_t* p_ml,
> vlc_ml_callback_t cb, void* p_data )
> +{
> + struct ml_callback_t* p_cb = malloc( sizeof( *p_cb ) );
> + if ( unlikely( p_cb == NULL ) )
> + return NULL;
> + p_cb->pf_cb = cb;
> + p_cb->p_data = p_data;
> + vlc_mutex_lock( &p_ml->lock );
> + vlc_list_append( &p_cb->node, &p_ml->cbs );
> + vlc_mutex_unlock( &p_ml->lock );
> + return &p_cb->node;
> +}
> +
> +void vlc_ml_event_unregister_callback( vlc_medialibrary_t* p_ml, void*
> p_handle )
> +{
> + struct ml_callback_t* p_cb = container_of( p_handle, struct
> ml_callback_t, node );
> + vlc_mutex_lock( &p_ml->lock );
> + vlc_list_remove( (struct vlc_list*)p_handle );
> + vlc_mutex_unlock( &p_ml->lock );
> + free( p_cb );
> +}
> +
> +static vlc_medialibrary_callbacks_t callbacks = {
> + .pf_send_event = &vlc_ml_event_send
> +};
> +
> vlc_medialibrary_t* libvlc_MlCreate( libvlc_int_t* p_libvlc )
> {
> vlc_medialibrary_t *p_ml =
> vlc_custom_create( VLC_OBJECT( p_libvlc ),
> sizeof( *p_ml ),
> "medialibrary" );
> if ( unlikely( p_ml == NULL ) )
> return NULL;
> + vlc_mutex_init( &p_ml->lock );
> + vlc_list_init( &p_ml->cbs );
> + p_ml->m.cbs = &callbacks;
> p_ml->m.p_module = module_need( &p_ml->m, "medialibrary", NULL,
> false );
> if ( p_ml->m.p_module == NULL )
> {
> vlc_object_release( &p_ml->m );
> + vlc_mutex_destroy( &p_ml->lock );
> return NULL;
> }
> return p_ml;
> @@ -62,6 +121,8 @@ void libvlc_MlRelease( vlc_medialibrary_t* p_ml )
> {
> assert( p_ml != NULL );
> module_unneed( &p_ml->m, p_ml->m.p_module );
> + assert( vlc_list_is_empty( &p_ml->cbs ) );
> + vlc_mutex_destroy( &p_ml->lock );
> vlc_object_release( &p_ml->m );
> }
>
Seems like I forgot to update the documentation after reworking the vlc_ml_event_t structure, will fix locally
--
Hugo Beauzée-Luyssen
hugo at beauzee.fr
More information about the vlc-devel
mailing list