]> git.sesse.net Git - vlc/blob - src/control/hierarchical_node_media_list_view.c
update module LIST file.
[vlc] / src / control / hierarchical_node_media_list_view.c
1 /*****************************************************************************
2  * hierarchical_node_media_list_view.c: libvlc hierarchical nodes media list
3  * view functs.
4  *****************************************************************************
5  * Copyright (C) 2007 the VideoLAN team
6  * $Id$
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 /* FIXME: This version is probably a bit overheaded, and we may want to store
31  * the items in a vlc_array_t to speed everything up */
32
33 //#define DEBUG_HIERARCHICAL_VIEW
34
35 #ifdef DEBUG_HIERARCHICAL_VIEW
36 # define trace( fmt, ... ) printf( "[HIERARCHICAL_NODE] %s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
37 #else
38 # define trace( ... ) {}
39 #endif
40
41 struct libvlc_media_list_view_private_t
42 {
43     vlc_array_t array;
44 };
45
46 /*
47  * Private functions
48  */
49
50 /**************************************************************************
51  *       flat_media_list_view_count  (private)
52  * (called by media_list_view_count)
53  **************************************************************************/
54 static int
55 hierarch_node_media_list_view_count( libvlc_media_list_view_t * p_mlv,
56                                 libvlc_exception_t * p_e )
57 {
58     /* FIXME: we may want to cache that */
59     int i, ret, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
60     libvlc_media_t * p_md;
61     libvlc_media_list_t * p_submlist;
62     ret = 0;
63     trace("\n");
64     for( i = 0; i < count; i++ )
65     {
66         p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
67         if( !p_md ) continue;
68         p_submlist = libvlc_media_subitems( p_md, p_e );
69         if( !p_submlist ) continue;
70         libvlc_media_release( p_md );
71         libvlc_media_list_release( p_submlist );
72         ret++;
73     }
74     return ret;
75 }
76
77 /**************************************************************************
78  *       flat_media_list_view_item_at_index  (private)
79  * (called by flat_media_list_view_item_at_index)
80  **************************************************************************/
81 static libvlc_media_t *
82 hierarch_node_media_list_view_item_at_index( libvlc_media_list_view_t * p_mlv,
83                                         int index,
84                                         libvlc_exception_t * p_e )
85 {
86     /* FIXME: we may want to cache that */
87     libvlc_media_t * p_md;
88     libvlc_media_list_t * p_submlist;
89     trace("%d\n", index);
90     int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
91     current_index = -1;
92     for( i = 0; i < count; i++ )
93     {
94         p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
95         if( !p_md ) continue;
96         p_submlist = libvlc_media_subitems( p_md, p_e );
97         if( !p_submlist ) continue;
98         libvlc_media_list_release( p_submlist );
99         current_index++;
100         if( current_index == index )
101             return p_md;
102         libvlc_media_release( p_md );
103     }
104
105     libvlc_exception_raise( p_e, "Index out of bound in Media List View" );
106     return NULL;
107 }
108
109 /**************************************************************************
110  *       flat_media_list_view_item_at_index  (private)
111  * (called by flat_media_list_view_item_at_index)
112  **************************************************************************/
113 static libvlc_media_list_view_t *
114 hierarch_node_media_list_view_children_at_index( libvlc_media_list_view_t * p_mlv,
115                                             int index,
116                                             libvlc_exception_t * p_e )
117 {
118     libvlc_media_t * p_md;
119     libvlc_media_list_t * p_submlist;
120     libvlc_media_list_view_t * p_ret;
121     p_md = hierarch_node_media_list_view_item_at_index( p_mlv, index, p_e );
122     if( !p_md ) return NULL;
123     p_submlist = libvlc_media_subitems( p_md, p_e );
124     libvlc_media_release( p_md );
125     if( !p_submlist ) return NULL;
126     p_ret = libvlc_media_list_hierarchical_node_view( p_submlist, p_e );
127     libvlc_media_list_release( p_submlist );
128
129     return p_ret;
130 }
131
132 /* Helper */
133 static int
134 index_of_item( libvlc_media_list_view_t * p_mlv, libvlc_media_t * p_md )
135 {
136     libvlc_media_t * p_iter_md;
137     libvlc_media_list_t * p_submlist;
138
139     int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, NULL );
140     current_index = -1;
141     for( i = 0; i < count; i++ )
142     {
143         p_iter_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL );
144         if( !p_iter_md ) continue;
145         p_submlist = libvlc_media_subitems( p_iter_md, NULL );
146         if( !p_submlist ) continue;
147         libvlc_media_list_release( p_submlist );
148         libvlc_media_release( p_iter_md );
149         current_index++;
150         if( p_md == p_iter_md )
151             return current_index;
152     }
153     return -1;
154 }
155
156 static vlc_bool_t
157 item_is_already_added( libvlc_media_t * p_md )
158 {
159     libvlc_media_list_t * p_submlist;
160
161     p_submlist = libvlc_media_subitems( p_md, NULL );
162     if( !p_submlist ) return VLC_FALSE;
163     int count = libvlc_media_list_count( p_submlist, NULL );
164     libvlc_media_list_release( p_submlist );
165     return count > 1;
166 }
167
168
169 /**************************************************************************
170  *       media_list_(item|will)_* (private) (Event callback)
171  **************************************************************************/
172 static void
173 items_subitems_added( const libvlc_event_t * p_event, void * user_data )
174 {
175     libvlc_media_t * p_md;
176     libvlc_media_list_view_t * p_mlv = user_data;
177     int index;
178     p_md = p_event->p_obj;
179     if( !item_is_already_added( p_md ) )
180     {
181         index = index_of_item( p_mlv, p_md );
182         trace("%d\n", index);
183         if( index >= 0 )
184         {
185             libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
186             libvlc_media_list_view_item_added( p_mlv, p_md, index );
187         }
188     }
189     else
190     {
191         trace("item already added\n");
192     }
193 }
194
195 static void
196 media_list_item_added( const libvlc_event_t * p_event, void * user_data )
197 {
198     libvlc_media_t * p_md;
199     libvlc_media_list_view_t * p_mlv = user_data;
200     int index;
201     p_md = p_event->u.media_list_item_added.item;
202     index = index_of_item( p_mlv, p_md );
203     trace("%d\n", index);
204     if( index >= 0)
205         libvlc_media_list_view_item_added( p_mlv, p_md, index );
206     libvlc_event_attach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
207                          items_subitems_added, p_mlv, NULL );
208                          
209 }
210 static void
211 media_list_will_add_item( const libvlc_event_t * p_event, void * user_data )
212 {
213     libvlc_media_t * p_md;
214     libvlc_media_list_view_t * p_mlv = user_data;
215     int index;
216     p_md = p_event->u.media_list_will_add_item.item;
217     index = index_of_item( p_mlv, p_md );
218     trace("%d\n", index);
219     if( index >= 0)
220         libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
221 }
222 static void
223 media_list_item_deleted( const libvlc_event_t * p_event, void * user_data )
224 {
225     libvlc_media_t * p_md;
226     libvlc_media_list_view_t * p_mlv = user_data;
227     int index;
228     p_md = p_event->u.media_list_item_deleted.item;
229     index = index_of_item( p_mlv, p_md );
230     trace("%d\n", index);
231     if( index >= 0)
232         libvlc_media_list_view_item_deleted( p_mlv, p_md, index );
233     libvlc_event_detach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
234                          items_subitems_added, p_mlv, NULL );
235 }
236 static void
237 media_list_will_delete_item( const libvlc_event_t * p_event, void * user_data )
238 {
239     libvlc_media_t * p_md;
240     libvlc_media_list_view_t * p_mlv = user_data;
241     int index;
242     p_md = p_event->u.media_list_will_delete_item.item;
243     index = index_of_item( p_mlv, p_md );
244     trace("%d\n", index);
245     if( index >= 0)
246         libvlc_media_list_view_will_delete_item( p_mlv, p_md, index );
247 }
248
249
250 /*
251  * Public libvlc functions
252  */
253
254
255 /**************************************************************************
256  *       flat_media_list_view_release (private)
257  * (called by media_list_view_release)
258  **************************************************************************/
259 static void
260 hierarch_node_media_list_view_release( libvlc_media_list_view_t * p_mlv )
261 {
262     trace("\n");
263     libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
264                          libvlc_MediaListItemAdded,
265                          media_list_item_added, p_mlv, NULL );
266     libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
267                          libvlc_MediaListWillAddItem,
268                          media_list_will_add_item, p_mlv, NULL );
269     libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
270                          libvlc_MediaListItemDeleted,
271                          media_list_item_deleted, p_mlv, NULL );
272     libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
273                          libvlc_MediaListWillDeleteItem,
274                          media_list_will_delete_item, p_mlv, NULL );
275 }
276
277 /**************************************************************************
278  *       libvlc_media_list_flat_view (Public)
279  **************************************************************************/
280 libvlc_media_list_view_t *
281 libvlc_media_list_hierarchical_node_view( libvlc_media_list_t * p_mlist,
282                                      libvlc_exception_t * p_e )
283 {
284     trace("\n");
285     libvlc_media_list_view_t * p_mlv;
286     p_mlv = libvlc_media_list_view_new( p_mlist,
287                                         hierarch_node_media_list_view_count,
288                                         hierarch_node_media_list_view_item_at_index,
289                                         hierarch_node_media_list_view_children_at_index,
290                                         libvlc_media_list_hierarchical_node_view,
291                                         hierarch_node_media_list_view_release,
292                                         NULL,
293                                         p_e );
294     libvlc_media_list_lock( p_mlist );
295     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
296                          libvlc_MediaListItemAdded,
297                          media_list_item_added, p_mlv, NULL );
298     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
299                          libvlc_MediaListWillAddItem,
300                          media_list_will_add_item, p_mlv, NULL );
301     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
302                          libvlc_MediaListItemDeleted,
303                          media_list_item_deleted, p_mlv, NULL );
304     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
305                          libvlc_MediaListWillDeleteItem,
306                          media_list_will_delete_item, p_mlv, NULL );
307     libvlc_media_list_unlock( p_mlist );
308     return p_mlv;
309 }