1 /*****************************************************************************
2 * media_list.c: libvlc new API media list functions
3 *****************************************************************************
4 * Copyright (C) 2007 VLC authors and VideoLAN
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
30 #include <vlc/libvlc.h>
31 #include <vlc/libvlc_media.h>
32 #include <vlc/libvlc_media_list.h>
33 #include <vlc/libvlc_events.h>
35 #include <vlc_common.h>
36 #include <vlc_input.h>
38 #include "libvlc_internal.h"
39 #include "media_internal.h" // libvlc_media_new_from_input_item()
40 #include "media_list_internal.h"
42 typedef enum EventPlaceInTime {
53 /**************************************************************************
54 * notify_item_addition (private)
56 * Do the appropriate action when an item is deleted.
57 **************************************************************************/
59 notify_item_addition( libvlc_media_list_t * p_mlist,
60 libvlc_media_t * p_md,
62 EventPlaceInTime event_status )
66 /* Construct the event */
67 if( event_status == EventDidHappen )
69 event.type = libvlc_MediaListItemAdded;
70 event.u.media_list_item_added.item = p_md;
71 event.u.media_list_item_added.index = index;
73 else /* if( event_status == EventWillHappen ) */
75 event.type = libvlc_MediaListWillAddItem;
76 event.u.media_list_will_add_item.item = p_md;
77 event.u.media_list_will_add_item.index = index;
81 libvlc_event_send( p_mlist->p_event_manager, &event );
84 /**************************************************************************
85 * notify_item_deletion (private)
87 * Do the appropriate action when an item is added.
88 **************************************************************************/
90 notify_item_deletion( libvlc_media_list_t * p_mlist,
91 libvlc_media_t * p_md,
93 EventPlaceInTime event_status )
97 /* Construct the event */
98 if( event_status == EventDidHappen )
100 event.type = libvlc_MediaListItemDeleted;
101 event.u.media_list_item_deleted.item = p_md;
102 event.u.media_list_item_deleted.index = index;
104 else /* if( event_status == EventWillHappen ) */
106 event.type = libvlc_MediaListWillDeleteItem;
107 event.u.media_list_will_delete_item.item = p_md;
108 event.u.media_list_will_delete_item.index = index;
112 libvlc_event_send( p_mlist->p_event_manager, &event );
115 /* LibVLC internal */
116 void libvlc_media_list_internal_end_reached( libvlc_media_list_t * p_mlist )
118 libvlc_event_t event;
120 event.type = libvlc_MediaListEndReached;
123 libvlc_event_send( p_mlist->p_event_manager, &event );
126 /**************************************************************************
127 * static mlist_is_writable (private)
128 **************************************************************************/
130 bool mlist_is_writable( libvlc_media_list_t *p_mlist )
132 if( !p_mlist||p_mlist->b_read_only )
134 /* We are read-only from user side */
135 libvlc_printerr( "Attempt to write a read-only media list" );
142 * Public libvlc functions
145 /**************************************************************************
146 * libvlc_media_list_new (Public)
149 **************************************************************************/
150 libvlc_media_list_t *
151 libvlc_media_list_new( libvlc_instance_t * p_inst )
153 libvlc_media_list_t * p_mlist;
155 p_mlist = malloc(sizeof(libvlc_media_list_t));
156 if( unlikely(p_mlist == NULL) )
158 libvlc_printerr( "Not enough memory" );
162 p_mlist->p_libvlc_instance = p_inst;
163 p_mlist->p_event_manager = libvlc_event_manager_new( p_mlist, p_inst );
164 if( unlikely(p_mlist->p_event_manager == NULL) )
170 p_mlist->b_read_only = false;
172 libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
173 libvlc_MediaListItemAdded );
174 libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
175 libvlc_MediaListWillAddItem );
176 libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
177 libvlc_MediaListItemDeleted );
178 libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
179 libvlc_MediaListWillDeleteItem );
180 libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
181 libvlc_MediaListEndReached );
183 vlc_mutex_init( &p_mlist->object_lock );
184 vlc_mutex_init( &p_mlist->refcount_lock ); // FIXME: spinlock?
186 vlc_array_init( &p_mlist->items );
187 assert( p_mlist->items.i_count == 0 );
188 p_mlist->i_refcount = 1;
189 p_mlist->p_md = NULL;
190 p_mlist->p_internal_md = NULL;
195 /**************************************************************************
196 * libvlc_media_list_release (Public)
199 **************************************************************************/
200 void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
202 libvlc_media_t * p_md;
205 vlc_mutex_lock( &p_mlist->refcount_lock );
206 p_mlist->i_refcount--;
207 if( p_mlist->i_refcount > 0 )
209 vlc_mutex_unlock( &p_mlist->refcount_lock );
212 vlc_mutex_unlock( &p_mlist->refcount_lock );
214 /* Refcount null, time to free */
216 libvlc_event_manager_release( p_mlist->p_event_manager );
218 libvlc_media_release( p_mlist->p_md );
220 for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
222 p_md = vlc_array_item_at_index( &p_mlist->items, i );
223 libvlc_media_release( p_md );
226 vlc_mutex_destroy( &p_mlist->object_lock );
227 vlc_mutex_destroy( &p_mlist->refcount_lock );
228 vlc_array_clear( &p_mlist->items );
233 /**************************************************************************
234 * libvlc_media_list_retain (Public)
236 * Increase an object refcount.
237 **************************************************************************/
238 void libvlc_media_list_retain( libvlc_media_list_t * p_mlist )
240 vlc_mutex_lock( &p_mlist->refcount_lock );
241 p_mlist->i_refcount++;
242 vlc_mutex_unlock( &p_mlist->refcount_lock );
246 /**************************************************************************
247 * add_file_content (Public)
248 **************************************************************************/
250 libvlc_media_list_add_file_content( libvlc_media_list_t * p_mlist,
251 const char * psz_uri )
253 input_item_t * p_input_item;
254 libvlc_media_t * p_md;
256 p_input_item = input_item_NewExt( psz_uri,
257 _("Media Library"), 0, NULL, 0, -1 );
261 libvlc_printerr( "Not enough memory" );
265 p_md = libvlc_media_new_from_input_item( p_mlist->p_libvlc_instance,
269 vlc_gc_decref( p_input_item );
273 if( libvlc_media_list_add_media( p_mlist, p_md ) )
275 #warning Missing error handling!
276 /* printerr and leaks */
280 input_Read( p_mlist->p_libvlc_instance->p_libvlc_int, p_input_item );
284 /**************************************************************************
286 **************************************************************************/
287 void libvlc_media_list_set_media( libvlc_media_list_t * p_mlist,
288 libvlc_media_t * p_md )
291 vlc_mutex_lock( &p_mlist->object_lock );
292 if( p_mlist->p_internal_md || !mlist_is_writable(p_mlist) )
294 vlc_mutex_unlock( &p_mlist->object_lock );
297 libvlc_media_release( p_mlist->p_md );
298 libvlc_media_retain( p_md );
299 p_mlist->p_md = p_md;
300 vlc_mutex_unlock( &p_mlist->object_lock );
303 /**************************************************************************
306 * If this media_list comes is a media's subitems,
307 * This holds the corresponding media.
308 * This md is also seen as the information holder for the media_list.
309 * Indeed a media_list can have meta information through this
311 **************************************************************************/
313 libvlc_media_list_media( libvlc_media_list_t * p_mlist )
315 libvlc_media_t *p_md;
317 vlc_mutex_lock( &p_mlist->object_lock );
318 p_md = p_mlist->p_internal_md ? p_mlist->p_internal_md : p_mlist->p_md;
320 libvlc_media_retain( p_md );
321 vlc_mutex_unlock( &p_mlist->object_lock );
326 /**************************************************************************
327 * libvlc_media_list_count (Public)
329 * Lock should be held when entering.
330 **************************************************************************/
331 int libvlc_media_list_count( libvlc_media_list_t * p_mlist )
333 return vlc_array_count( &p_mlist->items );
336 /**************************************************************************
337 * libvlc_media_list_add_media (Public)
339 * Lock should be held when entering.
340 **************************************************************************/
341 int libvlc_media_list_add_media( libvlc_media_list_t * p_mlist,
342 libvlc_media_t * p_md )
344 if( !mlist_is_writable(p_mlist) )
346 libvlc_media_list_internal_add_media( p_mlist, p_md );
350 /* LibVLC internal version */
351 void libvlc_media_list_internal_add_media( libvlc_media_list_t * p_mlist,
352 libvlc_media_t * p_md )
354 libvlc_media_retain( p_md );
356 notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items ),
358 vlc_array_append( &p_mlist->items, p_md );
359 notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items )-1,
363 /**************************************************************************
364 * libvlc_media_list_insert_media (Public)
366 * Lock should be hold when entering.
367 **************************************************************************/
368 int libvlc_media_list_insert_media( libvlc_media_list_t * p_mlist,
369 libvlc_media_t * p_md,
372 if( !mlist_is_writable(p_mlist) )
374 libvlc_media_list_internal_insert_media( p_mlist, p_md, index );
378 /* LibVLC internal version */
379 void libvlc_media_list_internal_insert_media( libvlc_media_list_t * p_mlist,
380 libvlc_media_t * p_md,
383 libvlc_media_retain( p_md );
385 notify_item_addition( p_mlist, p_md, index, EventWillHappen );
386 vlc_array_insert( &p_mlist->items, p_md, index );
387 notify_item_addition( p_mlist, p_md, index, EventDidHappen );
390 /**************************************************************************
391 * libvlc_media_list_remove_index (Public)
393 * Lock should be held when entering.
394 **************************************************************************/
395 int libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist,
398 if( !mlist_is_writable(p_mlist) )
400 return libvlc_media_list_internal_remove_index( p_mlist, index );
403 /* LibVLC internal version */
404 int libvlc_media_list_internal_remove_index( libvlc_media_list_t * p_mlist,
407 libvlc_media_t * p_md;
409 if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
411 libvlc_printerr( "Index out of bounds" );
415 p_md = vlc_array_item_at_index( &p_mlist->items, index );
417 notify_item_deletion( p_mlist, p_md, index, EventWillHappen );
418 vlc_array_remove( &p_mlist->items, index );
419 notify_item_deletion( p_mlist, p_md, index, EventDidHappen );
421 libvlc_media_release( p_md );
425 /**************************************************************************
426 * libvlc_media_list_item_at_index (Public)
428 * Lock should be held when entering.
429 **************************************************************************/
431 libvlc_media_list_item_at_index( libvlc_media_list_t * p_mlist,
434 libvlc_media_t * p_md;
436 if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
438 libvlc_printerr( "Index out of bounds" );
442 p_md = vlc_array_item_at_index( &p_mlist->items, index );
443 libvlc_media_retain( p_md );
447 /**************************************************************************
448 * libvlc_media_list_index_of_item (Public)
450 * Lock should be held when entering.
451 * Warning: this function returns the first matching item.
452 **************************************************************************/
453 int libvlc_media_list_index_of_item( libvlc_media_list_t * p_mlist,
454 libvlc_media_t * p_searched_md )
456 libvlc_media_t * p_md;
458 for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
460 p_md = vlc_array_item_at_index( &p_mlist->items, i );
461 if( p_searched_md == p_md )
464 libvlc_printerr( "Media not found" );
468 /**************************************************************************
469 * libvlc_media_list_is_readonly (Public)
471 * This indicates if this media list is read-only from a user point of view
472 **************************************************************************/
473 int libvlc_media_list_is_readonly( libvlc_media_list_t * p_mlist )
475 return p_mlist->b_read_only;
478 /**************************************************************************
479 * libvlc_media_list_lock (Public)
481 * The lock must be held in access operations. It is never used in the
483 **************************************************************************/
484 void libvlc_media_list_lock( libvlc_media_list_t * p_mlist )
486 vlc_mutex_lock( &p_mlist->object_lock );
490 /**************************************************************************
491 * libvlc_media_list_unlock (Public)
493 * The lock must be held in access operations
494 **************************************************************************/
495 void libvlc_media_list_unlock( libvlc_media_list_t * p_mlist )
497 vlc_mutex_unlock( &p_mlist->object_lock );
501 /**************************************************************************
502 * libvlc_media_list_p_event_manager (Public)
504 * The p_event_manager is immutable, so you don't have to hold the lock
505 **************************************************************************/
506 libvlc_event_manager_t *
507 libvlc_media_list_event_manager( libvlc_media_list_t * p_mlist )
509 return p_mlist->p_event_manager;