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"
33 static void add_media_list( libvlc_media_list_t * p_mlist, libvlc_media_list_t * p_submlist );
34 static void remove_media_list( libvlc_media_list_t * p_fmlist, libvlc_media_list_t * p_mlist );
35 static void add_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md );
36 static void remove_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md );
37 static void subitems_created( const libvlc_event_t * p_event , void * p_user_data);
38 static void sublist_item_added( const libvlc_event_t * p_event, void * p_user_data );
39 static void sublist_item_removed( const libvlc_event_t * p_event, void * p_user_data );
40 static void install_flat_mlist_observer( libvlc_media_list_t * p_mlist );
41 static void uninstall_flat_mlist_observer( libvlc_media_list_t * p_mlist );
43 /**************************************************************************
44 * uninstall_media_list_observer (Private)
45 **************************************************************************/
47 uninstall_media_list_observer( libvlc_media_list_t * p_mlist,
48 libvlc_media_list_t * p_submlist )
50 libvlc_event_detach( p_submlist->p_event_manager,
51 libvlc_MediaListItemAdded,
52 sublist_item_added, p_mlist, NULL );
53 libvlc_event_detach( p_submlist->p_event_manager,
54 libvlc_MediaListItemDeleted,
55 sublist_item_removed, p_mlist, NULL );
59 /**************************************************************************
60 * install_media_list_observer (Private)
61 **************************************************************************/
63 install_media_list_observer( libvlc_media_list_t * p_mlist,
64 libvlc_media_list_t * p_submlist )
66 libvlc_event_attach( p_submlist->p_event_manager,
67 libvlc_MediaListItemAdded,
68 sublist_item_added, p_mlist, NULL );
69 libvlc_event_attach( p_submlist->p_event_manager,
70 libvlc_MediaListItemDeleted,
71 sublist_item_removed, p_mlist, NULL );
74 /**************************************************************************
75 * add_media_list (Private)
76 **************************************************************************/
78 add_media_list( libvlc_media_list_t * p_mlist,
79 libvlc_media_list_t * p_submlist )
81 int count = libvlc_media_list_count( p_submlist, NULL );
84 for( i = 0; i < count; i++ )
86 libvlc_media_descriptor_t * p_md;
87 p_md = libvlc_media_list_item_at_index( p_submlist, i, NULL );
88 add_item( p_mlist, p_md );
90 install_media_list_observer( p_mlist, p_submlist );
93 /**************************************************************************
94 * remove_media_list (Private)
95 **************************************************************************/
97 remove_media_list( libvlc_media_list_t * p_mlist,
98 libvlc_media_list_t * p_submlist )
100 int count = libvlc_media_list_count( p_submlist, NULL );
102 uninstall_media_list_observer( p_mlist, p_submlist );
104 for( i = 0; i < count; i++ )
106 libvlc_media_descriptor_t * p_md;
107 p_md = libvlc_media_list_item_at_index( p_submlist, i, NULL );
108 remove_item( p_mlist, p_md );
113 /**************************************************************************
115 **************************************************************************/
117 add_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
119 /* Only add the media descriptor once to our flat list */
120 if( libvlc_media_list_index_of_item( p_mlist->p_flat_mlist, p_md, NULL ) < 0 )
122 if( p_md->p_subitems )
124 add_media_list( p_mlist->p_flat_mlist, p_md->p_subitems );
128 libvlc_event_attach( p_md->p_event_manager,
129 libvlc_MediaDescriptorSubItemAdded,
130 subitems_created, p_mlist, NULL );
131 uninstall_flat_mlist_observer( p_mlist );
132 libvlc_media_list_add_media_descriptor( p_mlist->p_flat_mlist,
134 install_flat_mlist_observer( p_mlist );
139 /**************************************************************************
140 * remove_item (private)
141 **************************************************************************/
143 remove_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
145 if( p_md->p_subitems ) /* XXX: Don't access that directly */
146 remove_media_list( p_mlist, p_md->p_subitems );
147 libvlc_event_detach( p_md->p_event_manager,
148 libvlc_MediaDescriptorSubItemAdded,
149 subitems_created, p_mlist, NULL );
150 int i = libvlc_media_list_index_of_item( p_mlist->p_flat_mlist, p_md, NULL );
151 uninstall_flat_mlist_observer( p_mlist );
152 libvlc_media_list_remove_index( p_mlist->p_flat_mlist, i, NULL );
153 install_flat_mlist_observer( p_mlist );
156 /**************************************************************************
157 * subitems_created (private) (Event Callback)
158 **************************************************************************/
160 subitems_created( const libvlc_event_t * p_event , void * p_user_data)
162 libvlc_media_list_t * p_mlist = p_user_data;
163 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
165 /* Remove the item and add the playlist */
166 remove_item( p_mlist->p_flat_mlist, p_md );
168 add_media_list( p_mlist->p_flat_mlist, p_md->p_subitems );
171 /**************************************************************************
172 * sublist_item_added (private) (Event Callback)
174 * This is called if the dynamic sublist's data provider adds a new item.
175 **************************************************************************/
177 sublist_item_added( const libvlc_event_t * p_event, void * p_user_data )
179 libvlc_media_list_t * p_mlist = p_user_data;
180 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
181 add_item( p_mlist, p_md );
184 /**************************************************************************
185 * sublist_remove_item (private) (Event Callback)
186 **************************************************************************/
188 sublist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
190 libvlc_media_list_t * p_mlist = p_user_data;
191 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
192 remove_item( p_mlist, p_md );
195 /**************************************************************************
196 * remove_item_in_submlist_rec (private)
197 **************************************************************************/
199 remove_item_in_submlist_rec( libvlc_media_list_t * p_mlist,
200 libvlc_media_list_t * p_submlist,
201 libvlc_media_descriptor_t * p_md )
203 libvlc_media_descriptor_t * p_md_insub;
204 int count = libvlc_media_list_count( p_submlist, NULL );
206 for( i = 0; i < count; i++ )
208 p_md_insub = libvlc_media_list_item_at_index( p_submlist,
210 if( p_md_insub->p_subitems )
211 remove_item_in_submlist_rec( p_mlist, p_submlist, p_md );
212 if( p_md == p_md_insub )
214 uninstall_media_list_observer( p_mlist, p_submlist );
215 libvlc_media_list_remove_index( p_submlist, i, NULL );
216 install_media_list_observer( p_mlist, p_submlist );
221 /**************************************************************************
222 * flat_mlist_item_removed (private) (Event Callback)
223 **************************************************************************/
225 flat_mlist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
227 /* Remove all occurences of that one in sublist */
228 libvlc_media_list_t * p_mlist = p_user_data;
229 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
230 remove_item( p_mlist, p_md ); /* Just to detach the event */
231 remove_item_in_submlist_rec( p_mlist, p_mlist, p_md );
234 /**************************************************************************
235 * flat_mlist_item_added (private) (Event Callback)
236 **************************************************************************/
238 flat_mlist_item_added( const libvlc_event_t * p_event, void * p_user_data )
240 libvlc_media_list_t * p_mlist = p_user_data;
241 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
243 /* Add in our root */
244 uninstall_media_list_observer( p_mlist, p_mlist );
245 libvlc_media_list_add_media_descriptor( p_mlist, p_md, NULL );
246 install_media_list_observer( p_mlist, p_mlist );
249 /**************************************************************************
250 * install_flat_mlist_observer (Private)
251 **************************************************************************/
253 install_flat_mlist_observer( libvlc_media_list_t * p_mlist )
255 libvlc_event_attach( p_mlist->p_flat_mlist->p_event_manager,
256 libvlc_MediaListItemAdded,
257 flat_mlist_item_added, p_mlist, NULL );
258 libvlc_event_attach( p_mlist->p_flat_mlist->p_event_manager,
259 libvlc_MediaListItemDeleted,
260 flat_mlist_item_removed, p_mlist, NULL );
264 /**************************************************************************
265 * uninstall_flat_mlist_observer (Private)
266 **************************************************************************/
268 uninstall_flat_mlist_observer( libvlc_media_list_t * p_mlist )
270 libvlc_event_detach( p_mlist->p_flat_mlist->p_event_manager,
271 libvlc_MediaListItemAdded,
272 flat_mlist_item_added, p_mlist, NULL );
273 libvlc_event_attach( p_mlist->p_flat_mlist->p_event_manager,
274 libvlc_MediaListItemDeleted,
275 flat_mlist_item_removed, p_mlist, NULL );
280 * libvlc Internal functions
282 /**************************************************************************
283 * flat_media_list_release (Internal)
284 **************************************************************************/
286 libvlc_media_list_flat_media_list_release( libvlc_media_list_t * p_mlist )
288 if( !p_mlist->p_flat_mlist )
290 uninstall_flat_mlist_observer( p_mlist );
291 libvlc_media_list_release( p_mlist->p_flat_mlist );
295 * Public libvlc functions
298 /**************************************************************************
299 * media_list (Public)
300 **************************************************************************/
301 libvlc_media_list_t *
302 libvlc_media_list_flat_media_list( libvlc_media_list_t * p_mlist,
303 libvlc_exception_t * p_e )
305 if( !p_mlist->p_flat_mlist )
307 p_mlist->p_flat_mlist = libvlc_media_list_new(
308 p_mlist->p_libvlc_instance,
310 add_media_list( p_mlist, p_mlist );
311 install_flat_mlist_observer( p_mlist );
313 libvlc_media_list_retain( p_mlist->p_flat_mlist );
314 return p_mlist->p_flat_mlist;