2018-02-27 18:06:05 +01:00
/* Author: Max Howell <max.howell@methylblue.com>, (C) 2004
Copyright : See COPYING file that comes with this distribution
This has to be a c file or for some reason it won ' t link ! ( GCC 3.4 .1 )
2018-06-28 23:12:39 +02:00
2018-02-27 18:06:05 +01:00
*/
/* need access to port_ticket */
2019-05-27 21:56:07 +02:00
# ifndef XINE_ENGINE_INTERNAL
# define XINE_ENGINE_INTERNAL
# endif
2018-02-27 18:06:05 +01:00
# include "config.h"
# include "xinescope.h"
# include <xine/post.h>
# include <xine/xine_internal.h>
typedef struct scope_plugin_s scope_plugin_t ;
2018-05-01 00:41:33 +02:00
struct scope_plugin_s {
2018-06-28 23:12:39 +02:00
post_plugin_t post ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
metronom_t metronom ;
int channels ;
MyNode * list ;
2018-02-27 18:06:05 +01:00
} ;
/*************************
* post plugin functions *
* * * * * * * * * * * * * * * * * * * * * * * * */
2018-06-28 01:15:32 +02:00
static int scope_port_open ( xine_audio_port_t * port_gen , xine_stream_t * stream , uint32_t bits , uint32_t rate , int mode ) {
2018-05-01 00:41:33 +02:00
2018-06-28 23:12:39 +02:00
# define port ((post_audio_port_t*)port_gen)
# define this ((scope_plugin_t*)((post_audio_port_t*)port_gen)->post)
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
_x_post_rewire ( ( post_plugin_t * ) port - > post ) ;
_x_post_inc_usage ( port ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
port - > stream = stream ;
port - > bits = bits ;
port - > rate = rate ;
port - > mode = mode ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
this - > channels = _x_ao_mode2channels ( mode ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
return port - > original_port - > open ( port - > original_port , stream , bits , rate , mode ) ;
2018-02-27 18:06:05 +01:00
}
2018-06-28 01:15:32 +02:00
static void scope_port_close ( xine_audio_port_t * port_gen , xine_stream_t * stream ) {
2018-05-01 00:41:33 +02:00
2018-06-28 23:12:39 +02:00
MyNode * node ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
/* ensure the buffers are deleted during the next XineEngine::timerEvent() */
for ( node = this - > list - > next ; node ! = this - > list ; node = node - > next )
node - > vpts = node - > vpts_end = - 1 ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
port - > stream = NULL ;
port - > original_port - > close ( port - > original_port , stream ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
_x_post_dec_usage ( port ) ;
2018-02-27 18:06:05 +01:00
}
2018-06-28 01:15:32 +02:00
static void scope_port_put_buffer ( xine_audio_port_t * port_gen , audio_buffer_t * buf , xine_stream_t * stream ) {
/* 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) */
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
const int num_samples = buf - > num_frames * this - > channels ;
metronom_t * myMetronom = & this - > metronom ;
MyNode * new_node ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
/* I keep my own metronom because xine wouldn't for some reason */
memcpy ( & this - > metronom , stream - > metronom , sizeof ( metronom_t ) ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
new_node = ( MyNode * ) malloc ( sizeof ( MyNode ) ) ;
new_node - > vpts = myMetronom - > got_audio_samples ( myMetronom , buf - > vpts , buf - > num_frames ) ;
new_node - > num_frames = buf - > num_frames ;
new_node - > mem = ( int16_t * ) malloc ( num_samples * 2 ) ;
memcpy ( new_node - > mem , buf - > mem , num_samples * 2 ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
{
int64_t
2020-07-16 00:44:41 +02:00
K = 32768 ; /*smpls = 1<<16 samples*/
2018-06-28 23:12:39 +02:00
K * = num_samples ;
K / = ( 1 < < 16 ) ;
K + = new_node - > vpts ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
new_node - > vpts_end = K ;
}
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
port - > original_port - > put_buffer ( port - > original_port , buf , stream ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
/* Finally we should append the current buffer to the list
* This is thread - safe due to the way we handle the list in the GUI thread */
new_node - > next = this - > list - > next ;
this - > list - > next = new_node ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
# undef port
# undef this
2018-02-27 18:06:05 +01:00
}
2018-06-28 23:12:39 +02:00
static void scope_dispose ( post_plugin_t * post ) {
MyNode * list = ( ( scope_plugin_t * ) post ) - > list ;
MyNode * prev ;
MyNode * node = list ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
/* Free all elements of the list (a ring buffer) */
do {
prev = node - > next ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
free ( node - > mem ) ;
free ( node ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
node = prev ;
}
while ( node ! = list ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
free ( post ) ;
2018-02-27 18:06:05 +01:00
}
/************************
* plugin init function *
* * * * * * * * * * * * * * * * * * * * * * * */
2018-06-28 23:12:39 +02:00
xine_post_t * scope_plugin_new ( xine_t * xine , xine_audio_port_t * audio_target ) {
2018-05-01 00:41:33 +02:00
2018-06-28 23:12:39 +02:00
scope_plugin_t * scope_plugin = ( scope_plugin_t * ) calloc ( 1 , sizeof ( scope_plugin_t ) ) ;
post_plugin_t * post_plugin = ( post_plugin_t * ) scope_plugin ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
{
post_in_t * input ;
post_out_t * output ;
post_audio_port_t * port ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
_x_post_init ( post_plugin , 1 , 0 ) ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
port = _x_post_intercept_audio_port ( post_plugin , audio_target , & input , & output ) ;
port - > new_port . open = scope_port_open ;
port - > new_port . close = scope_port_close ;
port - > new_port . put_buffer = scope_port_put_buffer ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
post_plugin - > xine_post . audio_input [ 0 ] = & port - > new_port ;
post_plugin - > xine_post . type = PLUGIN_POST ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
post_plugin - > dispose = scope_dispose ;
}
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
// code is straight from xine_init_post() can't use that function as it only dlopens the plugins and our plugin is statically linked in
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
post_plugin - > running_ticket = xine - > port_ticket ;
post_plugin - > xine = xine ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
/* scope_plugin_t init */
scope_plugin - > list = ( MyNode * ) calloc ( 1 , sizeof ( MyNode ) ) ;
scope_plugin - > list - > next = scope_plugin - > list ;
2018-02-27 18:06:05 +01:00
2018-06-28 23:12:39 +02:00
return & post_plugin - > xine_post ;
2018-02-27 18:06:05 +01:00
}
2018-06-28 23:12:39 +02:00
MyNode * scope_plugin_list ( void * post ) {
return ( ( scope_plugin_t * ) post ) - > list ;
2018-02-27 18:06:05 +01:00
}
2018-06-28 01:15:32 +02:00
int scope_plugin_channels ( void * post ) {
2018-06-28 23:12:39 +02:00
return ( ( scope_plugin_t * ) post ) - > channels ;
2018-02-27 18:06:05 +01:00
}
2018-06-28 01:15:32 +02:00
metronom_t * scope_plugin_metronom ( void * post ) {
2018-06-28 23:12:39 +02:00
return & ( ( scope_plugin_t * ) post ) - > metronom ;
2018-02-27 18:06:05 +01:00
}