@ -18,8 +18,7 @@ typedef struct scope_plugin_s scope_plugin_t;
struct scope_plugin_s
struct scope_plugin_s
{
{
post_plugin_t post ;
post_plugin_t post ;
int64_t pts_per_smpls ;
metronom_t metronom ;
int channels ;
int channels ;
MyNode * list ;
MyNode * list ;
} ;
} ;
@ -31,8 +30,8 @@ struct scope_plugin_s
static int
static int
scope_port_open ( xine_audio_port_t * port_gen , xine_stream_t * stream , uint32_t bits , uint32_t rate , int mode )
scope_port_open ( xine_audio_port_t * port_gen , xine_stream_t * stream , uint32_t bits , uint32_t rate , int mode )
{
{
# define port ((post_audio_port_t*)port_gen)
post_audio_port_t * port = ( post_audio_port_t * ) port_gen ;
# define this ((scope_plugin_t*)((post_audio_port_t*)port_gen)->post)
scope_plugin_t * this = ( scope_plugin_t * ) port - > post ;
_x_post_rewire ( ( post_plugin_t * ) port - > post ) ;
_x_post_rewire ( ( post_plugin_t * ) port - > post ) ;
_x_post_inc_usage ( port ) ;
_x_post_inc_usage ( port ) ;
@ -44,17 +43,28 @@ scope_port_open( xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t bi
this - > channels = _x_ao_mode2channels ( mode ) ;
this - > channels = _x_ao_mode2channels ( mode ) ;
return port - > original_port - > open ( port - > original_port , stream , bits , rate , mode ) ;
int ret = port - > original_port - > open ( port - > original_port , stream , bits , rate , mode ) ;
# if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION > = 10 )
this - > pts_per_smpls = ( ( uint32_t ) 90000 * ( uint32_t ) 32768 ) / rate ;
# else
this - > pts_per_smpls = stream - > metronom - > pts_per_smpls ;
# endif
return ret ;
}
}
static void
static void
scope_port_close ( xine_audio_port_t * port_gen , xine_stream_t * stream )
scope_port_close ( xine_audio_port_t * port_gen , xine_stream_t * stream )
{
{
MyNode * node ;
post_audio_port_t * port = ( post_audio_port_t * ) port_gen ;
scope_plugin_t * this = ( scope_plugin_t * ) port - > post ;
/* ensure the buffers are deleted during the next XineEngine::timerEvent() */
/* ensure the buffers are deleted during the next XineEngine::timerEvent() */
MyNode * node ;
for ( node = this - > list - > next ; node ! = this - > list ; node = node - > next )
for ( node = this - > list - > next ; node ! = this - > list ; node = node - > next )
{
node - > vpts = node - > vpts_end = - 1 ;
node - > vpts = node - > vpts_end = - 1 ;
}
port - > stream = NULL ;
port - > stream = NULL ;
port - > original_port - > close ( port - > original_port , stream ) ;
port - > original_port - > close ( port - > original_port , stream ) ;
@ -65,27 +75,27 @@ scope_port_close( xine_audio_port_t *port_gen, xine_stream_t *stream )
static void
static void
scope_port_put_buffer ( xine_audio_port_t * port_gen , audio_buffer_t * buf , xine_stream_t * stream )
scope_port_put_buffer ( xine_audio_port_t * port_gen , audio_buffer_t * buf , xine_stream_t * stream )
{
{
# if XINE_MAJOR_VERSION < 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION < 2) || \
post_audio_port_t * port = ( post_audio_port_t * ) port_gen ;
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION < 10 )
scope_plugin_t * this = ( scope_plugin_t * ) port - > post ;
/* FIXME With 8-bit samples the scope won't work correctly. For a special 8-bit code path,
/* FIXME With 8-bit samples the scope won't work correctly. For a special 8-bit code path,
the sample size could be checked like this : if ( port - > bits = = 8 ) */
the sample size could be checked like this : if ( port - > bits = = 8 ) */
const int num_samples = buf - > num_frames * this - > channels ;
const int num_samples = buf - > num_frames * this - > channels ;
metronom_t * myMetronom = & this - > metronom ;
MyNode * new_node ;
MyNode * new_node ;
/* I keep my own metronom because xine wouldn't for some reason */
memcpy ( & this - > metronom , stream - > metronom , sizeof ( metronom_t ) ) ;
new_node = malloc ( sizeof ( MyNode ) ) ;
new_node = malloc ( sizeof ( MyNode ) ) ;
new_node - > vpts = myMetronom - > got_audio_samples ( myMetronom , buf - > vpts , buf - > num_frames ) ;
# ifdef METRONOM_VPTS
new_node - > vpts = stream - > metronom - > get_option ( stream - > metronom , METRONOM_VPTS ) ;
# else
new_node - > vpts = stream - > metronom - > got_audio_samples ( stream - > metronom , 0 , 0 ) ;
# endif
new_node - > num_frames = buf - > num_frames ;
new_node - > num_frames = buf - > num_frames ;
new_node - > mem = malloc ( num_samples * 2 ) ;
new_node - > mem = malloc ( num_samples * 2 ) ;
memcpy ( new_node - > mem , buf - > mem , num_samples * 2 ) ;
memcpy ( new_node - > mem , buf - > mem , num_samples * 2 ) ;
{
{
int64_t
int64_t
K = myMetronom - > pts_per_smpls ; /*smpls = 1<<16 samples*/
K = this - > pts_per_smpls ;
K * = num_samples ;
K * = num_samples ;
K / = ( 1 < < 16 ) ;
K / = ( 1 < < 16 ) ;
K + = new_node - > vpts ;
K + = new_node - > vpts ;
@ -99,10 +109,6 @@ scope_port_put_buffer( xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_st
* this is thread - safe due to the way we handle the list in the GUI thread */
* this is thread - safe due to the way we handle the list in the GUI thread */
new_node - > next = this - > list - > next ;
new_node - > next = this - > list - > next ;
this - > list - > next = new_node ;
this - > list - > next = new_node ;
# endif
# undef port
# undef this
}
}
static void
static void
@ -123,7 +129,6 @@ scope_dispose( post_plugin_t *this )
}
}
while ( node ! = list ) ;
while ( node ! = list ) ;
free ( this ) ;
free ( this ) ;
}
}
@ -132,10 +137,14 @@ scope_dispose( post_plugin_t *this )
* plugin init function *
* plugin init function *
* * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * */
xine_post_t *
# if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
scope_plugin_new ( xine_t * xine , xine_audio_port_t * audio_target )
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION > = 10 )
static post_plugin_t * scope_plugin_new ( post_class_t * class_gen , int inputs , xine_audio_port_t * audio_target [ ] , xine_video_port_t * video_target [ ] )
# else
xine_post_t * scope_plugin_new ( xine_t * xine , xine_audio_port_t * audio_target )
# endif
{
{
scope_plugin_t * scope_plugin = xine_xmalloc ( sizeof ( scope_plugin_t ) ) ;
scope_plugin_t * scope_plugin = calloc( 1 , sizeof ( scope_plugin_t ) ) ;
post_plugin_t * post_plugin = ( post_plugin_t * ) scope_plugin ;
post_plugin_t * post_plugin = ( post_plugin_t * ) scope_plugin ;
{
{
@ -145,7 +154,12 @@ scope_plugin_new( xine_t *xine, xine_audio_port_t *audio_target )
_x_post_init ( post_plugin , 1 , 0 ) ;
_x_post_init ( post_plugin , 1 , 0 ) ;
# if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION > = 10 )
port = _x_post_intercept_audio_port ( post_plugin , audio_target [ 0 ] , & input , & output ) ;
# else
port = _x_post_intercept_audio_port ( post_plugin , audio_target , & input , & output ) ;
port = _x_post_intercept_audio_port ( post_plugin , audio_target , & input , & output ) ;
# endif
port - > new_port . open = scope_port_open ;
port - > new_port . open = scope_port_open ;
port - > new_port . close = scope_port_close ;
port - > new_port . close = scope_port_close ;
port - > new_port . put_buffer = scope_port_put_buffer ;
port - > new_port . put_buffer = scope_port_put_buffer ;
@ -161,32 +175,60 @@ scope_plugin_new( xine_t *xine, xine_audio_port_t *audio_target )
/* code is straight from xine_init_post()
/* code is straight from xine_init_post()
can ' t use that function as it only dlopens the plugins
can ' t use that function as it only dlopens the plugins
and our plugin is statically linked in */
and our plugin is statically linked in */
post_plugin - > running_ticket = xine - > port_ticket ;
post_plugin - > running_ticket = xine - > port_ticket ;
post_plugin - > xine = xine ;
post_plugin - > xine = xine ;
# endif
# endif
/* scope_plugin_t init */
/* scope_plugin_t init */
scope_plugin - > list = xine_xmalloc( sizeof ( MyNode ) ) ;
scope_plugin - > list = calloc( 1 , sizeof ( MyNode ) ) ;
scope_plugin - > list - > next = scope_plugin - > list ;
scope_plugin - > list - > next = scope_plugin - > list ;
# if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION > = 10 )
return post_plugin ;
# else
return & post_plugin - > xine_post ;
return & post_plugin - > xine_post ;
# endif
}
}
MyNode *
MyNode * scope_plugin_list ( void * post )
scope_plugin_list ( void * post )
{
{
return ( ( scope_plugin_t * ) post ) - > list ;
return ( ( scope_plugin_t * ) post ) - > list ;
}
}
int
int scope_plugin_channels ( void * post )
scope_plugin_channels ( void * post )
{
{
return ( ( scope_plugin_t * ) post ) - > channels ;
return ( ( scope_plugin_t * ) post ) - > channels ;
}
}
metronom_t *
int64_t scope_plugin_pts_per_smpls ( void * post )
scope_plugin_metronom ( void * post )
{
{
return & ( ( scope_plugin_t * ) post ) - > metronom ;
return ( ( scope_plugin_t * ) post ) - > pts_per_smpls ;
}
# if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
( XINE_MAJOR_VERSION = = 1 & & XINE_MINOR_VERSION = = 2 & & XINE_SUB_VERSION > = 10 )
static void * scope_init_plugin ( xine_t * xine , const void * data )
{
static const post_class_t post_scope_class = {
. open_plugin = scope_plugin_new ,
. identifier = " amarok-scope " ,
. description = " Amarok Scope " ,
. dispose = NULL ,
} ;
( void ) xine ;
( void ) data ;
return ( void * ) & post_scope_class ;
}
}
static const post_info_t scope_special_info = {
. type = XINE_POST_TYPE_AUDIO_VISUALIZATION ,
} ;
const plugin_info_t scope_plugin_info [ ] = {
{ PLUGIN_POST , 10 , " amarok-scope " , XINE_VERSION_CODE , & scope_special_info , scope_init_plugin } ,
{ PLUGIN_NONE , 0 , NULL , 0 , NULL , NULL }
} ;
# endif