]> git.sesse.net Git - vlc/blob - src/control/hierarchical_node_media_list_view.c
03b8fa75dd590982eb53fe369c57e621251e6fcb
[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 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
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>
33
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"
37
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 */
40
41 //#define DEBUG_HIERARCHICAL_VIEW
42
43 #ifdef DEBUG_HIERARCHICAL_VIEW
44 # define trace( fmt, ... ) printf( "[HIERARCHICAL_NODE] %s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
45 #else
46 # define trace( ... ) {}
47 #endif
48
49 /*
50  * Private functions
51  */
52
53 /**************************************************************************
54  *       flat_media_list_view_count  (private)
55  * (called by media_list_view_count)
56  **************************************************************************/
57 static int
58 hierarch_node_media_list_view_count( libvlc_media_list_view_t * p_mlv,
59                                 libvlc_exception_t * p_e )
60 {
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;
65     ret = 0;
66     trace("\n");
67     for( i = 0; i < count; i++ )
68     {
69         p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
70         if( !p_md ) continue;
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 );
75         ret++;
76     }
77     return ret;
78 }
79
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,
86                                         int index,
87                                         libvlc_exception_t * p_e )
88 {
89     /* FIXME: we may want to cache that */
90     libvlc_media_t * p_md;
91     libvlc_media_list_t * p_submlist;
92     trace("%d\n", index);
93     int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist );
94     current_index = -1;
95     for( i = 0; i < count; i++ )
96     {
97         p_md = libvlc_media_list_item_at_index( p_mlv->p_mlist, i, p_e );
98         if( !p_md ) continue;
99         p_submlist = libvlc_media_subitems( p_md );
100         if( !p_submlist ) continue;
101         libvlc_media_list_release( p_submlist );
102         current_index++;
103         if( current_index == index )
104             return p_md;
105         libvlc_media_release( p_md );
106     }
107
108     libvlc_exception_raise( p_e );
109     libvlc_printerr( "Index out of bound in Media List View" );
110     return NULL;
111 }
112
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,
119                                             int index,
120                                             libvlc_exception_t * p_e )
121 {
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, p_e );
131     libvlc_media_list_release( p_submlist );
132
133     return p_ret;
134 }
135
136 /* Helper */
137 static int
138 index_of_item( libvlc_media_list_view_t * p_mlv, libvlc_media_t * p_md )
139 {
140     libvlc_media_t * p_iter_md;
141     libvlc_media_list_t * p_submlist;
142
143     int i, current_index, count = libvlc_media_list_count( p_mlv->p_mlist );
144     current_index = -1;
145     for( i = 0; i < count; i++ )
146     {
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 );
153         current_index++;
154         if( p_md == p_iter_md )
155             return current_index;
156     }
157     return -1;
158 }
159
160 static bool
161 item_is_already_added( libvlc_media_t * p_md )
162 {
163     libvlc_media_list_t * p_submlist;
164
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 );
169     return count > 1;
170 }
171
172
173 /**************************************************************************
174  *       media_list_(item|will)_* (private) (Event callback)
175  **************************************************************************/
176 static void
177 items_subitems_added( const libvlc_event_t * p_event, void * user_data )
178 {
179     libvlc_media_t * p_md;
180     libvlc_media_list_view_t * p_mlv = user_data;
181     int index;
182     p_md = p_event->p_obj;
183     if( !item_is_already_added( p_md ) )
184     {
185         index = index_of_item( p_mlv, p_md );
186         trace("%d\n", index);
187         if( index >= 0 )
188         {
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 );
191         }
192     }
193     else
194     {
195         trace("item already added\n");
196     }
197 }
198
199 static void
200 media_list_item_added( const libvlc_event_t * p_event, void * user_data )
201 {
202     libvlc_media_t * p_md;
203     libvlc_media_list_view_t * p_mlv = user_data;
204     int index;
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);
208     if( index >= 0)
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 );
212                          
213 }
214 static void
215 media_list_will_add_item( const libvlc_event_t * p_event, void * user_data )
216 {
217     libvlc_media_t * p_md;
218     libvlc_media_list_view_t * p_mlv = user_data;
219     int index;
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);
223     if( index >= 0)
224         libvlc_media_list_view_will_add_item( p_mlv, p_md, index );
225 }
226 static void
227 media_list_item_deleted( const libvlc_event_t * p_event, void * user_data )
228 {
229     libvlc_media_t * p_md;
230     libvlc_media_list_view_t * p_mlv = user_data;
231     int index;
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);
235     if( index >= 0)
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 );
239 }
240 static void
241 media_list_will_delete_item( const libvlc_event_t * p_event, void * user_data )
242 {
243     libvlc_media_t * p_md;
244     libvlc_media_list_view_t * p_mlv = user_data;
245     int index;
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);
249     if( index >= 0)
250         libvlc_media_list_view_will_delete_item( p_mlv, p_md, index );
251 }
252
253
254 /*
255  * Public libvlc functions
256  */
257
258
259 /**************************************************************************
260  *       flat_media_list_view_release (private)
261  * (called by media_list_view_release)
262  **************************************************************************/
263 static void
264 hierarch_node_media_list_view_release( libvlc_media_list_view_t * p_mlv )
265 {
266     trace("\n");
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 );
279 }
280
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,
286                                      libvlc_exception_t * p_e )
287 {
288     trace("\n");
289     libvlc_media_list_view_t * p_mlv;
290     p_mlv = libvlc_media_list_view_new( p_mlist,
291                                         hierarch_node_media_list_view_count,
292                                         hierarch_node_media_list_view_item_at_index,
293                                         hierarch_node_media_list_view_children_at_index,
294                                         libvlc_media_list_hierarchical_node_view,
295                                         hierarch_node_media_list_view_release,
296                                         NULL,
297                                         p_e );
298     libvlc_media_list_lock( p_mlist );
299     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
300                          libvlc_MediaListItemAdded,
301                          media_list_item_added, p_mlv );
302     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
303                          libvlc_MediaListWillAddItem,
304                          media_list_will_add_item, p_mlv );
305     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
306                          libvlc_MediaListItemDeleted,
307                          media_list_item_deleted, p_mlv );
308     libvlc_event_attach( p_mlv->p_mlist->p_event_manager,
309                          libvlc_MediaListWillDeleteItem,
310                          media_list_will_delete_item, p_mlv );
311     libvlc_media_list_unlock( p_mlist );
312     return p_mlv;
313 }