]> git.sesse.net Git - vlc/blob - src/control/media_list.c
codecleanup: Replace input_Item by input_item.
[vlc] / src / control / media_list.c
1 /*****************************************************************************
2  * media_list.c: libvlc new API media list functions
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
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 General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "libvlc_internal.h"
25 #include <vlc/libvlc.h>
26 #include <assert.h>
27 #include "vlc_arrays.h"
28
29 typedef enum EventPlaceInTime {
30     EventWillHappen,
31     EventDidHappen
32 } EventPlaceInTime;
33
34 //#define DEBUG_MEDIA_LIST
35
36 #ifdef DEBUG_MEDIA_LIST
37 # define trace( fmt, ... ) printf( "%s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
38 #else
39 # define trace( ... )
40 #endif
41
42 /*
43  * Private functions
44  */
45
46
47
48 /**************************************************************************
49  *       notify_item_addition (private)
50  *
51  * Do the appropriate action when an item is deleted.
52  **************************************************************************/
53 static void
54 notify_item_addition( libvlc_media_list_t * p_mlist,
55                       libvlc_media_t * p_md,
56                       int index,
57                       EventPlaceInTime event_status )
58 {
59     libvlc_event_t event;
60
61     /* Construct the event */
62     if( event_status == EventDidHappen )
63     {
64         trace("item was added at index %d\n", index);
65         event.type = libvlc_MediaListItemAdded;
66         event.u.media_list_item_added.item = p_md;
67         event.u.media_list_item_added.index = index;
68     }
69     else /* if( event_status == EventWillHappen ) */
70     {
71         event.type = libvlc_MediaListWillAddItem;
72         event.u.media_list_will_add_item.item = p_md;
73         event.u.media_list_will_add_item.index = index;
74     }
75
76     /* Send the event */
77     libvlc_event_send( p_mlist->p_event_manager, &event );
78 }
79
80 /**************************************************************************
81  *       notify_item_deletion (private)
82  *
83  * Do the appropriate action when an item is added.
84  **************************************************************************/
85 static void
86 notify_item_deletion( libvlc_media_list_t * p_mlist,
87                       libvlc_media_t * p_md,
88                       int index,
89                       EventPlaceInTime event_status )
90 {
91     libvlc_event_t event;
92
93     /* Construct the event */
94     if( event_status == EventDidHappen )
95     {
96         trace("item at index %d was deleted\n", index);
97         event.type = libvlc_MediaListItemDeleted;
98         event.u.media_list_item_deleted.item = p_md;
99         event.u.media_list_item_deleted.index = index;
100     }
101     else /* if( event_status == EventWillHappen ) */
102     {
103         event.type = libvlc_MediaListWillDeleteItem;
104         event.u.media_list_will_delete_item.item = p_md;
105         event.u.media_list_will_delete_item.index = index;
106     }
107
108     /* Send the event */
109     libvlc_event_send( p_mlist->p_event_manager, &event );
110 }
111
112 /*
113  * Public libvlc functions
114  */
115
116 /**************************************************************************
117  *       libvlc_media_list_new (Public)
118  *
119  * Init an object.
120  **************************************************************************/
121 libvlc_media_list_t *
122 libvlc_media_list_new( libvlc_instance_t * p_inst,
123                        libvlc_exception_t * p_e )
124 {
125     libvlc_media_list_t * p_mlist;
126
127     p_mlist = malloc(sizeof(libvlc_media_list_t));
128     if( !p_mlist )
129         return NULL;
130
131     p_mlist->p_libvlc_instance = p_inst;
132     p_mlist->p_event_manager = libvlc_event_manager_new( p_mlist, p_inst, p_e );
133
134     /* Code for that one should be handled in flat_media_list.c */
135     p_mlist->p_flat_mlist = NULL;
136     p_mlist->b_read_only = false;
137
138     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
139             libvlc_MediaListItemAdded, p_e );
140     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
141             libvlc_MediaListWillAddItem, p_e );
142     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
143             libvlc_MediaListItemDeleted, p_e );
144     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
145             libvlc_MediaListWillDeleteItem, p_e );
146
147     if( libvlc_exception_raised( p_e ) )
148     {
149         libvlc_event_manager_release( p_mlist->p_event_manager );
150         free( p_mlist );
151         return NULL;
152     }
153
154     vlc_mutex_init( &p_mlist->object_lock );
155
156     vlc_array_init( &p_mlist->items );
157     p_mlist->i_refcount = 1;
158     p_mlist->p_md = NULL;
159
160     return p_mlist;
161 }
162
163 /**************************************************************************
164  *       libvlc_media_list_release (Public)
165  *
166  * Release an object.
167  **************************************************************************/
168 void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
169 {
170     libvlc_media_t * p_md;
171     int i;
172
173     vlc_mutex_lock( &p_mlist->object_lock );
174     p_mlist->i_refcount--;
175     if( p_mlist->i_refcount > 0 )
176     {
177         vlc_mutex_unlock( &p_mlist->object_lock );
178         return;
179     }
180     vlc_mutex_unlock( &p_mlist->object_lock );
181
182     /* Refcount null, time to free */
183
184     libvlc_event_manager_release( p_mlist->p_event_manager );
185
186     if( p_mlist->p_md )
187         libvlc_media_release( p_mlist->p_md );
188
189     for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
190     {
191         p_md = vlc_array_item_at_index( &p_mlist->items, i );
192         libvlc_media_release( p_md );
193     }
194
195     vlc_mutex_destroy( &p_mlist->object_lock );
196     vlc_array_clear( &p_mlist->items );
197
198     free( p_mlist );
199 }
200
201 /**************************************************************************
202  *       libvlc_media_list_retain (Public)
203  *
204  * Increase an object refcount.
205  **************************************************************************/
206 void libvlc_media_list_retain( libvlc_media_list_t * p_mlist )
207 {
208     vlc_mutex_lock( &p_mlist->object_lock );
209     p_mlist->i_refcount++;
210     vlc_mutex_unlock( &p_mlist->object_lock );
211 }
212
213
214 /**************************************************************************
215  *       add_file_content (Public)
216  **************************************************************************/
217 void
218 libvlc_media_list_add_file_content( libvlc_media_list_t * p_mlist,
219                                     const char * psz_uri,
220                                     libvlc_exception_t * p_e )
221 {
222     input_item_t * p_input_item;
223     libvlc_media_t * p_md;
224
225     p_input_item = input_item_NewExt( p_mlist->p_libvlc_instance->p_libvlc_int, psz_uri,
226                                 _("Media Library"), 0, NULL, -1 );
227
228     if( !p_input_item )
229     {
230         libvlc_exception_raise( p_e, "Can't create an input item" );
231         return;
232     }
233
234     p_md = libvlc_media_new_from_input_item(
235             p_mlist->p_libvlc_instance,
236             p_input_item, p_e );
237
238     if( !p_md )
239     {
240         vlc_gc_decref( p_input_item );
241         return;
242     }
243
244     libvlc_media_list_add_media( p_mlist, p_md, p_e );
245     if( libvlc_exception_raised( p_e ) )
246         return;
247
248     input_Read( p_mlist->p_libvlc_instance->p_libvlc_int, p_input_item, true );
249
250     return;
251 }
252
253 /**************************************************************************
254  *       set_media (Public)
255  **************************************************************************/
256 void libvlc_media_list_set_media( libvlc_media_list_t * p_mlist,
257                                              libvlc_media_t * p_md,
258                                              libvlc_exception_t * p_e)
259
260 {
261     (void)p_e;
262     vlc_mutex_lock( &p_mlist->object_lock );
263     if( p_mlist->p_md )
264         libvlc_media_release( p_mlist->p_md );
265     libvlc_media_retain( p_md );
266     p_mlist->p_md = p_md;
267     vlc_mutex_unlock( &p_mlist->object_lock );
268 }
269
270 /**************************************************************************
271  *       media (Public)
272  *
273  * If this media_list comes is a media's subitems,
274  * This holds the corresponding media.
275  * This md is also seen as the information holder for the media_list.
276  * Indeed a media_list can have meta information through this
277  * media.
278  **************************************************************************/
279 libvlc_media_t *
280 libvlc_media_list_media( libvlc_media_list_t * p_mlist,
281                                     libvlc_exception_t * p_e)
282 {
283     libvlc_media_t *p_md;
284     (void)p_e;
285
286     vlc_mutex_lock( &p_mlist->object_lock );
287     p_md = p_mlist->p_md;
288     if( p_md )
289         libvlc_media_retain( p_md );
290     vlc_mutex_unlock( &p_mlist->object_lock );
291
292     return p_md;
293 }
294
295 /**************************************************************************
296  *       libvlc_media_list_count (Public)
297  *
298  * Lock should be hold when entering.
299  **************************************************************************/
300 int libvlc_media_list_count( libvlc_media_list_t * p_mlist,
301                              libvlc_exception_t * p_e )
302 {
303     (void)p_e;
304     return vlc_array_count( &p_mlist->items );
305 }
306
307 /**************************************************************************
308  *       libvlc_media_list_add_media (Public)
309  *
310  * Lock should be hold when entering.
311  **************************************************************************/
312 void libvlc_media_list_add_media(
313                                    libvlc_media_list_t * p_mlist,
314                                    libvlc_media_t * p_md,
315                                    libvlc_exception_t * p_e )
316 {
317     if( p_mlist->b_read_only )
318     {
319         /* We are read only from user side */
320         libvlc_exception_raise( p_e, "Trying to write into a read-only media list." );
321         return;
322     }
323
324     _libvlc_media_list_add_media( p_mlist, p_md, p_e );
325 }
326
327 /* LibVLC internal version */
328 void _libvlc_media_list_add_media(
329                                    libvlc_media_list_t * p_mlist,
330                                    libvlc_media_t * p_md,
331                                    libvlc_exception_t * p_e )
332 {
333     (void)p_e;
334     libvlc_media_retain( p_md );
335
336     notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items ), EventWillHappen );
337     vlc_array_append( &p_mlist->items, p_md );
338     notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items )-1, EventDidHappen );
339 }
340
341 /**************************************************************************
342  *       libvlc_media_list_insert_media (Public)
343  *
344  * Lock should be hold when entering.
345  **************************************************************************/
346 void libvlc_media_list_insert_media(
347                                    libvlc_media_list_t * p_mlist,
348                                    libvlc_media_t * p_md,
349                                    int index,
350                                    libvlc_exception_t * p_e )
351 {
352     if( p_mlist->b_read_only )
353     {
354         /* We are read only from user side */
355         libvlc_exception_raise( p_e, "Trying to write into a read-only media list." );
356         return;
357     }
358     _libvlc_media_list_insert_media( p_mlist, p_md, index, p_e );
359 }
360
361 /* LibVLC internal version */
362 void _libvlc_media_list_insert_media(
363                                    libvlc_media_list_t * p_mlist,
364                                    libvlc_media_t * p_md,
365                                    int index,
366                                    libvlc_exception_t * p_e )
367 {
368     (void)p_e;
369     libvlc_media_retain( p_md );
370
371     notify_item_addition( p_mlist, p_md, index, EventWillHappen );
372     vlc_array_insert( &p_mlist->items, p_md, index );
373     notify_item_addition( p_mlist, p_md, index, EventDidHappen );
374 }
375
376 /**************************************************************************
377  *       libvlc_media_list_remove_index (Public)
378  *
379  * Lock should be hold when entering.
380  **************************************************************************/
381 void libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist,
382                                      int index,
383                                      libvlc_exception_t * p_e )
384 {
385     if( p_mlist->b_read_only )
386     {
387         /* We are read only from user side */
388         libvlc_exception_raise( p_e, "Trying to write into a read-only media list." );
389         return;
390     }
391     _libvlc_media_list_remove_index( p_mlist, index, p_e );
392 }
393
394 /* LibVLC internal version */
395 void _libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist,
396                                      int index,
397                                      libvlc_exception_t * p_e )
398 {
399
400     libvlc_media_t * p_md;
401
402     if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
403     {
404         libvlc_exception_raise( p_e, "Index out of bounds exception");
405         return;
406     }
407
408     p_md = vlc_array_item_at_index( &p_mlist->items, index );
409
410     notify_item_deletion( p_mlist, p_md, index, EventWillHappen );
411     vlc_array_remove( &p_mlist->items, index );
412     notify_item_deletion( p_mlist, p_md, index, EventDidHappen );
413
414     libvlc_media_release( p_md );
415 }
416
417 /**************************************************************************
418  *       libvlc_media_list_item_at_index (Public)
419  *
420  * Lock should be hold when entering.
421  **************************************************************************/
422 libvlc_media_t *
423 libvlc_media_list_item_at_index( libvlc_media_list_t * p_mlist,
424                                  int index,
425                                  libvlc_exception_t * p_e )
426 {
427     VLC_UNUSED(p_e);
428
429     if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
430     {
431         libvlc_exception_raise( p_e, "Index out of bounds exception");
432         return NULL;
433     }
434
435     libvlc_media_t * p_md;
436     p_md = vlc_array_item_at_index( &p_mlist->items, index );
437     libvlc_media_retain( p_md );
438     return p_md;
439 }
440
441 /**************************************************************************
442  *       libvlc_media_list_index_of_item (Public)
443  *
444  * Lock should be hold when entering.
445  * Warning: this function would return the first matching item
446  **************************************************************************/
447 int libvlc_media_list_index_of_item( libvlc_media_list_t * p_mlist,
448                                      libvlc_media_t * p_searched_md,
449                                      libvlc_exception_t * p_e )
450 {
451     VLC_UNUSED(p_e);
452
453     libvlc_media_t * p_md;
454     int i;
455     for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
456     {
457         p_md = vlc_array_item_at_index( &p_mlist->items, i );
458         if( p_searched_md == p_md )
459             return i;
460     }
461     return -1;
462 }
463
464 /**************************************************************************
465  *       libvlc_media_list_is_readonly (Public)
466  *
467  * This indicates if this media list is read-only from a user point of view
468  **************************************************************************/
469 int libvlc_media_list_is_readonly( libvlc_media_list_t * p_mlist )
470 {
471     return p_mlist->b_read_only;
472 }
473
474 /**************************************************************************
475  *       libvlc_media_list_lock (Public)
476  *
477  * The lock must be held in access operations. It is never used in the
478  * Public method.
479  **************************************************************************/
480 void libvlc_media_list_lock( libvlc_media_list_t * p_mlist )
481 {
482     vlc_mutex_lock( &p_mlist->object_lock );
483 }
484
485
486 /**************************************************************************
487  *       libvlc_media_list_unlock (Public)
488  *
489  * The lock must be held in access operations
490  **************************************************************************/
491 void libvlc_media_list_unlock( libvlc_media_list_t * p_mlist )
492 {
493     vlc_mutex_unlock( &p_mlist->object_lock );
494 }
495
496
497 /**************************************************************************
498  *       libvlc_media_list_p_event_manager (Public)
499  *
500  * The p_event_manager is immutable, so you don't have to hold the lock
501  **************************************************************************/
502 libvlc_event_manager_t *
503 libvlc_media_list_event_manager( libvlc_media_list_t * p_mlist,
504                                     libvlc_exception_t * p_e )
505 {
506     (void)p_e;
507     return p_mlist->p_event_manager;
508 }