core: medialibrary: Add an event API
[vlc.git] / src / misc / medialibrary.c
blob4fb9d786db7068b588f731d25b9ff2cb13fde2c4
1 /*****************************************************************************
2 * medialib.cpp: medialibrary module
3 *****************************************************************************
4 * Copyright © 2015-2016 VLC authors, VideoLAN and VideoLabs
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <vlc_common.h>
26 #include <vlc_media_library.h>
27 #include <vlc_modules.h>
28 #include <vlc_list.h>
29 #include <vlc_threads.h>
30 #include <libvlc.h>
32 #include <assert.h>
34 struct vlc_ml_event_callback_t
36 vlc_ml_callback_t pf_cb;
37 void* p_data;
38 struct vlc_list node;
41 struct vlc_medialibrary_t
43 vlc_medialibrary_module_t m;
45 vlc_mutex_t lock;
46 struct vlc_list cbs;
49 static vlc_medialibrary_t* ml_priv( vlc_medialibrary_module_t* p_ml )
51 return container_of( p_ml, struct vlc_medialibrary_t, m );
54 void vlc_ml_entrypoints_release( vlc_ml_entrypoint_t* p_list, size_t i_nb_items )
56 for ( size_t i = 0; i < i_nb_items; ++i )
58 free( p_list[i].psz_mrl );
60 free( p_list );
63 static void vlc_ml_event_send( vlc_medialibrary_module_t* p_ml, const vlc_ml_event_t* p_event )
65 vlc_medialibrary_t* p_priv = ml_priv( p_ml );
66 vlc_mutex_lock( &p_priv->lock );
67 struct vlc_ml_event_callback_t* p_cb;
68 vlc_list_foreach( p_cb, &p_priv->cbs, node )
70 p_cb->pf_cb( p_cb->p_data, p_event );
72 vlc_mutex_unlock( &p_priv->lock );
75 vlc_ml_event_callback_t*
76 vlc_ml_event_register_callback( vlc_medialibrary_t* p_ml, vlc_ml_callback_t cb,
77 void* p_data )
79 struct vlc_ml_event_callback_t* p_cb = malloc( sizeof( *p_cb ) );
80 if ( unlikely( p_cb == NULL ) )
81 return NULL;
82 p_cb->pf_cb = cb;
83 p_cb->p_data = p_data;
84 vlc_mutex_lock( &p_ml->lock );
85 vlc_list_append( &p_cb->node, &p_ml->cbs );
86 vlc_mutex_unlock( &p_ml->lock );
87 return p_cb;
90 void vlc_ml_event_unregister_callback( vlc_medialibrary_t* p_ml,
91 vlc_ml_event_callback_t* p_cb )
93 vlc_mutex_lock( &p_ml->lock );
94 vlc_list_remove( &p_cb->node );
95 vlc_mutex_unlock( &p_ml->lock );
96 free( p_cb );
99 static const vlc_medialibrary_callbacks_t callbacks = {
100 .pf_send_event = &vlc_ml_event_send
103 vlc_medialibrary_t* libvlc_MlCreate( libvlc_int_t* p_libvlc )
105 vlc_medialibrary_t *p_ml = vlc_custom_create( VLC_OBJECT( p_libvlc ),
106 sizeof( *p_ml ), "medialibrary" );
107 if ( unlikely( p_ml == NULL ) )
108 return NULL;
109 vlc_mutex_init( &p_ml->lock );
110 vlc_list_init( &p_ml->cbs );
111 p_ml->m.cbs = &callbacks;
112 p_ml->m.p_module = module_need( &p_ml->m, "medialibrary", NULL, false );
113 if ( p_ml->m.p_module == NULL )
115 vlc_object_release( &p_ml->m );
116 vlc_mutex_destroy( &p_ml->lock );
117 return NULL;
119 return p_ml;
122 void libvlc_MlRelease( vlc_medialibrary_t* p_ml )
124 assert( p_ml != NULL );
125 module_unneed( &p_ml->m, p_ml->m.p_module );
126 assert( vlc_list_is_empty( &p_ml->cbs ) );
127 vlc_mutex_destroy( &p_ml->lock );
128 vlc_object_release( &p_ml->m );
131 #undef vlc_ml_instance_get
132 vlc_medialibrary_t* vlc_ml_instance_get( vlc_object_t* p_obj )
134 libvlc_priv_t* p_priv = libvlc_priv( p_obj->obj.libvlc );
135 return p_priv->p_media_library;
138 static void vlc_ml_show_release_inner( vlc_ml_show_t* p_show )
140 free( p_show->psz_artwork_mrl );
141 free( p_show->psz_name );
142 free( p_show->psz_summary );
143 free( p_show->psz_tvdb_id );
146 void vlc_ml_show_release( vlc_ml_show_t* p_show )
148 if ( p_show == NULL )
149 return;
150 vlc_ml_show_release_inner( p_show );
151 free( p_show );
154 static void vlc_ml_media_release_tracks_inner( vlc_ml_media_track_list_t* p_tracks )
156 if ( p_tracks == NULL )
157 return;
158 for ( size_t i = 0; i < p_tracks->i_nb_items; ++i )
160 vlc_ml_media_track_t* p_track = &p_tracks->p_items[i];
161 free( p_track->psz_codec );
162 free( p_track->psz_language );
163 free( p_track->psz_description );
165 free( p_tracks );
168 static void vlc_ml_media_release_inner( vlc_ml_media_t* p_media )
170 vlc_ml_file_list_release( p_media->p_files );
171 vlc_ml_media_release_tracks_inner( p_media->p_tracks );
172 free( p_media->psz_title );
173 free( p_media->psz_artwork_mrl );
174 switch( p_media->i_subtype )
176 case VLC_ML_MEDIA_SUBTYPE_ALBUMTRACK:
177 break;
178 case VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE:
179 free( p_media->show_episode.psz_summary );
180 free( p_media->show_episode.psz_tvdb_id );
181 break;
182 case VLC_ML_MEDIA_SUBTYPE_MOVIE:
183 free( p_media->movie.psz_summary );
184 free( p_media->movie.psz_imdb_id );
185 break;
186 default:
187 break;
191 static void vlc_ml_artist_release_inner( vlc_ml_artist_t* p_artist )
193 free( p_artist->psz_artwork_mrl );
194 free( p_artist->psz_name );
195 free( p_artist->psz_shortbio );
196 free( p_artist->psz_mb_id );
199 void vlc_ml_artist_release( vlc_ml_artist_t* p_artist )
201 if ( p_artist == NULL )
202 return;
203 vlc_ml_artist_release_inner( p_artist );
204 free( p_artist );
207 static void vlc_ml_album_release_inner( vlc_ml_album_t* p_album )
209 free( p_album->psz_artist );
210 free( p_album->psz_artwork_mrl );
211 free( p_album->psz_summary );
212 free( p_album->psz_title );
215 void vlc_ml_album_release( vlc_ml_album_t* p_album )
217 if ( p_album == NULL )
218 return;
219 vlc_ml_album_release_inner( p_album );
220 free( p_album );
223 void vlc_ml_genre_release( vlc_ml_genre_t* p_genre )
225 if ( p_genre == NULL )
226 return;
227 free( p_genre->psz_name );
228 free( p_genre );
231 static void vlc_ml_playlist_release_inner( vlc_ml_playlist_t* p_playlist )
233 free( p_playlist->psz_artwork_mrl );
234 free( p_playlist->psz_name );
237 void vlc_ml_playlist_release( vlc_ml_playlist_t* p_playlist )
239 if ( p_playlist == NULL )
240 return;
241 vlc_ml_playlist_release_inner( p_playlist );
242 free( p_playlist );
245 /* Lists release */
247 void vlc_ml_media_release( vlc_ml_media_t* p_media )
249 if ( p_media == NULL )
250 return;
251 vlc_ml_media_release_inner( p_media );
252 free( p_media );
255 void vlc_ml_label_list_release( vlc_ml_label_list_t* p_list )
257 if ( p_list == NULL )
258 return;
259 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
260 free( p_list->p_items[i].psz_name );
261 free( p_list );
264 void vlc_ml_file_list_release( vlc_ml_file_list_t* p_list )
266 if ( p_list == NULL )
267 return;
268 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
269 free( p_list->p_items[i].psz_mrl );
270 free( p_list );
273 void vlc_ml_artist_list_release( vlc_ml_artist_list_t* p_list )
275 if ( p_list == NULL )
276 return;
277 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
278 vlc_ml_artist_release_inner( &p_list->p_items[i] );
279 free( p_list );
283 void vlc_ml_media_list_release( vlc_ml_media_list_t* p_list )
285 if ( p_list == NULL )
286 return;
287 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
288 vlc_ml_media_release_inner( &p_list->p_items[i] );
289 free( p_list );
292 void vlc_ml_album_list_release( vlc_ml_album_list_t* p_list )
294 if ( p_list == NULL )
295 return;
296 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
297 vlc_ml_album_release_inner( &p_list->p_items[i] );
298 free( p_list );
301 void vlc_ml_show_list_release( vlc_ml_show_list_t* p_list )
303 if ( p_list == NULL )
304 return;
305 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
306 vlc_ml_show_release_inner( &p_list->p_items[i] );
307 free( p_list );
310 void vlc_ml_genre_list_release( vlc_ml_genre_list_t* p_list )
312 if ( p_list == NULL )
313 return;
314 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
315 free( p_list->p_items[i].psz_name );
316 free( p_list );
319 void vlc_ml_playlist_list_release( vlc_ml_playlist_list_t* p_list )
321 if ( p_list == NULL )
322 return;
323 for ( size_t i = 0; i < p_list->i_nb_items; ++i )
324 vlc_ml_playlist_release_inner( &p_list->p_items[i] );
325 free( p_list );
328 void* vlc_ml_get( vlc_medialibrary_t* p_ml, int i_query, int64_t i_id )
330 assert( p_ml != NULL );
331 return p_ml->m.pf_get( &p_ml->m, i_query, i_id );
334 int vlc_ml_control( vlc_medialibrary_t* p_ml, int i_query, ... )
336 va_list args;
337 va_start( args, i_query );
338 int i_res = p_ml->m.pf_control( &p_ml->m, i_query, args );
339 va_end( args );
340 return i_res;
343 int vlc_ml_list( vlc_medialibrary_t* p_ml, int i_query,
344 const vlc_ml_query_params_t* p_params, ... )
346 va_list args;
347 va_start( args, p_params );
348 int i_res = p_ml->m.pf_list( &p_ml->m, i_query, p_params, args );
349 va_end( args );
350 return i_res;