1 /*****************************************************************************
2 * dynamic_media_list.c: libvlc new API media list functions
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #include "libvlc_internal.h"
25 #include <vlc/libvlc.h>
27 #include "vlc_arrays.h"
29 static const char * libvlc_default_dynamic_media_list_tag_key = "VLCPlaylist";
35 /**************************************************************************
36 * own_media_list_item_added (private) (Event Callback)
37 **************************************************************************/
39 own_media_list_item_added( const libvlc_event_t * p_event, void * p_user_data )
42 libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
43 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
45 if( !p_dmlist->tag || !p_dmlist->psz_tag_key )
48 libvlc_media_descriptor_add_tag( p_md, p_dmlist->tag,
49 p_dmlist->psz_tag_key, NULL );
52 /**************************************************************************
53 * own_media_list_item_removed (private) (Event Callback)
54 **************************************************************************/
56 own_media_list_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
59 libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
60 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
62 if( !p_dmlist->tag || !p_dmlist->psz_tag_key )
65 libvlc_media_descriptor_remove_tag( p_md, p_dmlist->tag,
66 p_dmlist->psz_tag_key, NULL );
70 /**************************************************************************
71 * dynamic_list_propose_item (private) (Event Callback)
73 * This is called if the dynamic sublist's data provider adds a new item.
74 **************************************************************************/
76 dynamic_list_propose_item( const libvlc_event_t * p_event, void * p_user_data )
78 /* Check if the item matches our tag query */
79 libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
80 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_added.item;
82 //libvlc_media_descriptor_lock( p_md );
83 if( libvlc_tag_query_match( p_dmlist->p_query, p_md, NULL ) )
85 int i = libvlc_media_list_index_of_item( p_dmlist->p_mlist, p_md, NULL );
88 /* We already have it */
89 libvlc_media_list_unlock( p_dmlist->p_mlist );
93 libvlc_media_list_lock( p_dmlist->p_mlist );
94 libvlc_media_list_add_media_descriptor( p_dmlist->p_mlist, p_md, NULL );
95 libvlc_media_list_unlock( p_dmlist->p_mlist );
97 //libvlc_media_descriptor_unlock( p_md );
100 /**************************************************************************
101 * dynamic_list_remove_item (private) (Event Callback)
103 * This is called if the dynamic sublist's data provider adds a new item.
104 **************************************************************************/
106 dynamic_list_remove_item( const libvlc_event_t * p_event, void * p_user_data )
108 /* Remove the item here too if we have it */
109 libvlc_dynamic_media_list_t * p_dmlist = p_user_data;
110 libvlc_media_descriptor_t * p_md = p_event->u.media_list_item_deleted.item;
112 //libvlc_media_descriptor_lock( p_md );
113 if( libvlc_tag_query_match( p_dmlist->p_query, p_md, NULL ) )
116 libvlc_media_list_lock( p_dmlist->p_mlist );
117 i = libvlc_media_list_index_of_item( p_dmlist->p_mlist, p_md, NULL );
120 /* We've missed one item addition, that could happen especially
121 * if we add item in a threaded maner, so we just ignore */
122 libvlc_media_list_unlock( p_dmlist->p_mlist );
123 //libvlc_media_descriptor_unlock( p_md );
126 libvlc_media_list_remove_index( p_dmlist->p_mlist, i, NULL );
127 libvlc_media_list_unlock( p_dmlist->p_mlist );
129 //libvlc_media_descriptor_unlock( p_md );
133 * Public libvlc functions
136 /**************************************************************************
138 **************************************************************************/
139 libvlc_dynamic_media_list_t *
140 libvlc_dynamic_media_list_new(
141 libvlc_media_list_t * p_mlist,
142 libvlc_tag_query_t * p_query,
144 libvlc_exception_t * p_e )
146 libvlc_dynamic_media_list_t * p_dmlist;
147 libvlc_event_manager_t * p_em;
152 p_dmlist = malloc(sizeof(libvlc_dynamic_media_list_t));
157 p_dmlist->i_refcount = 1;
158 p_dmlist->p_libvlc_instance = p_mlist->p_libvlc_instance;
159 p_dmlist->tag = strdup( tag );
160 p_dmlist->psz_tag_key = strdup( libvlc_default_dynamic_media_list_tag_key );
162 p_dmlist->p_mlist = libvlc_media_list_new( p_mlist->p_libvlc_instance, p_e );
163 if( !p_dmlist->p_mlist )
165 if( !libvlc_exception_raised( p_e ) )
166 libvlc_exception_raise( p_e, "Can't get the new media_list" );
170 /* We have a query */
171 libvlc_tag_query_retain( p_query );
172 p_dmlist->p_query = p_query;
174 /* We have a media provider */
175 libvlc_media_list_retain( p_mlist );
176 p_dmlist->p_media_provider = p_mlist;
178 libvlc_media_list_lock( p_mlist );
180 count = libvlc_media_list_count( p_mlist, p_e );
182 /* This should be running in a thread, a good plan to achieve that
183 * move all the dynamic code to libvlc_tag_query. */
184 for( i = 0; i < count; i++ )
186 libvlc_media_descriptor_t * p_md;
187 p_md = libvlc_media_list_item_at_index( p_mlist, i, p_e );
188 if( libvlc_tag_query_match( p_query, p_md, NULL ) )
189 libvlc_media_list_add_media_descriptor( p_dmlist->p_mlist, p_md, p_e );
192 /* And we will listen to its event, so we can update p_dmlist->p_mlist
194 p_em = libvlc_media_list_event_manager( p_mlist, p_e );
195 libvlc_event_attach( p_em, libvlc_MediaListItemAdded,
196 dynamic_list_propose_item, p_dmlist, p_e );
197 libvlc_event_attach( p_em, libvlc_MediaListItemDeleted,
198 dynamic_list_remove_item, p_dmlist, p_e );
200 libvlc_media_list_unlock( p_mlist );
202 /* Make sure item added/removed will gain/loose our mark */
203 p_em = libvlc_media_list_event_manager( p_dmlist->p_mlist, p_e );
204 libvlc_event_attach( p_em, libvlc_MediaListItemAdded,
205 own_media_list_item_added, p_dmlist, p_e );
206 libvlc_event_attach( p_em, libvlc_MediaListItemDeleted,
207 own_media_list_item_deleted, p_dmlist, p_e );
213 /**************************************************************************
217 **************************************************************************/
218 void libvlc_dynamic_media_list_release( libvlc_dynamic_media_list_t * p_dmlist )
220 p_dmlist->i_refcount--;
221 if( p_dmlist->i_refcount > 0 )
224 free( p_dmlist->tag );
225 free( p_dmlist->psz_tag_key );
227 /* Refcount null, time to free */
228 if( p_dmlist->p_media_provider )
229 libvlc_media_list_release( p_dmlist->p_media_provider );
231 if( p_dmlist->p_query )
232 libvlc_tag_query_release( p_dmlist->p_query );
237 /**************************************************************************
239 **************************************************************************/
240 void libvlc_dynamic_media_list_retain( libvlc_dynamic_media_list_t * p_dmlist )
242 p_dmlist->i_refcount++;
246 /**************************************************************************
247 * media_list (Public)
248 **************************************************************************/
249 libvlc_media_list_t *
250 libvlc_dynamic_media_list_media_list(
251 libvlc_dynamic_media_list_t * p_dmlist,
252 libvlc_exception_t * p_e )
254 libvlc_media_list_retain( p_dmlist->p_mlist );
255 return p_dmlist->p_mlist;