]> git.sesse.net Git - vlc/blob - src/control/vlm.c
e6e96b653a23738766559afe2f36b4e172a4938e
[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 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <vlc/libvlc.h>
29 #include <vlc/libvlc_vlm.h>
30 #include <vlc_es.h>
31 #include <vlc_input.h>
32 #include <vlc_vlm.h>
33
34 #include "libvlc_internal.h"
35
36 /* VLM events callback. Transmit to libvlc */
37 static int VlmEvent( vlc_object_t *p_this, const char * name,
38                      vlc_value_t old_val, vlc_value_t newval, void *param )
39 {
40     VLC_UNUSED(p_this);
41     VLC_UNUSED(name);
42     VLC_UNUSED(old_val);    
43     vlm_event_t *event = (vlm_event_t*)newval.p_address;
44     libvlc_event_manager_t *p_event_manager = (libvlc_event_manager_t *) param;
45     libvlc_event_t libvlc_event;
46
47     libvlc_event.u.vlm_media_event.psz_instance_name = NULL;
48     libvlc_event.u.vlm_media_event.psz_media_name = event->psz_name;
49
50     switch( event->i_type )
51     {
52     case VLM_EVENT_MEDIA_ADDED:
53         libvlc_event.type = libvlc_VlmMediaAdded;
54         break;
55     case VLM_EVENT_MEDIA_REMOVED:
56         libvlc_event.type = libvlc_VlmMediaRemoved;
57         break;
58     case VLM_EVENT_MEDIA_CHANGED:
59         libvlc_event.type = libvlc_VlmMediaChanged;
60         break;
61     case VLM_EVENT_MEDIA_INSTANCE_STARTED:
62         libvlc_event.type = libvlc_VlmMediaInstanceStarted;
63         break;
64     case VLM_EVENT_MEDIA_INSTANCE_STOPPED:
65         libvlc_event.type = libvlc_VlmMediaInstanceStopped;
66         break;
67     case VLM_EVENT_MEDIA_INSTANCE_STATE:
68         libvlc_event.u.vlm_media_event.psz_instance_name =
69             event->psz_instance_name;
70         switch( event->input_state )
71         {
72         case INIT_S:
73             libvlc_event.type = libvlc_VlmMediaInstanceStatusInit;
74             break;
75         case OPENING_S:
76             libvlc_event.type =
77                 libvlc_VlmMediaInstanceStatusOpening;
78             break;
79         case PLAYING_S:
80             libvlc_event.type =
81                 libvlc_VlmMediaInstanceStatusPlaying;
82             break;
83         case PAUSE_S:
84             libvlc_event.type = libvlc_VlmMediaInstanceStatusPause;
85             break;
86         case END_S:
87             libvlc_event.type = libvlc_VlmMediaInstanceStatusEnd;
88             break;
89         case ERROR_S:
90             libvlc_event.type = libvlc_VlmMediaInstanceStatusError;
91             break;
92         default:
93             return 0;
94         }
95         break;
96     default:
97         return 0;
98     }
99     libvlc_event_send( p_event_manager, &libvlc_event );
100     return 0;
101 }
102
103 static void libvlc_vlm_release_internal( libvlc_instance_t *p_instance )
104 {
105     vlm_t *p_vlm = p_instance->libvlc_vlm.p_vlm;
106     if( !p_instance->libvlc_vlm.p_vlm )
107         return;
108     /* We need to remove medias in order to receive events */
109     vlm_Control( p_vlm, VLM_CLEAR_MEDIAS );
110     vlm_Control( p_vlm, VLM_CLEAR_SCHEDULES );
111
112     var_DelCallback( (vlc_object_t *)p_vlm, "intf-event", VlmEvent,
113                      p_instance->libvlc_vlm.p_event_manager );
114     p_instance->libvlc_vlm.pf_release = NULL;
115     libvlc_event_manager_release( p_instance->libvlc_vlm.p_event_manager );
116     p_instance->libvlc_vlm.p_event_manager = NULL;
117     vlm_Delete( p_vlm );
118     p_instance->libvlc_vlm.p_vlm = NULL;
119 }
120
121 static int libvlc_vlm_init( libvlc_instance_t *p_instance,
122                             libvlc_exception_t *p_exception )
123 {
124     if( !p_instance->libvlc_vlm.p_event_manager )
125     {
126         p_instance->libvlc_vlm.p_event_manager =
127             libvlc_event_manager_new( p_instance->libvlc_vlm.p_vlm,
128                                       p_instance, p_exception );
129         libvlc_event_manager_register_event_type(
130             p_instance->libvlc_vlm.p_event_manager,
131             libvlc_VlmMediaAdded, NULL );
132         libvlc_event_manager_register_event_type(
133             p_instance->libvlc_vlm.p_event_manager,
134             libvlc_VlmMediaRemoved, NULL );
135         libvlc_event_manager_register_event_type(
136             p_instance->libvlc_vlm.p_event_manager,
137             libvlc_VlmMediaChanged, NULL );
138         libvlc_event_manager_register_event_type(
139             p_instance->libvlc_vlm.p_event_manager,
140             libvlc_VlmMediaInstanceStarted, NULL );
141         libvlc_event_manager_register_event_type(
142             p_instance->libvlc_vlm.p_event_manager,
143             libvlc_VlmMediaInstanceStopped, NULL );
144         libvlc_event_manager_register_event_type(
145             p_instance->libvlc_vlm.p_event_manager,
146             libvlc_VlmMediaInstanceStatusInit, NULL );
147         libvlc_event_manager_register_event_type(
148             p_instance->libvlc_vlm.p_event_manager,
149             libvlc_VlmMediaInstanceStatusOpening, NULL );
150         libvlc_event_manager_register_event_type(
151             p_instance->libvlc_vlm.p_event_manager,
152             libvlc_VlmMediaInstanceStatusPlaying, NULL );
153         libvlc_event_manager_register_event_type(
154             p_instance->libvlc_vlm.p_event_manager,
155             libvlc_VlmMediaInstanceStatusPause, NULL );
156         libvlc_event_manager_register_event_type(
157             p_instance->libvlc_vlm.p_event_manager,
158             libvlc_VlmMediaInstanceStatusEnd, NULL );
159         libvlc_event_manager_register_event_type(
160             p_instance->libvlc_vlm.p_event_manager,
161             libvlc_VlmMediaInstanceStatusError, NULL );
162     }
163
164     if( !p_instance->libvlc_vlm.p_vlm )
165     {
166         p_instance->libvlc_vlm.p_vlm = vlm_New( p_instance->p_libvlc_int );
167         if( !p_instance->libvlc_vlm.p_vlm )
168         {
169             libvlc_exception_raise( p_exception,
170                                     "Unable to create VLM." );
171             return VLC_EGENERIC;
172         }
173         var_AddCallback( (vlc_object_t *)p_instance->libvlc_vlm.p_vlm,
174                          "intf-event", VlmEvent,
175                          p_instance->libvlc_vlm.p_event_manager );
176         p_instance->libvlc_vlm.pf_release = libvlc_vlm_release_internal;
177     }
178
179     return VLC_SUCCESS;
180 }
181
182 void libvlc_vlm_release( libvlc_instance_t *p_instance,
183                          libvlc_exception_t *p_exception)
184 {
185     VLC_UNUSED(p_exception);
186     libvlc_vlm_release_internal( p_instance );
187 }
188
189 #define VLM_RET(p,ret) do {                                     \
190     if( libvlc_vlm_init( p_instance, p_exception ) ) return ret;\
191     (p) = p_instance->libvlc_vlm.p_vlm;                                    \
192   } while(0)
193 #define VLM(p) VLM_RET(p,)
194
195 static vlm_media_instance_t *
196 libvlc_vlm_get_media_instance( libvlc_instance_t *p_instance,
197                                const char *psz_name, int i_minstance_idx,
198                                libvlc_exception_t *p_exception )
199 {
200     vlm_t *p_vlm;
201     vlm_media_instance_t **pp_minstance;
202     vlm_media_instance_t *p_minstance;
203     int i_minstance;
204     int64_t id;
205
206     VLM_RET(p_vlm, NULL);
207
208     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
209         vlm_Control( p_vlm, VLM_GET_MEDIA_INSTANCES, id, &pp_minstance,
210                      &i_minstance ) )
211     {
212         libvlc_exception_raise( p_exception, "Unable to get %s instances",
213                                 psz_name );
214         return NULL;
215     }
216     p_minstance = NULL;
217     if( i_minstance_idx >= 0 && i_minstance_idx < i_minstance )
218     {
219         p_minstance = pp_minstance[i_minstance_idx];
220         TAB_REMOVE( i_minstance, pp_minstance, p_minstance );
221     }
222     while( i_minstance > 0 )
223         vlm_media_instance_Delete( pp_minstance[--i_minstance] );
224     TAB_CLEAN( i_minstance, pp_minstance );
225     return p_minstance;
226 }
227
228 /* local function to be used in libvlc_vlm_show_media only */
229 static char* recurse_answer( vlm_message_t *p_answer, const char* psz_delim,
230                              const int i_list ) {
231     char* psz_childdelim = NULL;
232     char* psz_nametag = NULL;
233     char* psz_response = strdup( "" );
234     int i_success = 0;
235     int i;
236     vlm_message_t *aw_child, **paw_child;
237
238     i_success = asprintf( &psz_childdelim, "%s\t", psz_delim);
239
240     /* starting with the children of root node */
241     if( i_success != -1 && p_answer->i_child )
242     {
243         paw_child = p_answer->child;
244         aw_child = *( paw_child );
245         /* Iterate over children */
246         for( i = 0; i < p_answer->i_child; i++ )
247         {
248             /* Spare comma if it is the last element */
249             char c_comma = ',';
250             if( i == (p_answer->i_child - 1) )
251                 c_comma = ' ';
252
253             /* Append name of child node, if not in a list */
254             if( !i_list )
255             {
256                 i_success = asprintf( &psz_response, "%s\"%s\": ",
257                               psz_response, aw_child->psz_name );
258                 if( i_success == -1 ) break;
259             }
260
261             /* If child node has children, */
262             if( aw_child->i_child )
263             {
264                 /* If the parent node is a list (hence the child node is
265                  * inside a list), create a property of its name as if it
266                  * had a name value node
267                  */
268                 if( i_list )
269                 {
270                     i_success = asprintf( &psz_nametag, "\"name\": \"%s\",%s",
271                                   aw_child->psz_name, psz_childdelim );
272                     if( i_success == -1 ) break;
273                 }
274                 else
275                 {
276                     psz_nametag = strdup( "" );
277                 }
278                 /* If the child is a list itself, format it accordingly and
279                  * recurse through the child's children, telling them that
280                  * they are inside a list.
281                  */
282                 if( strcmp( aw_child->psz_name, "media" ) == 0 ||
283                     strcmp( aw_child->psz_name, "inputs" ) == 0 ||
284                     strcmp( aw_child->psz_name, "options" ) == 0 )
285                 {
286                     i_success = asprintf( &psz_response, "%s[%s%s%s]%c%s",
287                                           psz_response, psz_childdelim,
288                                           recurse_answer( aw_child,
289                                                           psz_childdelim, 1 ),
290                                           psz_delim, c_comma, psz_delim );
291                     if( i_success == -1 ) break;
292                 }
293                 /* Not a list, so format the child as a JSON object and
294                  * recurse through the child's children
295                  */
296                 else
297                 {
298                     i_success = asprintf( &psz_response, "%s{%s%s%s%s}%c%s",
299                                           psz_response, psz_childdelim, psz_nametag,
300                                           recurse_answer( aw_child,
301                                                           psz_childdelim, 0 ),
302                                           psz_delim, c_comma, psz_delim );
303                     if( i_success == -1 ) break;
304                 }
305             }
306             /* Otherwise - when no children are present - the node is a
307              * value node. So print the value string
308              */
309             else
310             {
311                 /* If value is equivalent to NULL, print it as null */
312                 if( aw_child->psz_value == NULL
313                     || strcmp( aw_child->psz_value, "(null)" ) == 0 )
314                 {
315                     i_success = asprintf( &psz_response, "%snull%c%s",
316                                           psz_response, c_comma, psz_delim );
317                     if( i_success == -1 )
318                         break;
319                 }
320                 /* Otherwise print the value in quotation marks */
321                 else
322                 {
323                     i_success = asprintf( &psz_response, "%s\"%s\"%c%s",
324                                           psz_response, aw_child->psz_value,
325                                           c_comma, psz_delim );
326                     if( i_success == -1 ) break;
327                 }
328             }
329             /* getting next child */
330             paw_child++;
331             aw_child = *( paw_child );
332         }
333     }
334     free( psz_nametag );
335     free( psz_childdelim );
336     if( i_success == -1 )
337     {
338         free( psz_response );
339         psz_response = strdup( "" );
340     }
341     return psz_response;
342 }
343
344 const char* libvlc_vlm_show_media( libvlc_instance_t *p_instance,
345                                    const char *psz_name,
346                                    libvlc_exception_t *p_exception )
347 {
348     char *psz_message = NULL;
349     vlm_message_t *answer = NULL;
350     char *psz_response = NULL;
351     const char *psz_fmt = NULL;
352     const char *psz_delimiter = NULL;
353     int i_list;
354     vlm_t *p_vlm = NULL;
355
356     VLM_RET(p_vlm, NULL);
357
358     if( psz_name == NULL )
359     {
360         libvlc_exception_raise( p_exception, "No media name supplied" );
361     }
362     else if( asprintf( &psz_message, "show %s", psz_name ) == -1 )
363     {
364         libvlc_exception_raise( p_exception, "Unable to call show %s",
365                                 psz_name );
366     }
367     else
368     {
369         vlm_ExecuteCommand( p_vlm, psz_message, &answer );
370         if( answer->psz_value )
371         {
372             libvlc_exception_raise( p_exception, "Unable to call show %s: %s",
373                                     psz_name, answer->psz_value );
374         }
375         else if ( answer->child ) {
376             /* in case everything was requested  */
377             if ( strcmp( psz_name, "" ) == 0 )
378             {
379                 psz_fmt = "{\n\t%s\n}\n";
380                 psz_delimiter = "\n\t";
381                 i_list = 0;
382             }
383             else
384             {
385                 psz_fmt = "%s\n";
386                 psz_delimiter = "\n";
387                 i_list = 1;
388             }
389             if( asprintf( &psz_response, psz_fmt,
390                           recurse_answer( answer, psz_delimiter, i_list ) )
391                 == -1 )
392             {
393                 libvlc_exception_raise( p_exception, "Error in show %s",
394                                         psz_name );
395             }
396         }
397     }
398     free( psz_message );
399     return( psz_response );
400 }
401
402
403 void libvlc_vlm_add_broadcast( libvlc_instance_t *p_instance,
404                                const char *psz_name,
405                                const char *psz_input,
406                                const char *psz_output, int i_options,
407                                const char * const *ppsz_options,
408                                int b_enabled, int b_loop,
409                                libvlc_exception_t *p_exception )
410 {
411     vlm_t *p_vlm;
412     vlm_media_t m;
413     int n;
414
415     VLM(p_vlm);
416
417     vlm_media_Init( &m );
418     m.psz_name = strdup( psz_name );
419     m.b_enabled = b_enabled;
420     m.b_vod = false;
421     m.broadcast.b_loop = b_loop;
422     if( psz_input )
423         TAB_APPEND( m.i_input, m.ppsz_input, strdup(psz_input) );
424     if( psz_output )
425         m.psz_output = strdup( psz_output );
426     for( n = 0; n < i_options; n++ )
427         TAB_APPEND( m.i_option, m.ppsz_option, strdup(ppsz_options[n]) );
428
429     n = vlm_Control( p_vlm, VLM_ADD_MEDIA, &m, NULL );
430     vlm_media_Clean( &m );
431     if( n )
432         libvlc_exception_raise( p_exception, "Media %s creation failed",
433                                 psz_name );
434 }
435
436 void libvlc_vlm_add_vod( libvlc_instance_t *p_instance, const char *psz_name,
437                          const char *psz_input, int i_options,
438                          const char * const *ppsz_options, int b_enabled,
439                          const char *psz_mux, libvlc_exception_t *p_exception )
440 {
441     vlm_t *p_vlm;
442     vlm_media_t m;
443     int n;
444
445     VLM(p_vlm);
446
447     vlm_media_Init( &m );
448     m.psz_name = strdup( psz_name );
449     m.b_enabled = b_enabled;
450     m.b_vod = true;
451     m.vod.psz_mux = psz_mux ? strdup( psz_mux ) : NULL;
452     if( psz_input )
453         TAB_APPEND( m.i_input, m.ppsz_input, strdup(psz_input) );
454     for( n = 0; n < i_options; n++ )
455         TAB_APPEND( m.i_option, m.ppsz_option, strdup(ppsz_options[n]) );
456
457     n = vlm_Control( p_vlm, VLM_ADD_MEDIA, &m, NULL );
458     vlm_media_Clean( &m );
459     if( n )
460         libvlc_exception_raise( p_exception, "Media %s creation failed",
461                                 psz_name );
462 }
463
464 void libvlc_vlm_del_media( libvlc_instance_t *p_instance, const char *psz_name,
465                            libvlc_exception_t *p_exception )
466 {
467     vlm_t *p_vlm;
468     int64_t id;
469
470     VLM(p_vlm);
471
472     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
473         vlm_Control( p_vlm, VLM_DEL_MEDIA, id ) )
474     {
475         libvlc_exception_raise( p_exception, "Unable to delete %s", psz_name );
476     }
477 }
478
479 #define VLM_CHANGE(psz_error, code ) do {   \
480     vlm_media_t *p_media;   \
481     vlm_t *p_vlm;           \
482     int64_t id;             \
483     VLM(p_vlm);             \
484     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||    \
485         vlm_Control( p_vlm, VLM_GET_MEDIA, id, &p_media ) ) {       \
486         libvlc_exception_raise( p_exception, psz_error, psz_name ); \
487         return;             \
488     }                       \
489     if( !p_media ) goto error;                                      \
490                             \
491     code;                   \
492                             \
493     if( vlm_Control( p_vlm, VLM_CHANGE_MEDIA, p_media ) ) {         \
494         vlm_media_Delete( p_media );                                \
495         goto error;         \
496     }                       \
497     vlm_media_Delete( p_media );                                    \
498     return;                 \
499   error:                    \
500     libvlc_exception_raise( p_exception, psz_error, psz_name );\
501   } while(0)
502
503 void libvlc_vlm_set_enabled( libvlc_instance_t *p_instance,
504                              const char *psz_name, int b_enabled,
505                              libvlc_exception_t *p_exception )
506 {
507 #define VLM_CHANGE_CODE { p_media->b_enabled = b_enabled; }
508     VLM_CHANGE( "Unable to delete %s", VLM_CHANGE_CODE );
509 #undef VLM_CHANGE_CODE
510 }
511
512 void libvlc_vlm_set_loop( libvlc_instance_t *p_instance, const char *psz_name,
513                           int b_loop, libvlc_exception_t *p_exception )
514 {
515 #define VLM_CHANGE_CODE { p_media->broadcast.b_loop = b_loop; }
516     VLM_CHANGE( "Unable to change %s loop property", VLM_CHANGE_CODE );
517 #undef VLM_CHANGE_CODE
518 }
519
520 void libvlc_vlm_set_mux( libvlc_instance_t *p_instance, const char *psz_name,
521                          const char *psz_mux, libvlc_exception_t *p_exception )
522 {
523 #define VLM_CHANGE_CODE { if( p_media->b_vod ) { \
524                             free( p_media->vod.psz_mux ); \
525                             p_media->vod.psz_mux = psz_mux \
526                                  ? strdup( psz_mux ) : NULL; \
527                           } }
528     VLM_CHANGE( "Unable to change %s mux property", VLM_CHANGE_CODE );
529 #undef VLM_CHANGE_CODE
530 }
531
532 void libvlc_vlm_set_output( libvlc_instance_t *p_instance,
533                             const char *psz_name, const char *psz_output,
534                             libvlc_exception_t *p_exception )
535 {
536 #define VLM_CHANGE_CODE { free( p_media->psz_output ); \
537                           p_media->psz_output = strdup( psz_output ); }
538     VLM_CHANGE( "Unable to change %s output property", VLM_CHANGE_CODE );
539 #undef VLM_CHANGE_CODE
540 }
541
542 void libvlc_vlm_set_input( libvlc_instance_t *p_instance,
543                            const char *psz_name, const char *psz_input,
544                            libvlc_exception_t *p_exception )
545 {
546 #define VLM_CHANGE_CODE { while( p_media->i_input > 0 ) \
547                             free( p_media->ppsz_input[--p_media->i_input] );\
548                           TAB_APPEND( p_media->i_input, p_media->ppsz_input, \
549                                       strdup(psz_input) ); }
550     VLM_CHANGE( "Unable to change %s input property", VLM_CHANGE_CODE );
551 #undef VLM_CHANGE_CODE
552 }
553
554 void libvlc_vlm_add_input( libvlc_instance_t *p_instance,
555                            const char *psz_name, const char *psz_input,
556                            libvlc_exception_t *p_exception )
557 {
558 #define VLM_CHANGE_CODE { TAB_APPEND( p_media->i_input, p_media->ppsz_input, \
559                           strdup(psz_input) ); }
560     VLM_CHANGE( "Unable to change %s input property", VLM_CHANGE_CODE );
561 #undef VLM_CHANGE_CODE
562 }
563
564 void libvlc_vlm_change_media( libvlc_instance_t *p_instance,
565                               const char *psz_name, const char *psz_input,
566                               const char *psz_output, int i_options,
567                               const char * const *ppsz_options, int b_enabled,
568                               int b_loop, libvlc_exception_t *p_exception )
569 {
570 #define VLM_CHANGE_CODE { int n;        \
571     p_media->b_enabled = b_enabled;     \
572     p_media->broadcast.b_loop = b_loop; \
573     while( p_media->i_input > 0 )       \
574         free( p_media->ppsz_input[--p_media->i_input] );    \
575     if( psz_input )                     \
576         TAB_APPEND( p_media->i_input, p_media->ppsz_input, strdup(psz_input) ); \
577     free( p_media->psz_output );        \
578     p_media->psz_output = psz_output ? strdup( psz_output ) : NULL; \
579     while( p_media->i_option > 0 )     \
580         free( p_media->ppsz_option[--p_media->i_option] );        \
581     for( n = 0; n < i_options; n++ )    \
582         TAB_APPEND( p_media->i_option, p_media->ppsz_option, \
583                     strdup(ppsz_options[n]) );   \
584   }
585     VLM_CHANGE( "Unable to change %s properties", VLM_CHANGE_CODE );
586 #undef VLM_CHANGE_CODE
587 }
588
589 void libvlc_vlm_play_media( libvlc_instance_t *p_instance,
590                             const char *psz_name,
591                             libvlc_exception_t *p_exception )
592 {
593     vlm_t *p_vlm;
594     int64_t id;
595
596     VLM(p_vlm);
597
598     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
599         vlm_Control( p_vlm, VLM_START_MEDIA_BROADCAST_INSTANCE, id, NULL, 0 ) )
600     {
601         libvlc_exception_raise( p_exception, "Unable to play %s", psz_name );
602     }
603 }
604
605 void libvlc_vlm_stop_media( libvlc_instance_t *p_instance,
606                             const char *psz_name,
607                             libvlc_exception_t *p_exception )
608 {
609     vlm_t *p_vlm;
610     int64_t id;
611
612     VLM(p_vlm);
613
614     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
615         vlm_Control( p_vlm, VLM_STOP_MEDIA_INSTANCE, id, NULL ) )
616     {
617         libvlc_exception_raise( p_exception, "Unable to stop %s", psz_name );
618     }
619 }
620
621 void libvlc_vlm_pause_media( libvlc_instance_t *p_instance,
622                              const char *psz_name,
623                              libvlc_exception_t *p_exception )
624 {
625     vlm_t *p_vlm;
626     int64_t id;
627
628     VLM(p_vlm);
629
630     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
631         vlm_Control( p_vlm, VLM_PAUSE_MEDIA_INSTANCE, id, NULL ) )
632     {
633         libvlc_exception_raise( p_exception, "Unable to pause %s", psz_name );
634     }
635 }
636
637 void libvlc_vlm_seek_media( libvlc_instance_t *p_instance,
638                             const char *psz_name, float f_percentage,
639                             libvlc_exception_t *p_exception )
640 {
641     vlm_t *p_vlm;
642     int64_t id;
643
644     VLM(p_vlm);
645
646     if( vlm_Control( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ||
647         vlm_Control( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, id, NULL,
648                      f_percentage ) )
649         libvlc_exception_raise( p_exception, "Unable to seek %s to %f",
650                                 psz_name, f_percentage );
651 }
652
653 float libvlc_vlm_get_media_instance_position( libvlc_instance_t *p_instance,
654                                               const char *psz_name,
655                                               int i_instance,
656                                               libvlc_exception_t *p_exception )
657 {
658     vlm_media_instance_t *p_mi;
659     float result = -1.;
660
661     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
662                                           i_instance, p_exception );
663     if( p_mi )
664     {
665         result = p_mi->d_position;
666         vlm_media_instance_Delete( p_mi );
667     }
668     return result;
669 }
670
671 int libvlc_vlm_get_media_instance_time( libvlc_instance_t *p_instance,
672                                         const char *psz_name, int i_instance,
673                                         libvlc_exception_t *p_exception )
674 {
675     vlm_media_instance_t *p_mi;
676     int result = -1;
677
678     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
679                                         i_instance, p_exception );
680     if( p_mi )
681     {
682         result = p_mi->i_time;
683         vlm_media_instance_Delete( p_mi );
684     }
685     return result;
686 }
687
688 int libvlc_vlm_get_media_instance_length( libvlc_instance_t *p_instance,
689                                           const char *psz_name,
690                                           int i_instance,
691                                           libvlc_exception_t *p_exception )
692 {
693     vlm_media_instance_t *p_mi;
694     int result = -1;
695
696     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
697                                           i_instance, p_exception );
698     if( p_mi )
699     {
700         result = p_mi->i_length;
701         vlm_media_instance_Delete( p_mi );
702     }
703     return result;
704 }
705
706 int libvlc_vlm_get_media_instance_rate( libvlc_instance_t *p_instance,
707                                         const char *psz_name, int i_instance,
708                                         libvlc_exception_t *p_exception )
709 {
710     vlm_media_instance_t *p_mi;
711     int result = -1;
712
713     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
714                                           i_instance, p_exception );
715     if( p_mi )
716     {
717         result = p_mi->i_rate;
718         vlm_media_instance_Delete( p_mi );
719     }
720     return result;
721 }
722
723 int libvlc_vlm_get_media_instance_title( libvlc_instance_t *p_instance,
724                                          const char *psz_name, int i_instance,
725                                          libvlc_exception_t *p_exception )
726 {
727     vlm_media_instance_t *p_mi;
728
729     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
730                                           i_instance, p_exception );
731     if( p_mi )
732         vlm_media_instance_Delete( p_mi );
733     return p_mi ? 0 : -1;
734 }
735
736 int libvlc_vlm_get_media_instance_chapter( libvlc_instance_t *p_instance,
737                                            const char *psz_name,
738                                            int i_instance,
739                                            libvlc_exception_t *p_exception )
740 {
741     vlm_media_instance_t *p_mi;
742
743     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
744                                           i_instance, p_exception );
745     if( p_mi )
746         vlm_media_instance_Delete( p_mi );
747     return p_mi ? 0 : -1;
748 }
749
750 int libvlc_vlm_get_media_instance_seekable( libvlc_instance_t *p_instance,
751                                             const char *psz_name,
752                                             int i_instance,
753                                             libvlc_exception_t *p_exception )
754 {
755     vlm_media_instance_t *p_mi;
756
757     p_mi = libvlc_vlm_get_media_instance( p_instance, psz_name,
758                                           i_instance, p_exception );
759     if( p_mi )
760         vlm_media_instance_Delete( p_mi );
761     return p_mi ? 0 : -1;
762 }
763
764 libvlc_event_manager_t * libvlc_vlm_get_event_manager( libvlc_instance_t *p_instance,
765                                                        libvlc_exception_t *p_exception )
766 {
767     vlm_t *p_vlm;
768     VLM_RET( p_vlm, NULL);
769     return p_instance->libvlc_vlm.p_event_manager;
770 }