diff --git a/CMakeLists.txt b/CMakeLists.txt index e494ced..2505696 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,49 +1,54 @@ project(plasma-volume-control) cmake_minimum_required(VERSION 2.8.12) set(PROJECT_VERSION "5.13.3") set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.7.0") set(KF5_MIN_VERSION "5.30.0") find_package(ECM 1.8.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/) add_definitions(-DTRANSLATION_DOMAIN=\"kcm_pulseaudio\") include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMOptionalAddSubdirectory) include(FindPkgConfig) -pkg_check_modules(GCONF REQUIRED gconf-2.0) -pkg_check_modules(GOBJECT REQUIRED gobject-2.0) +pkg_check_modules(GCONF gconf-2.0) +pkg_check_modules(GOBJECT gobject-2.0) +if (GCONF_FOUND AND GOBJECT_FOUND) + set(HAVE_GCONF TRUE) +endif() find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Gui DBus Widgets Quick ) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons Declarative DocTools GlobalAccel I18n Plasma ) find_package(PulseAudio 5.0.0 REQUIRED) find_package(Canberra REQUIRED) find_package(GLIB2 REQUIRED) +configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) + add_subdirectory(applet) add_subdirectory(src) add_subdirectory(data) add_subdirectory(doc) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/config.h.cmake b/config.h.cmake new file mode 100644 index 0000000..1643e50 --- /dev/null +++ b/config.h.cmake @@ -0,0 +1,3 @@ +/* config.h. Generated by cmake from config.h.cmake */ + +#cmakedefine01 HAVE_GCONF diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e6cddfc..09d108c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,59 +1,67 @@ -include_directories(${PULSEAUDIO_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} ${GCONF_INCLUDE_DIRS} - ${GOBJECT_INCLUDE_DIRS}) +include_directories(${PULSEAUDIO_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR}) set(cpp_SRCS card.cpp client.cpp context.cpp device.cpp maps.cpp operation.cpp port.cpp profile.cpp pulseaudio.cpp pulseobject.cpp sink.cpp sinkinput.cpp modulemanager.cpp - gconfitem.cpp source.cpp sourceoutput.cpp stream.cpp volumeobject.cpp debug.cpp server.cpp streamrestore.cpp module.cpp qml/globalactioncollection.cpp qml/plugin.cpp qml/volumeosd.cpp qml/volumefeedback.cpp ) set(qml_SRCS qml/qmldir qml/PulseObjectFilterModel.qml ) set_property(SOURCE qml/dbus/osdService.xml APPEND PROPERTY CLASSNAME OsdServiceInterface) qt5_add_dbus_interface(dbus_SRCS qml/dbus/osdService.xml osdservice) +if (HAVE_GCONF) + include_directories(${GCONF_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS}) + set(cpp_SRCS ${cpp_SRCS} gconfitem.cpp) +endif() + add_library(plasma-volume-declarative SHARED ${dbus_SRCS} ${cpp_SRCS} ${qml_SRCS}) target_link_libraries(plasma-volume-declarative Qt5::Core Qt5::Gui Qt5::DBus Qt5::Quick KF5::GlobalAccel ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} - ${GCONF_LDFLAGS} - ${GOBJECT_LDFLAGS} ${CANBERRA_LIBRARIES} ) +if (HAVE_GCONF) + target_link_libraries(plasma-volume-declarative + ${GCONF_LDFLAGS} + ${GOBJECT_LDFLAGS} + ) +endif() + set(PRIVATE_QML_INSTALL_DIR ${QML_INSTALL_DIR}/org/kde/plasma/private/volume) install(TARGETS plasma-volume-declarative DESTINATION ${PRIVATE_QML_INSTALL_DIR}) install(FILES ${qml_SRCS} DESTINATION ${PRIVATE_QML_INSTALL_DIR}) add_subdirectory(kcm) diff --git a/src/kcm/package/contents/ui/Advanced.qml b/src/kcm/package/contents/ui/Advanced.qml index b305cf1..0cd9eb9 100644 --- a/src/kcm/package/contents/ui/Advanced.qml +++ b/src/kcm/package/contents/ui/Advanced.qml @@ -1,94 +1,97 @@ /* Copyright 2014-2015 Harald Sitter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import QtQuick 2.0 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.3 import org.kde.plasma.private.volume 0.1 ScrollView { id: scrollView ColumnLayout { Component.onCompleted: { // Normal binding causes binding loops width = Qt.binding(function() { return scrollView.viewport.width; }); } Header { Layout.fillWidth: true enabled: view.count > 0 text: i18n("Device Profiles") disabledText: i18nc("@label", "No Device Profiles Available") } ListView { id: view Layout.fillWidth: true Layout.preferredHeight: contentHeight Layout.margins: units.gridUnit / 2 interactive: false spacing: units.smallSpacing * 2 model: CardModel {} delegate: CardListItem {} } Header { Layout.fillWidth: true text: i18n("Advanced Output Configuration") + visible: moduleManager.settingsSupported } ModuleManager { id: moduleManager } CheckBox { Layout.fillWidth: true Layout.topMargin: units.smallSpacing Layout.leftMargin: units.gridUnit / 2 Layout.rightMargin: units.gridUnit / 2 text: i18n("Add virtual output device for simultaneous output on all local sound cards") checked: moduleManager.combineSinks onCheckedChanged: moduleManager.combineSinks = checked; enabled: moduleManager.loadedModules.indexOf("module-gconf") != -1 + visible: moduleManager.settingsSupported } CheckBox { Layout.fillWidth: true Layout.leftMargin: units.gridUnit / 2 Layout.rightMargin: units.gridUnit / 2 text: i18n("Automatically switch all running streams when a new output becomes available") checked: moduleManager.switchOnConnect onCheckedChanged: moduleManager.switchOnConnect = checked; enabled: moduleManager.loadedModules.indexOf("module-gconf") != -1 + visible: moduleManager.settingsSupported } Label { Layout.alignment: Qt.AlignHCenter enabled: false font.italic: true text: i18n("Requires 'module-gconf' PulseAudio module") - visible: moduleManager.loadedModules.indexOf("module-gconf") == -1 + visible: moduleManager.settingsSupported && moduleManager.loadedModules.indexOf("module-gconf") == -1 } } } diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index 635adc8..5245ac5 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -1,138 +1,167 @@ /* Copyright 2016 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "modulemanager.h" #include "module.h" +#include "../config.h" +#if HAVE_GCONF +#include "gconfitem.h" #define PA_GCONF_ROOT "/system/pulseaudio" #define PA_GCONF_PATH_MODULES PA_GCONF_ROOT"/modules" - -#include "gconfitem.h" +#endif #include namespace QPulseAudio { +#if HAVE_GCONF class GConfModule : public GConfItem { - Q_OBJECT public: GConfModule(const QString &configName, const QString &moduleName, QObject *parent); bool isEnabled() const; void setEnabled(bool enabled, const QVariant &args=QVariant()); private: QString m_moduleName; }; GConfModule::GConfModule(const QString &configName, const QString &moduleName, QObject *parent) : GConfItem(QStringLiteral(PA_GCONF_PATH_MODULES"/") + configName, parent), m_moduleName(moduleName) { } bool GConfModule::isEnabled() const { return value(QStringLiteral("enabled")).toBool(); } void GConfModule::setEnabled(bool enabled, const QVariant &args) { set(QStringLiteral("locked"), true); if (enabled) { set(QStringLiteral("name0"), m_moduleName); set(QStringLiteral("args0"), args); set(QStringLiteral("enabled"), true); } else { set(QStringLiteral("enabled"), false); } set(QStringLiteral("locked"), false); } +#endif ModuleManager::ModuleManager(QObject *parent) : - QObject(parent), - m_combineSinks(new GConfModule(QStringLiteral("combine"), QStringLiteral("module-combine"), this)), - m_switchOnConnect(new GConfModule(QStringLiteral("switch-on-connect"), QStringLiteral("module-switch-on-connect"), this)), - m_deviceManager(new GConfModule(QStringLiteral("device-manager"), QStringLiteral("module-device-manager"), this)) + QObject(parent) { +#if HAVE_GCONF + m_combineSinks = new GConfModule(QStringLiteral("combine"), QStringLiteral("module-combine"), this); + m_switchOnConnect = new GConfModule(QStringLiteral("switch-on-connect"), QStringLiteral("module-switch-on-connect"), this); + m_deviceManager = new GConfModule(QStringLiteral("device-manager"), QStringLiteral("module-device-manager"), this); + connect(m_combineSinks, &GConfItem::subtreeChanged, this, &ModuleManager::combineSinksChanged); connect(m_switchOnConnect, &GConfItem::subtreeChanged, this, &ModuleManager::switchOnConnectChanged); connect(m_deviceManager, &GConfItem::subtreeChanged, this, &ModuleManager::switchOnConnectChanged); +#endif QTimer *updateModulesTimer = new QTimer(this); updateModulesTimer->setInterval(500); updateModulesTimer->setSingleShot(true); connect(updateModulesTimer, &QTimer::timeout, this, &ModuleManager::updateLoadedModules); connect(&Context::instance()->modules(), &MapBaseQObject::added, updateModulesTimer, static_cast(&QTimer::start)); connect(&Context::instance()->modules(), &MapBaseQObject::removed, updateModulesTimer, static_cast(&QTimer::start)); updateLoadedModules(); } ModuleManager::~ModuleManager() { }; +bool ModuleManager::settingsSupported() const +{ +#if HAVE_GCONF + return true; +#else + return false; +#endif +} + bool ModuleManager::combineSinks() const { +#if HAVE_GCONF return m_combineSinks->isEnabled(); +#else + return false; +#endif } void ModuleManager::setCombineSinks(bool combineSinks) { +#if HAVE_GCONF m_combineSinks->setEnabled(combineSinks); +#else + Q_UNUSED(combineSinks) +#endif } bool ModuleManager::switchOnConnect() const { //switch on connect and device-manager do the same task. Only one should be enabled //Note on the first run m_deviceManager will appear to be disabled even though it's actually running //because there is no gconf entry, however m_switchOnConnect will only exist if set by Plasma PA //hence only check this entry +#if HAVE_GCONF return m_switchOnConnect->isEnabled() ; +#else + return false; +#endif } void ModuleManager::setSwitchOnConnect(bool switchOnConnect) { +#if HAVE_GCONF m_deviceManager->setEnabled(!switchOnConnect); m_switchOnConnect->setEnabled(switchOnConnect); +#else + Q_UNUSED(switchOnConnect) +#endif } QStringList ModuleManager::loadedModules() const { return m_loadedModules; } void ModuleManager::updateLoadedModules() { m_loadedModules.clear(); const auto modules = Context::instance()->modules().data(); for (Module *module : modules) { m_loadedModules.append(module->name()); } Q_EMIT loadedModulesChanged(); } } - -#include "modulemanager.moc" diff --git a/src/modulemanager.h b/src/modulemanager.h index b8fcd0b..8108fe0 100644 --- a/src/modulemanager.h +++ b/src/modulemanager.h @@ -1,69 +1,72 @@ /* Copyright 2016 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef MODULEMANAGER_H #define MODULEMANAGER_H #include #include #include "context.h" // Properties need fully qualified classes even with pointers. #include "client.h" class GConfItem; namespace QPulseAudio { class GConfModule; class ModuleManager : public QObject { Q_OBJECT + Q_PROPERTY(bool settingsSupported READ settingsSupported CONSTANT) Q_PROPERTY(bool combineSinks READ combineSinks WRITE setCombineSinks NOTIFY combineSinksChanged) Q_PROPERTY(bool switchOnConnect READ switchOnConnect WRITE setSwitchOnConnect NOTIFY switchOnConnectChanged) Q_PROPERTY(QStringList loadedModules READ loadedModules NOTIFY loadedModulesChanged) public: ModuleManager(QObject *parent = nullptr); ~ModuleManager(); + + bool settingsSupported() const; bool combineSinks() const; void setCombineSinks(bool combineSinks); bool switchOnConnect() const; void setSwitchOnConnect(bool switchOnConnect); QStringList loadedModules() const; Q_SIGNALS: void combineSinksChanged(); void switchOnConnectChanged(); void loadedModulesChanged(); private: void updateLoadedModules(); GConfModule *m_combineSinks; GConfModule *m_switchOnConnect; GConfModule *m_deviceManager; QStringList m_loadedModules; }; } // QPulseAudio #endif // STREAM_H