1 /*****************************************************************************
2 * hierarchical_node_media_list_view.c: libvlc hierarchical nodes media list
4 *****************************************************************************
5 * Copyright (C) 2007 the VideoLAN team
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 <vlc/libvlc.h>
26 #include <vlc/libvlc_media.h>
27 #include <vlc/libvlc_media_list.h>
28 #include <vlc/libvlc_media_list_view.h>
30 #include "media_internal.h" // Abuse, could ans should be removed
31 #include "media_list_internal.h" // Abuse, could ans should be removed
32 #include "media_list_view_internal.h"
34 /* FIXME: This version is probably a bit overheaded, and we may want to store
35 * the items in a vlc_array_t to speed everything up */
37 //#define DEBUG_HIERARCHICAL_VIEW
39 #ifdef DEBUG_HIERARCHICAL_VIEW
40 # define trace( fmt, ... ) printf( "[HIERARCHICAL_NODE] %s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
42 # define trace( ... ) {}
49 /**************************************************************************
50 * flat_media_list_view_count (private)
51 * (called by media_list_view_count)
52 **************************************************************************/
54 hierarch_node_media_list_view_count( libvlc_media_list_view_t * p_mlv,
55 libvlc_exception_t * p_e )
57 /* FIXME: we may want to cache that */
58 int i, ret, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
59 libvlc_media_t * p_md;
60 libvlc_media_list_t * p_submlist;
63 for( i = 0; i < count; i++ )
65 p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
67 p_submlist = libvlc_media_subitems( p_md, p_e );
68 if( !p_submlist ) continue;
69 libvlc_media_release( p_md );
70 libvlc_media_list_release( p_submlist );
76 /**************************************************************************
77 * flat_media_list_view_item_at_index (private)
78 * (called by flat_media_list_view_item_at_index)
79 **************************************************************************/
80 static libvlc_media_t *
81 hierarch_node_media_list_view_item_at_index( libvlc_media_list_view_t * p_mlv,
83 libvlc_exception_t * p_e )
85 /* FIXME: we may want to cache that */
86 libvlc_media_t * p_md;
87 libvlc_media_list_t * p_submlist;
89 int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
91 for( i = 0; i < count; i++ )
93 p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
95 p_submlist = libvlc_media_subitems( p_md, p_e );
96 if( !p_submlist ) continue;
97 libvlc_media_list_release( p_submlist );
99 if( current_index == index )
101 libvlc_media_release( p_md );
104 libvlc_exception_raise( p_e, "Index out of bound in Media List View" );
108 /**************************************************************************
109 * flat_media_list_view_item_at_index (private)
110 * (called by flat_media_list_view_item_at_index)
111 **************************************************************************/
112 static libvlc_media_list_view_t *
113 hierarch_node_media_list_view_children_at_index( libvlc_media_list_view_t * p_mlv,
115 libvlc_exception_t * p_e )
117 libvlc_media_t * p_md;
118 libvlc_media_list_t * p_submlist;
119 libvlc_media_list_view_t * p_ret;
120 p_md = hierarch_node_media_list_view_item_at_index( p_mlv, index, p_e );
121 if( !p_md ) return NULL;
122 p_submlist = libvlc_media_subitems( p_md, p_e );
123 libvlc_media_release( p_md );
124 if( !p_submlist ) return NULL;
125 p_ret = libvlc_media_list_hierarchical_node_view( p_submlist, p_e );
126 libvlc_media_list_release( p_submlist );
133 index_of_item( libvlc_media_list_view_t * p_mlv, libvlc_media_t * p_md )
135 libvlc_media_t * p_iter_md;
136 libvlc_media_list_t * p_submlist;
138 int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, NULL );
140 for( i = 0; i < count; i++ )
142 p_iter_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL );
143 if( !p_iter_md ) continue;
144 p_submlist = libvlc_media_subitems( p_iter_md, NULL );
145 if( !p_submlist ) continue;
146 libvlc_media_list_release( p_submlist );
147 libvlc_media_release( p_iter_md );
149 if( p_md == p_iter_md )
150 return current_index;
156 item_is_already_added( libvlc_media_t * p_md )
158 libvlc_media_list_t * p_submlist;
160 p_submlist = libvlc_media_subitems( p_md, NULL );
161 if( !p_submlist ) return false;
162 int count = libvlc_media_list_count( p_submlist, NULL );
163 libvlc_media_list_release( p_submlist );
168 /**************************************************************************
169 * media_list_(item|will)_* (private) (Event callback)
170 **************************************************************************/
172 items_subitems_added( const libvlc_event_t * p_event, void * user_data )
174 libvlc_media_t * p_md;
175 libvlc_media_list_view_t * p_mlv = user_data;
177 p_md = p_event->p_obj;
178 if( !item_is_already_added( p_md ) )
180 index = index_of_item( p_mlv, p_md );
181 trace("%d\n", index);
184 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
185 libvlc_media_list_view_item_added( p_mlv, p_md, index );
190 trace("item already added\n");
195 media_list_item_added( const libvlc_event_t * p_event, void * user_data )
197 libvlc_media_t * p_md;
198 libvlc_media_list_view_t * p_mlv = user_data;
200 p_md = p_event->u.media_list_item_added.item;
201 index = index_of_item( p_mlv, p_md );
202 trace("%d\n", index);
204 libvlc_media_list_view_item_added( p_mlv, p_md, index );
205 libvlc_event_attach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
206 items_subitems_added, p_mlv, NULL );
210 media_list_will_add_item( const libvlc_event_t * p_event, void * user_data )
212 libvlc_media_t * p_md;
213 libvlc_media_list_view_t * p_mlv = user_data;
215 p_md = p_event->u.media_list_will_add_item.item;
216 index = index_of_item( p_mlv, p_md );
217 trace("%d\n", index);
219 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
222 media_list_item_deleted( const libvlc_event_t * p_event, void * user_data )
224 libvlc_media_t * p_md;
225 libvlc_media_list_view_t * p_mlv = user_data;
227 p_md = p_event->u.media_list_item_deleted.item;
228 index = index_of_item( p_mlv, p_md );
229 trace("%d\n", index);
231 libvlc_media_list_view_item_deleted( p_mlv, p_md, index );
232 libvlc_event_detach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
233 items_subitems_added, p_mlv, NULL );
236 media_list_will_delete_item( const libvlc_event_t * p_event, void * user_data )
238 libvlc_media_t * p_md;
239 libvlc_media_list_view_t * p_mlv = user_data;
241 p_md = p_event->u.media_list_will_delete_item.item;
242 index = index_of_item( p_mlv, p_md );
243 trace("%d\n", index);
245 libvlc_media_list_view_will_delete_item( p_mlv, p_md, index );
250 * Public libvlc functions
254 /**************************************************************************
255 * flat_media_list_view_release (private)
256 * (called by media_list_view_release)
257 **************************************************************************/
259 hierarch_node_media_list_view_release( libvlc_media_list_view_t * p_mlv )
262 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
263 libvlc_MediaListItemAdded,
264 media_list_item_added, p_mlv, NULL );
265 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
266 libvlc_MediaListWillAddItem,
267 media_list_will_add_item, p_mlv, NULL );
268 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
269 libvlc_MediaListItemDeleted,
270 media_list_item_deleted, p_mlv, NULL );
271 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
272 libvlc_MediaListWillDeleteItem,
273 media_list_will_delete_item, p_mlv, NULL );
276 /**************************************************************************
277 * libvlc_media_list_flat_view (Public)
278 **************************************************************************/
279 libvlc_media_list_view_t *
280 libvlc_media_list_hierarchical_node_view( libvlc_media_list_t * p_mlist,
281 libvlc_exception_t * p_e )
284 libvlc_media_list_view_t * p_mlv;
285 p_mlv = libvlc_media_list_view_new( p_mlist,
286 hierarch_node_media_list_view_count,
287 hierarch_node_media_list_view_item_at_index,
288 hierarch_node_media_list_view_children_at_index,
289 libvlc_media_list_hierarchical_node_view,
290 hierarch_node_media_list_view_release,
293 libvlc_media_list_lock( p_mlist );
294 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
295 libvlc_MediaListItemAdded,
296 media_list_item_added, p_mlv, NULL );
297 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
298 libvlc_MediaListWillAddItem,
299 media_list_will_add_item, p_mlv, NULL );
300 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
301 libvlc_MediaListItemDeleted,
302 media_list_item_deleted, p_mlv, NULL );
303 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
304 libvlc_MediaListWillDeleteItem,
305 media_list_will_delete_item, p_mlv, NULL );
306 libvlc_media_list_unlock( p_mlist );