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