From 7173de9b1d76aada67d30573b764579a818ac684 Mon Sep 17 00:00:00 2001 From: Roman Savochenko Date: Sun, 19 Nov 2023 10:20:26 +0200 Subject: [PATCH] KMix: Dynamism in tracing of appearance new audio-controllers Signed-off-by: Roman Savochenko --- kmix/kmix.cpp | 39 ++++++++++++++++++++++++++++++++++++++- kmix/kmix.h | 4 ++++ kmix/kmixapplet.cpp | 3 ++- kmix/kmixctrl.cpp | 3 ++- kmix/mixer.cpp | 2 ++ kmix/mixer.h | 1 + kmix/mixer_alsa9.cpp | 39 ++++++++++++++++++++++++++++++++------- kmix/mixertoolbox.cpp | 25 +++++++++++++++---------- kmix/mixertoolbox.h | 26 ++++++++++++++++++++++++-- 9 files changed, 120 insertions(+), 22 deletions(-) diff --git a/kmix/kmix.cpp b/kmix/kmix.cpp index 20e9c58f..bdc2c521 100644 --- a/kmix/kmix.cpp +++ b/kmix/kmix.cpp @@ -4,6 +4,7 @@ * Copyright (C) 2000 Stefan Schimanski * Copyright (C) 2001 Preston Brown * Copyright (C) 2003 Sven Leiber + * Copyright (C) 2020 Roman Savochenko * 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 @@ -98,12 +99,18 @@ KMixWindow::KMixWindow() hide(); } connect( kapp, TQT_SIGNAL( aboutToQuit()), TQT_SLOT( saveSettings()) ); + + mixersUpdTimer = new TQTimer(); + connect(mixersUpdTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(mixersUpdate())); + mixersUpdTimer->start(10000); } KMixWindow::~KMixWindow() { - MixerToolBox::deinitMixer(); + delete mixersUpdTimer; + + MixerToolBox::deinitMixer(Mixer::mixers()); } @@ -136,6 +143,34 @@ KMixWindow::initActions() createGUI( "kmixui.rc" ); } +void +KMixWindow::mixersUpdate() +{ + //Do not update the mixers at the mixer window and the dock widget visibility + if(!m_dockWidget || isVisible() || (m_dockWidget->_dockAreaPopup && ((TQWidget*)m_dockWidget->_dockAreaPopup)->isVisible())) return; + //Detection the mixers configuration change + else { + TQPtrList tmpMix; +#ifdef WITH_KMIX_EXPERIMENTAL + MixerToolBox::initMixer(tmpMix, KMixSettings::multiDriver(), m_hwInfoString, true); +#else + MixerToolBox::initMixer(tmpMix, false, m_hwInfoString, true); +#endif + bool chMixers = (tmpMix.count() != Mixer::mixers().count()); + MixerToolBox::deinitMixer(tmpMix); + if(!chMixers) return; + } + MixerToolBox::deinitMixer(Mixer::mixers()); +#ifdef WITH_KMIX_EXPERIMENTAL + MixerToolBox::initMixer(Mixer::mixers(), KMixSettings::multiDriver(), m_hwInfoString); +#else + MixerToolBox::initMixer(Mixer::mixers(), false, m_hwInfoString); +#endif + + initMixerWidgets(); + updateDocking(); +} + void KMixWindow::initWidgets() { @@ -271,6 +306,8 @@ void KMixWindow::initMixerWidgets() { m_mixerWidgets.clear(); + m_cMixer->clear(); + mixerNameLayout->show(); int id=0; Mixer *mixer; diff --git a/kmix/kmix.h b/kmix/kmix.h index 602102b5..64a5ad09 100644 --- a/kmix/kmix.h +++ b/kmix/kmix.h @@ -3,6 +3,7 @@ * * * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * Copyright (C) 2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -30,6 +31,7 @@ // include files for TQt #include #include +#include class TQHBox; class TQWidgetStack; @@ -128,9 +130,11 @@ KMixWindow : public TDEMainWindow, virtual public KMixIface KMixDockWidget *m_dockWidget; TQString m_hwInfoString; TQVBoxLayout *widgetsLayout; + TQTimer *mixersUpdTimer; private slots: //void removeMixerWidget( KMixerWidget *mw ); + void mixersUpdate(); void slotHWInfo(); void showSelectedMixer( int mixer ); void configureGlobalShortcuts(); diff --git a/kmix/kmixapplet.cpp b/kmix/kmixapplet.cpp index a4770993..30810c69 100644 --- a/kmix/kmixapplet.cpp +++ b/kmix/kmixapplet.cpp @@ -4,6 +4,7 @@ * * Copyright (C) 2000 Stefan Schimanski * Copyright (C) 2004 Christian Esken + * Copyright (C) 2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -226,7 +227,7 @@ KMixApplet::~KMixApplet() s_instCount--; if ( s_instCount == 0) { - MixerToolBox::deinitMixer(); + MixerToolBox::deinitMixer(Mixer::mixers()); } */ } diff --git a/kmix/kmixctrl.cpp b/kmix/kmixctrl.cpp index 9f6188c7..4cfa1281 100644 --- a/kmix/kmixctrl.cpp +++ b/kmix/kmixctrl.cpp @@ -2,6 +2,7 @@ * kmixctrl - kmix volume save/restore utility * * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de> + * Copyright (C) 2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -84,7 +85,7 @@ extern "C" KDE_EXPORT int kdemain(int argc, char *argv[]) mixer->volumeSave( TDEGlobal::config() ); } - MixerToolBox::deinitMixer(); + MixerToolBox::deinitMixer(Mixer::mixers()); return 0; } diff --git a/kmix/mixer.cpp b/kmix/mixer.cpp index 150b196d..b7bd2899 100644 --- a/kmix/mixer.cpp +++ b/kmix/mixer.cpp @@ -4,6 +4,7 @@ * * Copyright (C) 1996-2004 Christian Esken - esken@kde.org * 2002 Helio Chissini de Castro - helio@conectiva.com.br + * Copyright (C) 2017,2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -108,6 +109,7 @@ Mixer::~Mixer() { // Close the mixer. This might also free memory, depending on the called backend method close(); delete _pollingTimer; + delete _mixerBackend; } void Mixer::volumeSave( TDEConfig *config ) diff --git a/kmix/mixer.h b/kmix/mixer.h index 2ec99a1e..40d303dd 100644 --- a/kmix/mixer.h +++ b/kmix/mixer.h @@ -6,6 +6,7 @@ * 1996-2000 Christian Esken * Sven Fischer * 2002 - Helio Chissini de Castro + * Copyright (C) 2017 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/kmix/mixer_alsa9.cpp b/kmix/mixer_alsa9.cpp index 22303b43..29424226 100644 --- a/kmix/mixer_alsa9.cpp +++ b/kmix/mixer_alsa9.cpp @@ -6,6 +6,7 @@ * * Copyright (C) 2002 Helio Chissini de Castro * 2004 Christian Esken + * Copyright (C) 2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -107,11 +108,7 @@ Mixer_ALSA::open() snd_ctl_t *ctl_handle; snd_ctl_card_info_t *hw_info; - snd_ctl_card_info_alloca(&hw_info); - - snd_mixer_elem_t *elem; - snd_mixer_selem_id_t *sid; - snd_mixer_selem_id_alloca( &sid ); + snd_ctl_card_info_malloc(&hw_info); // Card information if ((unsigned)m_devnum > 31) m_devnum = -1; @@ -126,6 +123,7 @@ Mixer_ALSA::open() { kdDebug(67100) << probeMessage << "not found: snd_ctl_open err=" << snd_strerror(err) << endl; //_stateMessage = errorText( Mixer::ERR_NODEV ); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } @@ -134,6 +132,7 @@ Mixer_ALSA::open() kdDebug(67100) << probeMessage << "not found: snd_ctl_card_info err=" << snd_strerror(err) << endl; //_stateMessage = errorText( Mixer::ERR_READ ); snd_ctl_close( ctl_handle ); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_READ; } @@ -155,6 +154,7 @@ Mixer_ALSA::open() kdDebug(67100) << probeMessage << "not found: snd_mixer_open err=" << snd_strerror(err) << endl; //errormsg( Mixer::ERR_NODEV ); _handle = 0; + snd_ctl_card_info_free(hw_info); return Mixer::ERR_NODEV; // if we cannot open the mixer, we have no devices } //kdDebug(67100) << "OUT Mixer_ALSA snd_mixer_open()" << endl; @@ -163,6 +163,8 @@ Mixer_ALSA::open() { kdDebug(67100) << probeMessage << "not found: snd_mixer_attach err=" << snd_strerror(err) << endl; //errormsg( Mixer::ERR_PERM ); + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } @@ -170,6 +172,8 @@ Mixer_ALSA::open() { kdDebug(67100) << probeMessage << "not found: snd_mixer_selem_register err=" << snd_strerror(err) << endl; //errormsg( Mixer::ERR_READ ); + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_READ; } @@ -178,11 +182,15 @@ Mixer_ALSA::open() kdDebug(67100) << probeMessage << "not found: snd_mixer_load err=" << snd_strerror(err) << endl; //errormsg( Mixer::ERR_READ ); close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_READ; } kdDebug(67100) << probeMessage << "found" << endl; + snd_mixer_elem_t *elem; + snd_mixer_selem_id_t *sid; + unsigned int mixerIdx = 0; for ( elem = snd_mixer_first_elem( _handle ); elem; elem = snd_mixer_elem_next( elem ), mixerIdx++ ) { @@ -195,8 +203,7 @@ Mixer_ALSA::open() continue; } - - sid = (snd_mixer_selem_id_t*)malloc(snd_mixer_selem_id_sizeof()); // I believe *we* must malloc it for ourself + snd_mixer_selem_id_malloc( &sid ); snd_mixer_selem_get_id( elem, sid ); bool canPlay = false; @@ -359,6 +366,8 @@ Mixer_ALSA::open() } if( !found ) { + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_INCOMPATIBLESET; } } // !virginOpen @@ -372,6 +381,8 @@ Mixer_ALSA::open() ***************************************************************************************/ if ( !validDevice ) { + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_NODEV; } @@ -385,6 +396,8 @@ Mixer_ALSA::open() /* setup for select on stdin and the mixer fd */ if ((m_count = snd_mixer_poll_descriptors_count(_handle)) < 0) { kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << m_count << "\n"; + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } @@ -393,19 +406,27 @@ Mixer_ALSA::open() m_fds = (struct pollfd*)calloc(m_count, sizeof(struct pollfd)); if (m_fds == NULL) { kdDebug(67100) << "Mixer_ALSA::poll() , calloc() = null" << "\n"; + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } m_fds->events = POLLIN; if ((err = snd_mixer_poll_descriptors(_handle, m_fds, m_count)) < 0) { kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << err << "\n"; + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } if (err != m_count) { kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << err << " m_count=" << m_count << "\n"; + close(); + snd_ctl_card_info_free(hw_info); return Mixer::ERR_OPEN; } + snd_ctl_card_info_free(hw_info); + return 0; } @@ -462,6 +483,10 @@ Mixer_ALSA::close() } + for(int iMS = 0; iMS < mixer_sid_list.count(); iMS++) + if(mixer_sid_list[iMS]) + snd_mixer_selem_id_free(mixer_sid_list[iMS]); + mixer_elem_list.clear(); mixer_sid_list.clear(); m_mixDevices.clear(); diff --git a/kmix/mixertoolbox.cpp b/kmix/mixertoolbox.cpp index 4a19673b..f91fe9ad 100644 --- a/kmix/mixertoolbox.cpp +++ b/kmix/mixertoolbox.cpp @@ -3,6 +3,7 @@ * * * Copyright (C) 2004 Christian Esken + * Copyright (C) 2017,2020 Roman Savochenko * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -64,7 +65,7 @@ extern MixerFactory g_mixerFactories[]; * 'true' means to scan all backends. 'false' means: After scanning the * current backend the next backend is only scanned if no Mixers were found yet. */ -void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQString& ref_hwInfoString) +void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQString& ref_hwInfoString, bool isLight) { //kdDebug(67100) << "IN MixerToolBox::initMixer()"< &mixers, bool multiDriverMode, TQS // approach doesn't work for the one or other user. int devNumMax = 19; getDevIteratorFunc* f = g_mixerFactories[drv].getDevIterator; - for( DevIterator* I = f ? f() : new DevIterator(); !I->end(); I->next()) + DevIterator *I = f ? f() : new DevIterator(); + for( ; !I->end(); I->next()) { int dev = I->getdev(); Mixer *mixer = new Mixer( drv, dev ); if ( mixer->isValid() ) { - mixer->open(); + if(!isLight) mixer->open(); Mixer* m; if (dev >= 0) { for (m = mixers.first(); m; m = mixers.next()) @@ -131,7 +133,7 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS if (mixer->devnum() == m->devnum()) #endif break; - if (m) continue; + if (m) { delete mixer; continue; } } mixers.append( mixer ); // Count mixer nums for every mixer name to identify mixers with equal names. @@ -145,6 +147,7 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS * %2, the mixer name, is typically coming from an OS driver. It could contain colons. * %3, the mixer number, is a number: it does not contain colons. */ + if(!isLight) { TQString mixerName = mixer->mixerName(); mixerName.replace(":","_"); TQString primaryKeyOfMixer = TQString("%1::%2:%3") @@ -158,6 +161,7 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS primaryKeyOfMixer.replace("=","_"); mixer->setID(primaryKeyOfMixer); + } } // valid else @@ -174,7 +178,7 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS else { // In No-multiDriver-mode we only need to check after we reached devNumMax if ( dev == devNumMax ) { - if ( Mixer::mixers().count() != 0 ) { + if ( mixers.count() != 0 ) { // highest device number of driver and a Mixer => finished autodetectionFinished = true; } @@ -182,7 +186,7 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS } // !multiDriver // append driverName (used drivers) - if ( !drvInfoAppended ) + if ( !drvInfoAppended && !isLight ) { drvInfoAppended = true; TQString driverName = Mixer::driverName(drv); @@ -211,9 +215,10 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS } // !multipleDriversActive } // loop over sound card devices of current driver + delete I; } // loop over soundcard drivers - if (Mixer::masterCard() == 0) + if (Mixer::masterCard() == 0 && !isLight) { // We have no master card yet. This actually only happens when there was // not one defined in the kmixrc. @@ -252,15 +257,15 @@ void MixerToolBox::initMixer(TQPtrList &mixers, bool multiDriverMode, TQS /* * Clean up and free all ressources of all found Mixers, which were found in the initMixer() call */ -void MixerToolBox::deinitMixer() +void MixerToolBox::deinitMixer(TQPtrList &mixers) { //kdDebug(67100) << "IN MixerToolBox::deinitMixer()"<close(); - Mixer::mixers().remove(mixer); + mixers.remove(mixer); delete mixer; } // kdDebug(67100) << "OUT MixerToolBox::deinitMixer()"< + * Copyright (C) 2020 Roman Savochenko + * + * 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 MIXERTOOLBOX_H #define MIXERTOOLBOX_H @@ -14,8 +36,8 @@ class Mixer; */ class MixerToolBox { public: - static void initMixer(TQPtrList&, bool, TQString&); - static void deinitMixer(); + static void initMixer(TQPtrList&, bool, TQString&, bool isLight = false); + static void deinitMixer(TQPtrList&); };