Fixed xine scope plugin functionality with xine 1.2.10. This resolves issue #19.

Special thanks to xine developer Petri Hintukainen <phintuka@gmail.com>
for his support to get passed the last hurdle.

Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
(cherry picked from commit c5f901c03e)
r14.0.x
Michele Calgaro 4 years ago
parent f337cd3d7e
commit 997e94eafb
Signed by: MicheleC
GPG Key ID: 2A75B7CA8ADED5CF

@ -147,6 +147,11 @@ XineEngine::init()
xine_init( m_xine ); xine_init( m_xine );
#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)
xine_register_plugins( m_xine, scope_plugin_info );
#endif
makeNewStream(); makeNewStream();
#ifndef XINE_SAFE_MODE #ifndef XINE_SAFE_MODE
@ -190,9 +195,10 @@ XineEngine::makeNewStream()
(void*)this ); (void*)this );
#ifndef XINE_SAFE_MODE #ifndef XINE_SAFE_MODE
#if XINE_MAJOR_VERSION < 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION < 2) || \ #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) (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION == 2 && XINE_SUB_VERSION >= 10)
//implemented in xine-scope.h m_post = xine_post_init( m_xine, "amarok-scope", 1, &m_audioPort, NULL );
#else
m_post = scope_plugin_new( m_xine, m_audioPort ); m_post = scope_plugin_new( m_xine, m_audioPort );
#endif #endif
@ -267,12 +273,9 @@ XineEngine::load( const KURL &url, bool isStream )
//we must ensure the scope is pruned of old buffers //we must ensure the scope is pruned of old buffers
timerEvent( 0 ); timerEvent( 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)
xine_post_out_t *source = xine_get_audio_source( m_stream ); xine_post_out_t *source = xine_get_audio_source( m_stream );
xine_post_in_t *target = (xine_post_in_t*)xine_post_input( m_post, const_cast<char*>("audio in") ); xine_post_in_t *target = (xine_post_in_t*)xine_post_input( m_post, const_cast<char*>("audio in") );
xine_post_wire( source, target ); xine_post_wire( source, target );
#endif
#endif #endif
playlistChanged(); playlistChanged();
@ -724,10 +727,8 @@ XineEngine::scope()
if( !m_post || !m_stream || xine_get_status( m_stream ) != XINE_STATUS_PLAY ) if( !m_post || !m_stream || xine_get_status( m_stream ) != XINE_STATUS_PLAY )
return m_scope; return m_scope;
#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)
MyNode* const myList = scope_plugin_list( m_post ); MyNode* const myList = scope_plugin_list( m_post );
metronom_t* const myMetronom = scope_plugin_metronom( m_post ); const int64_t pts_per_smpls = scope_plugin_pts_per_smpls( m_post );
const int myChannels = scope_plugin_channels( m_post ); const int myChannels = scope_plugin_channels( m_post );
int scopeidx = 0; int scopeidx = 0;
@ -752,7 +753,7 @@ XineEngine::scope()
diff = m_currentVpts; diff = m_currentVpts;
diff -= best_node->vpts; diff -= best_node->vpts;
diff *= 1<<16; diff *= 1<<16;
diff /= myMetronom->pts_per_smpls; diff /= pts_per_smpls;
const int16_t* const int16_t*
data16 = best_node->mem; data16 = best_node->mem;
@ -784,7 +785,6 @@ XineEngine::scope()
} }
Log::scopeCallCount++; Log::scopeCallCount++;
#endif
return m_scope; return m_scope;
} }
@ -795,8 +795,6 @@ XineEngine::timerEvent( TQTimerEvent* )
if ( !m_stream ) if ( !m_stream )
return; return;
#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)
//here we prune the buffer list regularly //here we prune the buffer list regularly
MyNode *myList = scope_plugin_list( m_post ); MyNode *myList = scope_plugin_list( m_post );
@ -826,7 +824,6 @@ XineEngine::timerEvent( TQTimerEvent* )
prev = node; prev = node;
} }
#endif
} }
Amarok::PluginConfig* Amarok::PluginConfig*

@ -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)->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)
{ {
return &((scope_plugin_t*)post)->metronom; 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

@ -12,6 +12,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <xine/metronom.h> #include <xine/metronom.h>
#include <xine/xine_plugin.h>
typedef struct my_node_s MyNode; typedef struct my_node_s MyNode;
@ -28,21 +29,18 @@ struct my_node_s
extern "C" extern "C"
{ {
#endif #endif
xine_post_t* #if XINE_MAJOR_VERSION > 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION > 2) || \
scope_plugin_new( xine_t*, xine_audio_port_t* ); (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION == 2 && XINE_SUB_VERSION >= 10)
extern const plugin_info_t scope_plugin_info[];
/* we sacrifice type-safety here because some GCCs appear broken #else
* and choke on redefining the xine_post_t typedef xine_post_t* scope_plugin_new( xine_t*, xine_audio_port_t* );
*/ #endif
int64_t scope_plugin_pts_per_smpls( void* );
MyNode* MyNode* scope_plugin_list( void* );
scope_plugin_list( void* );
int int scope_plugin_channels( void* );
scope_plugin_channels( void* );
metronom_t*
scope_plugin_metronom( void* );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Loading…
Cancel
Save