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 *****************************************************************************/
25 #include <vlc_common.h>
26 #include <vlc_media_library.h>
27 #include <vlc_modules.h>
29 #include <vlc_threads.h>
34 struct vlc_ml_event_callback_t
36 vlc_ml_callback_t pf_cb
;
41 struct vlc_medialibrary_t
43 vlc_medialibrary_module_t m
;
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 static void vlc_ml_event_send( vlc_medialibrary_module_t
* p_ml
, const vlc_ml_event_t
* p_event
)
56 vlc_medialibrary_t
* p_priv
= ml_priv( p_ml
);
57 vlc_mutex_lock( &p_priv
->lock
);
58 struct vlc_ml_event_callback_t
* p_cb
;
59 vlc_list_foreach( p_cb
, &p_priv
->cbs
, node
)
61 p_cb
->pf_cb( p_cb
->p_data
, p_event
);
63 vlc_mutex_unlock( &p_priv
->lock
);
66 vlc_ml_event_callback_t
*
67 vlc_ml_event_register_callback( vlc_medialibrary_t
* p_ml
, vlc_ml_callback_t cb
,
70 struct vlc_ml_event_callback_t
* p_cb
= malloc( sizeof( *p_cb
) );
71 if ( unlikely( p_cb
== NULL
) )
74 p_cb
->p_data
= p_data
;
75 vlc_mutex_lock( &p_ml
->lock
);
76 vlc_list_append( &p_cb
->node
, &p_ml
->cbs
);
77 vlc_mutex_unlock( &p_ml
->lock
);
81 void vlc_ml_event_unregister_callback( vlc_medialibrary_t
* p_ml
,
82 vlc_ml_event_callback_t
* p_cb
)
84 vlc_mutex_lock( &p_ml
->lock
);
85 vlc_list_remove( &p_cb
->node
);
86 vlc_mutex_unlock( &p_ml
->lock
);
90 void vlc_ml_event_unregister_from_callback( vlc_medialibrary_t
* p_ml
,
91 vlc_ml_event_callback_t
* p_cb
)
93 vlc_mutex_assert( &p_ml
->lock
);
94 vlc_list_remove( &p_cb
->node
);
98 static const vlc_medialibrary_callbacks_t callbacks
= {
99 .pf_send_event
= &vlc_ml_event_send
102 vlc_medialibrary_t
* libvlc_MlCreate( libvlc_int_t
* p_libvlc
)
104 vlc_medialibrary_t
*p_ml
= vlc_custom_create( VLC_OBJECT( p_libvlc
),
105 sizeof( *p_ml
), "medialibrary" );
106 if ( unlikely( p_ml
== NULL
) )
108 vlc_mutex_init( &p_ml
->lock
);
109 vlc_list_init( &p_ml
->cbs
);
110 p_ml
->m
.cbs
= &callbacks
;
111 p_ml
->m
.p_module
= module_need( &p_ml
->m
, "medialibrary", NULL
, false );
112 if ( p_ml
->m
.p_module
== NULL
)
114 vlc_object_delete(&p_ml
->m
);
120 void libvlc_MlRelease( vlc_medialibrary_t
* p_ml
)
122 assert( p_ml
!= NULL
);
123 module_unneed( &p_ml
->m
, p_ml
->m
.p_module
);
124 assert( vlc_list_is_empty( &p_ml
->cbs
) );
125 vlc_object_delete(&p_ml
->m
);
128 #undef vlc_ml_instance_get
129 vlc_medialibrary_t
* vlc_ml_instance_get( vlc_object_t
* p_obj
)
131 libvlc_priv_t
* p_priv
= libvlc_priv( vlc_object_instance(p_obj
) );
132 return p_priv
->p_media_library
;
135 static void vlc_ml_thumbnails_release( vlc_ml_thumbnail_t
*p_thumbnails
)
137 for ( int i
= 0; i
< VLC_ML_THUMBNAIL_SIZE_COUNT
; ++i
)
138 free( p_thumbnails
[i
].psz_mrl
);
141 static void vlc_ml_show_release_inner( vlc_ml_show_t
* p_show
)
143 free( p_show
->psz_artwork_mrl
);
144 free( p_show
->psz_name
);
145 free( p_show
->psz_summary
);
146 free( p_show
->psz_tvdb_id
);
149 void vlc_ml_show_release( vlc_ml_show_t
* p_show
)
151 if ( p_show
== NULL
)
153 vlc_ml_show_release_inner( p_show
);
157 static void vlc_ml_media_release_tracks_inner( vlc_ml_media_track_list_t
* p_tracks
)
159 if ( p_tracks
== NULL
)
161 for ( size_t i
= 0; i
< p_tracks
->i_nb_items
; ++i
)
163 vlc_ml_media_track_t
* p_track
= &p_tracks
->p_items
[i
];
164 free( p_track
->psz_codec
);
165 free( p_track
->psz_language
);
166 free( p_track
->psz_description
);
171 static void vlc_ml_media_release_inner( vlc_ml_media_t
* p_media
)
173 vlc_ml_file_list_release( p_media
->p_files
);
174 vlc_ml_media_release_tracks_inner( p_media
->p_tracks
);
175 free( p_media
->psz_title
);
176 vlc_ml_thumbnails_release( p_media
->thumbnails
);
177 switch( p_media
->i_subtype
)
179 case VLC_ML_MEDIA_SUBTYPE_ALBUMTRACK
:
181 case VLC_ML_MEDIA_SUBTYPE_SHOW_EPISODE
:
182 free( p_media
->show_episode
.psz_summary
);
183 free( p_media
->show_episode
.psz_tvdb_id
);
185 case VLC_ML_MEDIA_SUBTYPE_MOVIE
:
186 free( p_media
->movie
.psz_summary
);
187 free( p_media
->movie
.psz_imdb_id
);
194 static void vlc_ml_artist_release_inner( vlc_ml_artist_t
* p_artist
)
196 vlc_ml_thumbnails_release( p_artist
->thumbnails
);
197 free( p_artist
->psz_name
);
198 free( p_artist
->psz_shortbio
);
199 free( p_artist
->psz_mb_id
);
202 void vlc_ml_artist_release( vlc_ml_artist_t
* p_artist
)
204 if ( p_artist
== NULL
)
206 vlc_ml_artist_release_inner( p_artist
);
210 static void vlc_ml_album_release_inner( vlc_ml_album_t
* p_album
)
212 vlc_ml_thumbnails_release( p_album
->thumbnails
);
213 free( p_album
->psz_artist
);
214 free( p_album
->psz_summary
);
215 free( p_album
->psz_title
);
218 void vlc_ml_album_release( vlc_ml_album_t
* p_album
)
220 if ( p_album
== NULL
)
222 vlc_ml_album_release_inner( p_album
);
226 void vlc_ml_genre_release( vlc_ml_genre_t
* p_genre
)
228 if ( p_genre
== NULL
)
230 free( p_genre
->psz_name
);
234 static void vlc_ml_playlist_release_inner( vlc_ml_playlist_t
* p_playlist
)
236 free( p_playlist
->psz_name
);
237 free( p_playlist
->psz_mrl
);
238 free( p_playlist
->psz_artwork_mrl
);
241 void vlc_ml_playlist_release( vlc_ml_playlist_t
* p_playlist
)
243 if ( p_playlist
== NULL
)
245 vlc_ml_playlist_release_inner( p_playlist
);
251 void vlc_ml_media_release( vlc_ml_media_t
* p_media
)
253 if ( p_media
== NULL
)
255 vlc_ml_media_release_inner( p_media
);
259 void vlc_ml_label_list_release( vlc_ml_label_list_t
* p_list
)
261 if ( p_list
== NULL
)
263 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
264 free( p_list
->p_items
[i
].psz_name
);
268 void vlc_ml_file_list_release( vlc_ml_file_list_t
* p_list
)
270 if ( p_list
== NULL
)
272 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
273 free( p_list
->p_items
[i
].psz_mrl
);
277 void vlc_ml_artist_list_release( vlc_ml_artist_list_t
* p_list
)
279 if ( p_list
== NULL
)
281 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
282 vlc_ml_artist_release_inner( &p_list
->p_items
[i
] );
287 void vlc_ml_media_list_release( vlc_ml_media_list_t
* p_list
)
289 if ( p_list
== NULL
)
291 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
292 vlc_ml_media_release_inner( &p_list
->p_items
[i
] );
296 void vlc_ml_album_list_release( vlc_ml_album_list_t
* p_list
)
298 if ( p_list
== NULL
)
300 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
301 vlc_ml_album_release_inner( &p_list
->p_items
[i
] );
305 void vlc_ml_show_list_release( vlc_ml_show_list_t
* p_list
)
307 if ( p_list
== NULL
)
309 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
310 vlc_ml_show_release_inner( &p_list
->p_items
[i
] );
314 void vlc_ml_genre_list_release( vlc_ml_genre_list_t
* p_list
)
316 if ( p_list
== NULL
)
318 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
319 free( p_list
->p_items
[i
].psz_name
);
323 void vlc_ml_playlist_list_release( vlc_ml_playlist_list_t
* p_list
)
325 if ( p_list
== NULL
)
327 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
328 vlc_ml_playlist_release_inner( &p_list
->p_items
[i
] );
332 void vlc_ml_entry_point_list_release( vlc_ml_entry_point_list_t
* p_list
)
334 if ( p_list
== NULL
)
336 for ( size_t i
= 0; i
< p_list
->i_nb_items
; ++i
)
337 free( p_list
->p_items
[i
].psz_mrl
);
341 void vlc_ml_playback_states_all_release( vlc_ml_playback_states_all
* prefs
)
343 free( prefs
->current_video_track
);
344 free( prefs
->current_audio_track
);
345 free( prefs
->current_subtitle_track
);
346 free( prefs
->aspect_ratio
);
348 free( prefs
->deinterlace
);
349 free( prefs
->video_filter
);
352 static void vlc_ml_bookmark_release_inner( vlc_ml_bookmark_t
* bookmark
)
354 free( bookmark
->psz_name
);
355 free( bookmark
->psz_description
);
358 void vlc_ml_bookmark_release( vlc_ml_bookmark_t
* bookmark
)
360 if ( bookmark
== NULL
)
362 vlc_ml_bookmark_release_inner( bookmark
);
366 void vlc_ml_bookmark_list_release( vlc_ml_bookmark_list_t
* list
)
370 for ( size_t i
= 0; i
< list
->i_nb_items
; ++i
)
371 vlc_ml_bookmark_release_inner( &list
->p_items
[i
] );
375 void* vlc_ml_get( vlc_medialibrary_t
* p_ml
, int i_query
, ... )
377 assert( p_ml
!= NULL
);
379 va_start( args
, i_query
);
380 void* res
= p_ml
->m
.pf_get( &p_ml
->m
, i_query
, args
);
385 int vlc_ml_control( vlc_medialibrary_t
* p_ml
, int i_query
, ... )
388 va_start( args
, i_query
);
389 int i_res
= p_ml
->m
.pf_control( &p_ml
->m
, i_query
, args
);
394 int vlc_ml_list( vlc_medialibrary_t
* p_ml
, int i_query
,
395 const vlc_ml_query_params_t
* p_params
, ... )
398 va_start( args
, p_params
);
399 int i_res
= p_ml
->m
.pf_list( &p_ml
->m
, i_query
, p_params
, args
);