[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
+