File indexing completed on 2025-02-16 14:23:20
0001 /* 0002 SPDX-FileCopyrightText: 2016 David Edmundson <davidedmundson@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "modulemanager.h" 0008 #include "module.h" 0009 #include "server.h" 0010 0011 #include "gsettingsitem.h" 0012 #define PA_SETTINGS_PATH_MODULES "/org/freedesktop/pulseaudio/module-groups" 0013 0014 #include <QTimer> 0015 #include <chrono> 0016 0017 using namespace std::chrono_literals; 0018 0019 namespace QPulseAudio 0020 { 0021 class ConfigModule : public GSettingsItem 0022 { 0023 public: 0024 ConfigModule(const QString &configName, const QString &moduleName, QObject *parent); 0025 bool isEnabled() const; 0026 void setEnabled(bool enabled, const QVariant &args = QVariant()); 0027 0028 private: 0029 QString m_moduleName; 0030 }; 0031 0032 ConfigModule::ConfigModule(const QString &configName, const QString &moduleName, QObject *parent) 0033 : GSettingsItem(QStringLiteral(PA_SETTINGS_PATH_MODULES "/") + configName + QStringLiteral("/"), parent) 0034 , m_moduleName(moduleName) 0035 { 0036 } 0037 0038 bool ConfigModule::isEnabled() const 0039 { 0040 return value(QStringLiteral("enabled")).toBool(); 0041 } 0042 0043 void ConfigModule::setEnabled(bool enabled, const QVariant &args) 0044 { 0045 set(QStringLiteral("locked"), true); 0046 0047 if (enabled) { 0048 set(QStringLiteral("name0"), m_moduleName); 0049 set(QStringLiteral("args0"), args); 0050 set(QStringLiteral("enabled"), true); 0051 } else { 0052 set(QStringLiteral("enabled"), false); 0053 } 0054 set(QStringLiteral("locked"), false); 0055 } 0056 0057 ModuleManager::ModuleManager(QObject *parent) 0058 : QObject(parent) 0059 { 0060 m_combineSinks = new ConfigModule(QStringLiteral("combine"), QStringLiteral("module-combine-sink"), this); 0061 m_switchOnConnect = new ConfigModule(QStringLiteral("switch-on-connect"), QStringLiteral("module-switch-on-connect"), this); 0062 m_deviceManager = new ConfigModule(QStringLiteral("device-manager"), QStringLiteral("module-device-manager"), this); 0063 0064 connect(m_combineSinks, &ConfigModule::subtreeChanged, this, &ModuleManager::combineSinksChanged); 0065 connect(m_switchOnConnect, &ConfigModule::subtreeChanged, this, &ModuleManager::switchOnConnectChanged); 0066 connect(m_deviceManager, &ConfigModule::subtreeChanged, this, &ModuleManager::switchOnConnectChanged); 0067 0068 connect(Context::instance()->server(), &Server::updated, this, &ModuleManager::serverUpdated); 0069 0070 auto *updateModulesTimer = new QTimer(this); 0071 updateModulesTimer->setInterval(500ms); 0072 updateModulesTimer->setSingleShot(true); 0073 connect(updateModulesTimer, &QTimer::timeout, this, &ModuleManager::updateLoadedModules); 0074 connect(&Context::instance()->modules(), &MapBaseQObject::added, updateModulesTimer, static_cast<void (QTimer::*)(void)>(&QTimer::start)); 0075 connect(&Context::instance()->modules(), &MapBaseQObject::removed, updateModulesTimer, static_cast<void (QTimer::*)(void)>(&QTimer::start)); 0076 updateLoadedModules(); 0077 } 0078 0079 ModuleManager::~ModuleManager() = default; 0080 ; 0081 0082 bool ModuleManager::settingsSupported() const 0083 { 0084 // PipeWire does not (yet) have support for module-switch-on-connect and module-combine-sink 0085 // Also switching streams is the default there 0086 // TODO Check whether there is a PipeWire-specific way to do these 0087 return !Context::instance()->server()->isPipeWire(); 0088 } 0089 0090 bool ModuleManager::combineSinks() const 0091 { 0092 return m_combineSinks->isEnabled(); 0093 } 0094 0095 void ModuleManager::setCombineSinks(bool combineSinks) 0096 { 0097 m_combineSinks->setEnabled(combineSinks); 0098 } 0099 0100 bool ModuleManager::switchOnConnect() const 0101 { 0102 // switch on connect and device-manager do the same task. Only one should be enabled 0103 0104 // Note on the first run m_deviceManager will appear to be disabled even though it's actually running 0105 // because there is no gconf entry, however m_switchOnConnect will only exist if set by Plasma PA 0106 // hence only check this entry 0107 return m_switchOnConnect->isEnabled(); 0108 } 0109 0110 void ModuleManager::setSwitchOnConnect(bool switchOnConnect) 0111 { 0112 m_deviceManager->setEnabled(!switchOnConnect); 0113 m_switchOnConnect->setEnabled(switchOnConnect); 0114 } 0115 0116 QStringList ModuleManager::loadedModules() const 0117 { 0118 return m_loadedModules; 0119 } 0120 0121 void ModuleManager::updateLoadedModules() 0122 { 0123 m_loadedModules.clear(); 0124 const auto modules = Context::instance()->modules().data(); 0125 for (Module *module : modules) { 0126 m_loadedModules.append(module->name()); 0127 } 0128 Q_EMIT loadedModulesChanged(); 0129 } 0130 0131 bool ModuleManager::configModuleLoaded() const 0132 { 0133 return m_loadedModules.contains(configModuleName()); 0134 } 0135 0136 QString ModuleManager::configModuleName() const 0137 { 0138 return QStringLiteral("module-gsettings"); 0139 } 0140 }