]> git.sesse.net Git - vlc/blob - src/control/vlm.c
libvlc_vlm_release : release events stuff Centralize vlm release operations in one...
[vlc] / src / control / vlm.c
1 /*****************************************************************************
2  * vlm.c: libvlc new API VLM handling functions
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@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 #include <vlc/libvlc.h>
25 #include <vlc/libvlc_vlm.h>
26 #include <vlc_es.h>
27 #include <vlc_input.h>
28 #include <vlc_vlm.h>
29
30 #include "libvlc_internal.h"
31
32 #if 0
33 /* local function to be used in libvlc_vlm_show_media only */
34 static char* recurse_answer( char* psz_prefix, vlm_message_t *p_answer ) {
35     char* psz_childprefix;
36     char* psz_response="";
37     char* response_tmp;
38     int i;
39     vlm_message_t *aw_child, **paw_child;
40
41     asprintf( &psz_childprefix, "%s%s.", psz_prefix, p_answer->psz_name );
42
43     if ( p_answer->i_child )
44     {
45         paw_child = p_answer->child;
46         aw_child = *( paw_child );
47         for( i = 0; i < p_answer->i_child; i++ )
48         {
49             asprintf( &response_tmp, "%s%s%s:%s\n",
50                       psz_response, psz_prefix, aw_child->psz_name,
51                       aw_child->psz_value );
52             free( psz_response );
53             psz_response = response_tmp;
54             if ( aw_child->i_child )
55             {
56                 asprintf(&response_tmp, "%s%s", psz_response,
57                          recurse_answer(psz_childprefix, aw_child));
58                 free( psz_response );
59                 psz_response = response_tmp;
60             }
61             paw_child++;
62             aw_child = *( paw_child );
63         }
64     }
65     free( psz_childprefix );
66     return psz_response;
67 }
68
69 char* libvlc_vlm_show_media( libvlc_instance_t *p_instance, char *psz_name,
70                              libvlc_exception_t *p_exception )
71 {
72     char *psz_message;
73     vlm_message_t *answer;
74     char *psz_response;
75
76     CHECK_VLM;
77     asprintf( &psz_message, "show %s", psz_name );
78     asprintf( &psz_response, "", psz_name );
79     vlm_ExecuteCommand( p_instance->libvlc_vlm.p_vlm, psz_message, &answer );
80     if( answer->psz_value )
81     {
82         libvlc_exception_raise( p_exception, "Unable to call show %s: %s",
83                                 psz_name, answer->psz_value );
84     }
85     else
86     {
87         if ( answer->child )
88         {
89             psz_response = recurse_answer( "", answer );
90         }
91     }
92     free( psz_message );
93     return(psz_response );
94 }
95 #else
96
97 char* libvlc_vlm_show_media( libvlc_instance_t *p_instance,
98                              const char *psz_name,
99                              libvlc_exception_t *p_exception )
100 {
101     (void)p_instance;
102     /* FIXME is it needed ? */
103     libvlc_exception_raise( p_exception, "Unable to call show %s", psz_name );
104     return NULL;
105 }
106
107 #endif /* 0 */
108 /* VLM events callback. Transmit to libvlc */
109 static int VlmEvent( vlc_object_t *p_this, const char * name,
110                      vlc_value_t old_val, vlc_value_t newval, void *param )
111 {
112     vlm_event_t *event = (vlm_event_t*)newval.p_address;
113     libvlc_event_manager_t *p_event_manager = (libvlc_event_manager_t *) param;
114     libvlc_event_t libvlc_event;
115
116     VLC_UNUSED( p_this );
117     VLC_UNUSED( name );
118     VLC_UNUSED( old_val );
119
120     libvlc_event.u.vlm_media_event.psz_media_name = event->psz_name;
121
122     switch( event->i_type )
123     {
124     case VLM_EVENT_MEDIA_ADDED:
125         libvlc_event.type = libvlc_VlmMediaAdded;
126         break;
127     case VLM_EVENT_MEDIA_REMOVED:
128         libvlc_event.type = libvlc_VlmMediaRemoved;
129         break;
130     case VLM_EVENT_MEDIA_CHANGED:
131         libvlc_event.type = libvlc_VlmMediaChanged;
132         break;
133     case VLM_EVENT_MEDIA_INSTANCE_STARTED:
134         libvlc_event.type = libvlc_VlmMediaInstanceStarted;
135         break;
136     case VLM_EVENT_MEDIA_INSTANCE_STOPPED:
137         libvlc_event.type = libvlc_VlmMediaInstanceStopped;
138         break;
139     }
140     libvlc_event_send( p_event_manager, &libvlc_event );
141     return 0;
142 }
143
144 static void libvlc_vlm_release_internal( libvlc_instance_t *p_instance )
145 {
146     vlm_t *p_vlm = p_instance->libvlc_vlm.p_vlm;
147     if( !p_instance->libvlc_vlm.p_vlm )
148         return;
149     /* We need to remove medias in order to receive events */
150     vlm_Control( p_vlm, VLM_CLEAR_MEDIAS );
151     vlm_Control( p_vlm, VLM_CLEAR_SCHEDULES );
152
153     var_DelCallback( (vlc_object_t *)p_vlm, "intf-event", VlmEvent,
154                      p_instance->libvlc_vlm.p_event_manager );
155     p_instance->libvlc_vlm.pf_release = NULL;
156     libvlc_event_manager_release( p_instance->libvlc_vlm.p_event_manager );
157     p_instance->libvlc_vlm.p_event_manager = NULL;
158     vlm_Delete( p_vlm );
159     p_instance->libvlc_vlm.p_vlm = NULL;
160 }
161
162 static int libvlc_vlm_init( libvlc_instance_t *p_instance,
163                             libvlc_exception_t *p_exception )
164 {
165     if( !p_instance->libvlc_vlm.p_event_manager )
166     {
167         p_instance->libvlc_vlm.p_event_manager = libvlc_event_manager_new( p_instance->libvlc_vlm.p_vlm,
168                                                                 p_instance, p_exception );
169         libvlc_event_manager_register_event_type( p_instance->libvlc_vlm.p_event_manager,
170                                                   libvlc_VlmMediaAdded, NULL );
171         libvlc_event_manager_register_event_type( p_instance->libvlc_vlm.p_event_manager,
172                                                   libvlc_VlmMediaRemoved, NULL );
173         libvlc_event_manager_register_event_type( p_instance->libvlc_vlm.p_event_manager,
174                                                   libvlc_VlmMediaChanged, NULL );
175         libvlc_event_manager_register_event_type( p_instance->libvlc_vlm.p_event_manager,
176                                                   libvlc_VlmMediaInstanceStarted, NULL );
177         libvlc_event_manager_register_event_type( p_instance->libvlc_vlm.p_event_manager,
178                                                   libvlc_VlmMediaInstanceStopped, NULL );
179     }
180
181     if( !p_instance->libvlc_vlm.p_vlm )
182     {
183         p_instance->libvlc_vlm.p_vlm = vlm_New( p_instance->p_libvlc_int );
184         if( !p_instance->libvlc_vlm.p_vlm )
185         {
186             libvlc_exception_raise( p_exception,
187                                     "Unable to create VLM." );
188             return VLC_EGENERIC;
189         }
190         var_AddCallback( (vlc_object_t *)p_instance->libvlc_vlm.p_vlm, "intf-event", VlmEvent,
191                          p_instance->libvlc_vlm.p_event_manager );
192         p_instance->libvlc_vlm.pf_release = libvlc_vlm_release_internal;
193     }
194
195     return VLC_SUCCESS;
196 }
197
198 void libvlc_vlm_release( libvlc_instance_t *p_instance,
199                          libvlc_exception_t *p_exception)
200 {
201     libvlc_vlm_release_internal( p_instance );
202 }
203
204 #define VLM_RET(p,ret) do {                                     \
205     if( libvlc_vlm_init( p_instance, p_exception ) ) return ret;\
206     (p) = p_instance->libvlc_vlm.p_vlm;                                    \
207   } while(0)
208 #define VLM(p) VLM_RET(p,)
209
210 static vlm_media_instance_t *
211 libvlc_vlm_get_media_instance( libvlc_instance_t *p_instance,
212                                const char *psz_name, int i_minstance_idx,
213                                libvlc_exception_t *p_exception )
214 {
215     vlm_t *p_vlm;
216     vlm_media_instance_t **pp_minstance;
217     vlm_media_instance_t *p_minstance;
218     int i_minstance;
219     int64_t id;
220
221     VLM_RET(p_vlm, NULL);
222
223     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
224         vlm_Control( p_vlm, VLM_GET_MEDIA_INSTANCES, id, &pp_minstance,
225                      &i_minstance ) )
226     {
227         libvlc_exception_raise( p_exception, "Unable to get %s instances",
228                                 psz_name );
229         return NULL;
230     }
231     p_minstance = NULL;
232     if( i_minstance_idx >= 0 && i_minstance_idx < i_minstance )
233     {
234         p_minstance = pp_minstance[i_minstance_idx];
235         TAB_REMOVE( i_minstance, pp_minstance, p_minstance );
236     }
237     while( i_minstance > 0 )
238         vlm_media_instance_Delete( pp_minstance[--i_minstance] );
239     TAB_CLEAN( i_minstance, pp_minstance );
240     return p_minstance;
241 }
242
243 void libvlc_vlm_add_broadcast( libvlc_instance_t *p_instance,
244                                const char *psz_name,
245                                const char *psz_input,
246                                const char *psz_output, int i_options,
247                                const char * const *ppsz_options,
248                                int b_enabled, int b_loop,
249                                libvlc_exception_t *p_exception )
250 {
251     vlm_t *p_vlm;
252     vlm_media_t m;
253     int n;
254
255     VLM(p_vlm);
256
257     vlm_media_Init( &m );
258     m.psz_name = strdup( psz_name );
259     m.b_enabled = b_enabled;
260     m.b_vod = false;
261     m.broadcast.b_loop = b_loop;
262     if( psz_input )
263         TAB_APPEND( m.i_input, m.ppsz_input, strdup(psz_input) );
264     if( psz_output )
265         m.psz_output = strdup( psz_output );
266     for( n = 0; n < i_options; n++ )
267         TAB_APPEND( m.i_option, m.ppsz_option, strdup(ppsz_options[n]) );
268
269     n = vlm_Control( p_vlm, VLM_ADD_MEDIA, &m, NULL );
270     vlm_media_Clean( &m );
271     if( n )
272         libvlc_exception_raise( p_exception, "Media %s creation failed",
273                                 psz_name );
274 }
275
276 void libvlc_vlm_add_vod( libvlc_instance_t *p_instance, const char *psz_name,
277                          const char *psz_input, int i_options,
278                          const char * const *ppsz_options, int b_enabled,
279                          const char *psz_mux, libvlc_exception_t *p_exception )
280 {
281     vlm_t *p_vlm;
282     vlm_media_t m;
283     int n;
284
285     VLM(p_vlm);
286
287     vlm_media_Init( &m );
288     m.psz_name = strdup( psz_name );
289     m.b_enabled = b_enabled;
290     m.b_vod = true;
291     m.vod.psz_mux = psz_mux ? strdup( psz_mux ) : NULL;
292     if( psz_input )
293         TAB_APPEND( m.i_input, m.ppsz_input, strdup(psz_input) );
294     for( n = 0; n < i_options; n++ )
295         TAB_APPEND( m.i_option, m.ppsz_option, strdup(ppsz_options[n]) );
296
297     n = vlm_Control( p_vlm, VLM_ADD_MEDIA, &m, NULL );
298     vlm_media_Clean( &m );
299     if( n )
300         libvlc_exception_raise( p_exception, "Media %s creation failed",
301                                 psz_name );
302 }
303
304 void libvlc_vlm_del_media( libvlc_instance_t *p_instance, const char *psz_name,
305                            libvlc_exception_t *p_exception )
306 {
307     vlm_t *p_vlm;
308     int64_t id;
309
310     VLM(p_vlm);
311
312     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
313         vlm_Control( p_vlm, VLM_DEL_MEDIA, id ) )
314     {
315         libvlc_exception_raise( p_exception, "Unable to delete %s", psz_name );
316     }
317 }
318
319 #define VLM_CHANGE(psz_error, code ) do {   \
320     vlm_media_t *p_media;   \
321     vlm_t *p_vlm;           \
322     int64_t id;             \
323     VLM(p_vlm);             \
324     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||    \
325         vlm_Control( p_vlm, VLM_GET_MEDIA, id, &p_media ) ) {       \
326         libvlc_exception_raise( p_exception, psz_error, psz_name ); \
327         return;             \
328     }                       \
329     if( !p_media ) goto error;                                      \
330                             \
331     code;                   \
332                             \
333     if( vlm_Control( p_vlm, VLM_CHANGE_MEDIA, p_media ) ) {         \
334         vlm_media_Delete( p_media );                                \
335         goto error;         \
336     }                       \
337     vlm_media_Delete( p_media );                                    \
338     return;                 \
339   error:                    \
340     libvlc_exception_raise( p_exception, psz_error, psz_name );\
341   } while(0)
342
343 void libvlc_vlm_set_enabled( libvlc_instance_t *p_instance,
344                              const char *psz_name, int b_enabled,
345                              libvlc_exception_t *p_exception )
346 {
347 #define VLM_CHANGE_CODE { p_media->b_enabled = b_enabled; }
348     VLM_CHANGE( "Unable to delete %s", VLM_CHANGE_CODE );
349 #undef VLM_CHANGE_CODE
350 }
351
352 void libvlc_vlm_set_loop( libvlc_instance_t *p_instance, const char *psz_name,
353                           int b_loop, libvlc_exception_t *p_exception )
354 {
355 #define VLM_CHANGE_CODE { p_media->broadcast.b_loop = b_loop; }
356     VLM_CHANGE( "Unable to change %s loop property", VLM_CHANGE_CODE );
357 #undef VLM_CHANGE_CODE
358 }
359
360 void libvlc_vlm_set_mux( libvlc_instance_t *p_instance, const char *psz_name,
361                          const char *psz_mux, libvlc_exception_t *p_exception )
362 {
363 #define VLM_CHANGE_CODE { if( p_media->b_vod ) { \
364                             free( p_media->vod.psz_mux ); \
365                             p_media->vod.psz_mux = psz_mux \
366                                  ? strdup( psz_mux ) : NULL; \
367                           } }
368     VLM_CHANGE( "Unable to change %s mux property", VLM_CHANGE_CODE );
369 #undef VLM_CHANGE_CODE
370 }
371
372 void libvlc_vlm_set_output( libvlc_instance_t *p_instance,
373                             const char *psz_name, const char *psz_output,
374                             libvlc_exception_t *p_exception )
375 {
376 #define VLM_CHANGE_CODE { free( p_media->psz_output ); \
377                           p_media->psz_output = strdup( psz_output ); }
378     VLM_CHANGE( "Unable to change %s output property", VLM_CHANGE_CODE );
379 #undef VLM_CHANGE_CODE
380 }
381
382 void libvlc_vlm_set_input( libvlc_instance_t *p_instance,
383                            const char *psz_name, const char *psz_input,
384                            libvlc_exception_t *p_exception )
385 {
386 #define VLM_CHANGE_CODE { while( p_media->i_input > 0 ) \
387                             free( p_media->ppsz_input[--p_media->i_input] );\
388                           TAB_APPEND( p_media->i_input, p_media->ppsz_input, \
389                                       strdup(psz_input) ); }
390     VLM_CHANGE( "Unable to change %s input property", VLM_CHANGE_CODE );
391 #undef VLM_CHANGE_CODE
392 }
393
394 void libvlc_vlm_add_input( libvlc_instance_t *p_instance,
395                            const char *psz_name, const char *psz_input,
396                            libvlc_exception_t *p_exception )
397 {
398 #define VLM_CHANGE_CODE { TAB_APPEND( p_media->i_input, p_media->ppsz_input, \
399                           strdup(psz_input) ); }
400     VLM_CHANGE( "Unable to change %s input property", VLM_CHANGE_CODE );
401 #undef VLM_CHANGE_CODE
402 }
403
404 void libvlc_vlm_change_media( libvlc_instance_t *p_instance,
405                               const char *psz_name, const char *psz_input,
406                               const char *psz_output, int i_options,
407                               const char * const *ppsz_options, int b_enabled,
408                               int b_loop, libvlc_exception_t *p_exception )
409 {
410 #define VLM_CHANGE_CODE { int n;        \
411     p_media->b_enabled = b_enabled;     \
412     p_media->broadcast.b_loop = b_loop; \
413     while( p_media->i_input > 0 )       \
414         free( p_media->ppsz_input[--p_media->i_input] );    \
415     if( psz_input )                     \
416         TAB_APPEND( p_media->i_input, p_media->ppsz_input, strdup(psz_input) ); \
417     free( p_media->psz_output );        \
418     p_media->psz_output = psz_output ? strdup( psz_output ) : NULL; \
419     while( p_media->i_option > 0 )     \
420         free( p_media->ppsz_option[--p_media->i_option] );        \
421     for( n = 0; n < i_options; n++ )    \
422         TAB_APPEND( p_media->i_option, p_media->ppsz_option, \
423                     strdup(ppsz_options[n]) );   \
424   }
425     VLM_CHANGE( "Unable to change %s properties", VLM_CHANGE_CODE );
426 #undef VLM_CHANGE_CODE
427 }
428
429 void libvlc_vlm_play_media( libvlc_instance_t *p_instance,
430                             const char *psz_name,
431                             libvlc_exception_t *p_exception )
432 {
433     vlm_t *p_vlm;
434     int64_t id;
435
436     VLM(p_vlm);
437
438     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
439         vlm_Control( p_vlm, VLM_START_MEDIA_BROADCAST_INSTANCE, id, NULL, 0 ) )
440     {
441         libvlc_exception_raise( p_exception, "Unable to play %s", psz_name );
442     }
443 }
444
445 void libvlc_vlm_stop_media( libvlc_instance_t *p_instance,
446                             const char *psz_name,
447                             libvlc_exception_t *p_exception )
448 {
449     vlm_t *p_vlm;
450     int64_t id;
451
452     VLM(p_vlm);
453
454     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
455         vlm_Control( p_vlm, VLM_STOP_MEDIA_INSTANCE, id, NULL ) )
456     {
457         libvlc_exception_raise( p_exception, "Unable to stop %s", psz_name );
458     }
459 }
460
461 void libvlc_vlm_pause_media( libvlc_instance_t *p_instance,
462                              const char *psz_name,
463                              libvlc_exception_t *p_exception )
464 {
465     vlm_t *p_vlm;
466     int64_t id;
467
468     VLM(p_vlm);
469
470     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
471         vlm_Control( p_vlm, VLM_PAUSE_MEDIA_INSTANCE, id, NULL ) )
472     {
473         libvlc_exception_raise( p_exception, "Unable to pause %s", psz_name );
474     }
475 }
476
477 void libvlc_vlm_seek_media( libvlc_instance_t *p_instance,
478                             const char *psz_name, float f_percentage,
479                             libvlc_exception_t *p_exception )
480 {
481     vlm_t *p_vlm;
482     int64_t id;
483
484     VLM(p_vlm);
485
486     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
487         vlm_Control( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, id, NULL,
488                      f_percentage ) )
489         libvlc_exception_raise( p_exception, "Unable to seek %s to %f",
490                                 psz_name, f_percentage );
491 }
492
493 float libvlc_vlm_get_media_instance_position( libvlc_instance_t *p_instance,
494                                               const char *psz_name,
495                                               int i_instance,
496                                               libvlc_exception_t *p_exception )
497 {
498     vlm_media_instance_t *p_mi;
499     float result = -1.;
500
501     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
502                                           i_instance, p_exception );
503     if( p_mi )
504     {
505         result = p_mi->d_position;
506         vlm_media_instance_Delete( p_mi );
507     }
508     return result;
509 }
510
511 int libvlc_vlm_get_media_instance_time( libvlc_instance_t *p_instance,
512                                         const char *psz_name, int i_instance,
513                                         libvlc_exception_t *p_exception )
514 {
515     vlm_media_instance_t *p_mi;
516     int result = -1;
517
518     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
519                                         i_instance, p_exception );
520     if( p_mi )
521     {
522         result = p_mi->i_time;
523         vlm_media_instance_Delete( p_mi );
524     }
525     return result;
526 }
527
528 int libvlc_vlm_get_media_instance_length( libvlc_instance_t *p_instance,
529                                           const char *psz_name,
530                                           int i_instance,
531                                           libvlc_exception_t *p_exception )
532 {
533     vlm_media_instance_t *p_mi;
534     int result = -1;
535
536     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
537                                           i_instance, p_exception );
538     if( p_mi )
539     {
540         result = p_mi->i_length;
541         vlm_media_instance_Delete( p_mi );
542     }
543     return result;
544 }
545
546 int libvlc_vlm_get_media_instance_rate( libvlc_instance_t *p_instance,
547                                         const char *psz_name, int i_instance,
548                                         libvlc_exception_t *p_exception )
549 {
550     vlm_media_instance_t *p_mi;
551     int result = -1;
552
553     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
554                                           i_instance, p_exception );
555     if( p_mi )
556     {
557         result = p_mi->i_rate;
558         vlm_media_instance_Delete( p_mi );
559     }
560     return result;
561 }
562
563 int libvlc_vlm_get_media_instance_title( libvlc_instance_t *p_instance,
564                                          const char *psz_name, int i_instance,
565                                          libvlc_exception_t *p_exception )
566 {
567     vlm_media_instance_t *p_mi;
568
569     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
570                                           i_instance, p_exception );
571     if( p_mi )
572         vlm_media_instance_Delete( p_mi );
573     return p_mi ? 0 : -1;
574 }
575
576 int libvlc_vlm_get_media_instance_chapter( libvlc_instance_t *p_instance,
577                                            const char *psz_name,
578                                            int i_instance,
579                                            libvlc_exception_t *p_exception )
580 {
581     vlm_media_instance_t *p_mi;
582
583     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
584                                           i_instance, p_exception );
585     if( p_mi )
586         vlm_media_instance_Delete( p_mi );
587     return p_mi ? 0 : -1;
588 }
589
590 int libvlc_vlm_get_media_instance_seekable( libvlc_instance_t *p_instance,
591                                             const char *psz_name,
592                                             int i_instance,
593                                             libvlc_exception_t *p_exception )
594 {
595     vlm_media_instance_t *p_mi;
596
597     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
598                                           i_instance, p_exception );
599     if( p_mi )
600         vlm_media_instance_Delete( p_mi );
601     return p_mi ? 0 : -1;
602 }
603
604 libvlc_event_manager_t * libvlc_vlm_get_event_manager( libvlc_instance_t *p_instance,
605                                                        libvlc_exception_t *p_exception )
606 {
607     vlm_t *p_vlm;
608     VLM_RET( p_vlm, NULL);
609     return p_instance->libvlc_vlm.p_event_manager;
610 }