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 );
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 );
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 );
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 );
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 );
109 libvlc_printerr( "Index out of bound in Media List View" );
113 /**************************************************************************
114 * flat_media_list_view_item_at_index (private)
115 * (called by flat_media_list_view_item_at_index)
116 **************************************************************************/
117 static libvlc_media_list_view_t *
118 hierarch_node_media_list_view_children_at_index( libvlc_media_list_view_t * p_mlv,
120 libvlc_exception_t * p_e )
122 libvlc_media_t * p_md;
123 libvlc_media_list_t * p_submlist;
124 libvlc_media_list_view_t * p_ret;
125 p_md = hierarch_node_media_list_view_item_at_index( p_mlv, index, p_e );
126 if( !p_md ) return NULL;
127 p_submlist = libvlc_media_subitems( p_md );
128 libvlc_media_release( p_md );
129 if( !p_submlist ) return NULL;
130 p_ret = libvlc_media_list_hierarchical_node_view( p_submlist );
131 libvlc_media_list_release( p_submlist );
138 index_of_item( libvlc_media_list_view_t * p_mlv, libvlc_media_t * p_md )
140 libvlc_media_t * p_iter_md;
141 libvlc_media_list_t * p_submlist;
143 int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist );
145 for( i = 0; i < count; i++ )
147 p_iter_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, NULL );
148 if( !p_iter_md ) continue;
149 p_submlist = libvlc_media_subitems( p_iter_md );
150 if( !p_submlist ) continue;
151 libvlc_media_list_release( p_submlist );
152 libvlc_media_release( p_iter_md );
154 if( p_md == p_iter_md )
155 return current_index;
161 item_is_already_added( libvlc_media_t * p_md )
163 libvlc_media_list_t * p_submlist;
165 p_submlist = libvlc_media_subitems( p_md );
166 if( !p_submlist ) return false;
167 int count = libvlc_media_list_count( p_submlist );
168 libvlc_media_list_release( p_submlist );
173 /**************************************************************************
174 * media_list_(item|will)_* (private) (Event callback)
175 **************************************************************************/
177 items_subitems_added( const libvlc_event_t * p_event, void * user_data )
179 libvlc_media_t * p_md;
180 libvlc_media_list_view_t * p_mlv = user_data;
182 p_md = p_event->p_obj;
183 if( !item_is_already_added( p_md ) )
185 index = index_of_item( p_mlv, p_md );
186 trace("%d\n", index);
189 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
190 libvlc_media_list_view_item_added( p_mlv, p_md, index );
195 trace("item already added\n");
200 media_list_item_added( const libvlc_event_t * p_event, void * user_data )
202 libvlc_media_t * p_md;
203 libvlc_media_list_view_t * p_mlv = user_data;
205 p_md = p_event->u.media_list_item_added.item;
206 index = index_of_item( p_mlv, p_md );
207 trace("%d\n", index);
209 libvlc_media_list_view_item_added( p_mlv, p_md, index );
210 libvlc_event_attach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
211 items_subitems_added, p_mlv );
215 media_list_will_add_item( const libvlc_event_t * p_event, void * user_data )
217 libvlc_media_t * p_md;
218 libvlc_media_list_view_t * p_mlv = user_data;
220 p_md = p_event->u.media_list_will_add_item.item;
221 index = index_of_item( p_mlv, p_md );
222 trace("%d\n", index);
224 libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
227 media_list_item_deleted( const libvlc_event_t * p_event, void * user_data )
229 libvlc_media_t * p_md;
230 libvlc_media_list_view_t * p_mlv = user_data;
232 p_md = p_event->u.media_list_item_deleted.item;
233 index = index_of_item( p_mlv, p_md );
234 trace("%d\n", index);
236 libvlc_media_list_view_item_deleted( p_mlv, p_md, index );
237 libvlc_event_detach( p_md->p_event_manager, libvlc_MediaSubItemAdded,
238 items_subitems_added, p_mlv );
241 media_list_will_delete_item( const libvlc_event_t * p_event, void * user_data )
243 libvlc_media_t * p_md;
244 libvlc_media_list_view_t * p_mlv = user_data;
246 p_md = p_event->u.media_list_will_delete_item.item;
247 index = index_of_item( p_mlv, p_md );
248 trace("%d\n", index);
250 libvlc_media_list_view_will_delete_item( p_mlv, p_md, index );
255 * Public libvlc functions
259 /**************************************************************************
260 * flat_media_list_view_release (private)
261 * (called by media_list_view_release)
262 **************************************************************************/
264 hierarch_node_media_list_view_release( libvlc_media_list_view_t * p_mlv )
267 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
268 libvlc_MediaListItemAdded,
269 media_list_item_added, p_mlv );
270 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
271 libvlc_MediaListWillAddItem,
272 media_list_will_add_item, p_mlv );
273 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
274 libvlc_MediaListItemDeleted,
275 media_list_item_deleted, p_mlv );
276 libvlc_event_detach( p_mlv->p_mlist->p_event_manager,
277 libvlc_MediaListWillDeleteItem,
278 media_list_will_delete_item, p_mlv );
281 /**************************************************************************
282 * libvlc_media_list_flat_view (Public)
283 **************************************************************************/
284 libvlc_media_list_view_t *
285 libvlc_media_list_hierarchical_node_view( libvlc_media_list_t * p_mlist )
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,
296 libvlc_media_list_lock( p_mlist );
297 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
298 libvlc_MediaListItemAdded,
299 media_list_item_added, p_mlv );
300 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
301 libvlc_MediaListWillAddItem,
302 media_list_will_add_item, p_mlv );
303 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
304 libvlc_MediaListItemDeleted,
305 media_list_item_deleted, p_mlv );
306 libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
307 libvlc_MediaListWillDeleteItem,
308 media_list_will_delete_item, p_mlv );
309 libvlc_media_list_unlock( p_mlist );