File indexing completed on 2022-09-27 14:35:03

0001 /*
0002  * KMix -- KDE's full featured mini mixer
0003  *
0004  * Copyright 1996-2000 Christian Esken <esken@kde.org>
0005  * Copyright 2000-2003 Christian Esken <esken@kde.org>, Stefan Schimanski <1Stein@gmx.de>
0006  * Copyright 2002-2007 Christian Esken <esken@kde.org>, Helio Chissini de Castro <helio@conectiva.com.br>
0007  *
0008  * This program is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU Library General Public
0010  * License as published by the Free Software Foundation; either
0011  * version 2 of the License, or (at your option) any later version.
0012  *
0013  * This program is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  * Library General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU Library General Public
0019  * License along with this program; if not, write to the Free
0020  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0021  */
0022 
0023 #include "kmixd.h"
0024 
0025 #include <kconfig.h>
0026 #include <klocalizedstring.h>
0027 #include <kpluginfactory.h>
0028 #include <kpluginloader.h> 
0029 
0030 // KMix
0031 #include "core/mixertoolbox.h"
0032 #include "core/kmixdevicemanager.h"
0033 #include "core/mixer.h"
0034 #include "settings.h"
0035 
0036 
0037 K_PLUGIN_FACTORY_WITH_JSON(KMixDFactory,
0038                            "kmixd.json",
0039                            registerPlugin<KMixD>();)
0040 
0041 
0042 /* KMixD
0043  * Constructs a mixer window (KMix main window)
0044  */
0045 KMixD::KMixD(QObject* parent, const QList<QVariant>&) :
0046    KDEDModule(parent),
0047    m_multiDriverMode (false) // -<- I never-ever want the multi-drivermode to be activated by accident
0048 {
0049     setObjectName( QStringLiteral("KMixD" ));
0050     qCDebug(KMIX_LOG) << "kmixd: Triggering delayed initialization";
0051     QTimer::singleShot( 3000, this, SLOT(delayedInitialization()));
0052 }
0053 
0054 /**
0055  * This is called by a singleShot timer. Reason is that KMixD seems to "collide" with other applications
0056  * on DBUS, likely creating deadlocks. See Bug 317926 for that. By artificially delaying initialization,
0057  * KMixD gets hopefully out of the way of the other applications, avoiding these deadlocks. A small delay
0058  * should also not harm too much, as apps using the Mixer DBUS calls on KMixD must be prepared that the
0059  * interface is not available right when they start.
0060  */
0061 void KMixD::delayedInitialization()
0062 {
0063     qCDebug(KMIX_LOG) << "Delayed initialization running now";
0064    //initActions(); // init actions first, so we can use them in the loadConfig() already
0065    loadConfig(); // Load config before initMixer(), e.g. due to "MultiDriver" keyword
0066    MixerToolBox::initMixer(m_multiDriverMode, m_backendFilter, true);
0067 
0068    KMixDeviceManager *theKMixDeviceManager = KMixDeviceManager::instance();
0069    connect(theKMixDeviceManager, &KMixDeviceManager::plugged, this, &KMixD::plugged);
0070    connect(theKMixDeviceManager, &KMixDeviceManager::unplugged, this, &KMixD::unplugged);
0071    theKMixDeviceManager->initHotplug();
0072 
0073    qCDebug(KMIX_LOG) << "Delayed initialization done";
0074 }
0075 
0076 
0077 KMixD::~KMixD()
0078 {
0079    MixerToolBox::deinitMixer();
0080 }
0081 
0082 
0083 
0084 void KMixD::saveConfig()
0085 {
0086    qCDebug(KMIX_LOG) << "About to save config";
0087    saveBaseConfig();
0088   // saveVolumes(); // -<- removed from kmixd, as it is possibly a bad idea if both kmix and kmixd write the same config "kmixctrlrc"
0089 #ifdef __GNUC_
0090 #warn We must Sync here, or we will lose configuration data. The reson for that is unknown.
0091 #endif
0092 
0093    qCDebug(KMIX_LOG) << "Saved config ... now syncing explicitly";
0094    Settings::self()->save();
0095    qCDebug(KMIX_LOG) << "Saved config ... sync finished";
0096 }
0097 
0098 void KMixD::saveBaseConfig()
0099 {
0100    qCDebug(KMIX_LOG) << "About to save config (Base)";
0101 
0102    Settings::setConfigVersion(KMIX_CONFIG_VERSION);
0103    const Mixer *mixerMasterCard = Mixer::getGlobalMasterMixer();
0104    if (mixerMasterCard!=nullptr) Settings::setMasterMixer(mixerMasterCard->id());
0105    shared_ptr<MixDevice> mdMaster = Mixer::getGlobalMasterMD();
0106    if (mdMaster) Settings::setMasterMixerDevice(mdMaster->id());
0107    Settings::setMixerIgnoreExpression(MixerToolBox::mixerIgnoreExpression());
0108    qCDebug(KMIX_LOG) << "Config (Base) saving done";
0109 }
0110 
0111 void KMixD::loadConfig()
0112 {
0113    loadBaseConfig();
0114 }
0115 
0116 void KMixD::loadBaseConfig()
0117 {
0118     m_multiDriverMode = Settings::multiDriver();
0119     QString mixerMasterCard = Settings::masterMixer();
0120     QString masterDev = Settings::masterMixerDevice();
0121     Mixer::setGlobalMaster(mixerMasterCard, masterDev, true);
0122     QString mixerIgnoreExpression = Settings::mixerIgnoreExpression();
0123     if (!mixerIgnoreExpression.isEmpty()) MixerToolBox::setMixerIgnoreExpression(mixerIgnoreExpression);
0124 
0125     m_backendFilter = Settings::backends();
0126     MixerToolBox::setMixerIgnoreExpression(mixerIgnoreExpression);
0127 }
0128 
0129 
0130 void KMixD::plugged(const char *driverName, const QString &udi, int dev)
0131 {
0132     qCDebug(KMIX_LOG) << "dev" << dev << "driver" << driverName << "udi" << udi;
0133 
0134     Mixer *mixer = new Mixer(QString::fromLocal8Bit(driverName), dev);
0135     if (mixer!=nullptr)
0136     {
0137         qCDebug(KMIX_LOG) << "adding mixer" << mixer->id() << mixer->readableName();
0138         MixerToolBox::possiblyAddMixer(mixer);
0139     }
0140 }
0141 
0142 
0143 void KMixD::unplugged(const QString &udi)
0144 {
0145     qCDebug(KMIX_LOG) << "udi" << udi;
0146 
0147 //     qCDebug(KMIX_LOG) << "Unplugged: udi=" <<udi << "\n";
0148     for (int i=0; i<Mixer::mixers().count(); ++i) {
0149         Mixer *mixer = (Mixer::mixers())[i];
0150 //         qCDebug(KMIX_LOG) << "Try Match with:" << mixer->udi() << "\n";
0151         if (mixer->udi() == udi ) {
0152             qCDebug(KMIX_LOG) << "Unplugged Match: Removing udi=" <<udi << "\n";
0153             //KMixToolBox::notification("MasterFallback", "aaa");
0154             bool globalMasterMixerDestroyed = ( mixer == Mixer::getGlobalMasterMixer() );
0155 
0156             MixerToolBox::removeMixer(mixer);
0157             // Check whether the Global Master disappeared, and select a new one if necessary
0158             shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD();
0159             if ( globalMasterMixerDestroyed || md.get() == 0 ) {
0160                 // We don't know what the global master should be now.
0161                 // So lets play stupid, and just select the recommended master of the first device
0162                 if ( Mixer::mixers().count() > 0 ) {
0163                     shared_ptr<MixDevice> master = ((Mixer::mixers())[0])->getLocalMasterMD();
0164                     if ( master.get() != 0 ) {
0165                         QString localMaster = master->id();
0166                         Mixer::setGlobalMaster( ((Mixer::mixers())[0])->id(), localMaster, false);
0167 
0168                         QString text;
0169                         text = i18n("The soundcard containing the master device was unplugged. Changing to control %1 on card %2.",
0170                                 master->readableName(),
0171                                 ((Mixer::mixers())[0])->readableName()
0172                         );
0173 //                        KMixToolBox::notification("MasterFallback", text);
0174                     }
0175                 }
0176             }
0177             if ( Mixer::mixers().count() == 0 ) {
0178                 QString text;
0179                 text = i18n("The last soundcard was unplugged.");
0180 //                KMixToolBox::notification("MasterFallback", text);
0181             }
0182             break;
0183         }
0184     }
0185 
0186 }
0187 
0188 
0189 #include "kmixd.moc"