mediacontrol-core.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:26k
源码类别:

多媒体

开发平台:

MultiPlatform

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