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 *****************************************************************************/
29 #include <vlc/libvlc.h>
30 #include <vlc/libvlc_media.h>
31 #include <vlc/libvlc_media_list.h>
32 #include <vlc/libvlc_media_list_view.h>
34 #include "media_internal.h" // Abuse, could ans should be removed
35 #include "media_list_internal.h" // Abuse, could ans should be removed
36 #include "media_list_view_internal.h"
38 /* FIXME: This version is probably a bit overheaded, and we may want to store
39 * the items in a vlc_array_t to speed everything up */
41 //#define DEBUG_HIERARCHICAL_VIEW
43 #ifdef DEBUG_HIERARCHICAL_VIEW
44 # define trace( fmt, ... ) printf( "[HIERARCHICAL_NODE] %s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
46 # define trace( ... ) {}
53 /**************************************************************************
54 * flat_media_list_view_count (private)
55 * (called by media_list_view_count)
56 **************************************************************************/
58 hierarch_node_media_list_view_count( libvlc_media_list_view_t * p_mlv,
59 libvlc_exception_t * p_e )
61 /* FIXME: we may want to cache that */
62 int i, ret, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
63 libvlc_media_t * p_md;
64 libvlc_media_list_t * p_submlist;
67 for( i = 0; i < count; i++ )
69 p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
71 p_submlist = libvlc_media_subitems( p_md, p_e );
72 if( !p_submlist ) continue;
73 libvlc_media_release( p_md );
74 libvlc_media_list_release( p_submlist );
80 /**************************************************************************
81 * flat_media_list_view_item_at_index (private)
82 * (called by flat_media_list_view_item_at_index)
83 **************************************************************************/
84 static libvlc_media_t *
85 hierarch_node_media_list_view_item_at_index( libvlc_media_list_view_t * p_mlv,
87 libvlc_exception_t * p_e )
89 /* FIXME: we may want to cache that */
90 libvlc_media_t * p_md;
91 libvlc_media_list_t * p_submlist;
93 int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, p_e );
95 for( i = 0; i < count; i++ )
97 p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
99 p_submlist = libvlc_media_subitems( p_md, p_e );
100 if( !p_submlist ) continue;
101 libvlc_media_list_release( p_submlist );
103 if( current_index == index )
105 libvlc_media_release( p_md );
108 libvlc_exception_raise( p_e, "Index out of bound in Media List View" );
112 /**************************************************************************
113 * flat_media_list_view_item_at_index (private)
114 * (called by flat_media_list_view_item_at_index)
115 **************************************************************************/
116 static libvlc_media_list_view_t *
117 hierarch_node_media_list_view_children_at_index( libvlc_media_list_view_t * p_mlv,
119 libvlc_exception_t * p_e )
121 libvlc_media_t * p_md;
122 libvlc_media_list_t * p_submlist;
123 libvlc_media_list_view_t * p_ret;
124 p_md = hierarch_node_media_list_view_item_at_index( p_mlv, index, p_e );
125 if( !p_md ) return NULL;
126 p_submlist = libvlc_media_subitems( p_md, p_e );
127 libvlc_media_release( p_md );
128 if( !p_submlist ) return NULL;
129 p_ret = libvlc_media_list_hierarchical_node_view( p_submlist, p_e );
130 libvlc_media_list_release( p_submlist );
137 index_of_item( libvlc_media_list_view_t * p_mlv, libvlc_media_t * p_md )
139 libvlc_media_t * p_iter_md;
140 libvlc_media_list_t * p_submlist;
142 int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist, NULL );
144 for( i = 0; i < count; i++ )
146 p_iter_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL );
147 if( !p_iter_md ) continue;
148 p_submlist = libvlc_media_subitems( p_iter_md, NULL );
149 if( !p_submlist ) continue;
150 libvlc_media_list_release( p_submlist );
151 libvlc_media_release( p_iter_md );
153 if( p_md == p_iter_md )
154 return current_index;
160 item_is_already_added( libvlc_media_t * p_md )
162 libvlc_media_list_t * p_submlist;
164 p_submlist = libvlc_media_subitems( p_md, NULL );
165 if( !p_submlist ) return false;
166 int count = libvlc_media_list_count( p_submlist, NULL );
167 libvlc_media_list_release( p_submlist );
172 /**************************************************************************
173 * media_list_(item|will)_* (private) (Event callback)
174 **************************************************************************/
176 items_subitems_added( const libvlc_event_t * p_event, void * user_data )
178 libvlc_media_t * p_md;
179 libvlc_media_list_view_t * p_mlv = user_data;
181 p_md = p_event->p_obj;
182 if( !item_is_already_added( p_md ) )
184 index = index_of_item( p_mlv, p_md );
185 trace("%d\n", index);
188 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
189 libvlc_media_list_view_item_added( p_mlv, p_md, index );
194 trace("item already added\n");
199 media_list_item_added( const libvlc_event_t * p_event, void * user_data )
201 libvlc_media_t * p_md;
202 libvlc_media_list_view_t * p_mlv = user_data;
204 p_md = p_event->u.media_list_item_added.item;
205 index = index_of_item( p_mlv, p_md );
206 trace("%d\n", index);
208 libvlc_media_list_view_item_added( p_mlv, p_md, index );
209 libvlc_event_attach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
210 items_subitems_added, p_mlv, NULL );
214 media_list_will_add_item( const libvlc_event_t * p_event, void * user_data )
216 libvlc_media_t * p_md;
217 libvlc_media_list_view_t * p_mlv = user_data;
219 p_md = p_event->u.media_list_will_add_item.item;
220 index = index_of_item( p_mlv, p_md );
221 trace("%d\n", index);
223 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
226 media_list_item_deleted( const libvlc_event_t * p_event, void * user_data )
228 libvlc_media_t * p_md;
229 libvlc_media_list_view_t * p_mlv = user_data;
231 p_md = p_event->u.media_list_item_deleted.item;
232 index = index_of_item( p_mlv, p_md );
233 trace("%d\n", index);
235 libvlc_media_list_view_item_deleted( p_mlv, p_md, index );
236 libvlc_event_detach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
237 items_subitems_added, p_mlv, NULL );
240 media_list_will_delete_item( const libvlc_event_t * p_event, void * user_data )
242 libvlc_media_t * p_md;
243 libvlc_media_list_view_t * p_mlv = user_data;
245 p_md = p_event->u.media_list_will_delete_item.item;
246 index = index_of_item( p_mlv, p_md );
247 trace("%d\n", index);
249 libvlc_media_list_view_will_delete_item( p_mlv, p_md, index );
254 * Public libvlc functions
258 /**************************************************************************
259 * flat_media_list_view_release (private)
260 * (called by media_list_view_release)
261 **************************************************************************/
263 hierarch_node_media_list_view_release( libvlc_media_list_view_t * p_mlv )
266 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
267 libvlc_MediaListItemAdded,
268 media_list_item_added, p_mlv, NULL );
269 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
270 libvlc_MediaListWillAddItem,
271 media_list_will_add_item, p_mlv, NULL );
272 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
273 libvlc_MediaListItemDeleted,
274 media_list_item_deleted, p_mlv, NULL );
275 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
276 libvlc_MediaListWillDeleteItem,
277 media_list_will_delete_item, p_mlv, NULL );
280 /**************************************************************************
281 * libvlc_media_list_flat_view (Public)
282 **************************************************************************/
283 libvlc_media_list_view_t *
284 libvlc_media_list_hierarchical_node_view( libvlc_media_list_t * p_mlist,
285 libvlc_exception_t * p_e )
288 libvlc_media_list_view_t * p_mlv;
289 p_mlv = libvlc_media_list_view_new( p_mlist,
290 hierarch_node_media_list_view_count,
291 hierarch_node_media_list_view_item_at_index,
292 hierarch_node_media_list_view_children_at_index,
293 libvlc_media_list_hierarchical_node_view,
294 hierarch_node_media_list_view_release,
297 libvlc_media_list_lock( p_mlist );
298 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
299 libvlc_MediaListItemAdded,
300 media_list_item_added, p_mlv, NULL );
301 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
302 libvlc_MediaListWillAddItem,
303 media_list_will_add_item, p_mlv, NULL );
304 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
305 libvlc_MediaListItemDeleted,
306 media_list_item_deleted, p_mlv, NULL );
307 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
308 libvlc_MediaListWillDeleteItem,
309 media_list_will_delete_item, p_mlv, NULL );
310 libvlc_media_list_unlock( p_mlist );