[Pkg-kde-commits] rev 899 - in people/dato/packages/trunk/amarok/debian: . patches

Adeodato Simó dato-guest@costa.debian.org
Wed, 23 Mar 2005 20:07:16 +0100


Author: dato-guest
Date: 2005-03-23 20:07:15 +0100 (Wed, 23 Mar 2005)
New Revision: 899

Added:
   people/dato/packages/trunk/amarok/debian/patches/gst-memleak-#299931.diff
Modified:
   people/dato/packages/trunk/amarok/debian/changelog
Log:
Backport patch from upstream CVS to fix a memory leak in the GStreamer
engine when a radio stream stalls. (Closes: #299931)


Modified: people/dato/packages/trunk/amarok/debian/changelog
===================================================================
--- people/dato/packages/trunk/amarok/debian/changelog	2005-03-23 18:47:58 UTC (rev 898)
+++ people/dato/packages/trunk/amarok/debian/changelog	2005-03-23 19:07:15 UTC (rev 899)
@@ -2,6 +2,9 @@
 
   * New upstream bugfix release.
 
+  * Backport patch from upstream CVS to fix a memory leak in the GStreamer
+    engine when a radio stream stalls. (Closes: #299931)
+
   * Added a menu file, plus XPM icons.
 
   * Switched to tarball-in-tarball for the .orig.tar.gz (which is sensble
@@ -13,7 +16,7 @@
   * Use the kde.mk class maintained by the Debian KDE Maintainers, instead
     of the one shipped with cdbs.
 
- -- Adeodato Simó <asp16@alu.ua.es>  Thu, 17 Mar 2005 19:12:56 +0100
+ -- Adeodato Simó <asp16@alu.ua.es>  Wed, 23 Mar 2005 19:23:56 +0100
 
 amarok (1.2.1-1) unstable; urgency=low
 

Added: people/dato/packages/trunk/amarok/debian/patches/gst-memleak-#299931.diff
===================================================================
--- people/dato/packages/trunk/amarok/debian/patches/gst-memleak-#299931.diff	2005-03-23 18:47:58 UTC (rev 898)
+++ people/dato/packages/trunk/amarok/debian/patches/gst-memleak-#299931.diff	2005-03-23 19:07:15 UTC (rev 899)
@@ -0,0 +1,1133 @@
+Index: src/engine/gst/gstengine.cpp
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/gstengine.cpp,v
+retrieving revision 1.242
+retrieving revision 1.248
+diff -u -p -r1.242 -r1.248
+--- amarok/src/engine/gst/gstengine.cpp	13 Mar 2005 21:52:05 -0000	1.242
++++ amarok/src/engine/gst/gstengine.cpp	23 Mar 2005 11:52:21 -0000	1.248
+@@ -1,18 +1,20 @@
+ /***************************************************************************
+-                       gstengine.cpp - GStreamer audio interface
+-
+-begin                : Jan 02 2003
+-copyright            : (C) 2003 by Mark Kretschmann
+-email                : markey@web.de
+-***************************************************************************/
+-
+-/***************************************************************************
++ *   Copyright (C) 2003-2005 by Mark Kretschmann <markey@web.de>           *
+  *                                                                         *
+  *   This program is free software; you can redistribute it and/or modify  *
+  *   it under the terms of the GNU General Public License as published by  *
+  *   the Free Software Foundation; either version 2 of the License, or     *
+  *   (at your option) any later version.                                   *
+  *                                                                         *
++ *   This program is distributed in the hope that it will be useful,       *
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
++ *   GNU General Public License for more details.                          *
++ *                                                                         *
++ *   You should have received a copy of the GNU General Public License     *
++ *   along with this program; if not, write to the                         *
++ *   Free Software Foundation, Inc.,                                       *
++ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+  ***************************************************************************/
+ 
+ #define DEBUG_PREFIX "Gst-Engine"
+@@ -37,10 +39,13 @@ email                : markey@web.de
+ 
+ #include <gst/gst.h>
+ 
+-//HACK
++//HACK Needed until debug.h gets fixed
+ #define indent gst_indent
+ #include "debug.h"
+ 
++#define RETURN_IF_PIPELINE_EMPTY if ( !m_pipelineFilled ) return;
++
++
+ using std::vector;
+ 
+ GstEngine* GstEngine::s_instance;
+@@ -54,14 +59,13 @@ AMAROK_EXPORT_PLUGIN( GstEngine )
+ /////////////////////////////////////////////////////////////////////////////////////
+ 
+ void
+-GstEngine::eos_cb( GstElement* /*element*/, gpointer inputPipeline ) //static
++GstEngine::eos_cb( GstElement* /*element*/, InputPipeline* input ) //static
+ {
+     DEBUG_FUNC_INFO
+ 
+     // Ignore eos when gst error was raised
+     if ( !instance()->m_gst_error.isEmpty() ) return;
+ 
+-    InputPipeline* input = static_cast<InputPipeline*>( inputPipeline );
+     input->m_eos = true;
+ 
+     //this is the Qt equivalent to an idle function: delay the call until all events are finished,
+@@ -71,12 +75,11 @@ GstEngine::eos_cb( GstElement* /*element
+ 
+ 
+ void
+-GstEngine::newPad_cb( GstElement*, GstPad* pad, gboolean, gpointer inputPipeline ) //static
++GstEngine::newPad_cb( GstElement*, GstPad* pad, gboolean, InputPipeline* input ) //static
+ {
+     DEBUG_BLOCK
+ 
+-    InputPipeline* input = static_cast<InputPipeline*>( inputPipeline );
+-    GstPad* audiopad = gst_element_get_pad( input->audioconvert, "sink" );
++    GstPad* const audiopad = gst_element_get_pad( input->audioconvert, "sink" );
+ 
+     if ( GST_PAD_IS_LINKED( audiopad ) ) {
+         debug() << "audiopad is already linked. Unlinking old pad." << endl;
+@@ -98,7 +101,7 @@ GstEngine::handoff_cb( GstElement*, GstB
+     instance()->m_mutexScope.lock();
+ 
+     // Check for buffer overflow
+-    uint available = gst_adapter_available( instance()->m_gst_adapter );
++    const uint available = gst_adapter_available( instance()->m_gst_adapter );
+     if ( available > SCOPEBUF_SIZE )
+         gst_adapter_flush( instance()->m_gst_adapter, available - 30000 );
+ 
+@@ -212,6 +215,7 @@ GstEngine::GstEngine()
+         , m_currentInput( 0 )
+         , m_gst_adapter( 0 )
+         , m_streamBuf( new char[STREAMBUF_SIZE] )
++        , m_streamBuffering( false )
+         , m_transferJob( 0 )
+         , m_pipelineFilled( false )
+         , m_fadeValue( 0.0 )
+@@ -297,6 +301,8 @@ GstEngine::init()
+ bool
+ GstEngine::canDecode( const KURL &url ) const
+ {
++    // TODO Consider using decodebin here as well
++
+     // We had some bug reports claiming that .mov files cause crashes in canDecode(),
+     // so don't try to decode them
+     if ( url.fileName().lower().endsWith( ".mov" ) ) return false;
+@@ -321,7 +327,7 @@ GstEngine::canDecode( const KURL &url ) 
+ 
+     gst_element_set_state( pipeline, GST_STATE_PLAYING );
+ 
+-    // Try to iterate over the bin until handoff gets triggered
++    // Try to iterate over the bin until signal "handoff" gets triggered
+     while ( gst_bin_iterate( GST_BIN( pipeline ) ) && !m_canDecodeSuccess && count < 1000 )
+         count++;
+ 
+@@ -427,8 +433,8 @@ GstEngine::scope()
+     int offset = available - static_cast<int>( factor * (double) available );
+     offset /= channels;
+     offset *= channels;
+-    if ( offset < 0 ) offset *= -1; //FIXME Offset should never become < 0. Find out why this happens.
+-    offset = QMIN( offset, available - SCOPE_VALUES*channels*sizeof( gint16 ) );
++    if ( offset < 0 ) offset = -offset; //FIXME Offset should never become < 0. Find out why this happens.
++    offset = QMIN( (guint) offset, available - SCOPE_VALUES*channels*sizeof( gint16 ) );
+ 
+     for ( long i = 0; i < SCOPE_VALUES; i++, data += channels ) {
+         long temp = 0;
+@@ -476,9 +482,8 @@ GstEngine::load( const KURL& url, bool s
+     debug() << "Loading url: " << url.url() << endl;
+ 
+     // Make sure we have a functional output pipeline
+-    if ( !m_pipelineFilled )
+-        if ( !createPipeline() )
+-            return false;
++    if ( !m_pipelineFilled && !createPipeline() )
++        return false;
+ 
+     InputPipeline* input = new InputPipeline();
+     if ( input->m_error ) {
+@@ -498,39 +503,45 @@ GstEngine::load( const KURL& url, bool s
+         gst_element_set( input->src, "buffer_min", STREAMBUF_MIN, NULL );
+         gst_bin_add ( GST_BIN ( input->bin ), input->src );
+         g_signal_connect( G_OBJECT( input->src ), "kio_resume", G_CALLBACK( kio_resume_cb ), input->bin );
++
++        m_streamBufIndex = 0;
++        m_streamBufStop = false;
++        m_streamBuffering = true;
++
++        if ( !stream ) {
++            // Use KIO for non-local files, except http, which is handled by StreamProvider
++            m_transferJob = KIO::get( url, false, false );
++            connect( m_transferJob, SIGNAL( data( KIO::Job*, const QByteArray& ) ), SLOT( newKioData( KIO::Job*, const QByteArray& ) ) );
++            connect( m_transferJob, SIGNAL( result( KIO::Job* ) ), SLOT( kioFinished() ) );
++        }
+     }
+ 
++    // Link all elements. The link from decodebin to audioconvert will be made in the newPad-callback
+     gst_element_link( input->src, input->decodebin );
+     gst_element_link_many( input->audioconvert, input->audioscale, input->volume, NULL );
+ 
+     // Prepare bin for playing
+     gst_element_set_state( input->bin, GST_STATE_READY );
+ 
++    // Check if another track is already playing
+     if ( m_currentInput ) {
+-        m_currentInput->setState( InputPipeline::XFADE_OUT );
+-        input->setState( InputPipeline::XFADE_IN );
++        if ( m_xfadeLength ) {
++            m_currentInput->setState( InputPipeline::XFADE_OUT );
++            input->setState( InputPipeline::XFADE_IN );
++            gst_element_set( input->volume, "volume", 0.0, NULL );
++        }
++        else
++            destroyInput( m_currentInput );
+     }
+     else
+-        input->setState( InputPipeline::FADE_IN );
++        if ( GstConfig::fadeinDuration() ) {
++            input->setState( InputPipeline::FADE_IN );
++            gst_element_set( input->volume, "volume", 0.0, NULL );
++    }
+ 
+     m_currentInput = input;
+     m_inputs.append( input );
+ 
+-    if ( !url.isLocalFile()  ) {
+-        m_streamBufIndex = 0;
+-        m_streamBufStop = false;
+-        m_streamBuffering = true;
+-
+-        if ( !stream ) {
+-            // Use KIO for non-local files, except http, which is handled by TitleProxy
+-            m_transferJob = KIO::get( url, false, false );
+-            connect( m_transferJob, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
+-                              this,   SLOT( newKioData( KIO::Job*, const QByteArray& ) ) );
+-            connect( m_transferJob, SIGNAL( result( KIO::Job* ) ),
+-                              this,   SLOT( kioFinished() ) );
+-        }
+-    }
+-
+     return true;
+ }
+ 
+@@ -544,7 +555,8 @@ GstEngine::play( uint offset )  //SLOT
+     if ( !m_currentInput ) return false;
+ 
+     // We must pause the queue before changing the state of the input thread, else the scheduler
+-    // freaks out
++    // freaks out. This is due to a bug in the queue element; will likely be fixed in gst-0.8.10.
++    // @see http://bugzilla.gnome.org/show_bug.cgi?id=166250
+     gst_element_set_state( m_gst_queue, GST_STATE_PAUSED );
+ 
+     if ( !gst_element_set_state( m_gst_inputThread, GST_STATE_PAUSED ) )
+@@ -580,7 +592,7 @@ GstEngine::stop()  //SLOT
+     emit stateChanged( Engine::Empty );
+     m_eosReached = false;
+ 
+-    if ( !m_currentInput ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+     // When engine is in pause mode, don't fade but destroy right away
+     if ( state() == Engine::Paused )
+@@ -594,8 +606,7 @@ void
+ GstEngine::pause()  //SLOT
+ {
+     DEBUG_BLOCK
+-
+-    if ( !m_currentInput ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+     if ( GST_STATE( m_currentInput->bin ) == GST_STATE_PAUSED ) {
+         gst_element_set_state( m_currentInput->bin, GST_STATE_PLAYING );
+@@ -611,13 +622,11 @@ GstEngine::pause()  //SLOT
+ void
+ GstEngine::seek( uint ms )  //SLOT
+ {
+-    if ( !m_pipelineFilled ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+-    if ( ms > 0 )
+-    {
+-        GstEvent* event = gst_event_new_seek( ( GstSeekType ) ( GST_FORMAT_TIME |
+-                                                                GST_SEEK_METHOD_SET |
+-                                                                GST_SEEK_FLAG_FLUSH ), ms * GST_MSECOND );
++    if ( ms > 0 ) {
++        const int seekType = GST_FORMAT_TIME | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH;
++        GstEvent* event = gst_event_new_seek( (GstSeekType) seekType, ms * GST_MSECOND );
+ 
+         gst_element_send_event( m_gst_audiosink, event );
+     }
+@@ -644,7 +653,7 @@ GstEngine::newStreamData( char* buf, int
+ void
+ GstEngine::setEqualizerEnabled( bool enabled ) //SLOT
+ {
+-    if ( !m_pipelineFilled ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+     gst_element_set( m_gst_equalizer, "active", enabled, NULL );
+ }
+@@ -653,7 +662,7 @@ GstEngine::setEqualizerEnabled( bool ena
+ void
+ GstEngine::setEqualizerParameters( int preamp, const QValueList<int>& bandGains ) //SLOT
+ {
+-    if ( !m_pipelineFilled ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+     // BEGIN Preamp
+     gst_element_set( m_gst_equalizer, "preamp", ( preamp + 100 ) / 2 , NULL );
+@@ -676,7 +685,7 @@ GstEngine::setEqualizerParameters( int p
+ void
+ GstEngine::setVolumeSW( uint percent )  //SLOT
+ {
+-    if ( !m_pipelineFilled ) return;
++    RETURN_IF_PIPELINE_EMPTY
+ 
+     gst_element_set( m_gst_volume, "volume", (double) percent * 0.01, NULL );
+ }
+@@ -684,8 +693,10 @@ GstEngine::setVolumeSW( uint percent )  
+ 
+ void GstEngine::timerEvent( QTimerEvent* )
+ {
+-    // Fading transition management:
++    // Display stream buffer status
++    sendBufferStatus();
+ 
++    // Fading transition management:
+     QPtrList<InputPipeline> destroyList;
+     InputPipeline* input;
+ 
+@@ -710,13 +721,12 @@ void GstEngine::timerEvent( QTimerEvent*
+                 }
+                 else {
+                     // Set new value for fadeout volume element
+-                    double value = 1.0 - log10( input->m_fade * 9.0 + 1.0 );
++                    const double value = 1.0 - log10( input->m_fade * 9.0 + 1.0 );
+ //                     kdDebug() << "XFADE_IN: " << value << endl;
+                     gst_element_set( input->volume, "volume", value, NULL );
+                 }
+                 break;
+ 
+-
+             case InputPipeline::FADE_OUT:
+                 input->m_fade -= ( GstConfig::fadeoutDuration() ) ?  1.0 / GstConfig::fadeoutDuration() * TIMER_INTERVAL : 1.0;
+ 
+@@ -725,13 +735,12 @@ void GstEngine::timerEvent( QTimerEvent*
+                     destroyList.append( input );
+                 else {
+                     // Set new value for fadeout volume element
+-                    double value = 1.0 - log10( ( 1.0 - input->m_fade ) * 9.0 + 1.0 );
++                    const double value = 1.0 - log10( ( 1.0 - input->m_fade ) * 9.0 + 1.0 );
+ //                     kdDebug() << "FADE_OUT: " << value << endl;
+                     gst_element_set( input->volume, "volume", value, NULL );
+                 }
+                 break;
+ 
+-
+             case InputPipeline::XFADE_IN:
+                 input->m_fade -= ( m_xfadeLength ) ?  1.0 / m_xfadeLength * TIMER_INTERVAL : 1.0;
+ 
+@@ -743,13 +752,12 @@ void GstEngine::timerEvent( QTimerEvent*
+                 }
+                 else {
+                     // Set new value for fadeout volume element
+-                    double value = 1.0 - input->m_fade;
++                    const double value = 1.0 - input->m_fade;
+ //                     kdDebug() << "XFADE_IN: " << value << endl;
+                     gst_element_set( input->volume, "volume", value, NULL );
+                 }
+                 break;
+ 
+-
+             case InputPipeline::XFADE_OUT:
+                 input->m_fade -= ( m_xfadeLength ) ?  1.0 / m_xfadeLength * TIMER_INTERVAL : 1.0;
+ 
+@@ -758,7 +766,7 @@ void GstEngine::timerEvent( QTimerEvent*
+                     destroyList.append( input );
+                 else {
+                     // Set new value for fadeout volume element
+-                    double value = 1.0 - log10( ( 1.0 - input->m_fade ) * 9.0 + 1.0 );
++                    const double value = 1.0 - log10( ( 1.0 - input->m_fade ) * 9.0 + 1.0 );
+ //                     kdDebug() << "XFADE_OUT: " << value << endl;
+                     gst_element_set( input->volume, "volume", value, NULL );
+                 }
+@@ -852,7 +860,7 @@ GstEngine::endOfStreamReached()  //SLOT
+ void
+ GstEngine::newKioData( KIO::Job*, const QByteArray& array )  //SLOT
+ {
+-    int size = array.size();
++    const int size = array.size();
+ 
+     if ( m_streamBufIndex >= STREAMBUF_MAX ) {
+         debug() << "SUSPENDING kio transfer.\n";
+@@ -876,7 +884,7 @@ GstEngine::newKioData( KIO::Job*, const 
+ void
+ GstEngine::newMetaData()  //SLOT
+ {
+-    emit instance()->metaData( m_metaBundle );
++    emit metaData( m_metaBundle );
+ }
+ 
+ 
+@@ -1106,7 +1114,6 @@ GstEngine::destroyInput( InputPipeline* 
+ 
+     if ( input ) {
+         debug() << "Destroying input pipeline.\n";
+-
+         // Destroy the pipeline
+         m_inputs.remove( input );
+     }
+@@ -1122,10 +1129,8 @@ GstEngine::destroyInput( InputPipeline* 
+ void
+ GstEngine::sendBufferStatus()
+ {
+-    if ( m_streamBuffering )
+-    {
+-        int percent = (int) ( (float) m_streamBufIndex / STREAMBUF_MIN * 105.0 );
+-
++    if ( m_streamBuffering ) {
++        const int percent = (int) ( (float) m_streamBufIndex / STREAMBUF_MIN * 105.0 );
+         emit statusText( i18n( "Buffering.. %1%" ).arg( MIN( percent, 100 ) ) );
+     }
+ }
+@@ -1143,8 +1148,6 @@ InputPipeline::InputPipeline()
+ {
+     DEBUG_BLOCK
+ 
+-    QString binName;
+-
+     /* create a new pipeline (thread) to hold the elements */
+     if ( !( bin = GstEngine::createElement( "bin" ) ) ) { goto error; }
+     if ( !( decodebin = GstEngine::createElement( "decodebin", bin ) ) ) { goto error; }
+@@ -1156,9 +1159,6 @@ InputPipeline::InputPipeline()
+     g_signal_connect( G_OBJECT( decodebin ), "new-decoded-pad", G_CALLBACK( GstEngine::newPad_cb ), this );
+     g_signal_connect( G_OBJECT( decodebin ), "found-tag", G_CALLBACK( GstEngine::found_tag_cb ), 0 );
+ 
+-    // Start silent
+-    gst_element_set( volume, "volume", 0.0, NULL );
+-
+     return;
+ 
+ error:
+@@ -1180,6 +1180,9 @@ InputPipeline::~InputPipeline()
+ 
+     if ( gst_element_get_managing_bin( bin ) == GST_BIN( GstEngine::instance()->m_gst_inputThread ) )
+     {
++        // We must pause the queue before changing the state of the input thread, else the scheduler
++        // freaks out. This is due to a bug in the queue element; will likely be fixed in gst-0.8.10.
++        // @see http://bugzilla.gnome.org/show_bug.cgi?id=166250
+         gst_element_set_state( GstEngine::instance()->m_gst_queue, GST_STATE_PAUSED );
+ 
+         if ( !gst_element_set_state( GstEngine::instance()->m_gst_inputThread, GST_STATE_PAUSED ) )
+Index: src/engine/gst/gstengine.h
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/gstengine.h,v
+retrieving revision 1.96
+retrieving revision 1.102
+diff -u -p -r1.96 -r1.102
+--- amarok/src/engine/gst/gstengine.h	13 Mar 2005 21:52:05 -0000	1.96
++++ amarok/src/engine/gst/gstengine.h	23 Mar 2005 16:23:58 -0000	1.102
+@@ -1,18 +1,20 @@
+ /***************************************************************************
+-                      gstengine.h - GStreamer audio interface
+-
+-begin                : Jan 02 2003
+-copyright            : (C) 2003 by Mark Kretschmann
+-email                : markey@web.de
+-***************************************************************************/
+-
+-/***************************************************************************
++ *   Copyright (C) 2003-2005 by Mark Kretschmann <markey@web.de>           *
+  *                                                                         *
+  *   This program is free software; you can redistribute it and/or modify  *
+  *   it under the terms of the GNU General Public License as published by  *
+  *   the Free Software Foundation; either version 2 of the License, or     *
+  *   (at your option) any later version.                                   *
+  *                                                                         *
++ *   This program is distributed in the hope that it will be useful,       *
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
++ *   GNU General Public License for more details.                          *
++ *                                                                         *
++ *   You should have received a copy of the GNU General Public License     *
++ *   along with this program; if not, write to the                         *
++ *   Free Software Foundation, Inc.,                                       *
++ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+  ***************************************************************************/
+ 
+ #ifndef AMAROK_GSTENGINE_H
+@@ -40,14 +42,24 @@ class KURL;
+ class InputPipeline;
+ 
+ /**
+- *  GstEngine uses following pipeline for playing (syntax used by gst-launch):
+- *  { filesrc location=file.ext ! decodebin ! audioconvert ! audioscale ! volume
+- *  ! adder } ! { queue ! equalizer ! identity ! volume ! audiosink }
+- *  Part of pipeline between filesrc and first volume is double while 
+- *  crossfading. First pair of curly braces encloses m_gst_inputThread, second
+- *  m_gst_outputThread
+-*/
+-
++ * @class GstEngine
++ * @short GStreamer engine plugin
++ * @author Mark Kretschmann <markey@web.de>
++ *
++ * GStreamer-Engine implements an N-track (unlimited number of tracks) crossfader
++ * design. Fading to the next track starts at an adjustable time before the current
++ * track ends. Additionally, separate values for volume fade-in and fade-out can be
++ * specified.
++ * Note that the engine cannot do true gapless play at this point. This is a
++ * planned feature.
++ *
++ * GstEngine uses following pipeline for playing (syntax used by gst-launch):
++ * { filesrc location=file.ext ! decodebin ! audioconvert ! audioscale ! volume
++ * ! adder } ! { queue ! equalizer ! identity ! volume ! audiosink }
++ * Part of pipeline between filesrc and first volume is double while
++ * crossfading. First pair of curly braces encloses m_gst_inputThread, second
++ * m_gst_outputThread
++ */
+ class GstEngine : public Engine::Base
+ {
+         friend class GstConfigDialog;
+@@ -78,10 +90,13 @@ class GstEngine : public Engine::Base
+         void stop();
+         void pause();
+         void seek( uint ms );
++
++        /** Copies incoming radio stream data from StreamProvider into StreamSrc's buffer */
+         void newStreamData( char* data, int size );
+ 
+         /** Set whether equalizer is enabled */
+         void setEqualizerEnabled( bool );
++
+         /** Set equalizer preamp and gains, range -100..100. Gains are 10 values. */
+         void setEqualizerParameters( int preamp, const QValueList<int>& bandGains );
+ 
+@@ -94,22 +109,22 @@ class GstEngine : public Engine::Base
+         void handleInputError();
+         void endOfStreamReached();
+         void kioFinished();
++
++        /** Copies incoming data from KIO into StreamSrc's buffer */
+         void newKioData( KIO::Job*, const QByteArray& array );
++
++        /** Called when no output sink was selected. Shows the GStreamer engine settings dialog. */
+         void errorNoOutput();
++
++        /** Rebuilds the pipeline after configuration changes */
+         void configChanged();
++
++        /** Transmits new decoded metadata to the application */
+         void newMetaData();
+ 
+     private:
+         static GstEngine* instance() { return s_instance; }
+ 
+-        #define KB 1000
+-        static const uint SCOPEBUF_SIZE  = 1000*KB;
+-        static const int  SCOPE_VALUES   = 512;
+-        static const int  STREAMBUF_SIZE = 600*KB;
+-        static const uint STREAMBUF_MIN  = 50*KB;
+-        static const int  STREAMBUF_MAX  = STREAMBUF_SIZE - 50*KB;
+-        #undef KB
+-
+         /**
+          * Creates a GStreamer element and puts it into pipeline.
+          * @param factoryName Name of the element class to create.
+@@ -119,20 +134,30 @@ class GstEngine : public Engine::Base
+          */
+         static GstElement* createElement( const QCString& factoryName, GstElement* bin = 0, const QCString& name = 0 );
+ 
++        /**
++         * Fetches a list of available output sink plugins
++         * @return List of output sinks
++         */
+         QStringList getOutputsList() { return getPluginList( "Sink/Audio" ); }
+ 
+         // CALLBACKS:
+         /** Called at end of track */
+-        static void eos_cb( GstElement*, gpointer );
++        static void eos_cb( GstElement*, InputPipeline* );
+         /** Called when decodebin has generated a new pad */
+-        static void newPad_cb( GstElement*, GstPad*, gboolean, gpointer );
++        static void newPad_cb( GstElement*, GstPad*, gboolean, InputPipeline* );
+         /** Duplicates audio data for application side processing */
+         static void handoff_cb( GstElement*, GstBuffer*, gpointer );
++        /** Used by canDecode(). When called, the format can be decoded */
+         static void candecode_handoff_cb( GstElement*, GstBuffer*, gpointer );
++        /** Called when new metadata tags have been found */
+         static void found_tag_cb( GstElement*, GstElement*, GstTagList*, gpointer );
++        /** Called when the output pipeline signals an error */
+         static void outputError_cb( GstElement*, GstElement*, GError*, gchar*, gpointer );
++        /** Called when the input pipeline signals an error */
+         static void inputError_cb( GstElement*, GstElement*, GError*, gchar*, gpointer );
++        /** Called when the KIO buffer is empty */
+         static void kio_resume_cb();
++        /** Called after the pipeline is shut down */
+         static void shutdown_cb();
+ 
+ 
+@@ -152,9 +177,20 @@ class GstEngine : public Engine::Base
+         void sendBufferStatus();
+ 
+         /////////////////////////////////////////////////////////////////////////////////////
+-        // ATTRIBUTES
++        // DATA MEMBERS
+         /////////////////////////////////////////////////////////////////////////////////////
+-        static const int TIMER_INTERVAL = 70; //msec
++        // Interval of main timer, handles the crossfading
++        static const int  TIMER_INTERVAL = 40; //msec
++
++        #define KB 1000
++        static const uint SCOPEBUF_SIZE  = 1000*KB;
++        static const int  SCOPE_VALUES   = 512;
++        static const int  STREAMBUF_SIZE = 600*KB;
++        static const uint STREAMBUF_MIN  = 100*KB;
++        static const int  STREAMBUF_MAX  = STREAMBUF_SIZE - 50*KB;
++        #undef KB
++
++
+         static GstEngine* s_instance;
+ 
+         // Root bin
+@@ -175,17 +211,20 @@ class GstEngine : public Engine::Base
+         QString m_gst_error;
+         QString m_gst_debug;
+ 
+-        QPtrList<InputPipeline> m_inputs;
+-        InputPipeline*          m_currentInput;
++        typedef QPtrList<InputPipeline> InputList;
++        InputList       m_inputs;
++        InputPipeline*  m_currentInput;
+ 
+         GstAdapter* m_gst_adapter;
+ 
++        // These variables are shared between gst-engine and streamsrc
+         char*    m_streamBuf;
+         int      m_streamBufIndex;
+         bool     m_streamBufStop;
+         bool     m_streamBuffering;
++
+         KIO::TransferJob* m_transferJob;
+-        QMutex   m_mutexScope;
++        QMutex            m_mutexScope;
+ 
+         bool        m_pipelineFilled;
+         float       m_fadeValue;
+@@ -199,6 +238,11 @@ class GstEngine : public Engine::Base
+ };
+ 
+ 
++/**
++ * @class InputPipeline
++ * @short Wraps input-pipeline tracks
++ * @author Mark Kretschmann <markey@web.de>
++ */
+ class InputPipeline
+ {
+     public:
+@@ -207,8 +251,6 @@ class InputPipeline
+         InputPipeline();
+         ~InputPipeline();
+ 
+-        void prepareToDie();
+-
+         State state() const { return m_state; }
+         void setState( State newState );
+ 
+Index: src/engine/gst/streamsrc.cpp
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/streamsrc.cpp,v
+retrieving revision 1.22
+retrieving revision 1.25
+diff -u -p -r1.22 -r1.25
+--- amarok/src/engine/gst/streamsrc.cpp	24 Sep 2004 17:53:15 -0000	1.22
++++ amarok/src/engine/gst/streamsrc.cpp	23 Mar 2005 11:52:21 -0000	1.25
+@@ -7,6 +7,7 @@
+ #include "config.h"
+ #include <kdebug.h>
+ 
++#define DEBUG_PREFIX "[StreamSrc] "
+ #define DEFAULT_BLOCKSIZE 4096
+ 
+ GST_DEBUG_CATEGORY_STATIC ( gst_streamsrc_debug );
+@@ -41,24 +42,11 @@ static guint gst_streamsrc_signals[ LAST
+ GST_BOILERPLATE_FULL ( GstStreamSrc, gst_streamsrc, GstElement, (GTypeFlags) GST_TYPE_ELEMENT, _do_init );
+ 
+ 
+-// Forward declarations
+-
+-static void gst_streamsrc_set_property ( GObject * object, guint prop_id,
+-        const GValue * value, GParamSpec * pspec );
+-
+-static void gst_streamsrc_get_property ( GObject * object, guint prop_id,
+-        GValue * value, GParamSpec * pspec );
+-
+-static GstElementStateReturn gst_streamsrc_change_state (GstElement* element);
+-
+-static GstData *gst_streamsrc_get ( GstPad * pad );
+-
+-
+ /////////////////////////////////////////////////////////////////////////////////////
+ // INIT
+ /////////////////////////////////////////////////////////////////////////////////////
+ 
+-static void
++void
+ gst_streamsrc_base_init ( gpointer g_class )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -68,7 +56,7 @@ gst_streamsrc_base_init ( gpointer g_cla
+ }
+ 
+ 
+-static void
++void
+ gst_streamsrc_class_init ( GstStreamSrcClass * klass )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -76,6 +64,7 @@ gst_streamsrc_class_init ( GstStreamSrcC
+     GObjectClass* gobject_class;
+     GstElementClass* gstelement_class = GST_ELEMENT_CLASS( klass );
+     gobject_class = G_OBJECT_CLASS( klass );
++    parent_class = GST_ELEMENT_CLASS( g_type_class_ref( GST_TYPE_ELEMENT ) );
+ 
+     g_object_class_install_property ( G_OBJECT_CLASS ( klass ), ARG_BLOCKSIZE,
+                                       g_param_spec_ulong ( "blocksize", "Block size",
+@@ -98,12 +87,13 @@ gst_streamsrc_class_init ( GstStreamSrcC
+ 
+     gobject_class->set_property = gst_streamsrc_set_property;
+     gobject_class->get_property = gst_streamsrc_get_property;
++    gobject_class->dispose      = gst_streamsrc_dispose;
+ 
+     gstelement_class->change_state = gst_streamsrc_change_state;
+ }
+ 
+ 
+-static void
++void
+ gst_streamsrc_init ( GstStreamSrc * streamsrc )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -122,10 +112,40 @@ gst_streamsrc_init ( GstStreamSrc * stre
+ 
+ 
+ /////////////////////////////////////////////////////////////////////////////////////
++// CONSTRUCTOR / DESTRUCTOR
++/////////////////////////////////////////////////////////////////////////////////////
++
++GstStreamSrc*
++gst_streamsrc_new ( char* buf, int* index, bool* stop, bool* buffering )
++{
++    GstStreamSrc * object = GST_STREAMSRC( g_object_new( GST_TYPE_STREAMSRC, NULL ) );
++    gst_object_set_name( (GstObject*) object, "StreamSrc" );
++
++    object->m_buf = buf;
++    object->m_bufIndex = index;
++    object->m_bufStop = stop;
++    object->m_buffering = buffering;
++
++    return object;
++}
++
++
++void
++gst_streamsrc_dispose( GObject *object )
++{
++    kdDebug() << k_funcinfo << endl;
++
++    GstStreamSrc* obj = GST_STREAMSRC( object );
++    *obj->m_buffering = false;
++    G_OBJECT_CLASS( parent_class )->dispose( object );
++}
++
++
++/////////////////////////////////////////////////////////////////////////////////////
+ // PUBLIC METHODS
+ /////////////////////////////////////////////////////////////////////////////////////
+ 
+-static void
++void
+ gst_streamsrc_set_property ( GObject * object, guint prop_id, const GValue * value,
+                              GParamSpec * pspec )
+ {
+@@ -137,24 +157,24 @@ gst_streamsrc_set_property ( GObject * o
+     src = GST_STREAMSRC ( object );
+ 
+     switch ( prop_id ) {
+-    case ARG_BLOCKSIZE:
+-        src->blocksize = g_value_get_ulong ( value );
+-        break;
+-    case ARG_BUFFER_MIN:
+-        src->buffer_min = g_value_get_uint ( value );
+-        src->buffer_resume = src->buffer_min + 100000;
+-        break;
+-    default:
+-        G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
+-        break;
++        case ARG_BLOCKSIZE:
++            src->blocksize = g_value_get_ulong ( value );
++            break;
++        case ARG_BUFFER_MIN:
++            src->buffer_min = g_value_get_uint ( value );
++            src->buffer_resume = src->buffer_min + 100000;
++            break;
++        default:
++            G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
++            break;
+     }
+ }
+ 
+ 
+-static void
++void
+ gst_streamsrc_get_property ( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec )
+ {
+-    GstStreamSrc * src;
++    GstStreamSrc* src;
+ 
+     /* it's not null if we got it, but it might not be ours */
+     g_return_if_fail ( GST_IS_STREAMSRC ( object ) );
+@@ -162,81 +182,77 @@ gst_streamsrc_get_property ( GObject * o
+     src = GST_STREAMSRC ( object );
+ 
+     switch ( prop_id ) {
+-    case ARG_BLOCKSIZE:
+-        g_value_set_ulong ( value, src->blocksize );
+-        break;
+-    case ARG_BUFFER_MIN:
+-        g_value_set_uint ( value, src->buffer_min );
+-        break;
+-    default:
+-        G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
+-        break;
++        case ARG_BLOCKSIZE:
++            g_value_set_ulong ( value, src->blocksize );
++            break;
++        case ARG_BUFFER_MIN:
++            g_value_set_uint ( value, src->buffer_min );
++            break;
++        default:
++            G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, prop_id, pspec );
++            break;
+     }
+ }
+ 
+ 
+-static GstElementStateReturn
++GstElementStateReturn
+ gst_streamsrc_change_state (GstElement * element)
+ {
+ //   GstStreamSrc *src = GST_STREAMSRC (element);
+ 
+-  switch (GST_STATE_TRANSITION (element)) {
+-    case GST_STATE_NULL_TO_READY:
+-      break;
+-    case GST_STATE_READY_TO_NULL:
+-      break;
+-    case GST_STATE_READY_TO_PAUSED:
+-      break;
+-    case GST_STATE_PAUSED_TO_READY:
+-      break;
+-    default:
+-      break;
+-  }
++    switch (GST_STATE_TRANSITION (element)) {
++        case GST_STATE_NULL_TO_READY:
++            break;
++        case GST_STATE_READY_TO_NULL:
++            break;
++        case GST_STATE_READY_TO_PAUSED:
++            break;
++        case GST_STATE_PAUSED_TO_READY:
++            break;
++        default:
++            break;
++    }
+ 
+-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+-    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
++    if (GST_ELEMENT_CLASS (parent_class)->change_state)
++        return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+ 
+-  return GST_STATE_SUCCESS;
++    return GST_STATE_SUCCESS;
+ }
+ 
+ 
+-static GstData*
++GstData*
+ gst_streamsrc_get ( GstPad* pad )
+ {
+     g_return_val_if_fail( pad != NULL, NULL );
+-    GstStreamSrc* src = GST_STREAMSRC ( GST_OBJECT_PARENT ( pad ) );
++    GstStreamSrc* const src = GST_STREAMSRC( GST_OBJECT_PARENT( pad ) );
+ 
+     if ( src->stopped )
+         return GST_DATA( gst_event_new( GST_EVENT_FLUSH ) );
+ 
+     // Signal KIO to resume transfer when buffer reaches our low limit
+-    if ( *src->m_bufIndex < src->buffer_resume )
++    if ( *src->m_bufIndex < (int) src->buffer_resume )
+         g_signal_emit ( G_OBJECT( src ), gst_streamsrc_signals[SIGNAL_KIO_RESUME], 0 );
+ 
+-    if ( *src->m_bufStop ) {
++    if ( *src->m_bufStop && *src->m_bufIndex == 0 ) {
+         // Send EOS event when buffer is empty
+-        if ( *src->m_bufIndex == 0 ) {
+-            kdDebug() << "Streamsrc EOS\n";
+-            src->stopped = true;
+-            gst_element_set_eos (GST_ELEMENT( src ) );
+-            return GST_DATA( gst_event_new( GST_EVENT_EOS ) );
+-        }
++        kdDebug() << "Streamsrc EOS\n";
++        src->stopped = true;
++        gst_element_set_eos( GST_ELEMENT( src ) );
++        return GST_DATA( gst_event_new( GST_EVENT_EOS ) );
+     }
+-    // When buffering, return filler-event when buffer index is below minimum level
+-    else if ( *src->m_buffering && *src->m_bufIndex < src->buffer_min )
+-        return GST_DATA( gst_event_new( GST_EVENT_FILLER ) );
+-
+-    // When buffer is empty, return filler-event and start rebuffering
+-    else if ( !*src->m_buffering && *src->m_bufIndex < src->blocksize ) {
+-        *src->m_buffering = true;
+-        return GST_DATA( gst_event_new( GST_EVENT_FILLER ) );
++    // When buffering, return empty buffer if buffer index is below minimum level
++    else if ( *src->m_buffering && *src->m_bufIndex < (int) src->buffer_min ) {
++        GstBuffer* const buf = gst_buffer_new_and_alloc( 0 );
++        GST_BUFFER_OFFSET( buf )     = src->curoffset;
++        GST_BUFFER_OFFSET_END( buf ) = src->curoffset;
++        return GST_DATA( buf );
+     }
+ 
+-    *src->m_buffering = false;
+-    int readBytes = MIN( *src->m_bufIndex, src->blocksize );
++    *src->m_buffering = *src->m_bufIndex ? false : true;
++    const int readBytes = MIN( *src->m_bufIndex, src->blocksize );
+ 
+-    GstBuffer* buf = gst_buffer_new_and_alloc( readBytes );
+-    guint8* data = GST_BUFFER_DATA( buf );
++    GstBuffer* const buf = gst_buffer_new_and_alloc( readBytes );
++    guint8*    const data = GST_BUFFER_DATA( buf );
+ 
+     // Copy stream buffer content into gst buffer
+     memcpy( data, src->m_buf, readBytes );
+@@ -246,25 +262,10 @@ gst_streamsrc_get ( GstPad* pad )
+     // Adjust buffer index
+     *src->m_bufIndex -= readBytes;
+ 
+-    GST_BUFFER_OFFSET ( buf ) = src->curoffset;
+-    GST_BUFFER_OFFSET_END ( buf ) = src->curoffset + readBytes;
++    GST_BUFFER_OFFSET( buf )     = src->curoffset;
++    GST_BUFFER_OFFSET_END( buf ) = src->curoffset + readBytes;
+     src->curoffset += readBytes;
+ 
+     return GST_DATA ( buf );
+ }
+ 
+-
+-GstStreamSrc*
+-gst_streamsrc_new ( char* buf, int* index, bool* stop, bool* buffering )
+-{
+-    GstStreamSrc * object = GST_STREAMSRC ( g_object_new ( GST_TYPE_STREAMSRC, NULL ) );
+-    gst_object_set_name( (GstObject*) object, "StreamSrc" );
+-
+-    object->m_buf = buf;
+-    object->m_bufIndex = index;
+-    object->m_bufStop = stop;
+-    object->m_buffering = buffering;
+-
+-    return object;
+-}
+-
+Index: src/engine/gst/streamsrc.h
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/streamsrc.h,v
+retrieving revision 1.13
+retrieving revision 1.14
+diff -u -p -r1.13 -r1.14
+--- amarok/src/engine/gst/streamsrc.h	24 Sep 2004 17:53:15 -0000	1.13
++++ amarok/src/engine/gst/streamsrc.h	23 Mar 2005 11:52:21 -0000	1.14
+@@ -55,11 +55,16 @@ struct _GstStreamSrcClass
+     void ( *kio_resume ) ( GstElement *element );
+ };
+ 
+-GType gst_streamsrc_get_type( void );
++
+ GstStreamSrc* gst_streamsrc_new ( char* buf, int* index, bool* stop, bool* buffering );
++void gst_streamsrc_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec );
++void gst_streamsrc_get_property( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec );
++GstElementStateReturn gst_streamsrc_change_state(GstElement* element);
++GstData *gst_streamsrc_get( GstPad * pad );
++void gst_streamsrc_dispose( GObject *object );
+ 
+-G_END_DECLS
+ 
++G_END_DECLS
+ 
+ #endif /* AMAROK_GST_STREAMSRC_H */
+ 
+Index: src/engine/gst/equalizer/gstequalizer.cpp
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/equalizer/gstequalizer.cpp,v
+retrieving revision 1.15
+retrieving revision 1.19
+diff -u -p -r1.15 -r1.19
+--- amarok/src/engine/gst/equalizer/gstequalizer.cpp	13 Mar 2005 21:52:05 -0000	1.15
++++ amarok/src/engine/gst/equalizer/gstequalizer.cpp	23 Mar 2005 16:15:42 -0000	1.19
+@@ -3,7 +3,6 @@
+ // (c) 2004 Mark Kretschmann <markey@web.de>
+ // License: GPL V2
+ 
+-#include "config.h"
+ 
+ #include "gstequalizer.h"
+ #include "iir_cf.h"         // IIR filter coefficients
+@@ -36,19 +35,19 @@ GstElementDetails gst_equalizer_details 
+                           (gchar*) "Parametric Equalizer",
+                           (gchar*) "Mark Kretschmann <markey@web.de>" );
+ 
+-GstStaticPadTemplate sink_template = 
++GstStaticPadTemplate sink_template =
+     GST_STATIC_PAD_TEMPLATE ( (gchar*) "sink",
+-    			       GST_PAD_SINK,
+-			       GST_PAD_ALWAYS,
+-			       GST_STATIC_CAPS ( GST_AUDIO_INT_PAD_TEMPLATE_CAPS ) 
+-			    );
++                    GST_PAD_SINK,
++                    GST_PAD_ALWAYS,
++                    GST_STATIC_CAPS ( GST_AUDIO_INT_PAD_TEMPLATE_CAPS )
++                  );
+ 
+-GstStaticPadTemplate src_template = 
++GstStaticPadTemplate src_template =
+     GST_STATIC_PAD_TEMPLATE (  (gchar*) "src",
+-    			       GST_PAD_SRC,
+-			       GST_PAD_ALWAYS,
+-			       GST_STATIC_CAPS ( GST_AUDIO_INT_PAD_TEMPLATE_CAPS )
+-			    );
++                    GST_PAD_SRC,
++                    GST_PAD_ALWAYS,
++                    GST_STATIC_CAPS ( GST_AUDIO_INT_PAD_TEMPLATE_CAPS )
++                   );
+ 
+ // static guint gst_equalizer_signals[ LAST_SIGNAL ] = { 0 };
+ 
+@@ -62,7 +61,7 @@ GST_BOILERPLATE_FULL ( GstEqualizer, gst
+ // INIT
+ /////////////////////////////////////////////////////////////////////////////////////
+ 
+-static void
++void
+ gst_equalizer_base_init ( gpointer g_class )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -72,7 +71,7 @@ gst_equalizer_base_init ( gpointer g_cla
+ }
+ 
+ 
+-static void
++void
+ gst_equalizer_class_init ( GstEqualizerClass * klass )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -90,7 +89,7 @@ gst_equalizer_class_init ( GstEqualizerC
+ }
+ 
+ 
+-static void
++void
+ gst_equalizer_init ( GstEqualizer* obj )
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -117,7 +116,7 @@ gst_equalizer_init ( GstEqualizer* obj )
+ // PUBLIC METHODS
+ /////////////////////////////////////////////////////////////////////////////////////
+ 
+-static GstPadLinkReturn
++GstPadLinkReturn
+ gst_equalizer_link (GstPad* pad, const GstCaps* caps)
+ {
+     kdDebug() << k_funcinfo << endl;
+@@ -153,7 +152,7 @@ gst_equalizer_link (GstPad* pad, const G
+     // Load the correct filter table according to the sampling rate
+     set_filters( obj );
+     /* Zero the history arrays */
+-    bzero(obj->data_history, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS);
++    memset(obj->data_history, 0, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS);
+ 
+     g_print ("Caps negotiation succeeded with %d Hz @ %d channels\n",
+             obj->samplerate, obj->channels);
+@@ -162,7 +161,7 @@ gst_equalizer_link (GstPad* pad, const G
+ }
+ 
+ 
+-static void
++void
+ gst_equalizer_set_property ( GObject * object, guint prop_id, const GValue * value,
+                              GParamSpec * pspec )
+ {
+@@ -197,7 +196,7 @@ gst_equalizer_set_property ( GObject * o
+ }
+ 
+ 
+-static void
++void
+ gst_equalizer_get_property ( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec )
+ {
+     /* it's not null if we got it, but it might not be ours */
+@@ -222,7 +221,7 @@ gst_equalizer_get_property ( GObject * o
+ }
+ 
+ 
+-static void
++void
+ set_filters( GstEqualizer* obj )
+ {
+     switch(obj->samplerate)
+@@ -246,7 +245,7 @@ set_filters( GstEqualizer* obj )
+ }
+ 
+ 
+-#ifdef ARCH_X86
++#ifdef __i386__
+ /* Round function provided by Frank Klemm which saves around 100K
+  * CPU cycles in my PIII for each call to the IIR function with 4K samples
+  */
+@@ -344,7 +343,7 @@ gst_equalizer_chain ( GstPad* pad, GstDa
+             out[channel] += pcm[channel]*0.25;
+ 
+             /* Round and convert to integer */
+-#ifdef ARCH_X86
++#ifdef __i386__
+             tempgint = round_trick(out[channel]);
+ #else
+             tempgint = (int)out[channel];
+Index: src/engine/gst/equalizer/gstequalizer.h
+===================================================================
+RCS file: /home/kde/kdeextragear-1/amarok/src/engine/gst/equalizer/gstequalizer.h,v
+retrieving revision 1.8
+retrieving revision 1.9
+diff -u -p -r1.8 -r1.9
+--- amarok/src/engine/gst/equalizer/gstequalizer.h	15 Dec 2004 20:28:29 -0000	1.8
++++ amarok/src/engine/gst/equalizer/gstequalizer.h	23 Mar 2005 11:52:21 -0000	1.9
+@@ -77,19 +77,14 @@ struct _GstEqualizerClass
+     /* signals */
+ };
+ 
+-static GstPadLinkReturn gst_equalizer_link (GstPad* pad, const GstCaps* caps);
+-
+-static void gst_equalizer_set_property ( GObject * object, guint prop_id,
+-                                         const GValue * value, GParamSpec * pspec );
+-
+-static void gst_equalizer_get_property ( GObject * object, guint prop_id,
+-                                         GValue * value, GParamSpec * pspec );
+-
+-static void set_filters( GstEqualizer* obj );
+-static void gst_equalizer_chain ( GstPad* pad, GstData* data );
+-
++GstPadLinkReturn gst_equalizer_link(GstPad* pad, const GstCaps* caps);
++void gst_equalizer_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec );
++void gst_equalizer_get_property( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec );
++void set_filters( GstEqualizer* obj );
++void gst_equalizer_chain( GstPad* pad, GstData* data );
+ GType gst_equalizer_get_type( void );
+-GstEqualizer* gst_equalizer_new ();
++GstEqualizer* gst_equalizer_new();
++
+ 
+ G_END_DECLS
+