1 /*****************************************************************************
2 * flat_media_list.c: libvlc flat media list functions. (extension to
4 *****************************************************************************
5 * Copyright (C) 2007 the VideoLAN team
6 * $Id: flat_media_list.c 21287 2007-08-20 01:28:12Z pdherbemont $
8 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #include "libvlc_internal.h"
26 #include <vlc/libvlc.h>
28 #include "vlc_arrays.h"
30 //#define DEBUG_FLAT_LIST
32 #ifdef DEBUG_FLAT_LIST
33 # define trace( fmt, ... ) printf( "%s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
41 static void add_media_list( libvlc_media_list_t * p_mlist, libvlc_media_list_t * p_submlist );
42 static void remove_media_list( libvlc_media_list_t * p_fmlist, libvlc_media_list_t * p_mlist );
43 static void add_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md );
44 static void remove_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md );
45 static void subitems_created( const libvlc_event_t * p_event , void * p_user_data);
46 static void sublist_item_added( const libvlc_event_t * p_event, void * p_user_data );
47 static void sublist_item_removed( const libvlc_event_t * p_event, void * p_user_data );
48 static void install_flat_mlist_observer( libvlc_media_list_t * p_mlist );
49 static void uninstall_flat_mlist_observer( libvlc_media_list_t * p_mlist );
51 /**************************************************************************
52 * uninstall_media_list_observer (Private)
53 **************************************************************************/
55 uninstall_media_list_observer( libvlc_media_list_t * p_mlist,
56 libvlc_media_list_t * p_submlist )
59 libvlc_event_detach( p_submlist->p_event_manager,
60 libvlc_MediaListItemAdded,
61 sublist_item_added, p_mlist, NULL );
62 libvlc_event_detach( p_submlist->p_event_manager,
63 libvlc_MediaListItemDeleted,
64 sublist_item_removed, p_mlist, NULL );
67 /**************************************************************************
68 * install_media_list_observer (Private)
69 **************************************************************************/
71 install_media_list_observer( libvlc_media_list_t * p_mlist,
72 libvlc_media_list_t * p_submlist )
75 libvlc_event_attach( p_submlist->p_event_manager,
76 libvlc_MediaListItemAdded,
77 sublist_item_added, p_mlist, NULL );
78 libvlc_event_attach( p_submlist->p_event_manager,
79 libvlc_MediaListItemDeleted,
80 sublist_item_removed, p_mlist, NULL );
83 /**************************************************************************
84 * add_media_list (Private)
85 **************************************************************************/
87 add_media_list( libvlc_media_list_t * p_mlist,
88 libvlc_media_list_t * p_submlist )
90 int count = libvlc_media_list_count( p_submlist, NULL );
94 for( i = 0; i < count; i++ )
96 libvlc_media_descriptor_t * p_md;
97 p_md = libvlc_media_list_item_at_index( p_submlist, i, NULL );
98 add_item( p_mlist, p_md );
100 install_media_list_observer( p_mlist, p_submlist );
103 /**************************************************************************
104 * remove_media_list (Private)
105 **************************************************************************/
107 remove_media_list( libvlc_media_list_t * p_mlist,
108 libvlc_media_list_t * p_submlist )
111 int count = libvlc_media_list_count( p_submlist, NULL );
113 uninstall_media_list_observer( p_mlist, p_submlist );
115 for( i = 0; i < count; i++ )
117 libvlc_media_descriptor_t * p_md;
118 p_md = libvlc_media_list_item_at_index( p_submlist, i, NULL );
119 remove_item( p_mlist, p_md );
124 /**************************************************************************
126 **************************************************************************/
128 add_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
130 trace( "p_md '%s'\n", p_md->p_input_item->psz_name );
132 /* Only add the media descriptor once to our flat list */
133 if( libvlc_media_list_index_of_item( p_mlist->p_flat_mlist, p_md, NULL ) < 0 )
135 if( p_md->p_subitems )
137 add_media_list( p_mlist, p_md->p_subitems );
141 libvlc_media_list_lock( p_mlist->p_flat_mlist );
142 libvlc_event_attach( p_md->p_event_manager,
143 libvlc_MediaDescriptorSubItemAdded,
144 subitems_created, p_mlist, NULL );
145 uninstall_flat_mlist_observer( p_mlist );
146 libvlc_media_list_add_media_descriptor( p_mlist->p_flat_mlist,
148 install_flat_mlist_observer( p_mlist );
149 libvlc_media_list_unlock( p_mlist->p_flat_mlist );
155 /**************************************************************************
156 * remove_item (private)
157 **************************************************************************/
159 remove_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
161 trace( "p_md '%s'\n", p_md->p_input_item->psz_name );
163 if( p_md->p_subitems ) /* XXX: Don't access that directly */
164 remove_media_list( p_mlist, p_md->p_subitems );
165 libvlc_event_detach( p_md->p_event_manager,
166 libvlc_MediaDescriptorSubItemAdded,
167 subitems_created, p_mlist, NULL );
169 libvlc_media_list_lock( p_mlist->p_flat_mlist );
170 int i = libvlc_media_list_index_of_item( p_mlist->p_flat_mlist, p_md, NULL );
173 uninstall_flat_mlist_observer( p_mlist );
174 libvlc_media_list_remove_index( p_mlist->p_flat_mlist, i, NULL );
175 install_flat_mlist_observer( p_mlist );
177 libvlc_media_list_unlock( p_mlist->p_flat_mlist );
180 /**************************************************************************
181 * subitems_created (private) (Event Callback)
182 **************************************************************************/
184 subitems_created( const libvlc_event_t * p_event , void * p_user_data)
186 libvlc_media_list_t * p_mlist = p_user_data;
187 libvlc_media_descriptor_t * p_md = p_event->p_obj;
189 trace( "parent p_md '%s'\n", p_md->p_input_item->psz_name );
191 /* Remove the item and add the playlist */
192 libvlc_media_list_lock( p_mlist->p_flat_mlist );
193 int i = libvlc_media_list_index_of_item( p_mlist->p_flat_mlist, p_md, NULL );
196 libvlc_event_detach_lock_state( p_md->p_event_manager,
197 libvlc_MediaDescriptorSubItemAdded,
198 subitems_created, p_mlist, libvlc_Locked, NULL );
199 uninstall_flat_mlist_observer( p_mlist );
200 libvlc_media_list_remove_index( p_mlist->p_flat_mlist, i, NULL );
201 install_flat_mlist_observer( p_mlist );
203 libvlc_media_list_unlock( p_mlist->p_flat_mlist );
205 trace( "Adding p_md '%s''s media list\n", p_md->p_input_item->psz_name );
207 add_media_list( p_mlist, p_md->p_subitems );
213 /**************************************************************************
214 * sublist_item_added (private) (Event Callback)
216 * This is called if the dynamic sublist's data provider adds a new item.
217 **************************************************************************/
219 sublist_item_added( const libvlc_event_t * p_event, void * p_user_data )
221 libvlc_media_list_t * p_mlist = p_user_data;
222 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
223 trace( "p_md '%s'\n", p_md->p_input_item->psz_name );
225 add_item( p_mlist, p_md );
228 /**************************************************************************
229 * sublist_remove_item (private) (Event Callback)
230 **************************************************************************/
232 sublist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
234 libvlc_media_list_t * p_mlist = p_user_data;
235 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
236 trace( "p_md '%s'\n", p_md->p_input_item->psz_name );
238 remove_item( p_mlist, p_md );
241 /**************************************************************************
242 * remove_item_in_submlist_rec (private)
243 **************************************************************************/
245 remove_item_in_submlist_rec( libvlc_media_list_t * p_mlist,
246 libvlc_media_list_t * p_submlist,
247 libvlc_media_descriptor_t * p_md )
249 libvlc_media_descriptor_t * p_md_insub;
250 int count = libvlc_media_list_count( p_submlist, NULL );
252 trace("p_md '%s'\n", p_md->p_input_item->psz_name);
254 for( i = 0; i < count; i++ )
256 p_md_insub = libvlc_media_list_item_at_index( p_submlist,
258 if( p_md == p_md_insub )
260 libvlc_media_list_lock( p_submlist );
261 uninstall_media_list_observer( p_mlist, p_submlist );
262 libvlc_media_list_remove_index( p_submlist, i, NULL );
263 install_media_list_observer( p_mlist, p_submlist );
264 libvlc_media_list_unlock( p_submlist );
265 } else if( p_md_insub->p_subitems )
266 remove_item_in_submlist_rec( p_mlist, p_md_insub->p_subitems, p_md );
270 /**************************************************************************
271 * flat_mlist_item_removed (private) (Event Callback)
272 **************************************************************************/
274 flat_mlist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
277 /* Remove all occurences of that one in sublist */
278 libvlc_media_list_t * p_mlist = p_user_data;
279 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
280 remove_item( p_mlist, p_md ); /* Just to detach the event */
281 remove_item_in_submlist_rec( p_mlist, p_mlist, p_md );
284 /**************************************************************************
285 * flat_mlist_item_added (private) (Event Callback)
286 **************************************************************************/
288 flat_mlist_item_added( const libvlc_event_t * p_event, void * p_user_data )
291 libvlc_media_list_t * p_mlist = p_user_data;
292 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
294 libvlc_event_attach( p_md->p_event_manager,
295 libvlc_MediaDescriptorSubItemAdded,
296 subitems_created, p_mlist, NULL );
298 /* Add in our root */
299 uninstall_media_list_observer( p_mlist, p_mlist );
300 libvlc_media_list_add_media_descriptor( p_mlist, p_md, NULL );
301 install_media_list_observer( p_mlist, p_mlist );
304 /**************************************************************************
305 * install_flat_mlist_observer (Private)
306 **************************************************************************/
308 install_flat_mlist_observer( libvlc_media_list_t * p_mlist )
311 libvlc_event_attach( p_mlist->p_flat_mlist->p_event_manager,
312 libvlc_MediaListItemAdded,
313 flat_mlist_item_added, p_mlist, NULL );
314 libvlc_event_attach( p_mlist->p_flat_mlist->p_event_manager,
315 libvlc_MediaListItemDeleted,
316 flat_mlist_item_removed, p_mlist, NULL );
320 /**************************************************************************
321 * uninstall_flat_mlist_observer (Private)
322 **************************************************************************/
324 uninstall_flat_mlist_observer( libvlc_media_list_t * p_mlist )
327 libvlc_event_detach( p_mlist->p_flat_mlist->p_event_manager,
328 libvlc_MediaListItemAdded,
329 flat_mlist_item_added, p_mlist, NULL );
330 libvlc_event_detach( p_mlist->p_flat_mlist->p_event_manager,
331 libvlc_MediaListItemDeleted,
332 flat_mlist_item_removed, p_mlist, NULL );
337 * libvlc Internal functions
339 /**************************************************************************
340 * flat_media_list_release (Internal)
341 **************************************************************************/
343 libvlc_media_list_flat_media_list_release( libvlc_media_list_t * p_mlist )
345 if( !p_mlist->p_flat_mlist )
347 uninstall_flat_mlist_observer( p_mlist );
348 libvlc_media_list_release( p_mlist->p_flat_mlist );
352 * Public libvlc functions
355 /**************************************************************************
356 * media_list (Public)
357 **************************************************************************/
358 libvlc_media_list_t *
359 libvlc_media_list_flat_media_list( libvlc_media_list_t * p_mlist,
360 libvlc_exception_t * p_e )
363 libvlc_media_list_lock( p_mlist );
364 if( !p_mlist->p_flat_mlist )
366 p_mlist->p_flat_mlist = libvlc_media_list_new(
367 p_mlist->p_libvlc_instance,
369 add_media_list( p_mlist, p_mlist );
371 libvlc_media_list_unlock( p_mlist );
372 libvlc_media_list_retain( p_mlist->p_flat_mlist );
373 return p_mlist->p_flat_mlist;