]> git.sesse.net Git - vlc/blob - modules/control/corba/mediacontrol-core.c
2069697bb158eed3f7f836d23fb87dc046058606
[vlc] / modules / control / corba / mediacontrol-core.c
1 #include "mediacontrol-core.h"
2
3 #include <vlc/intf.h>
4 #include <vlc/vout.h>
5 #include <vlc/aout.h>
6 #include <vlc_demux.h>
7
8 #include <osd.h>
9
10 #define HAS_SNAPSHOT 1
11
12 #ifdef HAS_SNAPSHOT
13 #include <snapshot.h>
14 #endif
15
16 #include <stdlib.h>                                      /* malloc(), free() */
17 #include <string.h>
18
19 #include <errno.h>                                                 /* ENOMEM */
20 #include <stdio.h>
21 #include <ctype.h>
22
23 #ifdef HAVE_UNISTD_H
24 #    include <unistd.h>
25 #endif
26
27 #ifdef HAVE_SYS_TIME_H
28 #    include <sys/time.h>
29 #endif
30 #include <sys/types.h>
31
32 #define RAISE( c, m )  exception->code = c; \
33                        exception->message = strdup(m);
34
35 long long mediacontrol_unit_convert( input_thread_t *p_input,
36                                      mediacontrol_PositionKey from,
37                                      mediacontrol_PositionKey to,
38                                      long long value )
39 {
40     if( to == from )
41         return value;
42
43     /* For all conversions, we need data from p_input */
44     if( !p_input )
45         return 0;
46
47     switch( from )
48     {
49     case mediacontrol_MediaTime:
50         if( to == mediacontrol_ByteCount )
51         {
52             /* FIXME */
53             /* vlc < 0.8 API */
54             /* return value * 50 * p_input->stream.i_mux_rate / 1000; */
55             return 0;
56         }
57         if( to == mediacontrol_SampleCount )
58         {
59             double f_fps;
60
61             if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
62                 return 0;
63             else
64                 return( value * f_fps / 1000.0 );
65         }
66         /* Cannot happen */
67         /* See http://catb.org/~esr/jargon/html/entry/can't-happen.html */
68         break;
69
70     case mediacontrol_SampleCount:
71     {
72         double f_fps;
73
74         if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
75             return 0;
76
77         if( to == mediacontrol_ByteCount )
78         {
79             /* FIXME */
80             /* vlc < 0.8 API */
81 /*             return ( long long )( value * 50 * p_input->stream.i_mux_rate / f_fps ); */
82             return 0;
83         }
84
85         if( to == mediacontrol_MediaTime )
86             return( long long )( value * 1000.0 / ( double )f_fps );
87
88         /* Cannot happen */
89         break;
90     }
91     case mediacontrol_ByteCount:
92         /* FIXME */
93         return 0;
94 /* vlc < 0.8 API: */
95
96 //         if( p_input->stream.i_mux_rate == 0 )
97 //             return 0;
98 // 
99 //         /* Convert an offset into milliseconds. Taken from input_ext-intf.c.
100 //            The 50 hardcoded constant comes from the definition of i_mux_rate :
101 //            i_mux_rate : the rate we read the stream (in units of 50 bytes/s) ;
102 //            0 if undef */
103 //         if( to == mediacontrol_MediaTime )
104 //             return ( long long )( 1000 * value / 50 / p_input->stream.i_mux_rate );
105 // 
106 //         if( to == mediacontrol_SampleCount )
107 //         {
108 //             double f_fps;
109 //             if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
110 //                 return 0;
111 //             else
112 //                 return ( long long )( value * f_fps / 50 / p_input->stream.i_mux_rate );
113 //         }
114         /* Cannot happen */
115         break;
116     }
117     /* Cannot happen */
118     return 0;
119 }
120
121 /* Converts a mediacontrol_Position into a time in microseconds in
122    movie clock time */
123 long long
124 mediacontrol_position2microsecond( input_thread_t* p_input, const mediacontrol_Position * pos )
125 {
126     switch( pos->origin )
127     {
128     case mediacontrol_AbsolutePosition:
129         return ( 1000 * mediacontrol_unit_convert( p_input,
130                                                    pos->key, /* from */
131                                                    mediacontrol_MediaTime,  /* to */
132                                                    pos->value ) );
133         break;
134     case mediacontrol_RelativePosition:
135     {
136         long long l_pos;
137         vlc_value_t val;
138
139         val.i_time = 0;
140         if( p_input )
141         {
142             var_Get( p_input, "time", &val );
143         }
144
145         l_pos = 1000 * mediacontrol_unit_convert( p_input,
146                                                   pos->key,
147                                                   mediacontrol_MediaTime,
148                                                   pos->value );
149         return val.i_time + l_pos;
150         break;
151     }
152     case mediacontrol_ModuloPosition:
153     {
154         long long l_pos;
155         vlc_value_t val;
156
157         val.i_time = 0;
158         if( p_input )
159         {
160             var_Get( p_input, "length", &val );
161         }
162
163         if( val.i_time > 0)
164         {
165             l_pos = ( 1000 * mediacontrol_unit_convert( p_input,
166                                                         pos->key,
167                                                         mediacontrol_MediaTime,
168                                                         pos->value ) );
169         }
170         else
171             l_pos = 0;
172
173         return l_pos % val.i_time;
174         break;
175     }
176     }
177     return 0;
178 }
179
180 mediacontrol_RGBPicture*
181 mediacontrol_RGBPicture__alloc( int datasize )
182 {
183     mediacontrol_RGBPicture* pic;
184
185     pic = ( mediacontrol_RGBPicture * )malloc( sizeof( mediacontrol_RGBPicture ) );
186     if( ! pic )
187         return NULL;
188
189     pic->size = datasize;
190     pic->data = ( char* )malloc( datasize );
191     return pic;
192 }
193
194 void
195 mediacontrol_RGBPicture__free( mediacontrol_RGBPicture* pic )
196 {
197     if( pic )
198         free( pic->data );
199     free( pic );
200 }
201
202 mediacontrol_PlaylistSeq*
203 mediacontrol_PlaylistSeq__alloc( int size )
204 {
205     mediacontrol_PlaylistSeq* ps;
206
207     ps =( mediacontrol_PlaylistSeq* )malloc( sizeof( mediacontrol_PlaylistSeq ) );
208     if( ! ps )
209         return NULL;
210
211     ps->size = size;
212     ps->data = ( char** )malloc( size * sizeof( char* ) );
213     return ps;
214 }
215
216 void
217 mediacontrol_PlaylistSeq__free( mediacontrol_PlaylistSeq* ps )
218 {
219     if( ps )
220     {
221         int i;
222         for( i = 0 ; i < ps->size ; i++ )
223             free( ps->data[i] );
224     }
225     free( ps->data );
226     free( ps );
227 }
228
229 mediacontrol_Exception*
230 mediacontrol_exception_init( mediacontrol_Exception *exception )
231 {
232     if( exception == NULL )
233     {
234         exception = ( mediacontrol_Exception* )malloc( sizeof( mediacontrol_Exception ) );
235     }
236
237     exception->code = 0;
238     exception->message = NULL;
239     return exception;
240 }
241
242 void
243 mediacontrol_exception_free( mediacontrol_Exception *exception )
244 {
245     if( ! exception )
246         return;
247
248     free( exception->message );
249     free( exception );
250 }
251
252 mediacontrol_Instance* mediacontrol_new_from_object( vlc_object_t* p_object,
253                                                      mediacontrol_Exception *exception )
254 {
255     mediacontrol_Instance* retval;
256     vlc_object_t *p_vlc;
257
258     p_vlc = vlc_object_find( p_object, VLC_OBJECT_ROOT, FIND_PARENT );
259     if( ! p_vlc )
260     {
261         RAISE( mediacontrol_InternalException, "Unable to initialize VLC" );
262         return NULL;
263     }
264     retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
265     retval->p_vlc = p_vlc;
266     retval->vlc_object_id = p_vlc->i_object_id;
267
268     /* We can keep references on these, which should not change. Is it true ? */
269     retval->p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
270     retval->p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_ANYWHERE );
271
272     if( ! retval->p_playlist || ! retval->p_intf )
273     {
274         RAISE( mediacontrol_InternalException, "No available interface" );
275         return NULL;
276     }
277     return retval;
278 };
279
280 /* Returns the current position in the stream. The returned value can
281    be relative or absolute( according to PositionOrigin ) and the unit
282    is set by PositionKey */
283 mediacontrol_Position*
284 mediacontrol_get_media_position( mediacontrol_Instance *self,
285                                  const mediacontrol_PositionOrigin an_origin,
286                                  const mediacontrol_PositionKey a_key,
287                                  mediacontrol_Exception *exception )
288 {
289     mediacontrol_Position* retval;
290     vlc_value_t val;
291     input_thread_t * p_input = self->p_playlist->p_input;
292
293     exception = mediacontrol_exception_init( exception );
294
295     retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) );
296     retval->origin = an_origin;
297     retval->key = a_key;
298
299     if( ! p_input )
300     {
301         /*
302            RAISE( mediacontrol_InternalException, "No input thread." );
303            return( NULL );
304         */
305         retval->value = 0;
306         return retval;
307     }
308
309     if(  an_origin == mediacontrol_RelativePosition
310          || an_origin == mediacontrol_ModuloPosition )
311     {
312         /* Relative or ModuloPosition make no sense */
313         retval->value = 0;
314         return retval;
315     }
316
317     /* We are asked for an AbsolutePosition. */
318     val.i_time = 0;
319     var_Get( p_input, "time", &val );
320     /* FIXME: check val.i_time > 0 */
321
322     retval->value = mediacontrol_unit_convert( p_input,
323                                                mediacontrol_MediaTime,
324                                                a_key,
325                                                val.i_time / 1000 );
326     return retval;
327 }
328
329 /* Sets the media position */
330 void
331 mediacontrol_set_media_position( mediacontrol_Instance *self,
332                                  const mediacontrol_Position * a_position,
333                                  mediacontrol_Exception *exception )
334 {
335     vlc_value_t val;
336     input_thread_t * p_input = self->p_playlist->p_input;
337
338     exception=mediacontrol_exception_init( exception );
339     if( ! p_input )
340     {
341         RAISE( mediacontrol_InternalException, "No input thread." );
342         return;
343     }
344
345     if( !var_GetBool( p_input, "seekable" ) )
346     {
347         RAISE( mediacontrol_InvalidPosition, "Stream not seekable" );
348         return;
349     }
350
351     val.i_time = mediacontrol_position2microsecond( p_input, a_position );
352     var_Set( p_input, "time", val );
353     return;
354 }
355
356 /* Starts playing a stream */
357 void
358 mediacontrol_start( mediacontrol_Instance *self,
359                     const mediacontrol_Position * a_position,
360                     mediacontrol_Exception *exception )
361 {
362     playlist_t * p_playlist = self->p_playlist;
363
364     exception = mediacontrol_exception_init( exception );
365     if( ! p_playlist )
366     {
367         RAISE( mediacontrol_PlaylistException, "No available playlist" );
368         return;
369     }
370
371     vlc_mutex_lock( &p_playlist->object_lock );
372     if( p_playlist->i_size )
373     {
374         vlc_value_t val;
375
376         vlc_mutex_unlock( &p_playlist->object_lock );
377
378         /* Set start time */
379         val.i_int = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000;
380         var_Set( p_playlist, "start-time", val );
381
382         playlist_Play( p_playlist );
383     }
384     else
385     {
386         RAISE( mediacontrol_PlaylistException, "Empty playlist." );
387         vlc_mutex_unlock( &p_playlist->object_lock );
388         return;
389     }
390
391     return;
392 }
393
394 void
395 mediacontrol_pause( mediacontrol_Instance *self,
396                     const mediacontrol_Position * a_position,
397                     mediacontrol_Exception *exception )
398 {
399     input_thread_t *p_input = self->p_playlist->p_input;;
400
401     /* FIXME: use the a_position parameter */
402     exception=mediacontrol_exception_init( exception );
403     if( p_input != NULL )
404     {
405         var_SetInteger( p_input, "state", PAUSE_S );
406     }
407     else
408     {
409         RAISE( mediacontrol_InternalException, "No input" );
410     }
411
412     return;
413 }
414
415 void
416 mediacontrol_resume( mediacontrol_Instance *self,
417                      const mediacontrol_Position * a_position,
418                      mediacontrol_Exception *exception )
419 {
420     input_thread_t *p_input = self->p_playlist->p_input;
421
422     /* FIXME: use the a_position parameter */
423     exception=mediacontrol_exception_init( exception );
424     if( p_input != NULL )
425     {
426         var_SetInteger( p_input, "state", PAUSE_S );
427     }
428     else
429     {
430         RAISE( mediacontrol_InternalException, "No input" );
431     }
432 }
433
434 void
435 mediacontrol_stop( mediacontrol_Instance *self,
436                    const mediacontrol_Position * a_position,
437                    mediacontrol_Exception *exception )
438 {
439     /* FIXME: use the a_position parameter */
440     exception=mediacontrol_exception_init( exception );
441     if( !self->p_playlist )
442     {
443         RAISE( mediacontrol_PlaylistException, "No playlist" );
444         return;
445     }
446
447     playlist_Stop( self->p_playlist );
448 }
449
450 void
451 mediacontrol_playlist_add_item( mediacontrol_Instance *self,
452                                 const char * psz_file,
453                                 mediacontrol_Exception *exception )
454 {
455     exception=mediacontrol_exception_init( exception );
456     if( !self->p_playlist )
457     {
458         RAISE( mediacontrol_InternalException, "No playlist" );
459         return;
460     }
461
462     playlist_Add( self->p_playlist, psz_file, psz_file , PLAYLIST_REPLACE, 0 );
463 }
464
465 void
466 mediacontrol_playlist_clear( mediacontrol_Instance *self,
467                              mediacontrol_Exception *exception )
468 {
469     exception=mediacontrol_exception_init( exception );
470     if( !self->p_playlist )
471     {
472         RAISE( mediacontrol_PlaylistException, "No playlist" );
473         return;
474     }
475
476     playlist_Clear( self->p_playlist );
477
478     return;
479 }
480
481 mediacontrol_PlaylistSeq *
482 mediacontrol_playlist_get_list( mediacontrol_Instance *self,
483                                 mediacontrol_Exception *exception )
484 {
485     mediacontrol_PlaylistSeq *retval;
486     int i_index;
487     playlist_t * p_playlist = self->p_playlist;;
488     int i_playlist_size;
489
490     exception=mediacontrol_exception_init( exception );
491     if( !p_playlist )
492     {
493         RAISE( mediacontrol_PlaylistException, "No playlist" );
494         return NULL;
495     }
496
497     vlc_mutex_lock( &p_playlist->object_lock );
498     i_playlist_size = p_playlist->i_size;
499
500     retval = mediacontrol_PlaylistSeq__alloc( i_playlist_size );
501
502     for( i_index = 0 ; i_index < i_playlist_size ; i_index++ )
503     {
504         retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->input.psz_uri );
505     }
506     vlc_mutex_unlock( &p_playlist->object_lock );
507
508     return retval;
509 }
510
511 mediacontrol_RGBPicture*
512 _mediacontrol_createRGBPicture( int i_width, int i_height, long i_chroma, long long l_date,
513                                 char* p_data, int i_datasize )
514 {
515     mediacontrol_RGBPicture *retval;
516
517     retval = mediacontrol_RGBPicture__alloc( i_datasize );
518     if( retval )
519     {
520         retval->width  = i_width;
521         retval->height = i_height;
522         retval->type   = i_chroma;
523         retval->date   = l_date;
524         retval->size   = i_datasize;
525         memcpy( retval->data, p_data, i_datasize );
526     }
527     return retval;
528 }
529
530 mediacontrol_RGBPicture *
531 mediacontrol_snapshot( mediacontrol_Instance *self,
532                        const mediacontrol_Position * a_position,
533                        mediacontrol_Exception *exception )
534 {
535     mediacontrol_RGBPicture *retval = NULL;
536     input_thread_t* p_input = self->p_playlist->p_input;
537     vout_thread_t *p_vout = NULL;
538     int i_datasize;
539     snapshot_t **pointer;
540     vlc_value_t val;
541     int i_index;
542     snapshot_t *p_best_snapshot;
543     long searched_date;
544 #ifdef HAS_SNAPSHOT
545     int i_cachesize;
546 #endif
547
548     exception=mediacontrol_exception_init( exception );
549
550     /*
551        if( var_Get( self->p_vlc, "snapshot-id", &val ) == VLC_SUCCESS )
552        p_vout = vlc_object_get( self->p_vlc, val.i_int );
553     */
554
555     /* FIXME: if in p_libvlc, we cannot have multiple video outputs */
556     /* Once corrected, search for snapshot-id to modify all instances */
557     if( var_Get( p_input, "snapshot-id", &val ) != VLC_SUCCESS )
558     {
559         RAISE( mediacontrol_InternalException, "No snapshot-id in p_input" );
560         return NULL;
561     }
562     p_vout = vlc_object_get( self->p_vlc, val.i_int );
563
564     if( ! p_vout )
565     {
566         RAISE( mediacontrol_InternalException, "No snapshot module" );
567         return NULL;
568     }
569
570 #ifdef HAS_SNAPSHOT
571     /* We test if the vout is a snapshot module. We cannot test
572        pvout_psz_object_name( which is NULL ). But we can check if
573        there are snapshot-specific variables */
574     if( var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS )
575     {
576         RAISE( mediacontrol_InternalException, "No snapshot module" );
577         vlc_object_release( p_vout );
578         return NULL;
579     }
580     i_datasize = val.i_int;
581
582     /* Handle the a_position parameter */
583     if( ! ( a_position->origin == mediacontrol_RelativePosition
584             && a_position->value == 0 ) )
585     {
586         /* The position is not the current one. Go to it. */
587         mediacontrol_set_media_position( self,
588                                          ( mediacontrol_Position* ) a_position,
589                                          exception );
590         if( exception->code )
591         {
592             vlc_object_release( p_vout );
593             return NULL;
594         }
595     }
596
597     /* FIXME: We should not go further until we got past the position
598        ( which means that we had the possibility to capture the right
599        picture ). */
600
601     vlc_mutex_lock( &p_vout->picture_lock );
602
603     searched_date = mediacontrol_position2microsecond( p_input,
604                                                        ( mediacontrol_Position * ) a_position );
605
606     var_Get( p_vout, "snapshot-cache-size", &val );
607     i_cachesize = val.i_int  ;
608
609     var_Get( p_vout, "snapshot-list-pointer", &val );
610     pointer = ( snapshot_t ** )val.p_address;
611
612     if( ! pointer )
613     {
614         RAISE( mediacontrol_InternalException, "No available snapshot" );
615
616         vlc_mutex_unlock( &p_vout->picture_lock );
617         vlc_object_release( p_vout );
618         return NULL;
619     }
620
621     /* Find the more appropriate picture, based on date */
622     p_best_snapshot = pointer[0];
623
624     for( i_index = 1 ; i_index < i_cachesize ; i_index++ )
625     {
626         long l_diff = pointer[i_index]->date - searched_date;
627         if( l_diff > 0 && l_diff < abs( p_best_snapshot->date - searched_date ))
628         {
629             /* This one is closer, and _after_ the requested position */
630             p_best_snapshot = pointer[i_index];
631         }
632     }
633
634     /* FIXME: add a test for the case that no picture matched the test
635        ( we have p_best_snapshot == pointer[0] */
636     retval = _mediacontrol_createRGBPicture( p_best_snapshot->i_width,
637                                              p_best_snapshot->i_height,
638                                              p_vout->output.i_chroma,
639                                              p_best_snapshot->date,
640                                              p_best_snapshot->p_data,
641                                              i_datasize );
642
643     vlc_mutex_unlock( &p_vout->picture_lock );
644     vlc_object_release( p_vout );
645
646 #endif
647
648     return retval;
649 }
650
651 mediacontrol_RGBPicture **
652 mediacontrol_all_snapshots( mediacontrol_Instance *self,
653                             mediacontrol_Exception *exception )
654 {
655     mediacontrol_RGBPicture **retval = NULL;
656     vout_thread_t *p_vout = NULL;
657     int i_datasize;
658     int i_cachesize;
659     vlc_value_t val;
660     int i_index;
661 #ifdef HAS_SNAPSHOT
662     snapshot_t **pointer;
663 #endif
664
665     exception=mediacontrol_exception_init( exception );
666
667     if( var_Get( self->p_playlist->p_input, "snapshot-id", &val ) == VLC_SUCCESS )
668         p_vout = vlc_object_get( self->p_vlc, val.i_int );
669
670     if( ! p_vout )
671     {
672         RAISE( mediacontrol_InternalException, "No snapshot module" );
673         return NULL;
674     }
675 #ifdef HAS_SNAPSHOT
676     /* We test if the vout is a snapshot module. We cannot test
677        pvout_psz_object_name( which is NULL ). But we can check if
678        there are snapshot-specific variables */
679     if( var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS )
680     {
681         RAISE( mediacontrol_InternalException, "No snapshot module" );
682         vlc_object_release( p_vout );
683         return NULL;
684     }
685     i_datasize = val.i_int;
686
687     vlc_mutex_lock( &p_vout->picture_lock );
688
689     var_Get( p_vout, "snapshot-cache-size", &val );
690     i_cachesize = val.i_int  ;
691
692     var_Get( p_vout, "snapshot-list-pointer", &val );
693     pointer = ( snapshot_t ** )val.p_address;
694
695     if( ! pointer )
696     {
697         RAISE( mediacontrol_InternalException, "No available picture" );
698
699         vlc_mutex_unlock( &p_vout->picture_lock );
700         vlc_object_release( p_vout );
701         return NULL;
702     }
703
704     retval = ( mediacontrol_RGBPicture** )malloc( (i_cachesize + 1 ) * sizeof( char* ));
705
706     for( i_index = 0 ; i_index < i_cachesize ; i_index++ )
707     {
708         snapshot_t *p_s = pointer[i_index];
709         mediacontrol_RGBPicture *p_rgb;
710
711         p_rgb = _mediacontrol_createRGBPicture( p_s->i_width,
712                                                 p_s->i_height,
713                                                 p_vout->output.i_chroma,
714                                                 p_s->date,
715                                                 p_s->p_data,
716                                                 i_datasize );
717
718         retval[i_index] = p_rgb;
719     }
720
721     retval[i_cachesize] = NULL;
722
723     vlc_mutex_unlock( &p_vout->picture_lock );
724     vlc_object_release( p_vout );
725
726 #endif
727
728     return retval;
729 }
730
731 void
732 mediacontrol_display_text( mediacontrol_Instance *self,
733                            const char * message,
734                            const mediacontrol_Position * begin,
735                            const mediacontrol_Position * end,
736                            mediacontrol_Exception *exception )
737 {
738     input_thread_t *p_input = NULL;
739     vout_thread_t *p_vout = NULL;
740
741     p_vout = vlc_object_find( self->p_playlist, VLC_OBJECT_VOUT, FIND_CHILD );
742     if( ! p_vout )
743     {
744         RAISE( mediacontrol_InternalException, "No video output" );
745         return;
746     }
747
748     if( begin->origin == mediacontrol_RelativePosition &&
749         begin->value == 0 &&
750         end->origin == mediacontrol_RelativePosition )
751     {
752         mtime_t i_duration = 0;
753
754         i_duration = 1000 * mediacontrol_unit_convert( self->p_playlist->p_input,
755                                                        end->key,
756                                                        mediacontrol_MediaTime,
757                                                        end->value );
758
759         vout_ShowTextRelative( p_vout, DEFAULT_CHAN, ( char* ) message, NULL,
760                                OSD_ALIGN_BOTTOM | OSD_ALIGN_LEFT, 20, 20,
761                                i_duration );
762     }
763     else
764     {
765         mtime_t i_debut, i_fin, i_now;
766
767         p_input = self->p_playlist->p_input;
768         if( ! p_input )
769         {
770             RAISE( mediacontrol_InternalException, "No input" );
771             vlc_object_release( p_vout );
772             return;
773         }
774
775         /* FIXME */
776         /* i_now = input_ClockGetTS( p_input, NULL, 0 ); */
777         i_now = 0;
778         
779         i_debut = mediacontrol_position2microsecond( p_input,
780                                                      ( mediacontrol_Position* ) begin );
781         i_debut += i_now;
782
783         i_fin = mediacontrol_position2microsecond( p_input,
784                                                    ( mediacontrol_Position * ) end );
785         i_fin += i_now;
786
787         vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, ( char* ) message, NULL,
788                                OSD_ALIGN_BOTTOM | OSD_ALIGN_LEFT, 20, 20,
789                                i_debut, i_fin );
790     }
791
792     vlc_object_release( p_vout );
793 }
794
795 mediacontrol_StreamInformation *
796 mediacontrol_get_stream_information( mediacontrol_Instance *self,
797                                      mediacontrol_PositionKey a_key,
798                                      mediacontrol_Exception *exception )
799 {
800     mediacontrol_StreamInformation *retval;
801     input_thread_t *p_input = self->p_playlist->p_input;
802     vlc_value_t val;
803
804     retval = ( mediacontrol_StreamInformation* )malloc( sizeof( mediacontrol_StreamInformation ) );
805     if( ! retval )
806     {
807         RAISE( mediacontrol_InternalException, "Out of memory" );
808         return NULL;
809     }
810
811     if( ! p_input )
812     {
813         /* No p_input defined */
814         retval->streamstatus = mediacontrol_UndefinedStatus;
815         retval->url          = strdup( "None" );
816         retval->position     = 0;
817         retval->length       = 0;
818     }
819     else
820     {
821         switch( var_GetInteger( p_input, "state" ) )
822         {
823         case PLAYING_S     :
824             retval->streamstatus = mediacontrol_PlayingStatus;
825             break;
826         case PAUSE_S       :
827             retval->streamstatus = mediacontrol_PauseStatus;
828             break;
829         case INIT_S        :
830             retval->streamstatus = mediacontrol_InitStatus;
831             break;
832         case END_S         :
833             retval->streamstatus = mediacontrol_EndStatus;
834             break;
835         default :
836             retval->streamstatus = mediacontrol_UndefinedStatus;
837             break;
838         }
839
840         retval->url = strdup( p_input->input.p_item->psz_uri );
841
842         /* TIME and LENGTH are in microseconds. We want them in ms */
843         var_Get( p_input, "time", &val);
844         retval->position = val.i_time / 1000;
845
846         var_Get( p_input, "length", &val);
847         retval->length = val.i_time / 1000;
848
849         retval->position = mediacontrol_unit_convert( p_input,
850                                                       mediacontrol_MediaTime, a_key,
851                                                       retval->position );
852         retval->length   = mediacontrol_unit_convert( p_input,
853                                                       mediacontrol_MediaTime, a_key,
854                                                       retval->length );
855     }
856     return retval;
857 }
858
859 unsigned short
860 mediacontrol_sound_get_volume( mediacontrol_Instance *self,
861                                mediacontrol_Exception *exception )
862 {
863     short retval;
864     audio_volume_t i_volume;
865
866     if( !self->p_intf )
867     {
868         RAISE( mediacontrol_InternalException, "No interface module" );
869         return 0;
870     }
871     aout_VolumeGet( self->p_intf, &i_volume );
872     retval = i_volume;
873     return retval;
874 }
875
876 void
877 mediacontrol_sound_set_volume( mediacontrol_Instance *self,
878                                const unsigned short volume,
879                                mediacontrol_Exception *exception )
880 {
881     if( !self->p_intf )
882     {
883         RAISE( mediacontrol_InternalException, "No interface module" );
884         return;
885     }
886     aout_VolumeSet( self->p_intf,( audio_volume_t )volume );
887 }