]> git.sesse.net Git - vlc/blob - src/control/flat_media_list.c
control/flat_media_list.c: Remove an other typo that could cause a crash.
[vlc] / src / control / flat_media_list.c
1 /*****************************************************************************
2  * flat_media_list.c: libvlc flat media list functions. (extension to
3  * media_list.c).
4  *****************************************************************************
5  * Copyright (C) 2007 the VideoLAN team
6  * $Id: flat_media_list.c 21287 2007-08-20 01:28:12Z pdherbemont $
7  *
8  * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 #include "libvlc_internal.h"
26 #include <vlc/libvlc.h>
27 #include <assert.h>
28 #include "vlc_arrays.h"
29
30 /*
31  * Private functions
32  */
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 );
42
43 /**************************************************************************
44  *       uninstall_media_list_observer (Private)
45  **************************************************************************/
46 static void
47 uninstall_media_list_observer( libvlc_media_list_t * p_mlist,
48                              libvlc_media_list_t * p_submlist )
49 {
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 );
56
57 }
58
59 /**************************************************************************
60  *       install_media_list_observer (Private)
61  **************************************************************************/
62 static void
63 install_media_list_observer( libvlc_media_list_t * p_mlist,
64                              libvlc_media_list_t * p_submlist )
65 {
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 );
72 }
73
74 /**************************************************************************
75  *       add_media_list (Private)
76  **************************************************************************/
77 static void
78 add_media_list( libvlc_media_list_t * p_mlist,
79                 libvlc_media_list_t * p_submlist )
80 {
81     int count = libvlc_media_list_count( p_submlist, NULL );
82     int i;
83
84     for( i = 0; i < count; i++ )
85     {
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 );
89     }
90     install_media_list_observer( p_mlist, p_submlist );
91 }
92
93 /**************************************************************************
94  *       remove_media_list (Private)
95  **************************************************************************/
96 static void
97 remove_media_list( libvlc_media_list_t * p_mlist,
98                    libvlc_media_list_t * p_submlist )
99 {
100     int count = libvlc_media_list_count( p_submlist, NULL );    
101     int i;
102     uninstall_media_list_observer( p_mlist, p_submlist );
103
104     for( i = 0; i < count; i++ )
105     {
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 );
109     }
110 }
111
112
113 /**************************************************************************
114  *       add_item (private) 
115  **************************************************************************/
116 static void
117 add_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
118 {
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 )
121     {
122         if( p_md->p_subitems )
123         {
124             add_media_list( p_mlist->p_flat_mlist, p_md->p_subitems );
125         }
126         else
127         {
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,
133                                                     p_md, NULL );
134             install_flat_mlist_observer( p_mlist );           
135         }
136     }
137 }
138
139 /**************************************************************************
140  *       remove_item (private) 
141  **************************************************************************/
142 static void
143 remove_item( libvlc_media_list_t * p_mlist, libvlc_media_descriptor_t * p_md )
144 {
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 );
154 }
155
156 /**************************************************************************
157  *       subitems_created (private) (Event Callback)
158  **************************************************************************/
159 static void
160 subitems_created( const libvlc_event_t * p_event , void * p_user_data)
161 {
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;
164
165     /* Remove the item and add the playlist */
166     remove_item( p_mlist->p_flat_mlist, p_md );
167
168     add_media_list( p_mlist->p_flat_mlist, p_md->p_subitems );
169 }
170
171 /**************************************************************************
172  *       sublist_item_added (private) (Event Callback)
173  *
174  * This is called if the dynamic sublist's data provider adds a new item.
175  **************************************************************************/
176 static void
177 sublist_item_added( const libvlc_event_t * p_event, void * p_user_data )
178 {
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 );
182 }
183
184 /**************************************************************************
185  *       sublist_remove_item (private) (Event Callback)
186  **************************************************************************/
187 static void
188 sublist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
189 {
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 );
193 }
194
195 /**************************************************************************
196  *       remove_item_in_submlist_rec (private)
197  **************************************************************************/
198 static void
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 )
202 {
203     libvlc_media_descriptor_t * p_md_insub;    
204     int count = libvlc_media_list_count( p_submlist, NULL );    
205     int i;
206     for( i = 0; i < count; i++ )
207     {
208         p_md_insub = libvlc_media_list_item_at_index( p_submlist,
209                                                       i, NULL );
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 )
213         {
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 );
217         }
218     }
219 }
220
221 /**************************************************************************
222  *       flat_mlist_item_removed (private) (Event Callback)
223  **************************************************************************/
224 static void
225 flat_mlist_item_removed( const libvlc_event_t * p_event, void * p_user_data )
226 {
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 );
232 }
233
234 /**************************************************************************
235  *       flat_mlist_item_added (private) (Event Callback)
236  **************************************************************************/
237 static void
238 flat_mlist_item_added( const libvlc_event_t * p_event, void * p_user_data )
239 {
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;
242
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 );
247 }
248
249 /**************************************************************************
250  *       install_flat_mlist_observer (Private)
251  **************************************************************************/
252 static void
253 install_flat_mlist_observer( libvlc_media_list_t * p_mlist )
254 {
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 );
261
262 }
263
264 /**************************************************************************
265  *       uninstall_flat_mlist_observer (Private)
266  **************************************************************************/
267 static void
268 uninstall_flat_mlist_observer( libvlc_media_list_t * p_mlist )
269 {
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 );
276
277 }
278
279 /*
280  * libvlc Internal functions
281  */
282 /**************************************************************************
283  *       flat_media_list_release (Internal)
284  **************************************************************************/
285 void
286 libvlc_media_list_flat_media_list_release( libvlc_media_list_t * p_mlist )
287 {
288     if( !p_mlist->p_flat_mlist )
289         return;
290     uninstall_flat_mlist_observer( p_mlist );
291     libvlc_media_list_release( p_mlist->p_flat_mlist );
292 }
293
294 /*
295  * Public libvlc functions
296  */
297
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 )
304 {
305     if( !p_mlist->p_flat_mlist )
306     {
307         p_mlist->p_flat_mlist = libvlc_media_list_new(
308                                             p_mlist->p_libvlc_instance,
309                                             p_e );
310         add_media_list( p_mlist, p_mlist );
311         install_flat_mlist_observer( p_mlist );
312     }
313     libvlc_media_list_retain( p_mlist->p_flat_mlist );
314     return p_mlist->p_flat_mlist;
315 }