[kdemultimedia] kmix crashes when pulseaudio exits (#804363)

Rex Dieter rdieter at fedoraproject.org
Tue Apr 24 12:34:19 UTC 2012


commit 081a614cf2f586c07f5978764077699a8f93898f
Author: Rex Dieter <rdieter at fedoraproject.org>
Date:   Tue Apr 24 07:35:03 2012 -0500

    kmix crashes when pulseaudio exits (#804363)
    
    - kmix is crashing after multiple volume changes (kde#290742)

 kdemultimedia-4.8.2-kmix_backport.patch | 4445 +++++++++++++++++++++++++++++++
 kdemultimedia.spec                      |   13 +-
 2 files changed, 4457 insertions(+), 1 deletions(-)
---
diff --git a/kdemultimedia-4.8.2-kmix_backport.patch b/kdemultimedia-4.8.2-kmix_backport.patch
new file mode 100644
index 0000000..3d9d0d9
--- /dev/null
+++ b/kdemultimedia-4.8.2-kmix_backport.patch
@@ -0,0 +1,4445 @@
+Index: kmix.desktop
+===================================================================
+--- kmix.desktop	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ kmix.desktop	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -109,6 +109,7 @@
+ Name[hne]=के-मिक्स
+ Name[hr]=KMix
+ Name[hu]=KMix
++Name[id]=KMix
+ Name[is]=KMix
+ Name[it]=KMix
+ Name[ja]=KMix
+Index: ConfigureChecks.cmake
+===================================================================
+--- ConfigureChecks.cmake	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ ConfigureChecks.cmake	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -7,16 +7,8 @@
+ # definitions like _GNU_SOURCE that are needed on each platform.
+ set(CMAKE_REQUIRED_DEFINITIONS ${_KDE4_PLATFORM_DEFINITIONS})
+ 
+-macro_bool_to_01(CARBON_FOUND HAVE_CARBON)
+-
+-macro_bool_to_01(AKODE_FOUND HAVE_AKODE)
+-
+ macro_bool_to_01(OGGVORBIS_FOUND HAVE_VORBIS)
+ 
+-macro_bool_to_01(X11_XShm_FOUND  HAVE_XSHMGETEVENTBASE)
+-
+-macro_bool_to_01(PULSEAUDIO_FOUND HAVE_PULSE)
+-
+ #now check for dlfcn.h using the cmake supplied CHECK_include_FILE() macro
+ # If definitions like -D_GNU_SOURCE are needed for these checks they
+ # should be added to _KDE4_PLATFORM_DEFINITIONS when it is originally
+@@ -29,20 +21,8 @@
+    set(CMAKE_REQUIRED_INCLUDES  ${KDEWIN32_INCLUDES} )
+ endif (WIN32)
+ 
+-check_include_files(machine/soundcard.h HAVE_MACHINE_SOUNDCARD_H)
+-check_include_files(soundcard.h HAVE_SOUNDCARD_H)
+-check_include_files(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
+-check_include_files(sys/stat.h HAVE_SYS_STAT_H)
+-check_include_files(linux/cdrom.h HAVE_LINUX_CDROM_H)
+-check_include_files(linux/ucdrom.h HAVE_LINUX_UCDROM_H)
+ check_include_files(machine/endian.h HAVE_MACHINE_ENDIAN_H)
+-check_include_files(sys/audioio.h HAVE_SYS_AUDIOIO_H)
+-check_include_files(Alib.h HAVE_ALIB_H)
+-check_include_files(alloca.h HAVE_ALLOCA_H)
+ # Linux has <endian.h>, FreeBSD has <sys/endian.h> and Solaris has neither.
+ check_include_files(endian.h HAVE_ENDIAN_H)
+ check_include_files(sys/endian.h HAVE_SYS_ENDIAN_H)
+ check_include_files(unistd.h HAVE_UNISTD_H)
+-
+-check_type_size("long" SIZEOF_LONG)
+-
+Index: kmixd.desktop
+===================================================================
+--- kmixd.desktop	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ kmixd.desktop	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,6 +20,7 @@
+ Name[gl]=KMixD
+ Name[hr]=KMixD
+ Name[hu]=KMixD
++Name[id]=KMixD
+ Name[is]=KMixD
+ Name[it]=KMixD
+ Name[ja]=KMixD
+Index: gui/mdwslider.h
+===================================================================
+--- gui/mdwslider.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwslider.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -52,7 +52,7 @@
+     Q_OBJECT
+ 
+ public:
+-    MDWSlider( MixDevice* md,
++    MDWSlider( shared_ptr<MixDevice> md,
+ 	       bool includePlayback, bool includeCapture,
+ 	       bool small, Qt::Orientation,
+ 	       QWidget* parent, ViewBase* view, ProfControl *pctl);
+Index: gui/viewbase.cpp
+===================================================================
+--- gui/viewbase.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewbase.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -49,7 +49,6 @@
+    setObjectName(id);
+    m_viewId = id;
+    _mixer = mixer;
+-   _mixSet = new MixSet();
+ 
+    // This must be populated now otherwise bad things happen (circular dependancies etc
+    // This is due to the fact that setMixSet() calls isDynamic() which in turn needs a populated
+@@ -89,7 +88,6 @@
+ }
+ 
+ ViewBase::~ViewBase() {
+-    delete _mixSet;
+     // Hint: The GUI profile will not be removed, as it is pooled and might be applied to a new View.
+ }
+ 
+@@ -103,7 +101,7 @@
+ 
+ bool ViewBase::isValid() const
+ {
+-   return ( _mixSet->count() > 0 || isDynamic() );
++   return ( !_mixSet.isEmpty() || isDynamic() );
+ }
+ 
+ void ViewBase::setIcons (bool on) { KMixToolBox::setIcons (_mdws, on ); }
+@@ -119,25 +117,13 @@
+  */
+ void ViewBase::createDeviceWidgets()
+ {
+-    // create devices
+-    foreach ( MixDevice* md, *_mixSet ) 
++    foreach ( shared_ptr<MixDevice> md, _mixSet )
+     {
+         QWidget* mdw = add(md); // a) Let the View implementation do its work
+         _mdws.append(mdw); // b) Add it to the local list
+     }
+     // allow view to "polish" itself
+     constructionFinished();
+-
+-// Moved the following up one Level to KMixerWidget
+-//   kDebug() << "CONNECT ViewBase count " << _mixers.size();
+-//  foreach ( Mixer* mixer, _mixers )
+-//  {
+-//    kDebug(67100) << "CONNECT ViewBase controlschanged" << mixer->id();
+-//   connect ( mixer, SIGNAL(controlChanged()), this, SLOT(refreshVolumeLevels()) );
+-//   connect ( mixer, SIGNAL(controlsReconfigured(QString)), this, SLOT(controlsReconfigured(QString)) );
+-//  }
+-
+-    
+ }
+ 
+ /**
+@@ -214,9 +200,9 @@
+ 
+ 	if (isRelevantMixer)
+ 	{
+-		kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << " is being redrawn (mixset contains: " << _mixSet->count() << ")";
++		kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << " is being redrawn (mixset contains: " << _mixSet.count() << ")";
+ 		setMixSet();
+-		kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << ": Recreating widgets (mixset contains: " << _mixSet->count() << ")";
++		kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << ": Recreating widgets (mixset contains: " << _mixSet.count() << ")";
+ 		createDeviceWidgets();
+ 	}
+ }
+@@ -249,13 +235,13 @@
+         while (!_mdws.isEmpty())
+         	delete _mdws.takeFirst();
+ 
+-        _mixSet->clear(); // Clean up our _mixSet so we can reapply our GUIProfile
++        _mixSet.clear(); // Clean up our _mixSet so we can reapply our GUIProfile
+     }
+     _setMixSet();
+     
+     _mixers.clear();
+     _mixers.insert(_mixer);
+-    foreach ( MixDevice* md, *_mixSet )
++    foreach ( shared_ptr<MixDevice> md, _mixSet )
+     {
+ //      kDebug() << "VVV Add to " << md->mixer()->id();
+ //      MixDeviceWidget* mdw = qobject_cast<MixDeviceWidget*>(qw);
+@@ -321,7 +307,7 @@
+            Workaround: If found, write back correct group name.
+         */
+          MixDeviceWidget* mdw = (MixDeviceWidget*)qmdw;
+-         MixDevice* md = mdw->mixDevice();
++         shared_ptr<MixDevice> md = mdw->mixDevice();
+ 
+          QString devgrp = QString("%1.%2.%3").arg(grp).arg(md->mixer()->id()).arg(md->id());
+          KConfigGroup devcg  = config->group( devgrp );
+@@ -398,7 +384,7 @@
+       if ( qmdw->inherits("MixDeviceWidget") )
+       {
+          MixDeviceWidget* mdw = (MixDeviceWidget*)qmdw;
+-         MixDevice* md = mdw->mixDevice();
++         shared_ptr<MixDevice> md = mdw->mixDevice();
+ 
+          //kDebug(67100) << "  grp=" << grp.toAscii();
+          //kDebug(67100) << "  mixer=" << view->id().toAscii();
+Index: gui/viewsliders.h
+===================================================================
+--- gui/viewsliders.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewsliders.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -25,6 +25,7 @@
+ //class QFormLayout;
+ #include <QFrame>
+ #include <QHash>
++class QLabel;
+ class QWidget;
+ 
+ class Mixer;
+@@ -35,9 +36,9 @@
+     Q_OBJECT
+ public:
+     ViewSliders(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actColl);
+-    ~ViewSliders();
++    virtual ~ViewSliders();
+ 
+-    virtual QWidget* add(MixDevice *mdw);
++    virtual QWidget* add(shared_ptr<MixDevice>);
+     virtual void constructionFinished();
+     virtual void configurationUpdate();
+ 
+@@ -52,6 +53,7 @@
+     QLayout* _layoutSliders;
+ 	QLayout* _layoutEnum;
+     QHash<QString,QFrame*> _separators;
++    QLabel* emptyStreamHint;
+ };
+ 
+ #endif
+Index: gui/kmixerwidget.h
+===================================================================
+--- gui/kmixerwidget.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixerwidget.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -91,7 +91,6 @@
+    
+    void createLayout(ViewBase::ViewFlags vflags);
+    bool possiblyAddView(ViewBase* vbase);
+-   void createViewsByProfile(Mixer* mixer, GUIProfile *guiprof, ViewBase::ViewFlags vflags);
+ };
+ 
+ #endif
+Index: gui/dialogselectmaster.cpp
+===================================================================
+--- gui/dialogselectmaster.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/dialogselectmaster.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/dialogselectmaster.h"
++
+ #include <qbuttongroup.h>
+ #include <QLabel>
+ #include <qradiobutton.h>
+@@ -30,7 +32,6 @@
+ #include <kdebug.h>
+ #include <klocale.h>
+ 
+-#include "gui/dialogselectmaster.h"
+ #include "core/mixdevice.h"
+ #include "core/mixer.h"
+ 
+@@ -159,16 +160,18 @@
+     m_vboxForScrollView = new KVBox(); //m_scrollableChannelSelector->viewport()
+ 
+     QString masterKey = "----noMaster---";  // Use a non-matching name as default
+-    MixDevice* master = mixer->getLocalMasterMD();
+-    if ( master != 0 ) masterKey = master->id();
++    shared_ptr<MixDevice> master = mixer->getLocalMasterMD();
++    if ( master.get() != 0 )
++    	masterKey = master->id();
+ 
+     const MixSet& mixset = mixer->getMixSet();
+     MixSet& mset = const_cast<MixSet&>(mixset);
+     for( int i=0; i< mset.count(); ++i )
+     {
+-        MixDevice* md = mset[i];
++    	shared_ptr<MixDevice> md = mset[i];
+         // Create a RadioButton for each MixDevice (excluding Enum's)
+-        if ( md->playbackVolume().hasVolume() ) {
++        if ( md->playbackVolume().hasVolume() )
++        {
+ //            kDebug(67100) << "DialogSelectMaster::createPage() mset append qrb";
+             QString mdName = md->readableName();
+             mdName.replace('&', "&&"); // Quoting the '&' needed, to prevent QRadioButton creating an accelerator
+Index: gui/mdwmoveaction.cpp
+===================================================================
+--- gui/mdwmoveaction.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwmoveaction.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -27,7 +27,7 @@
+ // Qt
+ #include <QString>
+ 
+-MDWMoveAction::MDWMoveAction(MixDevice* md, QObject *parent)
++MDWMoveAction::MDWMoveAction(shared_ptr<MixDevice> md, QObject *parent)
+  : KAction(parent), m_mixDevice(md)
+ {
+    Q_ASSERT(md);
+Index: gui/kmixtoolbox.cpp
+===================================================================
+--- gui/kmixtoolbox.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixtoolbox.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,7 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/kmixtoolbox.h"
+ 
+ #include <QWidget>
+ #include <QString>
+@@ -35,7 +36,8 @@
+ #include "core/mixer.h"
+ #include "viewbase.h"
+ 
+-#include "gui/kmixtoolbox.h"
++// TODO KMixToolbox is rather superfluous today, as there is no "KMix Applet" any more, and it was probably always bad style.
++//      I only have to think what to do with KMixToolBox::notification()
+ 
+ /***********************************************************************************
+  KMixToolbox contains several GUI relevant methods that are shared between the 
+Index: gui/mdwenum.h
+===================================================================
+--- gui/mdwenum.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwenum.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -45,7 +45,7 @@
+     Q_OBJECT
+ 
+ public:
+-    MDWEnum( MixDevice* md,
++    MDWEnum( shared_ptr<MixDevice> md,
+ 	       Qt::Orientation orientation,
+ 	       QWidget* parent, ViewBase* view, ProfControl* pctl);
+     ~MDWEnum();
+Index: gui/kmixprefdlg.h
+===================================================================
+--- gui/kmixprefdlg.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixprefdlg.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -26,6 +26,7 @@
+ 
+ class KMixPrefWidget;
+ class QCheckBox;
++class QFrame;
+ class QRadioButton;
+ 
+ class 
+@@ -37,7 +38,7 @@
+ 
+   public: 
+    KMixPrefDlg( QWidget *parent );
+-   ~KMixPrefDlg();
++   virtual ~KMixPrefDlg();
+ 
+   signals:
+    void signalApplied( KMixPrefDlg *prefDlg );
+Index: gui/kmixdockwidget.h
+===================================================================
+--- gui/kmixdockwidget.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixdockwidget.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -25,7 +25,7 @@
+ 
+ class QString;
+ #include <QWidget>
+-
++class QWidgetAction;
+ #include <kstatusnotifieritem.h>
+ 
+ class KMixWindow;
+@@ -46,7 +46,7 @@
+ 
+  public:
+    explicit KMixDockWidget(KMixWindow *parent,bool volumePopup);
+-   ~KMixDockWidget();
++   virtual ~KMixDockWidget();
+ 
+    void setErrorPixmap();
+    void ignoreNextEvent();
+Index: gui/ksmallslider.cpp
+===================================================================
+--- gui/ksmallslider.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/ksmallslider.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/ksmallslider.h"
++
+ // For INT_MAX
+ #include <limits.h>
+ 
+@@ -33,7 +35,6 @@
+ #include <QStyleOptionSlider>
+ 
+ #include "kglobalsettings.h"
+-#include "ksmallslider.h"
+ #include "core/mixer.h"
+ 
+ KSmallSlider::KSmallSlider( int minValue, int maxValue, int pageStep,
+Index: gui/mixdevicewidget.h
+===================================================================
+--- gui/mixdevicewidget.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mixdevicewidget.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -26,6 +26,7 @@
+ #define MIXDEVICEWIDGET_H
+ 
+ #include <QWidget>
++#include "core/mixdevice.h"
+ #include "core/volume.h"
+ #include <qpixmap.h>
+ 
+@@ -44,7 +45,7 @@
+       Q_OBJECT
+ 
+ public:
+-    MixDeviceWidget( MixDevice* md,
++    MixDeviceWidget( shared_ptr<MixDevice> md,
+                      bool small, Qt::Orientation orientation,
+                      QWidget* parent, ViewBase*, ProfControl * );
+     virtual ~MixDeviceWidget();
+@@ -52,7 +53,7 @@
+     void addActionToPopup( KAction *action );
+ 
+     virtual bool isDisabled() const;
+-    MixDevice* mixDevice() { return m_mixdevice; }
++    shared_ptr<MixDevice> mixDevice() { return m_mixdevice; }
+ 
+     virtual void setColors( QColor high, QColor low, QColor back );
+     virtual void setIcons( bool value );
+@@ -77,7 +78,7 @@
+ 
+ protected:
+ 
+-      MixDevice*           m_mixdevice;
++      shared_ptr<MixDevice>  m_mixdevice;
+       KActionCollection*   _mdwActions;
+       KActionCollection*   _mdwPopupActions;
+       ViewBase*            m_view;
+Index: gui/mdwslider.cpp
+===================================================================
+--- gui/mdwslider.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwslider.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/mdwslider.h"
++
+ #include <klocale.h>
+ #include <kiconloader.h>
+ #include <kconfig.h>
+@@ -40,20 +42,19 @@
+ #include <qwmatrix.h>
+ #include <QBoxLayout>
+ 
++#include "core/mixer.h"
+ #include "gui/guiprofile.h"
+-#include "mdwslider.h"
+-#include "volumeslider.h"
+-#include "core/mixer.h"
+-#include "viewbase.h"
+-#include "ksmallslider.h"
+-#include "verticaltext.h"
+-#include "mdwmoveaction.h"
++#include "gui/volumeslider.h"
++#include "gui/viewbase.h"
++#include "gui/ksmallslider.h"
++#include "gui/verticaltext.h"
++#include "gui/mdwmoveaction.h"
+ 
+ 
+ VolumeSliderExtraData MDWSlider::DummVolumeSliderExtraData;
+ bool MDWSlider::debugMe = false;
+  /**
+- * MixDeviceWidget that represents a single mix device, inlcuding PopUp, muteLED, ...
++ * MixDeviceWidget that represents a single mix device, including PopUp, muteLED, ...
+  *
+  * Used in KMix main window and DockWidget and PanelApplet.
+  * It can be configured to include or exclude the captureLED and the muteLED.
+@@ -62,7 +63,7 @@
+  *
+  * Due to the many options, this is the most complicated MixDeviceWidget subclass.
+  */
+-MDWSlider::MDWSlider(MixDevice* md, bool showMuteLED, bool showCaptureLED,
++MDWSlider::MDWSlider(shared_ptr<MixDevice> md, bool showMuteLED, bool showCaptureLED,
+         bool small, Qt::Orientation orientation, QWidget* parent
+         , ViewBase* view
+         , ProfControl* par_ctl
+@@ -91,6 +92,13 @@
+ 	{
+ 		delete slider;
+ 	}
++
++	/*
++	static int destructorCalls = 1;
++	kDebug() << "Destroying id=" << this->mixDevice()->id() << "desctructorCalls=" << destructorCalls;
++	++destructorCalls;
++	*/
++
+ }
+ 
+ void MDWSlider::createActions()
+@@ -546,7 +554,7 @@
+ 		QWidget *subcontrolLabel;
+ 
+ 		QString subcontrolTranslation;
+-		if ( type == 'c' ) subcontrolTranslation += i18n("Capture") + " ";
++		if ( type == 'c' ) subcontrolTranslation += i18n("Capture") + ' ';
+ 		subcontrolTranslation += Volume::ChannelNameReadable[vc.chid]; //Volume::getSubcontrolTranslation(chid);
+ 		subcontrolLabel = createLabel(this, subcontrolTranslation, volLayout, true);
+ 
+@@ -858,29 +866,19 @@
+ 
+ void MDWSlider::volumeChangeInternal( Volume& vol, QList<QAbstractSlider *>& ref_sliders  )
+ {
+-
+-	// --- Step 2: Change the volumes directly in the Volume object to reflect the Sliders ---
+ 	if ( isStereoLinked() )
+ 	{
+ 		QAbstractSlider* firstSlider = ref_sliders.first();
+-		long firstVolume = firstSlider->value();
+-		//kDebug(67100) << "firstVolume=" <<firstVolume;
+-		vol.setAllVolumes(firstVolume);
+-	} // stereoLinked()
+-
+-	else {
+-
+-	  	QAbstractSlider* firstSlider = ref_sliders.first();
+-		long firstVolume = firstSlider->value();
+-		//kDebug(67100) << "firstVolume=" <<firstVolume;
+-	  
+-		for( int i=0; i<ref_sliders.count(); i++ ) {
++		vol.setAllVolumes(firstSlider->value());
++	}
++	else
++	{
++		for( int i=0; i<ref_sliders.count(); i++ )
++		{
+ 			QAbstractSlider *sliderWidget = ref_sliders[i];
+ 			vol.setVolume( extraData(sliderWidget).getChid() ,sliderWidget->value());
+ 		} // iterate over all sliders
+-	} // !stereoLinked()
+-
+-	// --- Step 3: Write back the new volumes to the HW ---
++	}
+ }
+ 
+ 
+@@ -888,13 +886,15 @@
+    This slot is called, when a user has clicked the recsrc button. Also it is called by any other
+     associated KAction like the context menu.
+  */
+-void MDWSlider::toggleRecsrc() {
++void MDWSlider::toggleRecsrc()
++{
+ 	setRecsrc( m_mixdevice->isRecSource() );
+ }
+ 
+ void MDWSlider::setRecsrc(bool value )
+ {
+-	if ( m_mixdevice->captureVolume().hasSwitch() ) {
++	if ( m_mixdevice->captureVolume().hasSwitch() )
++	{
+ 		m_mixdevice->setRecSource( value );
+ 		m_mixdevice->mixer()->commitVolumeChange( m_mixdevice );
+ 	}
+@@ -905,7 +905,8 @@
+    This slot is called, when a user has clicked the mute button. Also it is called by any other
+     associated KAction like the context menu.
+  */
+-void MDWSlider::toggleMuted() {
++void MDWSlider::toggleMuted()
++{
+ 	setMuted( !m_mixdevice->isMuted() );
+ }
+ 
+@@ -1128,8 +1129,8 @@
+     _mdwMoveActions->addAction( QString("-"), a);
+ 
+     m_moveMenu->addAction( a );
+-    for (int i = 0; i < ms->count(); ++i) {
+-        MixDevice* md = (*ms)[i];
++    foreach (shared_ptr<MixDevice> md, *ms)
++    {
+         a = new MDWMoveAction(md, _mdwMoveActions);
+         _mdwMoveActions->addAction( QString("moveto") + md->id(), a);
+         connect(a, SIGNAL(moveRequest(QString)), SLOT(moveStream(QString)));
+Index: gui/viewdockareapopup.h
+===================================================================
+--- gui/viewdockareapopup.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewdockareapopup.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -35,9 +35,9 @@
+     Q_OBJECT
+ public:
+     ViewDockAreaPopup(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KMixWindow *dockW);
+-    ~ViewDockAreaPopup();
++    virtual ~ViewDockAreaPopup();
+ 
+-    virtual QWidget* add(MixDevice *mdw);
++    virtual QWidget* add(shared_ptr<MixDevice> md);
+     virtual void constructionFinished();
+     virtual void refreshVolumeLevels();
+     virtual void showContextMenu();
+Index: gui/viewsliders.cpp
+===================================================================
+--- gui/viewsliders.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewsliders.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -32,19 +32,22 @@
+ #endif
+ #endif
+ 
++#include "gui/viewsliders.h"
++
+ // KMix
+-#include "viewsliders.h"
+-#include "gui/guiprofile.h"
+-#include "mdwenum.h"
+-#include "mdwslider.h"
+ #include "core/mixdevicecomposite.h"
+ #include "core/mixer.h"
+-#include "verticaltext.h"
++#include "gui/guiprofile.h"
++#include "gui/mdwenum.h"
++#include "gui/mdwslider.h"
++#include "gui/verticaltext.h"
+ 
+ // KDE
+ #include <kdebug.h>
++#include <KLocale>
+ 
+ // Qt
++#include <QLabel>
+ #include <QWidget>
+ #include <QVBoxLayout>
+ #include <QHBoxLayout>
+@@ -55,6 +58,7 @@
+ /**
+  * Generic View implementation. This can hold now all kinds of controls (not just Sliders, as
+  *  the class name suggests).
++ *  TODO change "const char*" parameter to QString
+  */
+ ViewSliders::ViewSliders(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actColl)
+       : ViewBase(parent, name, mixer, Qt::FramelessWindowHint, vflags, guiprof, actColl)
+@@ -80,6 +84,28 @@
+    _layoutMDW->setSpacing(0);
+    _layoutMDW->addItem( _layoutSliders );
+ 
++    QString driverName = _mixer->getDriverName();
++
++
++    // Hint: This text comparison is not a clean solution, but one that will work for quite a while.
++    // TODO cesken Revise this "text comparison" thingy when I change the View constructor to take an "id" and a "readableName"
++    QString viewName(name);
++    if (viewName.contains(".Capture_Streams."))
++    	emptyStreamHint = new QLabel(i18n("Capture Streams"));
++    else if (viewName.contains(".Playback_Streams."))
++    	emptyStreamHint = new QLabel(i18n("Playback Streams"));
++    else if (viewName.contains(".Capture_Devices."))
++    	emptyStreamHint = new QLabel(i18n("Capture Devices"));
++    else if (viewName.contains(".Playback_Devices."))
++    	emptyStreamHint = new QLabel(i18n("Playback Devices"));
++    else
++    	emptyStreamHint = new QLabel(i18n("Playback Streams")); // Fallback. Assume Playback stream
++
++    emptyStreamHint->setAlignment(Qt::AlignCenter);
++    emptyStreamHint->setWordWrap( true );
++    emptyStreamHint->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
++    _layoutMDW->addWidget(emptyStreamHint);
++
+     setMixSet();
+ }
+ 
+@@ -90,13 +116,12 @@
+ 
+ 
+ 
+-QWidget* ViewSliders::add(MixDevice *md)
++QWidget* ViewSliders::add(shared_ptr<MixDevice> md)
++
+ {
+     MixDeviceWidget *mdw;
+     Qt::Orientation orientation = (_vflags & ViewBase::Vertical) ? Qt::Horizontal : Qt::Vertical;
+ 
+-
+-
+     if ( md->isEnum() ) {
+         mdw = new MDWEnum(
+                 md,           // MixDevice (parameter)
+@@ -121,6 +146,7 @@
+             _frm->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+         _separators.insert(md->id(),_frm);
+         _layoutSliders->addWidget(_frm);
++
+         mdw = new MDWSlider(
+                 md,           // MixDevice (parameter)
+                 true,         // Show Mute LED
+@@ -161,7 +187,7 @@
+ 
+ 
+ #ifdef TEST_MIXDEVICE_COMPOSITE
+-    QList<MixDevice*> mds;  // For temporary test
++    QList<shared_ptr<MixDevice> > mds;  // For temporary test
+ #endif
+ 
+     // This method iterates the controls from the Profile
+@@ -180,19 +206,18 @@
+         //kDebug(67100) << "ViewSliders::setMixSet(): Check GUIProfile id==" << control->id << "\n";
+         // The following for-loop could be simplified by using a std::find_if
+         for ( int i=0; i<mixset.count(); i++ ) {
+-            MixDevice *md = mixset[i];
++        	shared_ptr<MixDevice> md = mixset[i];
+ 
+             if ( md->id().contains(idRegexp) )
+             {
+                 // Match found (by name)
+-                if ( _mixSet->contains( md ) ) continue; // dup check
++                if ( _mixSet.contains( md ) ) continue; // dup check
+ 
+                 // Now check whether subcontrols match
+                 bool subcontrolPlaybackWanted = (control->useSubcontrolPlayback() && ( md->playbackVolume().hasVolume() || md->playbackVolume().hasSwitch()) );
+                 bool subcontrolCaptureWanted  = (control->useSubcontrolCapture()  && ( md->captureVolume() .hasVolume() || md->captureVolume() .hasSwitch()) );
+                 bool subcontrolEnumWanted  = (control->useSubcontrolEnum() && md->isEnum());
+                 bool subcontrolWanted =  subcontrolPlaybackWanted | subcontrolCaptureWanted | subcontrolEnumWanted;
+-		bool splitWanted = control->isSplit();
+ 
+                 if ( !subcontrolWanted ) continue;
+ 
+@@ -207,7 +232,7 @@
+                     else if ( control->getSwitchtype() == "Off"  )
+                         md->playbackVolume().setSwitchType(Volume::OffSwitch);
+                 }
+-                _mixSet->append(md);
++                _mixSet.append(md);
+ 
+ #ifdef TEST_MIXDEVICE_COMPOSITE
+                 if ( md->id() == "Front:0" || md->id() == "Surround:0") { mds.append(md); } // For temporary test
+@@ -224,6 +249,10 @@
+         }
+    } // iteration over all controls from the Profile
+ 
++	emptyStreamHint->setVisible(  _mixSet.isEmpty() && isDynamic() ); // show a hint why a tab is empty (dynamic controls!!!)
++	//  visibleControls() == 0 could be used for the !isDynamic() case
++
++
+ #ifdef TEST_MIXDEVICE_COMPOSITE
+ 	// @todo: This is currently hardcoded, and instead must be read as usual from the Profile
+     MixDeviceComposite *mdc = new MixDeviceComposite(_mixer, "Composite_Test", mds, "A Composite Control #1", MixDevice::KMIX_COMPOSITE);
+@@ -241,6 +270,7 @@
+ 
+ void ViewSliders::constructionFinished() {
+     configurationUpdate();
++    // TODO Add a "show more" / "configure this view" button
+ }
+ 
+ 
+@@ -274,6 +304,7 @@
+          if ( thisControlIsVisible ) firstVisibleControlFound=true;
+       }
+     } // for all  MDW's
++
+     _layoutMDW->activate();
+ }
+ 
+Index: gui/kmixerwidget.cpp
+===================================================================
+--- gui/kmixerwidget.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixerwidget.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -18,6 +18,7 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/kmixerwidget.h"
+ 
+ // Qt
+ #include <QLabel>
+@@ -39,12 +40,11 @@
+ // KMix
+ #include "apps/kmix.h"
+ #include "gui/guiprofile.h"
+-#include "gui/kmixerwidget.h"
+ #include "gui/kmixtoolbox.h"
+ #include "gui/mixdevicewidget.h"
++#include "gui/viewsliders.h"
+ #include "core/mixer.h"
+ #include "core/mixertoolbox.h"
+-#include "viewsliders.h"
+ 
+ 
+ /**
+@@ -104,61 +104,18 @@
+    * 2b) Create device widgets
+    * 2c) Add Views to Tab
+    ********************************************************************/
+-   createViewsByProfile(_mixer, _guiprof, vflags);
++   ViewSliders* view = new ViewSliders( this, _guiprof->getId().toLatin1(), _mixer, vflags, _guiprof, _actionCollection );
++   possiblyAddView(view);
+    show();
+    //    kDebug(67100) << "KMixerWidget::createLayout(): EXIT\n";
+ }
+ 
+ 
+ /**
+-* Creates the View based on the GUIProfile, for the Tab tabId
++ * Add the given view, if it is valid - it must have controls or at least have the chance to gain some (dynamic views)
++ * @param vbase
++ * @return true, if the view was added
+  */
+-void KMixerWidget::createViewsByProfile(Mixer* mixer, GUIProfile *guiprof, ViewBase::ViewFlags vflags)
+-{
+-    ViewSliders* view = new ViewSliders( this, "", mixer, vflags, guiprof, _actionCollection );
+-    bool added = possiblyAddView(view);
+-    if ( added && view->visibleControls() == 0)
+-    {
+-        QString driverName = mixer->getDriverName();
+-        QBoxLayout *lay = new QHBoxLayout(view);
+-        //lay->setSizeConstraint(QLayout::SetNoConstraint);
+-        lay->setAlignment(Qt::AlignCenter);
+-        QLabel* lbl = new QLabel();
+-        lbl->setAlignment(Qt::AlignCenter);
+-        lbl->setWordWrap( true );
+-        lbl->setText("Empty: " + driverName);
+-        lay->addWidget(lbl);
+-        //m_topLayout->addLayout(lay);
+-    }
+-
+-#if 0
+-   /*** How it works:
+-   * A loop is done over all tabs.
+-   * For each Tab a View (e.g. ViewSliders) is instanciated and added to the list of Views
+-   */
+-   QList<ProfTab*>::const_iterator itEnd = guiprof->tabs().end();
+-   for ( QList<ProfTab*>::const_iterator it = guiprof->tabs().begin(); it != itEnd; ++it) {
+-       ProfTab* profTab = *it;
+-       if ( profTab->type() == "Sliders" ) {
+-           if ( profTab->name() == 0 || profTab->name().isNull() )
+-            {
+-                kError() << "TAB NAME IS NULL";
+-                profTab->name() = "Undefined";
+-            }
+-            kDebug() << ">>> TAB NAME = " << profTab->name();
+-           QByteArray qba = profTab->name().toAscii();
+-            ViewSliders* view = new ViewSliders( this, qba, mixer, vflags, guiprof, _actionCollection );
+-            possiblyAddView(view);
+-            break;
+-        }
+-        else {
+-            kDebug(67100) << "KMixerWidget::createViewsByProfile(): Unknown Tab type '" << profTab->type() << "'\n";
+-        }
+-    } // search for correct tab
+-#endif
+-}
+-
+-
+ bool KMixerWidget::possiblyAddView(ViewBase* vbase)
+ {
+    if ( ! vbase->isValid()  ) {
+@@ -216,11 +173,7 @@
+  */
+ ViewBase* KMixerWidget::currentView()
+ {
+-    ViewBase* view = 0;
+-    if ( _views.size() > 0 ) {
+-        view = _views[0];
+-    }
+-    return view;
++	return _views.empty() ? 0 : _views[0];
+ }
+ 
+ 
+Index: gui/dialogaddview.cpp
+===================================================================
+--- gui/dialogaddview.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/dialogaddview.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/dialogaddview.h"
++
+ #include <qbuttongroup.h>
+ #include <QLabel>
+ #include <qradiobutton.h>
+@@ -30,7 +32,6 @@
+ #include <kdebug.h>
+ #include <klocale.h>
+ 
+-#include "gui/dialogaddview.h"
+ #include "core/mixdevice.h"
+ #include "core/mixer.h"
+ 
+Index: gui/guiprofile.cpp
+===================================================================
+--- gui/guiprofile.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/guiprofile.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -118,9 +118,9 @@
+         fname += ".%1.%2";
+         fname = fname.arg(mixer->getBaseName()).arg(mixer->getCardInstance());
+     }
+-    fname += "." + profileName;
++    fname += '.' + profileName;
+ 
+-    fname.replace(" ","_");
++    fname.replace(' ','_');
+     return fname;
+ }
+ 
+@@ -133,10 +133,10 @@
+     QString fname;
+     fname += mixer->getBaseName();
+     if ( mixer->getCardInstance() > 1 ) {
+-        fname += " " + mixer->getCardInstance();
++        fname += ' ' + mixer->getCardInstance();
+     }
+     if ( profileName != "default" ) {
+-        fname += " " + profileName;
++        fname += ' ' + profileName;
+     }
+ 
+     return fname;
+@@ -322,7 +322,7 @@
+    bool ret = false;
+    QString fileName, fileNameFQ;
+    fileName = "profiles/" + getId() + ".xml";
+-   fileName.replace(":", ".");
++   fileName.replace(':', '.');
+    fileNameFQ = KStandardDirs::locateLocal("appdata", fileName, true );
+ 
+    kDebug() << "Write profile:" << fileNameFQ ;
+@@ -424,9 +424,9 @@
+ QString xmlify(QString raw)
+ {
+ // 	kDebug() << "Before: " << raw;
+-	raw = raw.replace("&", "&amp;");
+-	raw = raw.replace("<", "&lt;");
+-	raw = raw.replace(">", "&gt;");
++	raw = raw.replace('&', "&amp;");
++	raw = raw.replace('<', "&lt;");
++	raw = raw.replace('>', "&gt;");
+ 	raw = raw.replace("'", "&apos;");
+ 	raw = raw.replace("\"", "&quot;");
+ // 	kDebug() << "After : " << raw;
+@@ -777,7 +777,7 @@
+     if ( !id.isNull() ) {
+         // We need at least an "id". We can set defaults for the rest, if undefined.
+         if ( subcontrols.isNull() || subcontrols.isEmpty() ) {
+-            subcontrols = "*";  // for compatibility reasons, we interpret an empty string as match-all (aka "*")
++            subcontrols = '*';  // for compatibility reasons, we interpret an empty string as match-all (aka "*")
+         }
+         if ( name.isNull() ) {
+             // ignore. isNull() will be checked by all users.
+@@ -793,7 +793,7 @@
+         }
+ 
+         ProfControl *profControl = new ProfControl(id, subcontrols);
+-        if ( show.isNull() ) { show = "*"; }
++        if ( show.isNull() ) { show = '*'; }
+ 
+ 	profControl->name = name;
+ 	profControl->show = show;
+Index: gui/viewbase.h
+===================================================================
+--- gui/viewbase.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewbase.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -29,12 +29,14 @@
+ // KDE
+ #include <KActionCollection>
+ class KMenu;
+-class MixSet;
++
+ class Mixer;
+ class MixDevice;
+ 
+ // KMix
+ class GUIProfile;
++#include "core/mixdevice.h"
++#include "core/mixset.h"
+ 
+ /**
+   * The ViewBase is a virtual base class, to be used for subclassing the real Mixer Views.
+@@ -95,9 +97,8 @@
+ 
+     /**
+      * Creates a suitable representation for the given MixDevice.
+-     * The default implementation creates a label
+      */
+-    virtual QWidget* add(MixDevice *) = 0;
++    virtual QWidget* add(shared_ptr<MixDevice>) = 0;
+ 
+     /**
+      * Popup stuff
+@@ -130,7 +131,7 @@
+ 
+ 
+ protected:
+-    MixSet *_mixSet;
++    MixSet _mixSet;
+     Mixer *_mixer;
+     QSet<Mixer*> _mixers; // this might deprecate _mixer in the future. Currently only in use by ViewDockAreaPopup
+     KMenu *_popMenu;
+Index: gui/kmixprefdlg.cpp
+===================================================================
+--- gui/kmixprefdlg.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixprefdlg.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,18 +20,17 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/kmixprefdlg.h"
++
+ #include <qbuttongroup.h>
+ #include <qwhatsthis.h>
+ #include <QCheckBox>
+ #include <QLabel>
+ #include <qradiobutton.h>
+ 
+-#include <klocale.h>
+-// For "kapp"
+ #include <kapplication.h>
++#include <klocale.h>
+ 
+-//#include "apps/kmix.h"
+-#include "gui/kmixprefdlg.h"
+ #include "gui/kmixerwidget.h"
+ 
+ 
+Index: gui/mdwenum.cpp
+===================================================================
+--- gui/mdwenum.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwenum.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -47,7 +47,7 @@
+  * Class that represents an Enum element (a select one-from-many selector)
+  * The orientation (horizontal, vertical) is ignored
+  */
+-MDWEnum::MDWEnum( MixDevice* md,
++MDWEnum::MDWEnum( shared_ptr<MixDevice> md,
+                  Qt::Orientation orientation,
+                  QWidget* parent, ViewBase* view, ProfControl* par_pctl) :
+    MixDeviceWidget(md, false, orientation, parent, view, par_pctl),
+Index: gui/kmixdockwidget.cpp
+===================================================================
+--- gui/kmixdockwidget.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/kmixdockwidget.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -21,6 +21,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/kmixdockwidget.h"
++
+ #include <kaction.h>
+ #include <klocale.h>
+ #include <kapplication.h>
+@@ -46,7 +48,6 @@
+ 
+ #include "gui/dialogselectmaster.h"
+ #include "apps/kmix.h"
+-#include "gui/kmixdockwidget.h"
+ #include "core/mixer.h"
+ #include "gui/mixdevicewidget.h"
+ #include "core/mixertoolbox.h"
+@@ -77,7 +78,7 @@
+     
+     if ( NO_MENU_ANYMORE )
+     {
+-      connect(contextMenu(), SIGNAL(aboutToShow()), this, SLOT(activateMenuOrWindow(bool,QPoint)));
++      connect(contextMenu(), SIGNAL(aboutToShow()), this, SLOT(contextMenuAboutToShow()));
+     }
+     else
+     {
+@@ -85,10 +86,10 @@
+       connect(contextMenu(), SIGNAL(aboutToShow()), this, SLOT(contextMenuAboutToShow()));
+     }
+ 
+-#ifdef _GNU_SOURCE
+-// TODO minimizeRestore usage is currently a bit broken. It only works by chance
++#ifdef __GNUC__
+ #warning minimizeRestore usage is currently slightly broken in KMIx. This should be fixed before doing a release.
+ #endif
++    // TODO minimizeRestore usage is currently a bit broken. It only works by chance
+ 
+     if (_volumePopup) {
+         kDebug() << "Construct the ViewDockAreaPopup and actions";
+@@ -128,8 +129,9 @@
+ {
+    QMenu *menu = contextMenu();
+    
+-   MixDevice* md = Mixer::getGlobalMasterMD();
+-  if ( md != 0 && md->playbackVolume().hasSwitch() ) {
++   shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++  if ( md.get() != 0 && md->playbackVolume().hasSwitch() )
++  {
+     // Put "Mute" selector in context menu
+     KToggleAction *action = actionCollection()->add<KToggleAction>( "dock_mute" );
+     action->setText( i18n( "M&ute" ) );
+@@ -212,11 +214,11 @@
+ void
+ KMixDockWidget::setVolumeTip()
+ {
+-    MixDevice *md = Mixer::getGlobalMasterMD();
++	shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
+     QString tip = "";
+     int newToolTipValue = 0;
+ 
+-    if ( md == 0 )
++    if ( md.get() == 0 )
+     {
+         tip = i18n("Mixer cannot be found"); // !! text could be reworked
+         newToolTipValue = -2;
+@@ -225,14 +227,8 @@
+     {
+         // Playback volume will be used for the DockIcon if available.
+         // This heuristic is "good enough" for the DockIcon for now.
+-        int val = 0;
+-        Volume& vol       = md->playbackVolume();
+-        if (! vol.hasVolume() ) {
+-           vol = md->captureVolume();
+-        }
+-        if ( vol.hasVolume() ) {
+-            val = vol.getAvgVolumePercent(Volume::MALL);
+-        }
++        Volume& vol = md->playbackVolume().hasVolume() ? md->playbackVolume() : md->captureVolume();
++       	int val = vol.getAvgVolumePercent(Volume::MALL);
+ 
+         // create a new "virtual" value. With that we see "volume changes" as well as "muted changes"
+         newToolTipValue = val;
+@@ -256,34 +252,31 @@
+ void
+ KMixDockWidget::updatePixmap()
+ {
+-    MixDevice *md = Mixer::getGlobalMasterMD();
++	shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
+ 
+     char newPixmapType;
+     if ( md == 0 )
+     {
+         newPixmapType = 'e';
+     }
+-    else if ( md->playbackVolume().hasSwitch() && md->isMuted() )
+-    {
+-        newPixmapType = 'm';
+-    }
+     else
+     {
+-        Volume& vol = md->playbackVolume();
+-        if (! vol.hasVolume() ) {
+-            vol = md->captureVolume();
+-        }
+-        int percentage         = vol.getAvgVolumePercent(Volume::MALL);
++    	Volume& vol = md->playbackVolume().hasVolume() ? md->playbackVolume() : md->captureVolume();
++    	bool isInactive =  vol.isCapture() ? !md->isRecSource() : md->isMuted();
++		if ( isInactive )
++		{
++			newPixmapType = 'm';
++		}
++		else
++		{
++			int percentage         = vol.getAvgVolumePercent(Volume::MALL);
++			if      ( percentage <= 0 ) newPixmapType = '0';  // Hint: also negative-values
++			else if ( percentage < 25 ) newPixmapType = '1';
++			else if ( percentage < 75 ) newPixmapType = '2';
++			else                        newPixmapType = '3';
++	   }
++    }
+ 
+-       // kDebug() << "TrayVol id=" << md->id() << " vol=" << vol.getAvgVolumePercent(Volume::MALL);
+-
+-        if      ( percentage <= 0 ) newPixmapType = '0';  // Hint: also negative-values
+-        else if ( percentage < 25 ) newPixmapType = '1';
+-        else if ( percentage < 75 ) newPixmapType = '2';
+-        else                        newPixmapType = '3';
+-   }
+-
+-
+    if ( newPixmapType != _oldPixmapType ) {
+       // Pixmap must be changed => do so
+       switch ( newPixmapType ) {
+@@ -381,18 +374,15 @@
+     }
+ }
+ 
+-// void
+-// KMixDockWidget::trayToolTipEvent(QHelpEvent *e ) {
+-//    kDebug(67100) << "trayToolTipEvent" ;
+-//    setVolumeTip();
+-// }
+ 
+ void
+ KMixDockWidget::trayWheelEvent(int delta,Qt::Orientation wheelOrientation)
+ {
+-  MixDevice *md = Mixer::getGlobalMasterMD();
+-  if ( md != 0 )
+-  {
++	shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++	if ( md.get() == 0 )
++		return;
++
++
+       Volume &vol = ( md->playbackVolume().hasVolume() ) ?  md->playbackVolume() : md->captureVolume();
+       int inc = vol.volumeSpan() / Mixer::VOLUME_STEP_DIVISOR;
+ 
+@@ -403,10 +393,15 @@
+ 
+     long int cv = inc * (delta / 120 );
+ //    kDebug() << "twe: " << cv << " : " << vol;
+-	if ( cv > 0 && md->isMuted())
++    bool isInactive =  vol.isCapture() ? !md->isRecSource() : md->isMuted();
++    kDebug() << "Operating on capture=" << vol.isCapture() << ", isInactive=" << isInactive;
++	if ( cv > 0 && isInactive)
+ 	{   // increasing from muted state: unmute and start with a low volume level
+-	    md->setMuted(false);
+-	    vol.setAllVolumes(cv);
++		if ( vol.isCapture())
++			md->setRecSource(true);
++		else
++			md->setMuted(false);
++		vol.setAllVolumes(cv);
+ 	}
+ 	else
+ 	    vol.changeAllVolumes(cv);
+@@ -421,15 +416,15 @@
+ 
+     md->mixer()->commitVolumeChange(md);
+     setVolumeTip();
+-  }
+ }
+ 
+ 
+ void
+ KMixDockWidget::dockMute()
+ {
+-   MixDevice *md = Mixer::getGlobalMasterMD();
+-   if ( md ) {
++	shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++	if ( md )
++   {
+       md->toggleMute();
+       md->mixer()->commitVolumeChange( md );
+    }
+@@ -460,13 +455,15 @@
+     */
+ 
+     // Enable/Disable "Muted" menu item
+-    MixDevice* md = Mixer::getGlobalMasterMD();
++	shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
+     KToggleAction *dockMuteAction = static_cast<KToggleAction*>(actionCollection()->action("dock_mute"));
+     //kDebug(67100) << "---> md=" << md << "dockMuteAction=" << dockMuteAction << "isMuted=" << md->isMuted();
+     if ( md != 0 && dockMuteAction != 0 ) {
+-        bool hasSwitch = md->playbackVolume().hasSwitch();
++    	Volume& vol = md->playbackVolume().hasVolume() ? md->playbackVolume() : md->captureVolume();
++    	bool isInactive =  vol.isCapture() ? md->isMuted() : !md->isRecSource();
++        bool hasSwitch = vol.hasSwitch();
+         dockMuteAction->setEnabled( hasSwitch );
+-        dockMuteAction->setChecked( hasSwitch && md->isMuted() );
++        dockMuteAction->setChecked( hasSwitch && !isInactive );
+     }
+     _contextMenuWasOpen = true;
+ }
+Index: gui/mixdevicewidget.cpp
+===================================================================
+--- gui/mixdevicewidget.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mixdevicewidget.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,9 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "gui/mixdevicewidget.h"
++
++#include <kactioncollection.h>
+ #include <klocale.h>
+ #include <kiconloader.h>
+ #include <kconfig.h>
+@@ -33,10 +36,7 @@
+ #include <qpixmap.h>
+ #include <qwmatrix.h>
+ 
+-#include <kactioncollection.h>
+-
+ #include "core/mixer.h"
+-#include "gui/mixdevicewidget.h"
+ #include "core/mixertoolbox.h"
+ #include "viewbase.h"
+ #include "ksmallslider.h"
+@@ -51,7 +51,7 @@
+  * SHOULD honor these values - those who do not might not be suitable for placing in
+  * the panel applet or any other smallish settings.
+  */
+-MixDeviceWidget::MixDeviceWidget(MixDevice* md,
++MixDeviceWidget::MixDeviceWidget(shared_ptr<MixDevice> md,
+                                  bool small, Qt::Orientation orientation,
+                                  QWidget* parent, ViewBase* view, ProfControl* par_pctl) :
+    QWidget( parent ), m_mixdevice( md ), m_view( view ), _pctl(par_pctl),
+Index: gui/mdwmoveaction.h
+===================================================================
+--- gui/mdwmoveaction.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/mdwmoveaction.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -23,14 +23,14 @@
+ 
+ #include <KAction>
+ 
+-class MixDevice;
++#include "core/mixdevice.h"
+ 
+ class MDWMoveAction : public KAction
+ {
+     Q_OBJECT
+ 
+     public:
+-        MDWMoveAction(MixDevice* md, QObject *parent);
++        MDWMoveAction(shared_ptr<MixDevice> md, QObject *parent);
+         ~MDWMoveAction();
+ 
+     signals:
+@@ -40,7 +40,7 @@
+         void triggered(bool checked);
+ 
+    private:
+-        MixDevice *m_mixDevice;
++        shared_ptr<MixDevice> m_mixDevice;
+ };
+ 
+ #endif
+Index: gui/dialogviewconfiguration.cpp
+===================================================================
+--- gui/dialogviewconfiguration.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/dialogviewconfiguration.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "dialogviewconfiguration.h"
++
+ #include <algorithm>
+ 
+ #include <QCheckBox>
+@@ -33,7 +35,6 @@
+ #include <klocale.h>
+ #include <kvbox.h>
+ 
+-#include "dialogviewconfiguration.h"
+ #include "gui/guiprofile.h"
+ #include "gui/mixdevicewidget.h"
+ #include "core/mixdevice.h"
+@@ -254,7 +255,7 @@
+       QWidget *qw = mdws[i];
+       if ( qw->inherits("MixDeviceWidget") ) {
+             MixDeviceWidget *mdw = static_cast<MixDeviceWidget*>(qw);
+-            MixDevice *md = mdw->mixDevice();
++            shared_ptr<MixDevice> md = mdw->mixDevice();
+             QString mdName = md->readableName();
+ 
+             int splitted = -1;
+@@ -380,7 +381,7 @@
+             if ( ctlId.contains(idRegexp) ) {
+                 // found. Create a copy
+                 ProfControl* newCtl = new ProfControl(*control);
+-                newCtl->id =  "^" + ctlId + "$"; // Replace the (possible generic) regexp by the actual ID
++                newCtl->id =  '^' + ctlId + '$'; // Replace the (possible generic) regexp by the actual ID
+                 // We have made this an an actual control. As it is derived (from e.g. ".*") it is NOT mandatory.
+                 newCtl->setMandatory(false);
+                 if ( isActiveView ) {
+Index: gui/viewdockareapopup.cpp
+===================================================================
+--- gui/viewdockareapopup.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ gui/viewdockareapopup.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -77,43 +77,41 @@
+ 
+ void ViewDockAreaPopup::_setMixSet()
+ {
+-   // kDebug(67100) << "ViewDockAreaPopup::setMixSet()\n";
++	// kDebug(67100) << "ViewDockAreaPopup::setMixSet()\n";
+ 
+-  // -- remove controls
+-   if ( _mixer->isDynamic() ) {
+-      // Our _layoutMDW now should only contain spacer widgets from the QSpacerItem's in add() below.
+-      // We need to trash those too otherwise all sliders gradually migrate away from the edge :p
+-      QLayoutItem *li;
+-      while ( ( li = _layoutMDW->takeAt(0) ) )
+-         delete li;
+-   }
++	// -- remove controls
++	if ( _mixer->isDynamic() ) {
++		// Our _layoutMDW now should only contain spacer widgets from the QSpacerItem's in add() below.
++		// We need to trash those too otherwise all sliders gradually migrate away from the edge :p
++		QLayoutItem *li;
++		while ( ( li = _layoutMDW->takeAt(0) ) )
++			delete li;
++	}
+ 
+-   MixDevice *dockMD = Mixer::getGlobalMasterMD();
+-   if ( dockMD == 0 ) {
+-      // If we have no dock device yet, we will take the first available mixer device
+-      if ( _mixer->size() > 0) {
+-         dockMD = (*_mixer)[0];
+-      }
+-   }
+-   if ( dockMD != 0 ) {
+-      _mixSet->append(dockMD);
+-   }
+-   
+-   Mixer* mixer2;
+-   foreach ( mixer2 , Mixer::mixers() )
+-   {
+-   MixDevice *md;
+-   foreach ( md, mixer2->getMixSet() )
+-   {
+-     if (md->isApplicationStream())
+-     {
+-      _mixSet->append(md);
+-      kDebug(67100) << "Add to tray popup: " << md->id();
+-     }
+-   }
++	shared_ptr<MixDevice>dockMD = Mixer::getGlobalMasterMD();
++	if ( dockMD == 0 ) {
++		// If we have no dock device yet, we will take the first available mixer device
++		if ( _mixer->size() > 0) {
++			dockMD = (*_mixer)[0];
++		}
++	}
++	if ( dockMD != 0 ) {
++		_mixSet.append(dockMD);
++	}
++
++	foreach ( Mixer* mixer2 , Mixer::mixers() )
++	{
++		foreach ( shared_ptr<MixDevice> md, mixer2->getMixSet() )
++		{
++			if (md->isApplicationStream())
++			{
++				_mixSet.append(md);
++				kDebug(67100) << "Add to tray popup: " << md->id();
++			}
++		}
++	}
++
+ }
+-   
+-}
+ 
+ 
+ void ViewDockAreaPopup::controlsReconfigured( const QString& mixer_ID )
+@@ -124,15 +122,15 @@
+ }
+ 
+ 
+-QWidget* ViewDockAreaPopup::add(MixDevice *md)
++QWidget* ViewDockAreaPopup::add(shared_ptr<MixDevice> md)
+ {
+     QString dummyMatchAll("*");
+-    QString matchAllPlaybackAndTheCswitch("pvolume,pswitch,cswitch");
++    QString matchAllPlaybackAndTheCswitch("pvolume,cvolume,pswitch,cswitch");
+     ProfControl *pctl = new ProfControl( dummyMatchAll, matchAllPlaybackAndTheCswitch);
+     MixDeviceWidget *mdw = new MDWSlider(
+       md,           // only 1 device.
+       true,         // Show Mute LED
+-      false,        // Show Record LED
++      true,        // Show Record LED
+       false,        // Small
+       _dock->toplevelOrientation(), // Direction: only 1 device, so doesn't matter
+       this,         // parent
+Index: kmix_autostart.desktop
+===================================================================
+--- kmix_autostart.desktop	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ kmix_autostart.desktop	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -114,6 +114,7 @@
+ Name[hne]=के-मिक्स
+ Name[hr]=KMix
+ Name[hu]=KMix
++Name[id]=KMix
+ Name[is]=KMix
+ Name[it]=KMix
+ Name[ja]=KMix
+Index: core/mixdevicecomposite.cpp
+===================================================================
+--- core/mixdevicecomposite.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixdevicecomposite.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -25,7 +25,7 @@
+ 
+ const long MixDeviceComposite::VolMax = 10000;
+ 
+-MixDeviceComposite::MixDeviceComposite( Mixer* mixer,  const QString& id, QList<MixDevice*>& mds, const QString& name, ChannelType type ) :
++MixDeviceComposite::MixDeviceComposite( Mixer* mixer,  const QString& id, QList<shared_ptr<MixDevice> >& mds, const QString& name, ChannelType type ) :
+    MixDevice( mixer, id, name, type )  // this will use doNotRestore == true
+ {
+     setArtificial(true);
+@@ -33,9 +33,9 @@
+     _compositePlaybackVolume->addVolumeChannel(Volume::LEFT);
+     _compositePlaybackVolume->addVolumeChannel(Volume::RIGHT);
+ 
+-    QListIterator<MixDevice*> it(mds);
++    QListIterator<shared_ptr<MixDevice> > it(mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         _mds.append(md);
+     }
+ }
+@@ -75,11 +75,12 @@
+ 
+ long MixDeviceComposite::calculateVolume(Volume::VolumeType vt)
+ {
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     long volSum = 0;
+     int  volCount = 0;
+-    while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    while ( it.hasNext())
++    {
++    	shared_ptr<MixDevice> md = it.next();
+ 
+         Volume& vol =  ( vt == Volume::CaptureVT ) ? md->captureVolume() : md->playbackVolume();
+         if (vol.hasVolume() && (vol.maxVolume() != 0) ) {
+@@ -100,9 +101,9 @@
+ bool MixDeviceComposite::isMuted()
+ {
+     bool isMuted = false;
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         isMuted |= md->isMuted();
+         if ( isMuted ) break;  // Enough. It can't get more true :-)
+     }
+@@ -113,9 +114,9 @@
+ 
+ void MixDeviceComposite::setMuted(bool value)
+ {
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         md->setMuted(value);
+     }
+ }
+@@ -123,9 +124,9 @@
+ bool MixDeviceComposite::isRecSource()
+ {
+     bool isRecSource = false;
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         isRecSource |= md->isRecSource();
+         if ( isRecSource ) break;  // Enough. It can't get more true :-)
+     }
+@@ -135,9 +136,9 @@
+ 
+ void MixDeviceComposite::setRecSource(bool value)
+ {
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         md->setRecSource(value);
+     }
+ }
+@@ -146,9 +147,9 @@
+ bool MixDeviceComposite::isEnum()
+ {
+     bool isEnum = true;
+-    QListIterator<MixDevice*> it(_mds);
++    QListIterator<shared_ptr<MixDevice> > it(_mds);
+     while ( it.hasNext()) {
+-        MixDevice* md = it.next();
++    	shared_ptr<MixDevice> md = it.next();
+         isEnum &= md->isEnum();
+         if ( ! isEnum ) break;  // Enough. It can't get more false :-)
+     }
+Index: core/MasterControl.h
+===================================================================
+--- core/MasterControl.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/MasterControl.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -10,6 +10,11 @@
+ 
+ #include <QString>
+ 
++// std::shared_ptr
++#include <memory>
++#include <tr1/memory>
++using namespace ::std::tr1;
++
+ class MasterControl
+ {
+ public:
+Index: core/mixdevicecomposite.h
+===================================================================
+--- core/mixdevicecomposite.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixdevicecomposite.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -74,7 +74,7 @@
+     *  @par name is the readable name. This one is presented to the user in the GUI
+     *  @par type The control type. It is only used to find an appropriate icon
+     */
+-   MixDeviceComposite( Mixer* mixer,  const QString& id, QList<MixDevice*>& mds, const QString& name, ChannelType type );
++   MixDeviceComposite( Mixer* mixer,  const QString& id, QList<shared_ptr<MixDevice> >& mds, const QString& name, ChannelType type );
+ //   MixDevice( Mixer* mixer, const QString& id, const QString& name, const QString& iconName = "", bool doNotRestore = false, MixSet* moveDestinationMixSet = 0 );
+    ~MixDeviceComposite();
+ 
+@@ -99,7 +99,7 @@
+    long calculateVolume(Volume::VolumeType vt);
+ 
+    Mixer *_mixer;
+-   QList<MixDevice*> _mds;
++   QList<shared_ptr<MixDevice> > _mds;
+ 
+    static const long VolMax;
+ 
+Index: core/volume.cpp
+===================================================================
+--- core/volume.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/volume.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,12 +19,13 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "core/volume.h"
++
+ // for operator<<()
+ #include <iostream>
+ 
+ #include <kdebug.h>
+ 
+-#include "core/volume.h"
+ 
+ 
+ int Volume::_channelMaskEnum[9] =
+Index: core/mixset.cpp
+===================================================================
+--- core/mixset.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixset.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -33,6 +33,10 @@
+ #include <QString>
+ 
+ 
++MixSet::~MixSet()
++{
++	clear();
++}
+ 
+ void MixSet::read( KConfig *config, const QString& grp )
+ {
+@@ -40,9 +44,8 @@
+    KConfigGroup group = config->group(grp);
+    m_name = group.readEntry( "name", m_name );
+ 
+-   for(int i=0; i < count() ; i++ )
++   foreach ( shared_ptr<MixDevice> md, *this)
+    {
+-       MixDevice *md = operator[](i);
+        md->read( config, grp );
+    }
+ }
+@@ -53,9 +56,8 @@
+    KConfigGroup conf = config->group(grp);
+    conf.writeEntry( "name", m_name );
+ 
+-   for(int i=0; i < count() ; i++ )
++   foreach ( shared_ptr<MixDevice> md, *this)
+    {
+-       MixDevice *md = operator[](i);
+        md->write( config, grp );
+    }
+ }
+@@ -65,23 +67,26 @@
+     m_name = name;
+ }
+ 
+-MixDevice* MixSet::get(QString id)
++shared_ptr<MixDevice> MixSet::get(QString id)
+ {
+-  MixDevice* md = 0;
+-  for(int i=0; i < count() ; i++ )
+-  {
+-    md = operator[](i);
+-    if ( md->id() == id )
+-      break;
+-  }
+-  return md;
++	shared_ptr<MixDevice> mdRet;
++
++	foreach ( shared_ptr<MixDevice> md, *this)
++	{
++		if ( md->id() == id )
++		{
++			mdRet = md;
++			break;
++		}
++	}
++	return mdRet;
+ }
+ 
+ void MixSet::removeById(QString id)
+ {
+ 	for (int i=0; i < count() ; i++ )
+ 	{
+-		MixDevice* md = operator[](i);
++		shared_ptr<MixDevice> md = operator[](i);
+ 	    if ( md->id() == id )
+ 	    {
+ 	    	removeAt(i);
+Index: core/mixdevice.cpp
+===================================================================
+--- core/mixdevice.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixdevice.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,16 +19,18 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "core/mixdevice.h"
++
+ #include <qregexp.h>
+ 
+ #include <kdebug.h>
+ #include <klocale.h>
+ 
+-#include "core/mixdevice.h"
++#include "core/ControlPool.h"
+ #include "core/mixer.h"
++#include "dbus/dbuscontrolwrapper.h"
+ #include "gui/guiprofile.h"
+ #include "core/volume.h"
+-#include "dbus/dbuscontrolwrapper.h"
+ 
+ static const QString channelTypeToIconName( MixDevice::ChannelType type )
+ {
+@@ -113,6 +115,7 @@
+ {
+     _artificial = false;
+     _applicationStream = false;
++    _dbusControlWrapper = 0; // will be set in addToPool()
+     _mixer = mixer;
+     _id = id;
+     mediaPlayControl = false;
+@@ -128,14 +131,31 @@
+         _iconName = iconName;
+     _moveDestinationMixSet = moveDestinationMixSet;
+     if ( _id.contains(' ') ) {
+-        // The key is used in the config file. It MUST NOT contain spaces
++        // The key is used in the config file. IdbusControlWrappert MUST NOT contain spaces
+         kError(67100) << "MixDevice::setId(\"" << id << "\") . Invalid key - it must not contain spaces" << endl;
+         _id.replace(' ', '_');
+     }
+     kDebug(67100) << "MixDevice::init() _id=" << _id;
+-    new DBusControlWrapper( this, dbusPath() );
+ }
+ 
++shared_ptr<MixDevice> MixDevice::addToPool()
++{
++    const QString& fullyQualifiedId = getFullyQualifiedId();
++    kDebug() << "MixDevice::init() id=" << fullyQualifiedId;
++
++    shared_ptr<MixDevice> thisSharedPtr(this);
++    //shared_ptr<MixDevice> thisSharedPtr = ControlPool::instance()->add(fullyQualifiedId, this);
++    _dbusControlWrapper = new DBusControlWrapper( thisSharedPtr, dbusPath() );
++	return thisSharedPtr;
++}
++
++
++QString MixDevice::getFullyQualifiedId()
++{
++	QString fqId = QString("%1@%2").arg(_id).arg(_mixer->id());
++	return fqId;
++}
++
+ void MixDevice::addPlaybackVolume(Volume &playbackVol)
+ {
+    // Hint: "_playbackVolume" gets COPIED from "playbackVol", because the copy-constructor actually copies the volume levels.
+@@ -164,6 +184,7 @@
+ 
+ MixDevice::~MixDevice() {
+     _enumValues.clear(); // The QString's inside will be auto-deleted, as they get unref'ed
++    delete _dbusControlWrapper;
+ }
+ 
+ Volume& MixDevice::playbackVolume()
+Index: core/mixset.h
+===================================================================
+--- core/mixset.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixset.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -25,16 +25,18 @@
+ 
+ #include "core/mixdevice.h"
+ 
+-class MixSet : public QList <MixDevice *>
++class MixSet : public QList <shared_ptr<MixDevice> >
+ {
+    public:
++	~MixSet();
++
+       void read( KConfig *config, const QString& grp );
+       void write( KConfig *config, const QString& grp );
+ 
+       QString name() { return m_name; }
+       void setName( const QString &name );
+       
+-      MixDevice* get(QString id);
++      shared_ptr<MixDevice> get(QString id);
+ 
+       void removeById(QString id);
+ 
+Index: core/mixdevice.h
+===================================================================
+--- core/mixdevice.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixdevice.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -21,11 +21,17 @@
+ #ifndef MixDevice_h
+ #define MixDevice_h
+ 
++// std::shared_ptr
++#include <memory>
++#include <tr1/memory>
++using namespace ::std::tr1;
++
+ //KMix
+ class Mixer;
+ class MixSet;
+ class ProfControl;
+ #include "core/volume.h"
++class DBusControlWrapper;
+ 
+ // KDE
+ #include <kconfig.h>
+@@ -96,7 +102,10 @@
+    enum SwitchType { OnOff, Mute, Capture, Activator };
+ 
+    /**
+-    * Constructor:
++    * Constructor for a MixDevice.
++    * After having constructed a MixDevice, you <b>must</b> add it to the ControlPool
++    * by calling addToPool(). You may then <b>not</b> delete this object.
++    *
+     * @par mixer The mixer this control belongs to
+     * @par id  Defines the ID, e.g. used in looking up the keys in kmixrc. Also it is used heavily inside KMix as unique key. 
+     *      It is advised to set a nice name, like 'PCM:2', which would  mean 
+@@ -112,6 +121,8 @@
+    MixDevice( Mixer* mixer, const QString& id, const QString& name, const QString& iconName = "", MixSet* moveDestinationMixSet = 0 );
+    ~MixDevice();
+ 
++   shared_ptr<MixDevice> addToPool();
++
+    const QString& iconName() const { return _iconName; }
+ 
+    void addPlaybackVolume(Volume &playbackVol);
+@@ -141,6 +152,7 @@
+     */
+  
+    const QString& id() const;
++   QString getFullyQualifiedId();
+ 
+    /**
+     * Returns the DBus path for this MixDevice
+@@ -216,6 +228,8 @@
+    int _enumCurrentId;
+    QList<QString> _enumValues; // A MixDevice, that is an ENUM, has these _enumValues
+ 
++   DBusControlWrapper *_dbusControlWrapper;
++
+    // A virtual control. It will not be saved/restored and/or doesn't get shortcuts
+    // Actually we discriminate those "virtual" controls in artificial controls and dynamic controls:
+    // Type        Shortcut  Restore
+Index: core/kmixdevicemanager.cpp
+===================================================================
+--- core/kmixdevicemanager.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/kmixdevicemanager.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -141,7 +141,7 @@
+                         dev = devExpr.cap(1); // Get device number from device name (e.g "/dev/mixer1" or "/dev/sound/mixer2")
+                     }
+                     else {
+-                        dev = "0"; // "/dev/mixer" or "/dev/sound/mixer"
++                        dev = '0'; // "/dev/mixer" or "/dev/sound/mixer"
+                     }
+                     emit plugged("OSS", udi, dev);
+                 }
+Index: core/mixer.cpp
+===================================================================
+--- core/mixer.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixer.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,13 +20,13 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "core/mixer.h"
+ 
+ #include <klocale.h>
+ #include <kconfig.h>
+ #include <kglobal.h>
+ #include <kdebug.h>
+ 
+-#include "core/mixer.h"
+ #include "backends/mixer_backend.h"
+ #include "backends/kmix-backends.cpp"
+ #include "core/volume.h"
+@@ -130,16 +130,16 @@
+      * %3, the mixer number, is a number: it does not contain colons.
+      */
+     QString mixerName = getBaseName();
+-    mixerName.replace(":","_");
++    mixerName.replace(':','_');
+     QString primaryKeyOfMixer = QString("%1::%2:%3")
+             .arg(getDriverName())
+             .arg(mixerName)
+             .arg(_cardInstance);
+     // The following 3 replaces are for not messing up the config file
+-    primaryKeyOfMixer.replace("]","_");
+-    primaryKeyOfMixer.replace("[","_"); // not strictly necessary, but lets play safe
+-    primaryKeyOfMixer.replace(" ","_");
+-    primaryKeyOfMixer.replace("=","_");
++    primaryKeyOfMixer.replace(']','_');
++    primaryKeyOfMixer.replace('[','_'); // not strictly necessary, but lets play safe
++    primaryKeyOfMixer.replace(' ','_');
++    primaryKeyOfMixer.replace('=','_');
+     _id = primaryKeyOfMixer;
+ }
+ 
+@@ -170,10 +170,12 @@
+    _mixerBackend->m_mixDevices.read( config, grp );
+ 
+    // set new settings
+-   //QListIterator<MixDevice*> it( _mixerBackend->m_mixDevices );
+    for(int i=0; i<_mixerBackend->m_mixDevices.count() ; i++ )
+    {
+-       MixDevice *md = _mixerBackend->m_mixDevices[i];
++	   shared_ptr<MixDevice> md = _mixerBackend->m_mixDevices[i];
++	   if ( md.get() == 0 )
++		   continue;
++
+        _mixerBackend->writeVolumeToHW( md->id(), md );
+        if ( md->isEnum() ) _mixerBackend->setEnumIdHW( md->id(), md->enumId() );
+    }
+@@ -188,15 +190,18 @@
+  */
+ bool Mixer::openIfValid() {
+     bool ok = _mixerBackend->openIfValid();
+-    if ( ok ) {
+-        recreateId(); // Fallback call. Actually recreateId() is supposed to be called later again, via setCardInstance()
+-        MixDevice* recommendedMaster = _mixerBackend->recommendedMaster();
+-        if ( recommendedMaster != 0 ) {
++    if ( ok )
++    {
++        recreateId(); // TODO NOW : We actually cannot postpone it to here, due to ControlPool. Move to Mixer !!!. Actually recreateId() is supposed to be called later again, via setCardInstance()
++        shared_ptr<MixDevice> recommendedMaster = _mixerBackend->recommendedMaster();
++        if ( recommendedMaster.get() != 0 )
++        {
+             QString recommendedMasterStr = recommendedMaster->id();
+             setLocalMasterMD( recommendedMasterStr );
+             kDebug() << "Mixer::open() detected master: " << recommendedMaster->id();
+         }
+-        else {
++        else
++        {
+             if ( !m_dynamic )
+                 kError(67100) << "Mixer::open() no master detected." << endl;
+             QString noMaster = "---no-master-detected---";
+@@ -229,14 +234,13 @@
+   return _mixerBackend->m_mixDevices.count();
+ }
+ 
+-MixDevice* Mixer::operator[](int num)
++shared_ptr<MixDevice> Mixer::operator[](int num)
+ {
+-  MixDevice* md =  _mixerBackend->m_mixDevices.at( num );
+-  Q_ASSERT( md );
+-  return md;
++	shared_ptr<MixDevice> md =  _mixerBackend->m_mixDevices.at( num );
++	return md;
+ }
+ 
+-MixSet Mixer::getMixSet()
++MixSet& Mixer::getMixSet()
+ {
+   return _mixerBackend->m_mixDevices;
+ }
+@@ -285,8 +289,9 @@
+ 
+    m_balance = balance;
+ 
+-   MixDevice* master = getLocalMasterMD();
+-   if ( master == 0 ) {
++   shared_ptr<MixDevice> master = getLocalMasterMD();
++   if ( master.get() == 0 )
++   {
+       // no master device available => return
+       return;
+    }
+@@ -427,39 +432,41 @@
+ }
+ 
+ 
+-MixDevice* Mixer::getGlobalMasterMD()
++shared_ptr<MixDevice> Mixer::getGlobalMasterMD()
+ {
+    return getGlobalMasterMD(true);
+ }
+ 
+ 
+-MixDevice* Mixer::getGlobalMasterMD(bool fallbackAllowed)
++shared_ptr<MixDevice> Mixer::getGlobalMasterMD(bool fallbackAllowed)
+ {
+-   MixDevice* md = 0;
+-   Mixer *mixer;
+-   if ( fallbackAllowed)
+-      mixer = Mixer::getGlobalMasterMixer();
+-   else
+-      mixer = Mixer::getGlobalMasterMixerNoFalback();
+-   if ( mixer != 0 ) {
+-      for(int i=0; i < mixer->_mixerBackend->m_mixDevices.count() ; i++ )
+-      {
+-         md = mixer->_mixerBackend->m_mixDevices[i];
+-         if ( md->id() == _globalMasterCurrent.getControl() ) {
+-            //kDebug() << "Mixer::masterCardDevice() found " << _globalMasterCardDevice;
+-            break;
+-         }
+-      }
+-   }
+-   if ( ! md ) 
+-        kDebug() << "Mixer::masterCardDevice() returns 0 (no globalMaster)";
+-   return md;
++	shared_ptr<MixDevice> mdRet;
++	Mixer *mixer = fallbackAllowed ?
++		   Mixer::getGlobalMasterMixer() : Mixer::getGlobalMasterMixerNoFalback();
++
++	if ( mixer == 0 )
++		return mdRet;
++
++	foreach (shared_ptr<MixDevice> md, mixer->_mixerBackend->m_mixDevices )
++	{
++		if ( md.get() == 0 )
++			continue; // invalid
++		if ( md->id() == _globalMasterCurrent.getControl() )
++		{
++			mdRet = md;
++			break; // found
++		}
++	}
++	if ( mdRet.get() == 0 )
++		kDebug() << "Mixer::masterCardDevice() returns 0 (no globalMaster)";
++
++	return mdRet;
+ }
+ 
+ 
+ 
+ 
+-MixDevice* Mixer::getLocalMasterMD()
++shared_ptr<MixDevice> Mixer::getLocalMasterMD()
+ {
+   return find( _masterDevicePK );
+ }
+@@ -470,25 +477,32 @@
+ }
+ 
+ 
+-MixDevice* Mixer::find(const QString& mixdeviceID)
++shared_ptr<MixDevice> Mixer::find(const QString& mixdeviceID)
+ {
+-   MixDevice *md = 0;
+-   for(int i=0; i<_mixerBackend->m_mixDevices.count() ; i++ )
+-   {
+-       md = _mixerBackend->m_mixDevices[i];
+-       if( mixdeviceID == md->id() ) {
+-           break;
+-       }
+-    }
+-    return md;
++
++	shared_ptr<MixDevice> mdRet;
++
++	foreach (shared_ptr<MixDevice> md, _mixerBackend->m_mixDevices )
++	{
++		if ( md.get() == 0 )
++			continue; // invalid
++		if ( md->id() == mixdeviceID )
++		{
++			mdRet = md;
++			break; // found
++		}
++	}
++
++    return mdRet;
+ }
+ 
+ 
+-MixDevice* Mixer::getMixdeviceById( const QString& mixdeviceID )
++shared_ptr<MixDevice> Mixer::getMixdeviceById( const QString& mixdeviceID )
+ {
+-   MixDevice* md = 0;
++	shared_ptr<MixDevice> md;
+    int num = _mixerBackend->id2num(mixdeviceID);
+-   if ( num!=-1 && num < (int)size() ) {
++   if ( num!=-1 && num < (int)size() )
++   {
+       md = (*this)[num];
+    }
+    return md;
+@@ -502,7 +516,8 @@
+    - It is fast               (no copying of Volume objects required)
+    - It is easy to understand ( read - modify - commit )
+ */
+-void Mixer::commitVolumeChange( MixDevice* md ) {
++void Mixer::commitVolumeChange( shared_ptr<MixDevice> md )
++{
+   _mixerBackend->writeVolumeToHW(md->id(), md );
+    if (md->isEnum()) _mixerBackend->setEnumIdHW(md->id(), md->enumId() );
+    if ( md->captureVolume().hasSwitch() ) {
+@@ -533,8 +548,9 @@
+ void Mixer::increaseOrDecreaseVolume( const QString& mixdeviceID, bool decrease )
+ {
+ 
+-    MixDevice *md= getMixdeviceById( mixdeviceID );
+-    if (md != 0) {
++	shared_ptr<MixDevice> md= getMixdeviceById( mixdeviceID );
++    if (md.get() != 0)
++    {
+         Volume& volP=md->playbackVolume();
+         if ( volP.hasVolume() ) {
+         	long volSpan = volP.volumeSpan();
+Index: core/mixer.h
+===================================================================
+--- core/mixer.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixer.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -65,7 +65,7 @@
+     static int numDrivers();
+     QString getDriverName();
+ 
+-    MixDevice* find(const QString& devPK);
++    shared_ptr<MixDevice>  find(const QString& devPK);
+     static Mixer* findMixer( const QString& mixer_id);
+ 
+     void volumeSave( KConfig *config );
+@@ -75,12 +75,12 @@
+     unsigned int size() const;
+ 
+     /// Returns a pointer to the mix device with the given number
+-    MixDevice* operator[](int val_i_num);
++    shared_ptr<MixDevice> operator[](int val_i_num);
+ 
+     /// Returns a pointer to the mix device whose type matches the value
+     /// given by the parameter and the array MixerDevNames given in
+     /// mixer_oss.cpp (0 is Volume, 4 is PCM, etc.)
+-    MixDevice *getMixdeviceById( const QString& deviceID );
++    shared_ptr<MixDevice> getMixdeviceById( const QString& deviceID );
+ 
+     /// Open/grab the mixer for further intraction
+     bool openIfValid();
+@@ -148,8 +148,8 @@
+     At the moment it is only used for selecting the Mixer to use in KMix's DockIcon.
+     ******************************************/
+     static void setGlobalMaster(QString ref_card, QString ref_control, bool preferred);
+-    static MixDevice* getGlobalMasterMD();
+-    static MixDevice* getGlobalMasterMD(bool fallbackAllowed);
++    static shared_ptr<MixDevice> getGlobalMasterMD();
++    static shared_ptr<MixDevice> getGlobalMasterMD(bool fallbackAllowed);
+     static Mixer* getGlobalMasterMixer();
+     static Mixer* getGlobalMasterMixerNoFalback();
+     static MasterControl& getGlobalMasterPreferred();
+@@ -157,11 +157,11 @@
+     /******************************************
+     The recommended master of this Mixer.
+     ******************************************/
+-    MixDevice* getLocalMasterMD();
++    shared_ptr<MixDevice> getLocalMasterMD();
+     void setLocalMasterMD(QString&);
+ 
+     /// get the actual MixSet
+-    MixSet getMixSet();
++    MixSet& getMixSet();
+ 
+     static float VOLUME_STEP_DIVISOR;     // The divisor for defining volume control steps (for mouse-wheel, DBUS and Normal step for Sliders )
+     static float VOLUME_PAGESTEP_DIVISOR; // The divisor for defining volume control steps (page-step for sliders)
+@@ -181,7 +181,7 @@
+    virtual int mediaNext(QString id) { return _mixerBackend->mediaNext(id); };
+ 
+     
+-    void commitVolumeChange( MixDevice* md );
++    void commitVolumeChange( shared_ptr<MixDevice> md );
+ 
+ public slots:
+     void readSetFromHWforceUpdate() const;
+Index: core/version.h
+===================================================================
+--- core/version.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/version.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,6 +20,6 @@
+  */
+ 
+ #ifndef APP_VERSION
+-#define APP_VERSION "4"
++#define APP_VERSION "4.1"
+ #define KMIX_CONFIG_VERSION 3
+ #endif // APP_VERSION
+Index: core/mixertoolbox.cpp
+===================================================================
+--- core/mixertoolbox.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ core/mixertoolbox.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,6 +19,7 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "core/mixer.h"
+ 
+ #include <QDir>
+ #include <QWidget>
+@@ -30,7 +31,6 @@
+ 
+ #include "core/kmixdevicemanager.h"
+ #include "core/mixdevice.h"
+-#include "core/mixer.h"
+ 
+ #include "core/mixertoolbox.h"
+ 
+@@ -195,7 +195,7 @@
+       // not one defined in the kmixrc.
+       // So lets just set the first card as master card.
+       if ( Mixer::mixers().count() > 0 ) {
+-         MixDevice* master = Mixer::mixers().first()->getLocalMasterMD();
++    	  shared_ptr<MixDevice> master = Mixer::mixers().first()->getLocalMasterMD();
+          if ( master != 0 ) {
+              QString controlId = master->id();
+              Mixer::setGlobalMaster( Mixer::mixers().first()->id(), controlId, true);
+@@ -205,7 +205,7 @@
+    else {
+       // setGlobalMaster was already set after reading the configuration.
+       // So we must make the local master consistent
+-      MixDevice* md = Mixer::getGlobalMasterMD();
++	  shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
+       QString mdID = md->id();
+       md->mixer()->setLocalMasterMD(mdID);
+    }
+Index: dbus/dbuscontrolwrapper.cpp
+===================================================================
+--- dbus/dbuscontrolwrapper.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbuscontrolwrapper.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -24,11 +24,10 @@
+ #include "core/mixer.h"
+ #include "core/volume.h"
+ 
+-#include <QDebug>
+-
+-DBusControlWrapper::DBusControlWrapper(MixDevice* parent, QString path)
+-	: QObject(parent)
+-	, m_dbusPath(path)
++DBusControlWrapper::DBusControlWrapper(shared_ptr<MixDevice> parent, const QString& path)
++	: QObject(0)
++// TODO cesken I might need to look into memory leak issues here, as it was required to remove the MixDevice from being parent()
++//      I am not about leaking m_md, but the whole DBusControlWrapper instance
+ {
+ 	m_md = parent;
+ 	new ControlAdaptor( this );
+@@ -56,17 +55,6 @@
+ 
+ void DBusControlWrapper::setVolume(int percentage)
+ {
+-    // @todo Is hardcoded to PlaybackVolume
+-    // @todo This will not work, if minVolume != 0      !!!
+-	//       e.g.: minVolume=5 or minVolume=-10
+-	// The solution is to check two cases:
+-	//     volume < 0 => use minVolume for volumeRange
+-	//     volume > 0 => use maxVolume for volumeRange
+-	//     If chosen volumeRange==0 => return 0
+-	// As this is potentially used often (Sliders, ...), it
+-	// should be implemented in the Volume class.
+-	// For now we go with "maxVolume()", like in the rest of KMix.
+-	//  - esken
+ 	Volume& volP = m_md->playbackVolume();
+ 	Volume& volC = m_md->captureVolume();
+ 	volP.setAllVolumes( volP.minVolume() + ((percentage * volP.volumeSpan()) / 100) );
+@@ -76,7 +64,8 @@
+ 
+ int DBusControlWrapper::volume()
+ {
+-	return m_md->playbackVolume().getAvgVolumePercent(Volume::MALL);
++	Volume &useVolume = (m_md->playbackVolume().count() != 0) ? m_md->playbackVolume() : m_md->captureVolume();
++	return useVolume.getAvgVolumePercent(Volume::MALL);
+ }
+ 
+ void DBusControlWrapper::increaseVolume()
+@@ -91,30 +80,27 @@
+ 
+ long DBusControlWrapper::absoluteVolumeMin()
+ {
+-	// @todo Is hardcoded do playbackVolume
+-	return m_md->playbackVolume().minVolume();
++	Volume &useVolume = (m_md->playbackVolume().count() != 0) ? m_md->playbackVolume() : m_md->captureVolume();
++	return useVolume.minVolume();
+ }
+ 
+ long DBusControlWrapper::absoluteVolumeMax()
+ {
+-	// @todo Is hardcoded do playbackVolume
+-	return m_md->playbackVolume().maxVolume();
++	Volume &useVolume = (m_md->playbackVolume().count() != 0) ? m_md->playbackVolume() : m_md->captureVolume();
++	return useVolume.maxVolume();
+ }
+ 
+ void DBusControlWrapper::setAbsoluteVolume(long absoluteVolume)
+ {
+-	Volume& volP = m_md->playbackVolume();
+-	Volume& volC = m_md->captureVolume();
+-	volP.setAllVolumes( absoluteVolume );
+-	volC.setAllVolumes( absoluteVolume );
++	m_md->playbackVolume().setAllVolumes( absoluteVolume );
++	m_md->captureVolume().setAllVolumes( absoluteVolume );
+ 	m_md->mixer()->commitVolumeChange( m_md );
+ }
+ 
+ long DBusControlWrapper::absoluteVolume()
+ {
+-	// @todo hardcoded
+-	Volume& vol = m_md->playbackVolume();
+-	qreal avgVol= vol.getAvgVolume( Volume::MMAIN );
++	Volume &useVolume = (m_md->playbackVolume().count() != 0) ? m_md->playbackVolume() : m_md->captureVolume();
++	qreal avgVol= useVolume.getAvgVolume( Volume::MALL );
+ 	long avgVolRounded = avgVol <0 ? avgVol-.5 : avgVol+.5;
+ 	return avgVolRounded;
+ }
+@@ -133,7 +119,7 @@
+ 
+ bool DBusControlWrapper::canMute()
+ {
+-    return m_md->playbackVolume().hasSwitch();
++	return m_md->playbackVolume().hasSwitch();
+ }
+ 
+ bool DBusControlWrapper::isMuted()
+@@ -148,8 +134,11 @@
+ 
+ void DBusControlWrapper::setRecordSource(bool on)
+ {
+-	MixDevice* md = m_md->mixer()->getMixdeviceById(m_md->id());
+-	if ( md != 0 )
+-		md->setRecSource(on);
++	m_md->setRecSource(on);
+ 	m_md->mixer()->commitVolumeChange( m_md );
+ }
++
++bool DBusControlWrapper::hasCaptureSwitch()
++{
++	return m_md->captureVolume().hasSwitch();
++}
+Index: dbus/dbusmixerwrapper.cpp
+===================================================================
+--- dbus/dbusmixerwrapper.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbusmixerwrapper.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,14 +19,15 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "dbusmixerwrapper.h"
++
+ #include <QStringList>
+ 
+-#include "dbusmixerwrapper.h"
+ #include "core/mixdevice.h"
+ #include "core/volume.h"
+ #include "mixeradaptor.h"
+ 
+-DBusMixerWrapper::DBusMixerWrapper(Mixer* parent, QString path)
++DBusMixerWrapper::DBusMixerWrapper(Mixer* parent, const QString& path)
+ 	: QObject(parent)
+ 	, m_dbusPath(path)
+ {
+@@ -51,7 +52,7 @@
+ QStringList DBusMixerWrapper::controls()
+ {
+ 	QStringList result;
+-	foreach ( MixDevice* md, m_mixer->getMixSet() )
++	foreach ( shared_ptr<MixDevice> md, m_mixer->getMixSet() )
+ 	{
+ 		result.append( md->dbusPath() );
+ 	}
+@@ -60,7 +61,7 @@
+ 
+ QString DBusMixerWrapper::masterControl()
+ {
+-	MixDevice* md = m_mixer->getLocalMasterMD();
++	shared_ptr<MixDevice> md = m_mixer->getLocalMasterMD();
+ 	// XXX: Since empty object path is invalid, using "/"
+ 	return md ? md->dbusPath() : QString("/");
+ }
+Index: dbus/dbuscontrolwrapper.h
+===================================================================
+--- dbus/dbuscontrolwrapper.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbuscontrolwrapper.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -38,17 +38,18 @@
+ 	Q_PROPERTY(bool mute READ isMuted WRITE setMute)
+ 	Q_PROPERTY(bool recordSource READ isRecordSource WRITE setRecordSource)
+ 	Q_PROPERTY(bool canMute READ canMute)
++	Q_PROPERTY(bool hasCaptureSwitch READ hasCaptureSwitch)
+ 
+ 	public:
+-		DBusControlWrapper(MixDevice* parent, QString path);
++		DBusControlWrapper(shared_ptr<MixDevice> parent, const QString& path);
+ 		~DBusControlWrapper();
+ 
+ 		void increaseVolume();
+ 		void decreaseVolume();
+ 		void toggleMute();
+ 	private:
+-		MixDevice *m_md;
+-		QString m_dbusPath;
++		shared_ptr<MixDevice> m_md;
++		
+ 		QString id();
+ 		QString readableName();
+ 		QString iconName();
+@@ -61,10 +62,11 @@
+ 		long absoluteVolumeMax();
+ 		long absoluteVolume();
+ 
+-        bool canMute();
++		bool canMute();
+ 		void setMute(bool muted);
+ 		bool isMuted();
+ 
++		bool hasCaptureSwitch();
+ 		void setRecordSource(bool on);
+ 		bool isRecordSource();
+ };
+Index: dbus/dbusmixerwrapper.h
+===================================================================
+--- dbus/dbusmixerwrapper.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbusmixerwrapper.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,8 +19,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
+-#ifndef DBUS_MIXER_WRAPPER_H
+-#define DBUS_MIXER_WRAPPER_H
++#ifndef DBUSMIXERWRAPPER_H
++#define DBUSMIXERWRAPPER_H
+ 
+ #include <QObject>
+ #include <QStringList>
+@@ -40,7 +40,7 @@
+ 	Q_PROPERTY(QStringList controls READ controls)
+ 
+ 	public:
+-		DBusMixerWrapper(Mixer* parent, QString path);
++		DBusMixerWrapper(Mixer* parent, const QString& path);
+ 		~DBusMixerWrapper();
+ 		QString driverName();
+ 
+@@ -62,4 +62,4 @@
+ 		void slotControlsReconfigured();
+ };
+ 
+-#endif /* DBUS_MIXER_WRAPPER_H */
++#endif /* DBUSMIXERWRAPPER_H */
+Index: dbus/dbusmixsetwrapper.cpp
+===================================================================
+--- dbus/dbusmixsetwrapper.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbusmixsetwrapper.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -18,11 +18,12 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "dbusmixsetwrapper.h"
++
+ #include "core/mixdevice.h"
+-#include "dbusmixsetwrapper.h"
+ #include "mixsetadaptor.h"
+ 
+-DBusMixSetWrapper::DBusMixSetWrapper(QObject* parent, QString path)
++DBusMixSetWrapper::DBusMixSetWrapper(QObject* parent, const QString& path)
+ 	: QObject(parent)
+ 	, m_dbusPath( path )
+ {
+@@ -55,7 +56,7 @@
+ 
+ QString DBusMixSetWrapper::currentMasterControl() const
+ {
+-    MixDevice* masterControl = Mixer::getGlobalMasterMD();
++	shared_ptr<MixDevice> masterControl = Mixer::getGlobalMasterMD();
+     return masterControl ? masterControl->id() : QString();
+ }
+ 
+Index: dbus/dbusmixsetwrapper.h
+===================================================================
+--- dbus/dbusmixsetwrapper.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/dbusmixsetwrapper.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -18,8 +18,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
+-#ifndef DBUS_KMIX_WRAPPER_H
+-#define DBUS_KMIX_WRAPPER_H
++#ifndef DBUSMIXSETWRAPPER_H
++#define DBUSMIXSETWRAPPER_H
+ 
+ #include <QStringList>
+ #include "core/mixer.h"
+@@ -33,7 +33,7 @@
+ 	Q_PROPERTY(QString preferredMasterMixer READ preferredMasterMixer)
+ 	Q_PROPERTY(QString preferredMasterControl READ preferredMasterControl)
+ 	public:
+-		DBusMixSetWrapper(QObject* parent, QString path);
++		DBusMixSetWrapper(QObject* parent, const QString& path);
+ 		~DBusMixSetWrapper();
+ 	public slots:
+ 		QStringList mixers() const;
+@@ -55,4 +55,4 @@
+         
+ };
+ 
+-#endif /* DBUS_KMIX_WRAPPER_H */
++#endif /* DBUSMIXSETWRAPPER_H */
+Index: dbus/org.kde.kmix.control.xml
+===================================================================
+--- dbus/org.kde.kmix.control.xml	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ dbus/org.kde.kmix.control.xml	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -4,10 +4,11 @@
+   <interface name="org.kde.KMix.Control">
+     <property access="read" name="id" type="s"/>
+     <property access="read" name="readableName" type="s"/>
+-	<property access="read" name="iconName" type="s"/>
++    <property access="read" name="iconName" type="s"/>
+     <property access="readwrite" name="mute" type="b"/>
+     <property access="read" name="canMute" type="b"/>
+     <property access="readwrite" name="recordSource" type="b"/>
++    <property access="read" name="hasCaptureSwitch" type="b"/>
+     <property access="readwrite" name="volume" type="i"/>
+     <property access="readwrite" name="absoluteVolume" type="i"/>
+     <property access="read" name="absoluteVolumeMin" type="i"/>
+Index: TestCases
+===================================================================
+--- TestCases	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ TestCases	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -14,6 +14,7 @@
+ 11: kmixctrl --restore  (with existing .kmixctrlrc) must restore volumes
+ 12: kmixctrl --restore  (without existing .kmixctrlrc) must NOT change volumes
+ 13: "Switch-only" controls are available and work (e.g: IEC958': Capabilities: pswitch pswitch-joined cswitch cswitch-joined)
++14: Rapid stream creation/deletion works properly (KMix shows and hides the controls, no crash). for i in 1 2 3 4 5 6 7 8 9 10; do paplay  /Multimedia/Kennedy_berliner.ogg& done
+  
+ 
+ 
+Index: tests/dialogtest.cpp
+===================================================================
+--- tests/dialogtest.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ tests/dialogtest.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,3 +1,5 @@
++#include <dialogtest.h>
++
+ #include <QCheckBox>
+ #include <QLabel>
+ #include <QScrollArea>
+@@ -8,9 +10,7 @@
+ #include <kcmdlineargs.h>
+ #include <kglobal.h>
+ 
+-#include <dialogtest.h>
+ 
+-
+ extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
+ {
+     KAboutData aboutData( "dialogtest", 0, ki18n("dialogtest"),
+Index: tests/CMakeLists.txt
+===================================================================
+--- tests/CMakeLists.txt	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ tests/CMakeLists.txt	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -30,9 +30,9 @@
+     target_link_libraries(profiletest ${ASOUND_LIBRARY})
+ endif (HAVE_LIBASOUND2)
+ 
+-if (HAVE_PULSE)
++if (PULSEAUDIO_FOUND)
+     target_link_libraries(profiletest ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} ${GLIB2_LIBRARIES})
+-endif (HAVE_PULSE)
++endif (PULSEAUDIO_FOUND)
+ 
+ ########### next target ###############
+ set(dialogtest_KDEINIT_SRCS dialogtest.cpp )
+Index: apps/kmix.cpp
+===================================================================
+--- apps/kmix.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ apps/kmix.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -883,13 +883,13 @@
+             }
+             MixerToolBox::instance()->removeMixer(mixer);
+             // Check whether the Global Master disappeared, and select a new one if necessary
+-            MixDevice* md = Mixer::getGlobalMasterMD();
+-            if ( globalMasterMixerDestroyed || md == 0 ) {
++            shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++            if ( globalMasterMixerDestroyed || md.get() == 0 ) {
+                 // We don't know what the global master should be now.
+                 // So lets play stupid, and just select the recommended master of the first device
+                 if ( Mixer::mixers().count() > 0 ) {
+-                    MixDevice *master = ((Mixer::mixers())[0])->getLocalMasterMD();
+-                    if ( md != 0 ) {
++                	shared_ptr<MixDevice> master = ((Mixer::mixers())[0])->getLocalMasterMD();
++                    if ( master.get() != 0 ) {
+                         QString localMaster = master->id();
+                         Mixer::setGlobalMaster( ((Mixer::mixers())[0])->id(), localMaster, false);
+ 
+@@ -1036,9 +1036,12 @@
+ void KMixWindow::increaseOrDecreaseVolume(bool increase)
+ {
+     Mixer* mixer = Mixer::getGlobalMasterMixer(); // only needed for the awkward construct below
+-    if ( mixer == 0 ) return; // e.g. when no soundcard is available
+-    MixDevice *md = Mixer::getGlobalMasterMD();
+-    if ( md == 0 ) return; // shouldn't happen, but lets play safe
++    if ( mixer == 0 )
++    	return; // e.g. when no soundcard is available
++    shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++    if ( md.get() == 0 )
++    	return; // shouldn't happen, but lets play safe
++
+     md->setMuted(false);
+     if (increase)
+         mixer->increaseVolume(md->id());    // this is awkward. Better move the increaseVolume impl to the Volume class.
+@@ -1061,9 +1064,11 @@
+ void KMixWindow::showVolumeDisplay()
+ {
+     Mixer* mixer = Mixer::getGlobalMasterMixer();
+-    if ( mixer == 0 ) return; // e.g. when no soundcard is available
+-    MixDevice *md = Mixer::getGlobalMasterMD();
+-    if ( md == 0 ) return; // shouldn't happen, but lets play safe
++    if ( mixer == 0 )
++    	return; // e.g. when no soundcard is available
++    shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++    if ( md.get() == 0 )
++    	return; // shouldn't happen, but lets play safe
+     // Current volume
+     Volume& vol = md->playbackVolume();
+ 
+@@ -1082,9 +1087,11 @@
+ void KMixWindow::slotMute()
+ {
+     Mixer* mixer = Mixer::getGlobalMasterMixer();
+-    if ( mixer == 0 ) return; // e.g. when no soundcard is available
+-    MixDevice *md = Mixer::getGlobalMasterMD();
+-    if ( md == 0 ) return; // shouldn't happen, but lets play safe
++    if ( mixer == 0 )
++    	return; // e.g. when no soundcard is available
++    shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++    if ( md.get() == 0 )
++    	return; // shouldn't happen, but lets play safe
+ 	md->toggleMute();
+     mixer->commitVolumeChange( md );
+     showVolumeDisplay();
+@@ -1191,7 +1198,7 @@
+         msg += startErrorMessage;
+         msg += "\n(";
+         msg +=  args.join( QLatin1String( " " ));
+-        msg += ")";
++        msg += ')';
+         errorPopup(msg);
+     }
+ 
+Index: apps/kmixd.cpp
+===================================================================
+--- apps/kmixd.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ apps/kmixd.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,6 +20,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "kmixd.h"
++
+ #include <kaboutdata.h> 
+ #include <kcmdlineargs.h>
+ 
+@@ -27,9 +29,7 @@
+ #include <klocale.h>
+ #include <kconfig.h>
+ #include <kaction.h>
+-//#include <kapplication.h>
+ #include <kstandardaction.h>
+-//#include <kmenu.h>
+ #include <kdebug.h>
+ #include <kxmlguifactory.h>
+ #include <kglobal.h>
+@@ -40,20 +40,10 @@
+ #include <kpluginloader.h> 
+ 
+ // KMix
+-//#include "gui/guiprofile.h"
+ #include "core/mixertoolbox.h"
+-#include "kmixd.h"
+ #include "core/kmixdevicemanager.h"
+-//#include "gui/kmixerwidget.h"
+-//#include "gui/kmixprefdlg.h"
+-//#include "gui/kmixdockwidget.h"
+-//#include "gui/kmixtoolbox.h"
+ #include "core/version.h"
+-//#include "gui/viewdockareapopup.h"
+-//#include "gui/dialogselectmaster.h"
+ 
+-//#include "gui/osdwidget.h"
+-
+ K_PLUGIN_FACTORY(KMixDFactory,
+                  registerPlugin<KMixD>();
+     )
+@@ -167,7 +157,7 @@
+    if ( mixerMasterCard != 0 ) {
+       config.writeEntry( "MasterMixer", mixerMasterCard->id() );
+    }
+-   MixDevice* mdMaster = Mixer::getGlobalMasterMD();
++   shared_ptr<MixDevice> mdMaster = Mixer::getGlobalMasterMD();
+    if ( mdMaster != 0 ) {
+       config.writeEntry( "MasterMixerDevice", mdMaster->id() );
+    }
+@@ -299,13 +289,13 @@
+ 
+             MixerToolBox::instance()->removeMixer(mixer);
+             // Check whether the Global Master disappeared, and select a new one if necessary
+-            MixDevice* md = Mixer::getGlobalMasterMD();
+-            if ( globalMasterMixerDestroyed || md == 0 ) {
++            shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
++            if ( globalMasterMixerDestroyed || md.get() == 0 ) {
+                 // We don't know what the global master should be now.
+                 // So lets play stupid, and just select the recommended master of the first device
+                 if ( Mixer::mixers().count() > 0 ) {
+-                    MixDevice *master = ((Mixer::mixers())[0])->getLocalMasterMD();
+-                    if ( md != 0 ) {
++                	shared_ptr<MixDevice> master = ((Mixer::mixers())[0])->getLocalMasterMD();
++                    if ( master.get() != 0 ) {
+                         QString localMaster = master->id();
+                         Mixer::setGlobalMaster( ((Mixer::mixers())[0])->id(), localMaster, false);
+ 
+Index: config.h.cmake
+===================================================================
+--- config.h.cmake	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ config.h.cmake	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,39 +1,9 @@
+ /* config.h.  Generated by cmake from config.h.cmake */
+ /* Don't add anything new here!!! Use per-directory generated files. */
+ 
+-/* Define to 1 if you have the <Alib.h> header file. */
+-#cmakedefine HAVE_ALIB_H 1
+-
+-/* Define to 1 if you have the <alloca.h> header file. */
+-#cmakedefine HAVE_ALLOCA_H 1
+-
+-/* define to 1 if you have PulseAudio headers */
+-#cmakedefine HAVE_PULSE 1
+-
+ /* Define if you ogg/vorbis installed */
+ #cmakedefine HAVE_VORBIS ${OGGVORBIS_VERSION}
+ 
+-/* Define to 1 if you have the <linux/cdrom.h> header file. */
+-#cmakedefine HAVE_LINUX_CDROM_H 1
+-
+-/* Define to 1 if you have the <linux/ucdrom.h> header file. */
+-#cmakedefine HAVE_LINUX_UCDROM_H 1
+-
+-/* Define to 1 if you have the <machine/soundcard.h> header file. */
+-#cmakedefine HAVE_MACHINE_SOUNDCARD_H 1
+-
+-/* Define to 1 if you have the <soundcard.h> header file. */
+-#cmakedefine HAVE_SOUNDCARD_H 1
+-
+-/* Define to 1 if you have the <sys/audioio.h> header file. */
+-#cmakedefine HAVE_SYS_AUDIOIO_H 1
+-
+-/* Define to 1 if you have the <sys/soundcard.h> header file. */
+-#cmakedefine HAVE_SYS_SOUNDCARD_H 1
+-
+-/* Define to 1 if you have the <sys/stat.h> header file. */
+-#cmakedefine HAVE_SYS_STAT_H 1
+-
+ /* Define to 1 if you have the <machine/endian.h> header file. */
+ #cmakedefine HAVE_MACHINE_ENDIAN_H 1
+ 
+@@ -43,14 +13,5 @@
+ /* Define to 1 if you have the <sys/endian.h> header file. */
+ #cmakedefine HAVE_ENDIAN_H 1
+ 
+-/* Define if you have XShmGetEventBase in <X11/extensions/XShm.h */
+-#cmakedefine HAVE_XSHMGETEVENTBASE 1
+-
+-/* The size of a `long', as computed by sizeof. */
+-#define SIZEOF_LONG ${SIZEOF_LONG}
+-
+-/* Compatibility with older version of xine */
+-/* #undef _x_ao_new_port */
+-
+ /* Define to 1 if you have the <unistd.h> header file. */
+ #cmakedefine HAVE_UNISTD_H 1
+Index: backends/mixer_hpux.cpp
+===================================================================
+--- backends/mixer_hpux.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_hpux.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,243 +0,0 @@
+-/*
+- *              KMix -- KDE's full featured mini mixer
+- *
+- *
+- *              Copyright (C) 1996-2000 Christian Esken <esken at kde.org>
+- * HP/UX-Port:	Copyright (C) 1999 by Helge Deller <deller at gmx.de>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library 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
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this program; if not, write to the Free
+- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+- */
+-
+-#include "mixer_hpux.h"
+-
+-#error "The HP/UX port is not maintained anymore, an no official part of KMix / KDE at this point of time! Please contact the current KMix maintainer if you would like to maintain the port."
+-
+-#define HPUX_ERROR_OFFSET 1024
+-
+-#define myGain 	AUnityGain	/* AUnityGain or AZeroGain */
+-
+-#define GAIN_OUT_DIFF	((long) ((int)aMaxOutputGain(audio) - (int)aMinOutputGain(audio)))
+-#define GAIN_OUT_MIN	((long) aMinOutputGain(audio))
+-#define GAIN_IN_DIFF	((long) ((int)aMaxInputGain(audio)  - (int)aMinInputGain(audio)))
+-#define GAIN_IN_MIN	((long) aMinOutputGain(audio))
+-
+-/* standard */
+-#define	ID_PCM			4
+-
+-/* AInputSrcType: */	     /*OSS:*/
+-#define ID_IN_MICROPHONE 	7	/* AISTMonoMicrophone */
+-#define ID_IN_AUX		6	/* AISTLeftAuxiliary, AISTRightAuxiliary */
+-
+-/* AOutputDstType: */
+-#define ID_OUT_INT_SPEAKER	0	/* AODTMonoIntSpeaker */
+-
+-/* not yet implemented:
+-    AODTLeftJack,    AODTRightJack,
+-    AODTLeftLineOut,  AODTRightLineOut,
+-    AODTLeftHeadphone, AODTRightHeadphone
+-
+-const char* MixerDevNames[32]={"Volume"  , "Bass"    , "Treble"    , "Synth"   , "Pcm"  ,    \
+-			       "Speaker" , "Line"    , "Microphone", "CD"      , "Mix"  ,    \
+-			       "Pcm2"    , "RecMon"  , "IGain"     , "OGain"   , "Line1",    \
+-			       "Line2"   , "Line3"   , "Digital1"  , "Digital2", "Digital3", \
+-			       "PhoneIn" , "PhoneOut", "Video"     , "Radio"   , "Monitor",  \
+-			       "3D-depth", "3D-center", "unknown"  , "unknown" , "unknown",  \
+-			       "unknown" , "unused" };
+-*/
+-
+-
+-
+-Mixer_HPUX::Mixer_HPUX(int devnum) : Mixer_Backend(devnum)
+-{
+-  char ServerName[10];
+-  ServerName[0] = 0;
+-  audio = AOpenAudio(ServerName,NULL);
+-}
+-
+-Mixer_HPUX::~Mixer_HPUX()
+-{
+-  if (audio) {
+-      ACloseAudio(audio,0);
+-      audio = 0;
+-  }
+-}
+-
+-
+-int Mixer_HPUX::open()
+-{
+-  if (audio==0) {
+-    return Mixer::ERR_OPEN;
+-  }
+-  else
+-  {
+-    /* Mixer is open. Now define properties */
+-    stereodevs = devmask = (1<<ID_PCM); /* activate pcm */
+-    recmask = 0;
+-
+-    /* check Input devices... */
+-    if (AInputSources(audio) & AMonoMicrophoneMask) {
+-	    devmask	|= (1<<ID_IN_MICROPHONE);
+-	    recmask	|= (1<<ID_IN_MICROPHONE);
+-    }
+-    if (AInputSources(audio) & (ALeftAuxiliaryMask|ARightAuxiliaryMask)) {
+-	    devmask	|= (1<<ID_IN_AUX);
+-	    recmask	|= (1<<ID_IN_AUX);
+-	    stereodevs	|= (1<<ID_IN_AUX);
+-    }
+-
+-    /* check Output devices... */
+-    if (AOutputDestinations(audio) & AMonoIntSpeakerMask) {
+-	    devmask	|= (1<<ID_OUT_INT_SPEAKER);
+-	    stereodevs	|= (1<<ID_OUT_INT_SPEAKER);
+-    }
+-
+-/*  implement later:
+-    ----------------
+-    if (AOutputDestinations(audio) & AMonoLineOutMask)	devmask |= 64; // Line
+-    if (AOutputDestinations(audio) & AMonoJackMask)	devmask |= (1<<14); // Line1
+-    if (AOutputDestinations(audio) & AMonoHeadphoneMask)	devmask |= (1<<15); // Line2
+-*/
+-
+-    MaxVolume = 255;
+-
+-    long error = 0;
+-    ASetSystemPlayGain(audio, myGain, &error);
+-    if (error) errorText(error + HPUX_ERROR_OFFSET);
+-    ASetSystemRecordGain(audio, myGain, &error);
+-    if (error) errorText(error + HPUX_ERROR_OFFSET);
+-
+-    i_recsrc = 0;
+-    m_isOpen = true;
+-
+-    m_mixerName = "HP Mixer"; /* AAudioString(audio); */
+-    return 0;
+-  }
+-}
+-
+-int Mixer_HPUX::close()
+-{
+-  _pollingTimer->stop();
+-  m_isOpen = false;
+-  m_mixDevices.clear();
+-  return 0;
+-}
+-
+-int Mixer_HPUX::readVolumeFromHW( int devnum, Volume &vol, Volume & )
+-{
+-    long Gain;
+-    long error = 0;
+-    int  vl,vr;
+-
+-    switch (devnum) {
+-    case ID_OUT_INT_SPEAKER:	/* AODTMonoIntSpeaker */
+-	AGetSystemChannelGain(audio, ASGTPlay, ACTMono, &Gain, &error );
+-	vl = vr = (Gain-GAIN_OUT_MIN)*255 / GAIN_OUT_DIFF;
+-	vol.setVolume( Volume::LEFT, vl);
+-	vol.setVolume( Volume::RIGHT, vr);
+-printf("READ - Devnum: %d, Left: %d, Right: %d\n", devnum, vl, vr );
+-	break;
+-
+-    case ID_IN_AUX:		/* AISTLeftAuxiliary, AISTRightAuxiliary */
+-    case ID_IN_MICROPHONE:	/* AISTMonoMicrophone */
+-	AGetSystemChannelGain(audio, ASGTRecord, ACTMono, &Gain, &error );
+-	vl = vr = (Gain-GAIN_IN_MIN)*255 / GAIN_IN_DIFF;
+-	vol.setVolume( Volume::LEFT, vl);
+-	vol.setVolume( Volume::RIGHT, vr);
+-	break;
+-
+-    default:
+-	error = Mixer::ERR_READ - HPUX_ERROR_OFFSET;
+-	break;
+-    };
+-
+-  return (error ? (error+HPUX_ERROR_OFFSET) : 0);
+-}
+-
+-/*
+-        ASystemGainType         =     ASGTPlay, ASGTRecord, ASGTMonitor
+-	AChType                	=     ACTMono, ACTLeft, ACTRight
+-*/
+-
+-int Mixer_HPUX::writeVolumeToHW( int devnum, Volume& vol, Volume & )
+-{
+-    long Gain;
+-    long error = 0;
+-    int vl = vol.getVolume(Volume::LEFT);
+-    int vr = vol.getVolume(Volume::RIGHT);
+-
+-    switch (devnum) {
+-    case ID_OUT_INT_SPEAKER:	/* AODTMonoIntSpeaker */
+-printf("WRITE - Devnum: %d, Left: %d, Right: %d\n", devnum, vl, vr);
+-	Gain = vl;	// only left Volume
+-	Gain = (Gain*GAIN_OUT_DIFF) / 255 - GAIN_OUT_MIN;
+-	ASetSystemChannelGain(audio, ASGTPlay, ACTMono, (AGainDB) Gain, &error );
+-	break;
+-
+-    case ID_IN_MICROPHONE:	/* AISTMonoMicrophone */
+-	Gain = vl;	// only left Volume
+-	Gain = (Gain*GAIN_IN_DIFF) / 255 - GAIN_IN_MIN;
+-	ASetSystemChannelGain(audio, ASGTRecord, ACTMono, (AGainDB) Gain, &error );
+-	break;
+-
+-    case ID_IN_AUX:		/* AISTLeftAuxiliary, AISTRightAuxiliary */
+-	Gain = (vl*GAIN_IN_DIFF) / 255 - GAIN_IN_MIN;
+-	ASetSystemChannelGain(audio, ASGTRecord, ACTLeft, (AGainDB) Gain, &error );
+-	Gain = (vr*GAIN_IN_DIFF) / 255 - GAIN_IN_MIN;
+-	ASetSystemChannelGain(audio, ASGTRecord, ACTRight, (AGainDB) Gain, &error );
+-	break;
+-
+-    default:
+-	error = Mixer::ERR_READ - HPUX_ERROR_OFFSET;
+-	break;
+-    };
+-  return (error ? (error+HPUX_ERROR_OFFSET) : 0);
+-}
+-
+-
+-QString Mixer_HPUX::errorText(int mixer_error)
+-{
+-  QString l_s_errmsg;
+-  if (mixer_error >= HPUX_ERROR_OFFSET) {
+-      char errorstr[200];
+-      AGetErrorText(audio, (AError) (mixer_error-HPUX_ERROR_OFFSET),
+-                	    errorstr, sizeof(errorstr));
+-      printf("kmix: %s: %s\n",mixerName().data(), errorstr);
+-      l_s_errmsg = errorstr;
+-  } else
+-  switch (mixer_error)
+-    {
+-    case Mixer::ERR_OPEN:
+-		// should use i18n...
+-      l_s_errmsg = "kmix: HP-UX Alib-Mixer cannot be found.\n" \
+-			"Please check that you have:\n" \
+-			"  1. Installed the libAlib package  and\n" \
+-			"  2. started the Aserver program from the /opt/audio/bin directory\n";
+-      break;
+-    default:
+-      l_s_errmsg = Mixer_Backend::errorText(mixer_error);
+-      break;
+-    }
+-  return l_s_errmsg;
+-}
+-
+-QString HPUX_getDriverName() {
+-        return "HPUX";
+-}
+-
+-QString Mixer_HPUX::getDriverName()
+-{
+-        return "HPUX";
+-}
+-
+Index: backends/mixer_hpux.h
+===================================================================
+--- backends/mixer_hpux.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_hpux.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,56 +0,0 @@
+-//-*-C++-*-
+-/*
+- * KMix -- KDE's full featured mini mixer
+- *
+- * Copyright Christian Esken <esken at kde.org>
+- * Copyright (C) 1999 by Helge Deller <deller at gmx.de>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library 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
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this program; if not, write to the Free
+- * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+- */
+-#ifndef MIXER_HPUX_H
+-#define MIXER_HPUX_H
+-
+-#define DEFAULT_MIXER "HP-UX Mixer"
+-#ifdef HAVE_ALIB_H
+-#include <Alib.h>
+-#define HPUX_MIXER
+-#endif
+-
+-#include "mixer_backend.h"
+-
+-class Mixer_HPUX : public Mixer_Backend
+-{
+-public:
+-  Mixer_HPUX(int devnum=0);
+-  virtual ~Mixer_HPUX();
+-
+-  virtual QString errorText(int mixer_error);
+-
+-  virtual int readVolumeFromHW( int devnum, Volume &vol, Volume& );
+-  virtual int writeVolumeToHW ( int devnum, Volume &vol, Volume& );
+-
+-  virtual QString getDriverName();
+-
+-protected:
+-  virtual int open();
+-  virtual int close();
+-
+-  Audio	  *audio;
+-  unsigned int stereodevs,devmask, recmask, MaxVolume, i_recsrc;
+-    
+-
+-};
+-
+-#endif
+Index: backends/mixer_backend.h
+===================================================================
+--- backends/mixer_backend.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_backend.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -74,9 +74,9 @@
+   void readSetFromHWforceUpdate() const;
+ 
+   /// Volume Read
+-  virtual int readVolumeFromHW( const QString& id, MixDevice * ) = 0;
++  virtual int readVolumeFromHW( const QString& id, shared_ptr<MixDevice> ) = 0;
+   /// Volume Write
+-  virtual int writeVolumeToHW( const QString& id, MixDevice * ) = 0;
++  virtual int writeVolumeToHW( const QString& id, shared_ptr<MixDevice> ) = 0;
+ 
+   /// Enums
+   virtual void setEnumIdHW(const QString& id, unsigned int);
+@@ -91,7 +91,7 @@
+   /// Overwrite in the backend if the backend can see changes without polling
+   virtual bool needsPolling() { return true; }
+ 
+-  MixDevice* recommendedMaster();
++  shared_ptr<MixDevice> recommendedMaster();
+ 
+   /** Return a translated error text for the given error number.
+    * Subclasses can override this method to produce platform
+@@ -121,13 +121,13 @@
+ 
+   /******************************************************************************************
+    * Please don't access the next vars from the Mixer class (even though Mixer is a friend).
+-   * There are proper accesor methods for them.
++   * There are proper access methods for them.
+    ******************************************************************************************/
+   bool m_isOpen;
+   // The MixDevice that would qualify best as MasterDevice (according to the taste of the Backend developer)
+-  MixDevice* m_recommendedMaster;
++  shared_ptr<MixDevice> m_recommendedMaster;
+    // The Mixer is stored her only for one reason: The backend creates the MixDevice's, and it has shown
+-   // that it is helpful if the MixDevice's know their correspondig Mixer. KMix lived 10 years without that,
++   // that it is helpful if the MixDevice's know their corresponding Mixer. KMix lived 10 years without that,
+    // but just believe me. It's *really* better, for example, you can put controls of different soundcards in
+    // one View. That is very cool! Also the MDW doesn't need to store the Mixer any longer (MDW is a GUI element,
+    // so that was 'wrong' anyhow
+Index: backends/mixer_oss4.h
+===================================================================
+--- backends/mixer_oss4.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_oss4.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -9,15 +9,15 @@
+ class Mixer_OSS4 : public Mixer_Backend
+ {
+ public:
+-  Mixer_OSS4(Mixer* mixer, int device = -1);
++  Mixer_OSS4(Mixer* mixer, int device);
+   virtual ~Mixer_OSS4();
+ 
+   virtual QString errorText(int mixer_error);
+   virtual QString getDriverName();
+   virtual bool CheckCapture(oss_mixext *ext);
+   virtual bool prepareUpdateFromHW();
+-  virtual int readVolumeFromHW(const QString& id, MixDevice *md);
+-  virtual int writeVolumeToHW(const QString& id, MixDevice *md );
++  virtual int readVolumeFromHW(const QString& id, shared_ptr<MixDevice> md);
++  virtual int writeVolumeToHW(const QString& id, shared_ptr<MixDevice> md );
+   virtual void setEnumIdHW(const QString& id, unsigned int idx);
+   virtual unsigned int enumIdHW(const QString& id);
+ 
+Index: backends/mixer_pulse.h
+===================================================================
+--- backends/mixer_pulse.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_pulse.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -49,8 +49,8 @@
+         Mixer_PULSE(Mixer *mixer, int devnum);
+         virtual ~Mixer_PULSE();
+ 
+-        virtual int readVolumeFromHW( const QString& id, MixDevice *md  );
+-        virtual int writeVolumeToHW ( const QString& id, MixDevice *md  );
++        virtual int readVolumeFromHW( const QString& id, shared_ptr<MixDevice> );
++        virtual int writeVolumeToHW ( const QString& id, shared_ptr<MixDevice> );
+ 
+         virtual bool moveStream( const QString& id, const QString& destId );
+ 
+@@ -73,8 +73,8 @@
+     private:
+         void addDevice(devinfo& dev, bool = false);
+         bool connectToDaemon();
+-
+-    public slots:
++        void emitControlsReconfigured();
++public:
+         void reinit();
+ 
+ };
+Index: backends/mixer_oss.cpp
+===================================================================
+--- backends/mixer_oss.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_oss.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -148,8 +148,7 @@
+ 
+                   QString id;
+                   id.setNum(idx);
+-                  MixDevice* md =
+-                    new MixDevice(
++                  MixDevice* md = new MixDevice(
+                                    _mixer,
+                                    id,
+                                    i18n(MixerDevNames[idx]),
+@@ -163,7 +162,7 @@
+                      md->addCaptureVolume(captureVol);
+                  }
+ 
+-                  m_mixDevices.append( md );
++                  m_mixDevices.append( md->addToPool() );
+                 }
+               idx++;
+             }
+@@ -315,7 +314,7 @@
+     {
+         for(int i=0; i< m_mixDevices.count() ; i++ )
+         {
+-            MixDevice *md = m_mixDevices[i];
++        	shared_ptr<MixDevice> md = m_mixDevices[i];
+             bool isRecsrc =  ( (recsrcMask & ( 1<<devnum)) != 0 );
+             md->setRecSource(isRecsrc);
+         } // for all controls
+@@ -328,7 +327,7 @@
+ 
+ 
+ 
+-int Mixer_OSS::readVolumeFromHW( const QString& id, MixDevice* md )
++int Mixer_OSS::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+ 	int ret = 0;
+ 
+@@ -429,7 +428,7 @@
+ 
+ 
+ 
+-int Mixer_OSS::writeVolumeToHW( const QString& id, MixDevice *md)
++int Mixer_OSS::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md)
+ {
+     int volume;
+     int devnum = id2num(id);
+Index: backends/mixer_sun.cpp
+===================================================================
+--- backends/mixer_sun.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_sun.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -20,6 +20,8 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "mixer_sun.h"
++
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+@@ -29,7 +31,6 @@
+ #include <unistd.h>
+ #include <stdlib.h>
+ 
+-#include "mixer_sun.h"
+ #include "core/mixer.h"
+ #include <sys/soundcard.h>
+ #include <QTimer>
+@@ -202,7 +203,7 @@
+                      Volume captureVol( 100, 1, true, true );
+                      md->addCaptureVolume(captureVol);
+                  }
+-            m_mixDevices.append( md );
++            m_mixDevices.append( md->addToPool() );
+          }
+ 
+      m_mixerName = "SUN Audio Mixer";
+@@ -251,7 +252,7 @@
+ // FUNCTION    : Mixer::readVolumeFromHW
+ // DESCRIPTION : Read the audio information from the driver.
+ //======================================================================
+-int Mixer_SUN::readVolumeFromHW( const QString& id, MixDevice *md )
++int Mixer_SUN::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+    audio_info_t audioinfo;
+    int devnum = id2num(id);
+@@ -313,7 +314,7 @@
+ // FUNCTION    : Mixer::writeVolumeToHW
+ // DESCRIPTION : Write the specified audio settings to the hardware.
+ //======================================================================
+-int Mixer_SUN::writeVolumeToHW( const QString& id, MixDevice *md )
++int Mixer_SUN::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+    uint_t gain;
+    uchar_t balance;
+Index: backends/mixer_alsa9.cpp
+===================================================================
+--- backends/mixer_alsa9.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_alsa9.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -65,11 +65,13 @@
+    m_fds = 0;
+ //   m_sns = 0;
+    _handle = 0;
++   ctl_handle = 0;
+    _initialUpdate = true;
+ }
+ 
+ Mixer_ALSA::~Mixer_ALSA()
+ {
++	qDebug() << "Running Mixer_ALSA destructor";
+    close();
+ }
+ 
+@@ -158,7 +160,7 @@
+         QString mdID("%1:%2");
+         mdID = mdID.arg(snd_mixer_selem_id_get_name ( sid ) )
+                     .arg(snd_mixer_selem_id_get_index( sid ) );
+-        mdID.replace(" ","_"); // Any key/ID we use, must not uses spaces (rule)
++        mdID.replace(' ','_'); // Any key/ID we use, must not uses spaces (rule)
+ 
+         MixDevice::ChannelType ct = (MixDevice::ChannelType)identify( sid );
+ 
+@@ -186,7 +188,7 @@
+             // Add a number to the control name, like "PCM 2", when the index is > 0
+             QString idxString;
+             idxString.setNum(1+controlInstanceIndex);
+-            readableName += " ";
++            readableName += ' ';
+             readableName += idxString;
+         }
+ 
+@@ -208,12 +210,13 @@
+         idx++;
+ 
+ 
+-        MixDevice* md = new MixDevice(_mixer, finalMixdeviceID, readableName, ct );
++        MixDevice* mdNew = new MixDevice(_mixer, finalMixdeviceID, readableName, ct );
+ 
+-        if ( volPlay    != 0      ) md->addPlaybackVolume(*volPlay);
+-        if ( volCapture != 0      ) md->addCaptureVolume (*volCapture);
+-       	if ( !enumList.isEmpty()  ) md->addEnums(enumList);
+-         
++        if ( volPlay    != 0      ) mdNew->addPlaybackVolume(*volPlay);
++        if ( volCapture != 0      ) mdNew->addCaptureVolume (*volCapture);
++       	if ( !enumList.isEmpty()  ) mdNew->addEnums(enumList);
++
++       	shared_ptr<MixDevice> md = mdNew->addToPool();
+         m_mixDevices.append( md );
+          
+         qDeleteAll(enumList); // clear temporary list
+@@ -274,7 +277,6 @@
+ int Mixer_ALSA::openAlsaDevice(const QString& devName)
+ {
+     int err;
+-    snd_ctl_t *ctl_handle;
+ 
+     QString probeMessage;
+     probeMessage += "Trying ALSA Device '" + devName + "': ";
+@@ -482,6 +484,13 @@
+ {
+   int ret=0;
+   m_isOpen = false;
++
++  if ( ctl_handle != 0)
++  {
++	  //snd_ctl_close( ctl_handle );
++	  ctl_handle = 0;
++  }
++
+   if ( _handle != 0 )
+   {
+     //kDebug() << "IN  Mixer_ALSA::close()";
+@@ -696,7 +705,7 @@
+ 
+ 
+ int
+-Mixer_ALSA::readVolumeFromHW( const QString& id, MixDevice *md )
++Mixer_ALSA::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+     Volume& volumePlayback = md->playbackVolume();
+     Volume& volumeCapture  = md->captureVolume();
+@@ -776,9 +785,8 @@
+         // Refresh the capture switch information of *all* controls of this card.
+         // Doing it for all is necessary, because enabling one record source often
+         // automatically disables another record source (due to the hardware design)
+-        for(int i=0; i< m_mixDevices.count() ; i++ )
++        foreach ( shared_ptr<MixDevice> md, m_mixDevices )
+         {
+-            MixDevice *md = m_mixDevices[i];
+             bool isRecsrc =  isRecsrcHW( md->id() );
+             // kDebug() << "Mixer::setRecordSource(): isRecsrcHW(" <<  md->id() << ") =" <<  isRecsrc;
+             md->setRecSource( isRecsrc );
+@@ -790,7 +798,7 @@
+ }
+ 
+ int
+-Mixer_ALSA::writeVolumeToHW( const QString& id, MixDevice *md )
++Mixer_ALSA::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+     Volume& volumePlayback = md->playbackVolume();
+     Volume& volumeCapture  = md->captureVolume();
+Index: backends/mixer_oss.h
+===================================================================
+--- backends/mixer_oss.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_oss.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -33,8 +33,8 @@
+   virtual ~Mixer_OSS();
+ 
+   virtual QString errorText(int mixer_error);
+-  virtual int readVolumeFromHW( const QString& id, MixDevice *md );
+-  virtual int writeVolumeToHW ( const QString& id, MixDevice *md );
++  virtual int readVolumeFromHW( const QString& id, shared_ptr<MixDevice> );
++  virtual int writeVolumeToHW ( const QString& id, shared_ptr<MixDevice> );
+ 
+   virtual QString getDriverName();
+ 
+Index: backends/mixer_sun.h
+===================================================================
+--- backends/mixer_sun.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_sun.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -34,8 +34,8 @@
+   virtual ~Mixer_SUN();
+ 
+   virtual QString errorText(int mixer_error);
+-  virtual int readVolumeFromHW( const QString& id, MixDevice *md  );
+-  virtual int writeVolumeToHW ( const QString& id, MixDevice *md  );
++  virtual int readVolumeFromHW( const QString& id, shared_ptr<MixDevice> );
++  virtual int writeVolumeToHW ( const QString& id, shared_ptr<MixDevice> );
+ 
+   virtual QString getDriverName();
+ 
+Index: backends/kmix-backends.cpp
+===================================================================
+--- backends/kmix-backends.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/kmix-backends.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -46,13 +46,7 @@
+ #endif
+ 
+ #if defined(hpux)
+-# if defined(HAVE_ALIB_H)
+-#  define HPUX_MIXER
+-# else
+-#ifdef __GNUC__
+-#  warning ** YOU NEED to have libAlib installed to use the HP-UX-Mixer **
+-#endif
+-# endif // HAVE_ALIB_H
++#error "The HP/UX port is not maintained anymore, an no official part of KMix / KDE at this point of time! Please contact the current KMix maintainer if you would like to maintain the port."
+ #endif // hpux
+ 
+ // PORTING: add #ifdef PLATFORM , commands , #endif, add your new mixer below
+@@ -82,14 +76,7 @@
+ #include "backends/mixer_oss4.cpp"
+ #endif
+ 
+-#if defined(HPUX_MIXER)
+-#include "backends/mixer_hpux.cpp"
+-#endif
+ 
+-
+-
+-
+-
+ typedef Mixer_Backend *getMixerFunc( Mixer* mixer, int device );
+ typedef QString getDriverNameFunc( );
+ 
+@@ -137,10 +124,6 @@
+     // Possibly encapsualte by #ifdef HAVE_DBUS
+     { MPRIS2_getMixer, MPRIS2_getDriverName },
+ 
+-#if defined(HPUX_MIXER)
+-    { HPUX_getMixer, HPUX_getDriverName },
+-#endif
+-
+     { 0, 0 }
+ };
+ 
+Index: backends/mixer_mpris2.cpp
+===================================================================
+--- backends/mixer_mpris2.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_mpris2.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -22,26 +22,21 @@
+ #include "mixer_mpris2.h"
+ #include "core/mixer.h"
+ 
+-//#include <QtCore/QCoreApplication>
+ #include <QDebug>
+ #include <QStringList>
+ #include <QDBusReply>
+-
+-
+ #include <QString>
+ 
++#include <KLocale>
++
+ // Set the QDBUS_DEBUG env variable for debugging Qt DBUS calls.
+ 
+ Mixer_Backend* MPRIS2_getMixer(Mixer *mixer, int device )
+ {
+-
+-	Mixer_Backend *l_mixer;
+-
+-	l_mixer = new Mixer_MPRIS2(mixer,  device );
+-	return l_mixer;
++	return new Mixer_MPRIS2(mixer, device );
+ }
+ 
+-Mixer_MPRIS2::Mixer_MPRIS2(Mixer *mixer, int device) : Mixer_Backend(mixer,  device )
++Mixer_MPRIS2::Mixer_MPRIS2(Mixer *mixer, int device) : Mixer_Backend(mixer, device )
+ {
+ }
+ 
+@@ -51,6 +46,7 @@
+ 	if ( m_devnum !=  0 )
+ 		return Mixer::ERR_OPEN;
+ 
++	m_mixerName = i18n("Playback Streams");
+ 	_mixer->setDynamic();
+ 	addAllRunningPlayersAndInitHotplug();
+ 	return 0;
+@@ -58,7 +54,9 @@
+ 
+ int Mixer_MPRIS2::close()
+ {
+-	return 0;
++	  m_isOpen = false;
++	  m_mixDevices.clear();
++	 return 0;
+ }
+ 
+ int Mixer_MPRIS2::mediaPlay(QString id)
+@@ -98,7 +96,7 @@
+ }
+ 
+ 
+-int Mixer_MPRIS2::readVolumeFromHW( const QString& id, MixDevice * md)
++int Mixer_MPRIS2::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md)
+ {
+ 
+ 	int volInt = 0;
+@@ -134,7 +132,7 @@
+ 	return 0;
+ }
+ 
+-int Mixer_MPRIS2::writeVolumeToHW( const QString& id, MixDevice *md )
++int Mixer_MPRIS2::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+ 
+ 	qDebug() << "Shall send updated volume to MPRIS Player for " << id;
+@@ -276,18 +274,19 @@
+ 				ct = MixDevice::APPLICATION_XMM2;
+ 			}
+ 
+-			MixDevice* md = new MixDevice(_mixer, id, readableName, ct);
++			MixDevice* mdNew = new MixDevice(_mixer, id, readableName, ct);
+ 			// MPRIS2 doesn't support an actual mute switch. Mute is defined as volume = 0.0
+ 			// Thus we won't add the playback switch
+ 			Volume* vol = new Volume( 100, 0, false, false);
+ 			vol->addVolumeChannel(VolumeChannel(Volume::LEFT)); // MPRIS is only one control ("Mono")
+-			md->addMediaPlayControl();
+-			md->addMediaNextControl();
+-			md->addMediaPrevControl();
+-			md->setApplicationStream(true);
+-			md->addPlaybackVolume(*vol);
+-			m_mixDevices.append( md );
++			mdNew->addMediaPlayControl();
++			mdNew->addMediaNextControl();
++			mdNew->addMediaPrevControl();
++			mdNew->setApplicationStream(true);
++			mdNew->addPlaybackVolume(*vol);
+ 
++	        m_mixDevices.append( mdNew->addToPool() );
++
+ 			//	conn.connect("", QString("/org/mpris/MediaPlayer2"), "org.freedesktop.DBus.Properties", "PropertiesChanged", mad, SLOT(volumeChangedIncoming(QString,QList<QVariant>)) );
+ 			conn.connect(busDestination, QString("/org/mpris/MediaPlayer2"), "org.freedesktop.DBus.Properties", "PropertiesChanged", mad, SLOT(volumeChangedIncoming(QString,QVariantMap,QStringList)) );
+ 			connect(mad, SIGNAL(volumeChanged(MPrisAppdata*,double)), this, SLOT(volumeChanged(MPrisAppdata*,double)) );
+@@ -353,12 +352,12 @@
+ /**
+  * This slot is a simple proxy that enriches the DBUS signal with our data, which especially contains the id of the MixDevice.
+  */
+-void MPrisAppdata::volumeChangedIncoming(QString ifc,QVariantMap msg ,QStringList sl)
++void MPrisAppdata::volumeChangedIncoming(QString /*ifc*/,QVariantMap msg ,QStringList /*sl*/)
+ {
+ 	QMap<QString, QVariant>::iterator v = msg.find("Volume");
+ 	if (v != msg.end() )
+ 	{
+-		kDebug(67100) << "volumeChanged incoming: !!!!!!!!!" ;
++//		kDebug(67100) << "volumeChanged incoming: !!!!!!!!!" ;
+ 		double volDouble = v.value().toDouble();
+ 		emit volumeChanged( this, volDouble);
+ 	}
+@@ -378,7 +377,7 @@
+ {
+ 	int volInt = newVolume *100;
+ 	kDebug(67100) << "volumeChanged: " << mad->id << ": " << volInt;
+-	MixDevice * md = m_mixDevices.get(mad->id);
++	shared_ptr<MixDevice> md = m_mixDevices.get(mad->id);
+ 	Volume& vol = md->playbackVolume();
+ 	vol.setVolume( Volume::LEFT, volInt);
+ 	md->setMuted(volInt == 0);
+Index: backends/mixer_mpris2.h
+===================================================================
+--- backends/mixer_mpris2.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_mpris2.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -54,15 +54,15 @@
+ {
+   Q_OBJECT
+ public:
+-  explicit Mixer_MPRIS2(Mixer *mixer, int device = -1 );
++   Mixer_MPRIS2(Mixer *mixer, int device);
+     virtual ~Mixer_MPRIS2();
+     void addMprisControl(QDBusConnection& conn, QString arg1);
+     QString getDriverName();
+ 
+   virtual int open();
+   virtual int close();
+-  virtual int readVolumeFromHW( const QString& id, MixDevice * );
+-  virtual int writeVolumeToHW( const QString& id, MixDevice * );
++  virtual int readVolumeFromHW( const QString& id, shared_ptr<MixDevice> );
++  virtual int writeVolumeToHW( const QString& id, shared_ptr<MixDevice> );
+   virtual void setEnumIdHW(const QString& id, unsigned int);
+   virtual unsigned int enumIdHW(const QString& id);
+   virtual bool moveStream( const QString& id, const QString& destId );
+Index: backends/mixer_alsa.h
+===================================================================
+--- backends/mixer_alsa.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_alsa.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -42,8 +42,8 @@
+     explicit Mixer_ALSA(Mixer *mixer, int device = -1 );
+     ~Mixer_ALSA();
+ 
+-    virtual int  readVolumeFromHW( const QString& id, MixDevice *md );
+-    virtual int  writeVolumeToHW ( const QString& id, MixDevice *md );
++    virtual int  readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md );
++    virtual int  writeVolumeToHW ( const QString& id, shared_ptr<MixDevice> md );
+     virtual void setEnumIdHW( const QString& id, unsigned int);
+     virtual unsigned int enumIdHW(const QString& id);
+     virtual bool prepareUpdateFromHW();
+@@ -78,6 +78,8 @@
+ 
+     bool _initialUpdate;
+     snd_mixer_t *_handle;
++    snd_ctl_t *ctl_handle;
++
+     QString devName;
+     struct pollfd  *m_fds;
+     QList<QSocketNotifier*> m_sns;
+Index: backends/mixer_backend.cpp
+===================================================================
+--- backends/mixer_backend.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_backend.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -18,9 +18,10 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "mixer_backend.h"
++
+ #include <klocale.h>
+ 
+-#include "mixer_backend.h"
+ // for the "ERR_" declartions, #include mixer.h
+ #include "core/mixer.h"
+ #include <QTimer>
+@@ -32,19 +33,21 @@
+ #include "mixer_backend_i18n.cpp"
+ 
+ Mixer_Backend::Mixer_Backend(Mixer *mixer, int device) :
+-m_devnum (device) , m_isOpen(false), m_recommendedMaster(0), _mixer(mixer), _pollingTimer(0)
++m_devnum (device) , m_isOpen(false), m_recommendedMaster(), _mixer(mixer), _pollingTimer(0)
+ 
+ {
+ 	// In all cases create a QTimer. We will use it once as a singleShot(), even if something smart
+ 	// like ::select() is possible (as in ALSA).
+ 	_pollingTimer = new QTimer(); // will be started on open() and stopped on close()
+ 	connect( _pollingTimer, SIGNAL(timeout()), this, SLOT(readSetFromHW()), Qt::QueuedConnection);
++
+ }
+ 
+ Mixer_Backend::~Mixer_Backend()
+ {
++	qDebug() << "Running Mixer_Backend destructor";
+ 	delete _pollingTimer;
+-	qDeleteAll(m_mixDevices);
++	//qDeleteAll(m_mixDevices); // TODO cesken Leak check the removed qDeleteAll()
+ 	m_mixDevices.clear();
+ }
+ 
+@@ -117,10 +120,8 @@
+ 
+ 	int ret = Mixer::OK_UNCHANGED;
+ 
+-	int mdCount = m_mixDevices.count();
+-	for(int i=0; i<mdCount  ; ++i )
++	foreach (shared_ptr<MixDevice> md, m_mixDevices )
+ 	{
+-		MixDevice *md = m_mixDevices[i];
+ 		int retLoop = readVolumeFromHW( md->id(), md );
+ 		if (md->isEnum() ) {
+ 			/*
+@@ -160,6 +161,7 @@
+ 		// This code path is entered on Mixer::OK_UNCHANGED and ERROR
+ 		if ( !_fastPollingEndsAt.isNull() )
+ 		{
++			// Fast polling is currently active
+ 			if( _fastPollingEndsAt < QTime::currentTime () )
+ 			{
+ 				kDebug() << "End fast polling";
+@@ -176,20 +178,29 @@
+  * first device in the device list. Backends can override this (i.e. the ALSA Backend does so).
+  * The users preference is NOT returned by this method - see the Mixer class for that.
+  */
+-MixDevice* Mixer_Backend::recommendedMaster() {
+-	if ( m_recommendedMaster != 0 ) {
+-		return m_recommendedMaster;   // Backend has set a recommended master. Thats fine.
+-	} // recommendation from Backend
+-	else if ( m_mixDevices.count() > 0 ) {
+-		return m_mixDevices.at(0);  // Backend has NOT set a recommended master. Evil backend => lets help out.
+-	} //first device (if exists)
+-	else {
+-		if ( !_mixer->isDynamic()) {
+-			// This should never ever happen, as KMix doe NOT accept soundcards without controls
++shared_ptr<MixDevice> Mixer_Backend::recommendedMaster()
++{
++	if ( m_recommendedMaster != 0 )
++	{
++		// Backend has set a recommended master. Thats fine. Using it.
++		return m_recommendedMaster;
++	}
++	else if ( ! m_mixDevices.isEmpty() )
++	{
++		// Backend has NOT set a recommended master. Evil backend
++		// => lets help out, using the first device (if exists)
++		return m_mixDevices.at(0);
++	}
++	else
++	{
++		if ( !_mixer->isDynamic())
++			// This should never ever happen, as KMix does NOT accept soundcards without controls
+ 			kError(67100) << "Mixer_Backend::recommendedMaster(): returning invalid master. This is a bug in KMix. Please file a bug report stating how you produced this." << endl;
+-		}
+-		return (MixDevice*)0;
+ 	}
++
++	// If we reach this code path, then obiously m_recommendedMaster == 0 (see above)
++	return m_recommendedMaster;
++
+ }
+ 
+ /**
+Index: backends/mixer_oss4.cpp
+===================================================================
+--- backends/mixer_oss4.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_oss4.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -21,6 +21,9 @@
+ 
+ //OSS4 mixer backend for KMix by Yoper Team released under GPL v2 or later
+ 
++/* We're getting soundcard.h via mixer_oss4.h */
++#include "mixer_oss4.h"
++
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <unistd.h>
+@@ -28,8 +31,6 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ 
+-/* We're getting soundcard.h via mixer_oss4.h */
+-#include "mixer_oss4.h"
+ #include <klocale.h>
+ #include <QLinkedList>
+ #include <QRegExp>
+@@ -53,7 +54,7 @@
+ bool Mixer_OSS4::CheckCapture(oss_mixext *ext)
+ {
+ 	QString name = ext->extname;
+-	if ( ext->flags & MIXF_RECVOL || name.split(".").contains("in") )
++	if ( ext->flags & MIXF_RECVOL || name.split('.').contains("in") )
+ 	{
+ 		return true;
+ 	}
+@@ -214,7 +215,7 @@
+ 			bool masterChosen = false;
+ 			bool masterHeuristicAvailable = false;
+ 			bool saveAsMasterHeuristc = false;
+-			MixDevice *masterHeuristic = NULL;
++			shared_ptr<MixDevice> masterHeuristic;
+ 
+ 			oss_mixext ext;
+ 			ext.dev = m_devnum;
+@@ -360,7 +361,7 @@
+ 						masterChosen = true;
+ 					}
+ 
+-					m_mixDevices.append(md);
++					m_mixDevices.append(md->addToPool());
+ 				}
+ 				else if ( ext.type == MIXT_HEXVALUE )
+ 				{
+@@ -388,7 +389,7 @@
+ 						masterChosen = true;
+ 					}
+ 
+-					m_mixDevices.append(md);
++					m_mixDevices.append(md->addToPool());
+ 				}
+ 				else if ( ext.type == MIXT_ONOFF 
+ #ifdef MIXT_MUTE
+@@ -418,7 +419,7 @@
+ 						md->addPlaybackVolume(vol);
+ 					}
+ 
+-					m_mixDevices.append(md);
++					m_mixDevices.append(md->addToPool());
+ 				}
+ 				else if ( ext.type == MIXT_ENUM )
+ 				{
+@@ -452,7 +453,7 @@
+ 						}
+ 						md->addEnums(enumValuesRef);
+ 
+-						m_mixDevices.append(md);
++						m_mixDevices.append(md->addToPool());
+ 					}
+ 				}
+ 
+@@ -526,7 +527,7 @@
+ 	return true;
+ }
+ 
+-int Mixer_OSS4::readVolumeFromHW(const QString& id, MixDevice *md)
++int Mixer_OSS4::readVolumeFromHW(const QString& id, shared_ptr<MixDevice> md)
+ {
+ 	oss_mixext extinfo;
+ 	oss_mixer_value mv;
+@@ -592,7 +593,7 @@
+ 	return 0;
+ }
+ 
+-int Mixer_OSS4::writeVolumeToHW(const QString& id, MixDevice *md)
++int Mixer_OSS4::writeVolumeToHW(const QString& id, shared_ptr<MixDevice> md)
+ {
+ 	int volume = 0;
+ 
+Index: backends/mixer_pulse.cpp
+===================================================================
+--- backends/mixer_pulse.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ backends/mixer_pulse.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -19,17 +19,21 @@
+  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
+ 
++#include "mixer_pulse.h"
++
+ #include <cstdlib>
+ #include <QtCore/QAbstractEventDispatcher>
+ #include <QTimer>
+ 
+ #include <klocale.h>
+ 
+-#include "mixer_pulse.h"
+ #include "core/mixer.h"
+ 
+ #include <pulse/glib-mainloop.h>
+ #include <pulse/ext-stream-restore.h>
++#if defined(HAVE_CANBERRA)
++#  include <canberra.h>
++#endif
+ 
+ #define HAVE_SOURCE_OUTPUT_VOLUMES PA_CHECK_VERSION(1,0,0)
+ 
+@@ -47,6 +51,10 @@
+ static enum { UNKNOWN, ACTIVE, INACTIVE } s_pulseActive = UNKNOWN;
+ static int s_outstandingRequests = 0;
+ 
++#if defined(HAVE_CANBERRA)
++static ca_context *s_ccontext = NULL;
++#endif
++
+ QMap<int,Mixer_PULSE*> s_mixers;
+ 
+ typedef QMap<int,devinfo> devmap;
+@@ -129,11 +137,11 @@
+                     dev.chanMask = (Volume::ChannelMask)( dev.chanMask | Volume::MWOOFER);
+                     dev.chanIDs[i] = Volume::WOOFER;
+                     break;
+-                case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
++                case PA_CHANNEL_POSITION_SIDE_LEFT:
+                     dev.chanMask = (Volume::ChannelMask)( dev.chanMask | Volume::MREARSIDELEFT);
+                     dev.chanIDs[i] = Volume::REARSIDELEFT;
+                     break;
+-                case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
++                case PA_CHANNEL_POSITION_SIDE_RIGHT:
+                     dev.chanMask = (Volume::ChannelMask)( dev.chanMask | Volume::MREARSIDERIGHT);
+                     dev.chanIDs[i] = Volume::REARSIDERIGHT;
+                     break;
+@@ -751,6 +759,18 @@
+     return get_widget_map(type);
+ }
+ 
++void Mixer_PULSE::emitControlsReconfigured()
++{
++    // Do not emit directly to ensure all connected slots are executed
++    // in their own event loop.
++	kDebug() << "PULSE emitControlsReconfigured: mixerId=" << _mixer->id();
++//	emit controlsReconfigured(_mixer->id());
++    QMetaObject::invokeMethod(this,
++                              "controlsReconfigured",
++                              Qt::QueuedConnection,
++                              Q_ARG(QString, _mixer->id()));
++}
++
+ void Mixer_PULSE::addWidget(int index)
+ {
+     devmap* map = get_widget_map(m_devnum, index);
+@@ -760,12 +780,7 @@
+         return;
+     }
+     addDevice((*map)[index]);
+-    // Do not emit directly to ensure all connected slots are executed
+-    // in their own event loop.
+-    QMetaObject::invokeMethod(this,
+-                              "controlsReconfigured",
+-                              Qt::QueuedConnection,
+-                              Q_ARG(QString, _mixer->id()));
++    emitControlsReconfigured();
+ }
+ 
+ void Mixer_PULSE::removeWidget(int index)
+@@ -787,14 +802,9 @@
+     {
+         if ((*iter)->id() == id)
+         {
+-            delete *iter;
++//            delete *iter;  // TODO cesken LET-THIS-CHECK  Delete should not be required after migration to shared_ptr
+             m_mixDevices.erase(iter);
+-            // Do not emit directly to ensure all connected slots are executed
+-            // in their own event loop.
+-            QMetaObject::invokeMethod(this,
+-                                      "controlsReconfigured",
+-                                      Qt::QueuedConnection,
+-                                      Q_ARG(QString, _mixer->id()));
++            emitControlsReconfigured();
+             return;
+         }
+     }
+@@ -809,18 +819,16 @@
+     if (KMIXPA_APP_PLAYBACK == m_devnum)
+         outputRoles.clear();
+ 
+-    MixSet::iterator iter;
+-    for (iter = m_mixDevices.begin(); iter != m_mixDevices.end(); ++iter)
+-    {
+-        delete *iter;
+-        m_mixDevices.erase(iter);
+-    }
+-    // Do not emit directly to ensure all connected slots are executed
+-    // in their own event loop.
+-    QMetaObject::invokeMethod(this,
+-                              "controlsReconfigured",
+-                              Qt::QueuedConnection,
+-                              Q_ARG(QString, _mixer->id()));
++    m_mixDevices.clear();
++
++    // TODO cesken LET-THIS-CHECK  Delete should not be required after migration to shared_ptr
++//    MixSet::iterator iter;
++//    for (iter = m_mixDevices.begin(); iter != m_mixDevices.end(); ++iter)
++//    {
++//        delete *iter;
++//        m_mixDevices.erase(iter);
++//    }
++    emitControlsReconfigured();
+ }
+ 
+ void Mixer_PULSE::addDevice(devinfo& dev, bool isAppStream)
+@@ -841,7 +849,7 @@
+ 
+         md->addPlaybackVolume(v);
+         md->setMuted(dev.mute);
+-        m_mixDevices.append(md);
++        m_mixDevices.append(md->addToPool());
+     }
+ }
+ 
+@@ -944,6 +952,15 @@
+             Q_ASSERT(s_mainloop);
+ 
+             connectToDaemon();
++
++#if defined(HAVE_CANBERRA)
++            int ret = ca_context_create(&s_ccontext);
++            if (ret < 0) {
++                kDebug(67100) << "Disabling Sound Feedback. Canberra context failed.";
++                s_ccontext = NULL;
++            } else
++                ca_context_set_driver(s_ccontext, "pulse");
++#endif
+         }
+ 
+         kDebug(67100) <<  "PulseAudio status: " << (s_pulseActive==UNKNOWN ? "Unknown (bug)" : (s_pulseActive==ACTIVE ? "Active" : "Inactive"));
+@@ -962,6 +979,13 @@
+         --refcount;
+         if (0 == refcount)
+         {
++#if defined(HAVE_CANBERRA)
++            if (s_ccontext) {
++                ca_context_destroy(s_ccontext);
++                s_ccontext = NULL;
++            }
++#endif
++
+             if (s_context) {
+                 pa_context_unref(s_context);
+                 s_context = NULL;
+@@ -1039,7 +1063,7 @@
+     return num;
+ }
+ 
+-int Mixer_PULSE::readVolumeFromHW( const QString& id, MixDevice *md )
++int Mixer_PULSE::readVolumeFromHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+     devmap *map = get_widget_map(m_devnum, id);
+ 
+@@ -1057,7 +1081,7 @@
+     return 0;
+ }
+ 
+-int Mixer_PULSE::writeVolumeToHW( const QString& id, MixDevice *md )
++int Mixer_PULSE::writeVolumeToHW( const QString& id, shared_ptr<MixDevice> md )
+ {
+     devmap::iterator iter;
+     if (KMIXPA_PLAYBACK == m_devnum)
+@@ -1081,6 +1105,44 @@
+                 }
+                 pa_operation_unref(o);
+ 
++#if defined(HAVE_CANBERRA)
++                if (s_ccontext) {
++                    int playing = 0;
++                    int cindex = 2; // Note "2" is simply the index we've picked. It's somewhat irrelevant.
++
++                    
++                    ca_context_playing(s_ccontext, cindex, &playing);
++
++                    // NB Depending on how this is desired to work, we may want to simply
++                    // skip playing, or cancel the currently playing sound and play our
++                    // new one... for now, let's do the latter.
++                    if (playing) {
++                        ca_context_cancel(s_ccontext, cindex);
++                        playing = 0;
++                    }
++                    
++                    if (!playing) {
++                        char dev[64];
++
++                        snprintf(dev, sizeof(dev), "%lu", (unsigned long) iter->index);
++                        ca_context_change_device(s_ccontext, dev);
++
++                        // Ideally we'd use something like ca_gtk_play_for_widget()...
++                        ca_context_play(
++                            s_ccontext,
++                            cindex,
++                            CA_PROP_EVENT_DESCRIPTION, i18n("Volume Control Feedback Sound").toUtf8().constData(),
++                            CA_PROP_EVENT_ID, "audio-volume-change",
++                            CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
++                            CA_PROP_CANBERRA_ENABLE, "1",
++                            NULL
++                        );
++
++                        ca_context_change_device(s_ccontext, NULL);
++                    }
++                }
++#endif
++
+                 return 0;
+             }
+         }
+@@ -1152,7 +1214,7 @@
+                     info.mute = (md->isMuted() ? 1 : 0);
+ 
+                     pa_operation* o;
+-                    if (!(o = pa_ext_stream_restore_write(s_context, PA_UPDATE_REPLACE, &info, 1, TRUE, NULL, NULL))) {
++                    if (!(o = pa_ext_stream_restore_write(s_context, PA_UPDATE_REPLACE, &info, 1, true, NULL, NULL))) {
+                         kWarning(67100) <<  "pa_ext_stream_restore_write() failed" << info.channel_map.channels << info.volume.channels << info.name;
+                         return Mixer::ERR_READ;
+                     }
+@@ -1248,7 +1310,7 @@
+             info.mute = rule.mute ? 1 : 0;
+ 
+             pa_operation* o;
+-            if (!(o = pa_ext_stream_restore_write(s_context, PA_UPDATE_REPLACE, &info, 1, TRUE, NULL, NULL))) {
++            if (!(o = pa_ext_stream_restore_write(s_context, PA_UPDATE_REPLACE, &info, 1, true, NULL, NULL))) {
+                 kWarning(67100) <<  "pa_ext_stream_restore_write() failed" << info.channel_map.channels << info.volume.channels << info.name;
+                 return Mixer::ERR_READ;
+             }
+Index: CMakeLists.txt
+===================================================================
+--- CMakeLists.txt	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ CMakeLists.txt	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,5 +1,17 @@
+ project(kmix)
+ 
++find_package(KDE4 REQUIRED)
++include(KDE4Defaults)
++include(MacroLibrary)
++
++find_package(Alsa)
++
++macro_optional_find_package(PulseAudio "0.9.12")
++macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "PulseAudio Audio Server" "http://www.pulseaudio.org/" FALSE "0.9.12" "libpulse is needed to let KMix control PulseAudio")
++find_package(GLIB2)
++pkg_check_modules(CANBERRA libcanberra)
++macro_log_feature(CANBERRA_FOUND "libcanberra" "libcanberra audio library" "http://0pointer.de/lennart/projects/libcanberra/" FALSE "" "libcanberra is needed for kmix sound feedback")
++
+ alsa_configure_file(${CMAKE_BINARY_DIR}/config-alsa.h)
+ 
+ 
+@@ -21,6 +33,19 @@
+ add_subdirectory( profiles ) 
+ #add_subdirectory( tests )
+ 
++if (PULSEAUDIO_FOUND)
++  add_definitions(-DHAVE_PULSE)
++
++  include_directories(${PULSEAUDIO_INCLUDE_DIR})
++endif (PULSEAUDIO_FOUND)
++
++if (CANBERRA_FOUND)
++  add_definitions(-DHAVE_CANBERRA)
++
++  include_directories(${CANBERRA_INCLUDE_DIRS})
++endif (CANBERRA_FOUND)
++
++
+ set(kmix_adaptor_SRCS
+ 	dbus/dbusmixerwrapper.cpp
+ 	dbus/dbusmixsetwrapper.cpp
+@@ -42,10 +67,10 @@
+       backends/mixer_alsa9.cpp )
+ endif (HAVE_LIBASOUND2)
+ 
+-if (HAVE_PULSE)
++if (PULSEAUDIO_FOUND)
+   set(kmix_backend_SRCS ${kmix_backend_SRCS}
+       backends/mixer_pulse.cpp )
+-endif (HAVE_PULSE)
++endif (PULSEAUDIO_FOUND)
+ 
+ set(kmix_KDEINIT_SRCS ${kmix_adaptor_SRCS} ${kmix_backend_SRCS}
+    apps/main.cpp 
+@@ -72,6 +97,7 @@
+    gui/osdwidget.cpp
+    core/mixertoolbox.cpp
+    core/kmixdevicemanager.cpp
++   core/ControlPool.cpp
+    core/MasterControl.cpp
+    core/mixer.cpp
+    core/mixset.cpp
+@@ -89,10 +115,13 @@
+     target_link_libraries(kdeinit_kmix ${ASOUND_LIBRARY})
+ endif (HAVE_LIBASOUND2)
+ 
+-if (HAVE_PULSE)
++if (PULSEAUDIO_FOUND)
+     target_link_libraries(kdeinit_kmix ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} ${GLIB2_LIBRARIES})
+-endif (HAVE_PULSE)
++endif (PULSEAUDIO_FOUND)
+ 
++if (CANBERRA_FOUND)
++  target_link_libraries(kdeinit_kmix ${CANBERRA_LIBRARIES})
++endif (CANBERRA_FOUND)
+ 
+ install(TARGETS kdeinit_kmix  DESTINATION ${LIB_INSTALL_DIR} )
+ 
+@@ -103,6 +132,7 @@
+ 
+  set(kded_kmixd_SRCS ${kmix_adaptor_SRCS} ${kmix_backend_SRCS}
+     apps/kmixd.cpp 
++    core/ControlPool.cpp
+     core/MasterControl.cpp
+     core/mixer.cpp 
+     core/mixset.cpp 
+@@ -125,10 +155,14 @@
+     target_link_libraries(kded_kmixd ${ASOUND_LIBRARY})
+ endif (HAVE_LIBASOUND2)
+ 
+-if (HAVE_PULSE)
++if (PULSEAUDIO_FOUND)
+     target_link_libraries(kded_kmixd ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} ${GLIB2_LIBRARIES})
+-endif (HAVE_PULSE)
++endif (PULSEAUDIO_FOUND)
+ 
++if (CANBERRA_FOUND)
++  target_link_libraries(kded_kmixd ${CANBERRA_LIBRARIES})
++endif (CANBERRA_FOUND)
++
+ install(TARGETS kded_kmixd DESTINATION ${PLUGIN_INSTALL_DIR})
+ 
+ #target_link_libraries( kmixd kded_kmixd )
+@@ -140,6 +174,7 @@
+ 
+ set(kmixctrl_KDEINIT_SRCS ${kmix_adaptor_SRCS} ${kmix_backend_SRCS}
+    apps/kmixctrl.cpp 
++   core/ControlPool.cpp
+    core/MasterControl.cpp
+    core/mixer.cpp 
+    core/mixset.cpp 
+@@ -160,10 +195,14 @@
+     target_link_libraries(kdeinit_kmixctrl ${ASOUND_LIBRARY})
+ endif (HAVE_LIBASOUND2)
+ 
+-if (HAVE_PULSE)
++if (PULSEAUDIO_FOUND)
+     target_link_libraries(kdeinit_kmixctrl ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} ${GLIB2_LIBRARIES})
+-endif (HAVE_PULSE)
++endif (PULSEAUDIO_FOUND)
+ 
++if (CANBERRA_FOUND)
++  target_link_libraries(kdeinit_kmixctrl ${CANBERRA_LIBRARIES})
++endif (CANBERRA_FOUND)
++
+ ########### next target ###############
+ add_subdirectory( plasma )
+ 
+Index: plasma/engine/mixerengine.h
+===================================================================
+--- plasma/engine/mixerengine.h	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ plasma/engine/mixerengine.h	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -80,13 +80,14 @@
+ 	// Keys are mixerIds for control
+ 	QMultiHash<QString,ControlInfo*> m_controls;
+ 
+-	MixerInfo* createMixerInfo( QString dbusPath );
+-	ControlInfo* createControlInfo( QString mixerId, QString dbusPath );
++	MixerInfo* createMixerInfo( const QString& dbusPath );
++	ControlInfo* createControlInfo( const QString& mixerId, const QString& dbusPath );
+ 
+ 	void clearInternalData(bool removeSources);
+ 	bool getMixersData();
+-	bool getMixerData( const QString &source );
+-	bool getControlData( const QString &source );
++	bool getMixerData( const QString& source );
++	bool getControlData( const QString& source );
++	void setControlData( ControlInfo *ci );
+ private slots:
+ 	void getInternalData();
+ 	void updateInternalMixersData();
+Index: plasma/engine/mixer.operations
+===================================================================
+--- plasma/engine/mixer.operations	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ plasma/engine/mixer.operations	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -1,15 +1,20 @@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE kcfg SYSTEM
+-	"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
++    "http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
+ <kcfg>
+   <group name="setVolume">
+     <entry name="level" type="Int">
+       <label>The volume level between 0 and 100</label>
+-	</entry>
++    </entry>
+   </group>
+   <group name="setMute">
+     <entry name="muted" type="Bool">
+-	  <label>Mute</label>
+-	</entry>
++      <label>Mute</label>
++    </entry>
+   </group>
++  <group name="setRecordSource">
++    <entry name="recordSource" type="Bool">
++      <label>Record Source</label>
++    </entry>
++  </group>
+ </kcfg>
+Index: plasma/engine/mixerservice.cpp
+===================================================================
+--- plasma/engine/mixerservice.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ plasma/engine/mixerservice.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -60,7 +60,11 @@
+ 		setResult( res );
+ 		return;
+ 	}
+-
++	else if ( operation == "setRecordSource" ) {
++		bool res = m_service->iface()->setProperty( "recordSource", parameters().value("recordSource").toBool() );
++		setResult( res );
++		return;
++	}
+ }
+ 
+ #include "mixerservice.moc"
+Index: plasma/engine/mixerengine.cpp
+===================================================================
+--- plasma/engine/mixerengine.cpp	(.../tags/KDE/4.8.2/kdemultimedia/kmix)	(revision 1291338)
++++ plasma/engine/mixerengine.cpp	(.../branches/KDE/4.8/kdemultimedia/kmix)	(revision 1291338)
+@@ -68,7 +68,7 @@
+ 	getInternalData();
+ }
+ 
+-MixerInfo* MixerEngine::createMixerInfo( QString dbusPath )
++MixerInfo* MixerEngine::createMixerInfo( const QString& dbusPath )
+ {
+ 	MixerInfo* curmi = new MixerInfo;
+ 	curmi->iface = new OrgKdeKMixMixerInterface( KMIX_DBUS_SERVICE, dbusPath,
+@@ -85,7 +85,7 @@
+ 	return curmi;
+ }
+ 
+-ControlInfo* MixerEngine::createControlInfo( QString mixerId, QString dbusPath )
++ControlInfo* MixerEngine::createControlInfo( const QString& mixerId, const QString& dbusPath )
+ {
+ 	ControlInfo* curci = new ControlInfo;
+ 	curci->iface = new OrgKdeKMixControlInterface( KMIX_DBUS_SERVICE, dbusPath,
+@@ -112,12 +112,14 @@
+ 				"org.kde.KMix.MixSet", "changed",
+ 				this, SLOT(slotMixersChanged()) );
+ 	}
+-	Q_FOREACH( QString path, m_kmix->mixers() )
++	Q_FOREACH( const QString& path, m_kmix->mixers() )
+ 	{
+ 		MixerInfo* curmi = createMixerInfo( path );
+-		Q_FOREACH( QString controlPath, curmi->iface->controls() )
++		Q_FOREACH( const QString& controlPath, curmi->iface->controls() )
+ 			createControlInfo( curmi->id, controlPath );
+ 	}
++	// Update "Mixers" source
++	getMixersData();
+ }
+ 
+ void MixerEngine::clearInternalData(bool removeSources)
+@@ -133,7 +135,7 @@
+ 	Q_FOREACH( ControlInfo* ci, m_controls )
+ 	{
+ 		if ( removeSources )
+-			removeSource( ci->mixerId + "/" + ci->id );
++			removeSource( ci->mixerId + '/' + ci->id );
+ 		delete ci->iface;
+ 		delete ci;
+ 	}
+@@ -162,13 +164,24 @@
+ 	QStringList mixerIds;
+ 	if ( interface->isServiceRegistered( KMIX_DBUS_SERVICE ) )
+ 	{
+-		// 'Unused' flag is used for cleanup
+ 		Q_FOREACH( MixerInfo* mi, m_mixers )
+ 			mixerIds.append( mi->id );
++		/* FIXME: this is used to know whether kmix isn't running or
++		 * it can't find any audio device; also it works as a strange 
++		 * workaround: without it there is no dataUpdated() call sometimes
++		 * when it is updated here */
++		setData( "Mixers", "Running", true );
+ 		setData( "Mixers", "Mixers", mixerIds );
++		setData( "Mixers", "Current Master Mixer", m_kmix->currentMasterMixer() );
++		setData( "Mixers", "Current Master Control", m_kmix->currentMasterControl() );
+ 	}
+ 	else
++	{
++		setData( "Mixers", "Running", false );
+ 		removeData( "Mixers", "Mixers" );
++		removeData( "Mixers", "Current Master Mixer" );
++		removeData( "Mixers", "Current Master Control" );
++	}
+ 	return true;
+ }
+ 
+@@ -234,14 +247,23 @@
+ 		return false;
+ 	// Setting data
+ 	curci->updateRequired = true;
+-	setData( source, "Can Be Muted", curci->iface->canMute() );
+-	setData( source, "Volume", curci->iface->volume() );
+-	setData( source, "Mute", curci->iface->mute() );
+-	setData( source, "Readable Name", curci->iface->readableName() );
+-	setData( source, "Icon", KIcon(curci->iface->iconName()) );
++	setControlData( curci );
+ 	return true;
+ }
+ 
++void MixerEngine::setControlData(ControlInfo* ci)
++{
++	QString source = ci->mixerId + '/' + ci->id;
++	setData( source, "Volume", ci->iface->volume() );
++	setData( source, "Mute", ci->iface->mute() );
++	setData( source, "Can Be Muted", ci->iface->canMute() );
++	setData( source, "Readable Name", ci->iface->readableName() );
++	setData( source, "Icon", KIcon(ci->iface->iconName()) );
++	setData( source, "Record Source", ci->iface->recordSource() );
++	setData( source, "Has Capture Switch", ci->iface->hasCaptureSwitch() );
++}
++
++
+ void MixerEngine::slotServiceRegistered( const QString &serviceName)
+ {
+ 	// Let's give KMix some time to load
+@@ -253,7 +275,8 @@
+ {
+ 	if ( serviceName == KMIX_DBUS_SERVICE )
+ 		clearInternalData(true);
+-	removeData( "Mixers", "Mixers" );
++	// Updating 'Mixers' source
++	getMixersData();
+ }
+ 
+ void MixerEngine::slotControlChanged()
+@@ -265,13 +288,7 @@
+ 	// Updating all controls that might change
+ 	Q_FOREACH( ControlInfo* ci, m_controls.values( curmi->id ) )
+ 		if ( ci->updateRequired )
+-		{
+-			QString source = ci->mixerId + "/" + ci->id;
+-			setData( source, "Can Be Muted", ci->iface->canMute() );
+-			setData( source, "Volume", ci->iface->volume() );
+-			setData( source, "Mute", ci->iface->mute() );
+-			setData( source, "Readable Name", ci->iface->readableName() );
+-		}
++			setControlData( ci );
+ }
+ 
+ void MixerEngine::slotControlsReconfigured()
+@@ -284,9 +301,10 @@
+ 	QList<ControlInfo*> controlsForMixer = m_controls.values( curmi->id );
+ 	QStringList controlIds;
+ 	QStringList controlReadableNames;
++	QStringList controlIconNames;
+ 	Q_FOREACH( ControlInfo* ci, controlsForMixer )
+ 		ci->unused = true;
+-	Q_FOREACH( QString controlPath, curmi->iface->controls() )
++	Q_FOREACH( const QString& controlPath, curmi->iface->controls() )
+ 	{
+ 		ControlInfo* curci = 0;
+ 		Q_FOREACH( ControlInfo* ci, controlsForMixer )
+@@ -301,6 +319,7 @@
+ 		curci->unused = false;
+ 		controlIds.append( curci->id );
+ 		controlReadableNames.append( curci->iface->readableName() );
++		controlIconNames.append( curci->iface->iconName() );
+ 	}
+ 	// If control is unused then we should remove it
+ 	Q_FOREACH( ControlInfo* ci, controlsForMixer )
+@@ -312,9 +331,9 @@
+ 		}
+ 	if ( curmi->updateRequired )
+ 	{
+-		QString source = curmi->id;
+-		setData( source, "Controls", controlIds );
+-		setData( source, "Controls Readable Names", controlReadableNames );
++		setData( curmi->id, "Controls", controlIds );
++		setData( curmi->id, "Controls Readable Names", controlReadableNames );
++		setData( curmi->id, "Controls Icons Names", controlIconNames );
+ 	}
+ }
+ 
+@@ -323,7 +342,7 @@
+ 	// Some mixer added or removed
+ 	Q_FOREACH( MixerInfo* mi, m_mixers )
+ 		mi->unused = true;
+-	Q_FOREACH( QString mixerPath, m_kmix->mixers() )
++	Q_FOREACH( const QString& mixerPath, m_kmix->mixers() )
+ 	{
+ 		MixerInfo* curmi = m_mixers.value( mixerPath, 0 );
+ 		// if mixer was added, we need to add one to m_mixers
+@@ -331,7 +350,7 @@
+ 		if ( !curmi )
+ 		{
+ 			curmi = createMixerInfo( mixerPath );
+-			Q_FOREACH( QString controlPath, curmi->iface->controls() )
++			Q_FOREACH( const QString& controlPath, curmi->iface->controls() )
+ 				createControlInfo( curmi->id, controlPath );
+ 		}
+ 		curmi->unused = false;
+@@ -344,7 +363,7 @@
+ 			Q_FOREACH( ControlInfo* ci, m_controls.values( mi->id ) )
+ 			{
+ 				m_controls.remove( mi->id, ci );
+-				removeSource( ci->mixerId + "/" + ci->id );
++				removeSource( ci->mixerId + '/' + ci->id );
+ 				delete ci->iface;
+ 				delete ci;
+ 			}
diff --git a/kdemultimedia.spec b/kdemultimedia.spec
index 0fad996..4243caf 100644
--- a/kdemultimedia.spec
+++ b/kdemultimedia.spec
@@ -6,7 +6,7 @@
 Name:    kdemultimedia
 Epoch:   6
 Version: 4.8.2
-Release: 3%{?dist}
+Release: 4%{?dist}
 Summary: KDE Multimedia applications
 
 Group:   Applications/Multimedia
@@ -26,6 +26,10 @@ Patch1: kdemultimedia-4.6.2-no_thumbs.patch
 ## upstream patches
 # http://svnweb.mageia.org/packages/cauldron/kdemultimedia4/current/SOURCES/0100-Prevent-kmixctrl-running-with-PulseAudio.patch
 Patch100: 0100-Prevent-kmixctrl-running-with-PulseAudio.patch
+# svn diff \
+#   svn+ssh://anonsvn.kde.org/home/kde/tags/KDE/4.8.2/kdemultimedia/kmix/ \
+#   svn+ssh://anonsvn.kde.org/home/kde/branches/KDE/4.8/kdemultimedia/kmix 
+Patch101: kdemultimedia-4.8.2-kmix_backport.patch
 
 BuildRequires: cdparanoia-devel cdparanoia
 BuildRequires: kdepimlibs-devel >= %{version}
@@ -142,6 +146,9 @@ Requires: %{name}-kio_audiocd = %{?epoch:%{epoch}:}%{version}-%{release}
 %patch1 -p1 -b .no_thumbs
 
 %patch100 -p1 -b .kmixctrl-running-with-PulseAudio
+pushd kmix
+%patch101 -p0 -b .kmix_backport
+popd
 
 
 %build
@@ -333,6 +340,10 @@ fi
 
 
 %changelog
+* Tue Apr 24 2012 Rex Dieter <rdieter at fedoraproject.org> 6:4.8.2-4
+- kmix crashes when pulseaudio exits (#804363)
+- kmix is crashing after multiple volume changes (kde#290742)
+
 * Fri Apr 13 2012 Rex Dieter <rdieter at fedoraproject.org> 6:4.8.2-3
 - -dragonplayer: Provides: dragon
 


More information about the scm-commits mailing list