]> git.sesse.net Git - vlc/blob - src/control/media_discoverer.c
libvlc_event_manager: remove exceptions
[vlc] / src / control / media_discoverer.c
1 /*****************************************************************************
2  * media_discoverer.c: libvlc new API media discoverer functions
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <assert.h>
29
30 #include <vlc/libvlc.h>
31 #include <vlc/libvlc_media.h>
32 #include <vlc/libvlc_media_list.h>
33 #include <vlc/libvlc_media_discoverer.h>
34 #include <vlc/libvlc_events.h>
35
36 #include <vlc_services_discovery.h>
37
38 #include "libvlc_internal.h"
39 #include "media_internal.h" // libvlc_media_new_from_input_item()
40 #include "media_list_internal.h" // _libvlc_media_list_add_media()
41
42 struct libvlc_media_discoverer_t
43 {
44     libvlc_event_manager_t * p_event_manager;
45     libvlc_instance_t *      p_libvlc_instance;
46     services_discovery_t *   p_sd;
47     libvlc_media_list_t *    p_mlist;
48     bool                     running;
49     vlc_dictionary_t         catname_to_submedialist;
50 };
51
52 /*
53  * Private functions
54  */
55
56 /**************************************************************************
57  *       services_discovery_item_added (Private) (VLC event callback)
58  **************************************************************************/
59
60 static void services_discovery_item_added( const vlc_event_t * p_event,
61                                            void * user_data )
62 {
63     input_item_t * p_item = p_event->u.services_discovery_item_added.p_new_item;
64     const char * psz_cat = p_event->u.services_discovery_item_added.psz_category;
65     libvlc_media_t * p_md;
66     libvlc_media_discoverer_t * p_mdis = user_data;
67     libvlc_media_list_t * p_mlist = p_mdis->p_mlist;
68
69     p_md = libvlc_media_new_from_input_item(
70             p_mdis->p_libvlc_instance,
71             p_item, NULL );
72
73     /* If we have a category, that mean we have to group the items having
74      * that category in a media_list. */
75     if( psz_cat )
76     {
77         p_mlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, psz_cat );
78
79         if( p_mlist == kVLCDictionaryNotFound )
80         {
81             libvlc_media_t * p_catmd;
82             p_catmd = libvlc_media_new_as_node( p_mdis->p_libvlc_instance, psz_cat, NULL );
83             p_mlist = libvlc_media_subitems( p_catmd );
84             p_mlist->b_read_only = true;
85
86             /* Insert the newly created mlist in our dictionary */
87             vlc_dictionary_insert( &p_mdis->catname_to_submedialist, psz_cat, p_mlist );
88
89             /* Insert the md into the root list */
90             libvlc_media_list_lock( p_mdis->p_mlist );
91             _libvlc_media_list_add_media( p_mdis->p_mlist, p_catmd );
92             libvlc_media_list_unlock( p_mdis->p_mlist );
93
94             /* We don't release the mlist cause the dictionary
95              * doesn't retain the object. But we release the md. */
96             libvlc_media_release( p_catmd );
97         }
98     }
99
100     libvlc_media_list_lock( p_mlist );
101     _libvlc_media_list_add_media( p_mlist, p_md );
102     libvlc_media_list_unlock( p_mlist );
103
104     libvlc_media_release( p_md );
105 }
106
107 /**************************************************************************
108  *       services_discovery_item_removed (Private) (VLC event callback)
109  **************************************************************************/
110
111 static void services_discovery_item_removed( const vlc_event_t * p_event,
112                                              void * user_data )
113 {
114     input_item_t * p_item = p_event->u.services_discovery_item_added.p_new_item;
115     libvlc_media_t * p_md;
116     libvlc_media_discoverer_t * p_mdis = user_data;
117
118     int i, count = libvlc_media_list_count( p_mdis->p_mlist );
119     libvlc_media_list_lock( p_mdis->p_mlist );
120     for( i = 0; i < count; i++ )
121     {
122         p_md = libvlc_media_list_item_at_index( p_mdis->p_mlist, i, NULL );
123         if( p_md->p_input_item == p_item )
124         {
125             _libvlc_media_list_remove_index( p_mdis->p_mlist, i, NULL );
126             break;
127         }
128     }
129     libvlc_media_list_unlock( p_mdis->p_mlist );
130 }
131
132 /**************************************************************************
133  *       services_discovery_started (Private) (VLC event callback)
134  **************************************************************************/
135
136 static void services_discovery_started( const vlc_event_t * p_event,
137                                         void * user_data )
138 {
139     VLC_UNUSED(p_event);
140     libvlc_media_discoverer_t * p_mdis = user_data;
141     libvlc_event_t event;
142     p_mdis->running = true;
143     event.type = libvlc_MediaDiscovererStarted;
144     libvlc_event_send( p_mdis->p_event_manager, &event );
145 }
146
147 /**************************************************************************
148  *       services_discovery_ended (Private) (VLC event callback)
149  **************************************************************************/
150
151 static void services_discovery_ended( const vlc_event_t * p_event,
152                                       void * user_data )
153 {
154     VLC_UNUSED(p_event);
155     libvlc_media_discoverer_t * p_mdis = user_data;
156     libvlc_event_t event;
157     p_mdis->running = false;
158     event.type = libvlc_MediaDiscovererEnded;
159     libvlc_event_send( p_mdis->p_event_manager, &event );
160 }
161
162 /*
163  * Public libvlc functions
164  */
165
166 /**************************************************************************
167  *       new (Public)
168  *
169  * Init an object.
170  **************************************************************************/
171 libvlc_media_discoverer_t *
172 libvlc_media_discoverer_new_from_name( libvlc_instance_t * p_inst,
173                                        const char * psz_name,
174                                        libvlc_exception_t * p_e )
175 {
176     libvlc_media_discoverer_t * p_mdis;
177
178     p_mdis = malloc(sizeof(libvlc_media_discoverer_t));
179     if( !p_mdis )
180     {
181         libvlc_exception_raise( p_e );
182         libvlc_printerr( "Not enough memory" );
183         return NULL;
184     }
185
186     p_mdis->p_libvlc_instance = p_inst;
187     p_mdis->p_mlist = libvlc_media_list_new( p_inst, NULL );
188     p_mdis->p_mlist->b_read_only = true;
189     p_mdis->running = false;
190
191     vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 );
192
193     p_mdis->p_event_manager = libvlc_event_manager_new( p_mdis, p_inst );
194     if( unlikely(p_mdis->p_event_manager == NULL) )
195     {
196         free( p_mdis );
197         return NULL;
198     }
199
200     libvlc_event_manager_register_event_type( p_mdis->p_event_manager,
201             libvlc_MediaDiscovererStarted );
202     libvlc_event_manager_register_event_type( p_mdis->p_event_manager,
203             libvlc_MediaDiscovererEnded );
204
205     p_mdis->p_sd = vlc_sd_Create( (vlc_object_t*)p_inst->p_libvlc_int );
206
207     if( !p_mdis->p_sd )
208     {
209         libvlc_media_list_release( p_mdis->p_mlist );
210         libvlc_exception_raise( p_e );
211         libvlc_printerr( "%s: no such discovery module found", psz_name );
212         free( p_mdis );
213         return NULL;
214     }
215
216     vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
217                       vlc_ServicesDiscoveryItemAdded,
218                       services_discovery_item_added,
219                       p_mdis );
220     vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
221                       vlc_ServicesDiscoveryItemRemoved,
222                       services_discovery_item_removed,
223                       p_mdis );
224     vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
225                       vlc_ServicesDiscoveryStarted,
226                       services_discovery_started,
227                       p_mdis );
228     vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ),
229                       vlc_ServicesDiscoveryEnded,
230                       services_discovery_ended,
231                       p_mdis );
232
233     /* Here we go */
234     if( !vlc_sd_Start( p_mdis->p_sd, psz_name ) )
235     {
236         libvlc_media_list_release( p_mdis->p_mlist );
237         libvlc_exception_raise( p_e );
238         libvlc_printerr( "%s: internal module error", psz_name );
239         free( p_mdis );
240         return NULL;
241     }
242
243     return p_mdis;
244 }
245
246 /**************************************************************************
247  * release (Public)
248  **************************************************************************/
249 void
250 libvlc_media_discoverer_release( libvlc_media_discoverer_t * p_mdis )
251 {
252     int i;
253
254     vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ),
255                      vlc_ServicesDiscoveryItemAdded,
256                      services_discovery_item_added,
257                      p_mdis );
258     vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ),
259                      vlc_ServicesDiscoveryItemRemoved,
260                      services_discovery_item_removed,
261                      p_mdis );
262     vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ),
263                      vlc_ServicesDiscoveryStarted,
264                      services_discovery_started,
265                      p_mdis );
266     vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ),
267                      vlc_ServicesDiscoveryEnded,
268                      services_discovery_ended,
269                      p_mdis );
270
271     libvlc_media_list_release( p_mdis->p_mlist );
272
273     vlc_sd_StopAndDestroy( p_mdis->p_sd );
274
275     /* Free catname_to_submedialist and all the mlist */
276     char ** all_keys = vlc_dictionary_all_keys( &p_mdis->catname_to_submedialist );
277     for( i = 0; all_keys[i]; i++ )
278     {
279         libvlc_media_list_t * p_catmlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, all_keys[i] );
280         libvlc_media_list_release( p_catmlist );
281         free( all_keys[i] );
282     }
283     free( all_keys );
284
285     vlc_dictionary_clear( &p_mdis->catname_to_submedialist, NULL, NULL );
286     libvlc_event_manager_release( p_mdis->p_event_manager );
287
288     free( p_mdis );
289 }
290
291 /**************************************************************************
292  * localized_name (Public)
293  **************************************************************************/
294 char *
295 libvlc_media_discoverer_localized_name( libvlc_media_discoverer_t * p_mdis )
296 {
297     return services_discovery_GetLocalizedName( p_mdis->p_sd );
298 }
299
300 /**************************************************************************
301  * media_list (Public)
302  **************************************************************************/
303 libvlc_media_list_t *
304 libvlc_media_discoverer_media_list( libvlc_media_discoverer_t * p_mdis )
305 {
306     libvlc_media_list_retain( p_mdis->p_mlist );
307     return p_mdis->p_mlist;
308 }
309
310 /**************************************************************************
311  * event_manager (Public)
312  **************************************************************************/
313 libvlc_event_manager_t *
314 libvlc_media_discoverer_event_manager( libvlc_media_discoverer_t * p_mdis )
315 {
316     return p_mdis->p_event_manager;
317 }
318
319
320 /**************************************************************************
321  * running (Public)
322  **************************************************************************/
323 int
324 libvlc_media_discoverer_is_running( libvlc_media_discoverer_t * p_mdis )
325 {
326     return p_mdis->running;
327 }