📄 mediacontrol-core.c
字号:
#include "mediacontrol-core.h"#include <vlc/intf.h>#include <vlc/vout.h>#include <vlc/aout.h>#include <vlc_demux.h>#include <osd.h>#define HAS_SNAPSHOT 1#ifdef HAS_SNAPSHOT#include <snapshot.h>#endif#include <stdlib.h> /* malloc(), free() */#include <string.h>#include <errno.h> /* ENOMEM */#include <stdio.h>#include <ctype.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_TIME_H# include <sys/time.h>#endif#include <sys/types.h>#define RAISE( c, m ) exception->code = c; \ exception->message = strdup(m);long long mediacontrol_unit_convert( input_thread_t *p_input, mediacontrol_PositionKey from, mediacontrol_PositionKey to, long long value ){ if( to == from ) return value; /* For all conversions, we need data from p_input */ if( !p_input ) return 0; switch( from ) { case mediacontrol_MediaTime: if( to == mediacontrol_ByteCount ) { /* FIXME */ /* vlc < 0.8 API */ /* return value * 50 * p_input->stream.i_mux_rate / 1000; */ return 0; } if( to == mediacontrol_SampleCount ) { double f_fps; if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 ) return 0; else return( value * f_fps / 1000.0 ); } /* Cannot happen */ /* See http://catb.org/~esr/jargon/html/entry/can't-happen.html */ break; case mediacontrol_SampleCount: { double f_fps; if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 ) return 0; if( to == mediacontrol_ByteCount ) { /* FIXME */ /* vlc < 0.8 API *//* return ( long long )( value * 50 * p_input->stream.i_mux_rate / f_fps ); */ return 0; } if( to == mediacontrol_MediaTime ) return( long long )( value * 1000.0 / ( double )f_fps ); /* Cannot happen */ break; } case mediacontrol_ByteCount: /* FIXME */ return 0;/* vlc < 0.8 API: */// if( p_input->stream.i_mux_rate == 0 )// return 0;// // /* Convert an offset into milliseconds. Taken from input_ext-intf.c.// The 50 hardcoded constant comes from the definition of i_mux_rate :// i_mux_rate : the rate we read the stream (in units of 50 bytes/s) ;// 0 if undef */// if( to == mediacontrol_MediaTime )// return ( long long )( 1000 * value / 50 / p_input->stream.i_mux_rate );// // if( to == mediacontrol_SampleCount )// {// double f_fps;// if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )// return 0;// else// return ( long long )( value * f_fps / 50 / p_input->stream.i_mux_rate );// } /* Cannot happen */ break; } /* Cannot happen */ return 0;}/* Converts a mediacontrol_Position into a time in microseconds in movie clock time */long longmediacontrol_position2microsecond( input_thread_t* p_input, const mediacontrol_Position * pos ){ switch( pos->origin ) { case mediacontrol_AbsolutePosition: return ( 1000 * mediacontrol_unit_convert( p_input, pos->key, /* from */ mediacontrol_MediaTime, /* to */ pos->value ) ); break; case mediacontrol_RelativePosition: { long long l_pos; vlc_value_t val; val.i_time = 0; if( p_input ) { var_Get( p_input, "time", &val ); } l_pos = 1000 * mediacontrol_unit_convert( p_input, pos->key, mediacontrol_MediaTime, pos->value ); return val.i_time + l_pos; break; } case mediacontrol_ModuloPosition: { long long l_pos; vlc_value_t val; val.i_time = 0; if( p_input ) { var_Get( p_input, "length", &val ); } if( val.i_time > 0) { l_pos = ( 1000 * mediacontrol_unit_convert( p_input, pos->key, mediacontrol_MediaTime, pos->value ) ); } else l_pos = 0; return l_pos % val.i_time; break; } } return 0;}mediacontrol_RGBPicture*mediacontrol_RGBPicture__alloc( int datasize ){ mediacontrol_RGBPicture* pic; pic = ( mediacontrol_RGBPicture * )malloc( sizeof( mediacontrol_RGBPicture ) ); if( ! pic ) return NULL; pic->size = datasize; pic->data = ( char* )malloc( datasize ); return pic;}voidmediacontrol_RGBPicture__free( mediacontrol_RGBPicture* pic ){ if( pic ) free( pic->data ); free( pic );}mediacontrol_PlaylistSeq*mediacontrol_PlaylistSeq__alloc( int size ){ mediacontrol_PlaylistSeq* ps; ps =( mediacontrol_PlaylistSeq* )malloc( sizeof( mediacontrol_PlaylistSeq ) ); if( ! ps ) return NULL; ps->size = size; ps->data = ( char** )malloc( size * sizeof( char* ) ); return ps;}voidmediacontrol_PlaylistSeq__free( mediacontrol_PlaylistSeq* ps ){ if( ps ) { int i; for( i = 0 ; i < ps->size ; i++ ) free( ps->data[i] ); } free( ps->data ); free( ps );}mediacontrol_Exception*mediacontrol_exception_init( mediacontrol_Exception *exception ){ if( exception == NULL ) { exception = ( mediacontrol_Exception* )malloc( sizeof( mediacontrol_Exception ) ); } exception->code = 0; exception->message = NULL; return exception;}voidmediacontrol_exception_free( mediacontrol_Exception *exception ){ if( ! exception ) return; free( exception->message ); free( exception );}mediacontrol_Instance* mediacontrol_new_from_object( vlc_object_t* p_object, mediacontrol_Exception *exception ){ mediacontrol_Instance* retval; vlc_object_t *p_vlc; p_vlc = vlc_object_find( p_object, VLC_OBJECT_ROOT, FIND_PARENT ); if( ! p_vlc ) { RAISE( mediacontrol_InternalException, "Unable to initialize VLC" ); return NULL; } retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) ); retval->p_vlc = p_vlc; retval->vlc_object_id = p_vlc->i_object_id; /* We can keep references on these, which should not change. Is it true ? */ retval->p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); retval->p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_ANYWHERE ); if( ! retval->p_playlist || ! retval->p_intf ) { RAISE( mediacontrol_InternalException, "No available interface" ); return NULL; } return retval;};/* Returns the current position in the stream. The returned value can be relative or absolute( according to PositionOrigin ) and the unit is set by PositionKey */mediacontrol_Position*mediacontrol_get_media_position( mediacontrol_Instance *self, const mediacontrol_PositionOrigin an_origin, const mediacontrol_PositionKey a_key, mediacontrol_Exception *exception ){ mediacontrol_Position* retval; vlc_value_t val; input_thread_t * p_input = self->p_playlist->p_input; exception = mediacontrol_exception_init( exception ); retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) ); retval->origin = an_origin; retval->key = a_key; if( ! p_input ) { /* RAISE( mediacontrol_InternalException, "No input thread." ); return( NULL ); */ retval->value = 0; return retval; } if( an_origin == mediacontrol_RelativePosition || an_origin == mediacontrol_ModuloPosition ) { /* Relative or ModuloPosition make no sense */ retval->value = 0; return retval; } /* We are asked for an AbsolutePosition. */ val.i_time = 0; var_Get( p_input, "time", &val ); /* FIXME: check val.i_time > 0 */ retval->value = mediacontrol_unit_convert( p_input, mediacontrol_MediaTime, a_key, val.i_time / 1000 ); return retval;}/* Sets the media position */voidmediacontrol_set_media_position( mediacontrol_Instance *self, const mediacontrol_Position * a_position, mediacontrol_Exception *exception ){ vlc_value_t val; input_thread_t * p_input = self->p_playlist->p_input; exception=mediacontrol_exception_init( exception ); if( ! p_input ) { RAISE( mediacontrol_InternalException, "No input thread." ); return; } if( !var_GetBool( p_input, "seekable" ) ) { RAISE( mediacontrol_InvalidPosition, "Stream not seekable" ); return; } val.i_time = mediacontrol_position2microsecond( p_input, a_position ); var_Set( p_input, "time", val ); return;}/* Starts playing a stream */voidmediacontrol_start( mediacontrol_Instance *self, const mediacontrol_Position * a_position, mediacontrol_Exception *exception ){ playlist_t * p_playlist = self->p_playlist; exception = mediacontrol_exception_init( exception ); if( ! p_playlist ) { RAISE( mediacontrol_PlaylistException, "No available playlist" ); return; } vlc_mutex_lock( &p_playlist->object_lock ); if( p_playlist->i_size ) { vlc_value_t val; vlc_mutex_unlock( &p_playlist->object_lock ); /* Set start time */ val.i_int = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000; var_Set( p_playlist, "start-time", val ); playlist_Play( p_playlist ); } else { RAISE( mediacontrol_PlaylistException, "Empty playlist." ); vlc_mutex_unlock( &p_playlist->object_lock ); return; } return;}voidmediacontrol_pause( mediacontrol_Instance *self, const mediacontrol_Position * a_position, mediacontrol_Exception *exception ){ input_thread_t *p_input = self->p_playlist->p_input;; /* FIXME: use the a_position parameter */ exception=mediacontrol_exception_init( exception ); if( p_input != NULL ) { var_SetInteger( p_input, "state", PAUSE_S ); } else { RAISE( mediacontrol_InternalException, "No input" ); } return;}voidmediacontrol_resume( mediacontrol_Instance *self, const mediacontrol_Position * a_position, mediacontrol_Exception *exception ){ input_thread_t *p_input = self->p_playlist->p_input; /* FIXME: use the a_position parameter */ exception=mediacontrol_exception_init( exception ); if( p_input != NULL ) { var_SetInteger( p_input, "state", PAUSE_S ); } else { RAISE( mediacontrol_InternalException, "No input" ); }}voidmediacontrol_stop( mediacontrol_Instance *self, const mediacontrol_Position * a_position, mediacontrol_Exception *exception ){ /* FIXME: use the a_position parameter */ exception=mediacontrol_exception_init( exception ); if( !self->p_playlist ) { RAISE( mediacontrol_PlaylistException, "No playlist" ); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -