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