diff --git a/CMakeLists.txt b/CMakeLists.txt index bc2ecfc..6effc3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,97 @@ cmake_minimum_required(VERSION 3.0) project(PulseAudioQt VERSION 1.1.0) include(FeatureSummary) find_package(ECM 5.44.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://kde.org/products/frameworks/") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(GenerateExportHeader) include(CMakePackageConfigHelpers) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMQtDeclareLoggingCategory) include(ECMAddQch) +include(KDEClangFormat) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) # include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") ecm_setup_version(PROJECT VARIABLE_PREFIX PULSEAUDIOQT VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/pulseaudioqt_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5PulseAudioQtConfigVersion.cmake" SOVERSION 2) set(REQUIRED_QT_VERSION 5.10.0) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core Gui DBus) find_package(Qt5Test ${REQUIRED_QT_VERSION} CONFIG) set_package_properties(Qt5Test PROPERTIES DESCRIPTION "Autotests for PulseAudioQt" TYPE OPTIONAL) find_package(Qt5Qml ${REQUIRED_QT_VERSION} CONFIG) set_package_properties(Qt5Qml PROPERTIES DESCRIPTION "Tests for PulseAudioQt" TYPE OPTIONAL) find_package(Qt5Quick ${REQUIRED_QT_VERSION} CONFIG) set_package_properties(Qt5Quick PROPERTIES DESCRIPTION "Tests for PulseAudioQt" TYPE OPTIONAL) # create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5PulseAudioQt") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5PulseAudioQtConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5PulseAudioQtConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5PulseAudioQtConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5PulseAudioQtConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) find_package(PulseAudio 5.0.0 REQUIRED) find_package(GLIB2 REQUIRED) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ecm_install_po_files_as_qm(po) endif() add_subdirectory(src) if (BUILD_TESTING) add_subdirectory(tests) if(Qt5Test_FOUND) add_subdirectory(autotests) endif() endif() if (BUILD_QCH) ecm_install_qch_export( TARGETS KF5PulseAudioQt_QCH FILE KF5PulseAudioQtQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5PulseAudioQtQchTargets.cmake\")") endif() install(EXPORT KF5PulseAudioQtTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5PulseAudioQtTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pulseaudioqt_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) + +# add clang-format target for all our real source files +file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) +kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) diff --git a/autotests/mapstest.cpp b/autotests/mapstest.cpp index 6bc0862..9857de0 100644 --- a/autotests/mapstest.cpp +++ b/autotests/mapstest.cpp @@ -1,155 +1,155 @@ /* Copyright 2018 David Rosca 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 "mapstest.h" #include "maps.h" #include "module.h" -#include #include +#include using namespace PulseAudioQt; void MapsTest::initTestCase() { } void MapsTest::cleanupTestCase() { } static pa_module_info *module_info_new() { - pa_module_info *info = (pa_module_info*) calloc(1, sizeof(pa_module_info)); + pa_module_info *info = (pa_module_info *)calloc(1, sizeof(pa_module_info)); info->name = "name"; info->argument = "arg"; info->n_used = PA_INVALID_INDEX; info->proplist = pa_proplist_new(); return info; } static void module_info_free(pa_module_info *info) { pa_proplist_free(info->proplist); free(info); } void MapsTest::basicTest() { QObject p; ModuleMap map; pa_module_info *info = module_info_new(); info->index = 10; QCOMPARE(map.count(), 0); map.updateEntry(info, &p); QCOMPARE(map.count(), 1); map.updateEntry(info, &p); QCOMPARE(map.count(), 1); QObject *index10 = map.objectAt(0); QVERIFY(index10); QCOMPARE(map.indexOfObject(index10), 0); // Add 0 (10, 0) info->index = 0; map.updateEntry(info, &p); QCOMPARE(map.count(), 2); QCOMPARE(map.objectAt(0), index10); QObject *index0 = map.objectAt(1); QVERIFY(index0); QCOMPARE(map.indexOfObject(index0), 1); QCOMPARE(map.indexOfObject(index10), 0); // Add 4, 15 (10, 0, 4, 15) info->index = 4; map.updateEntry(info, &p); info->index = 15; map.updateEntry(info, &p); QCOMPARE(map.count(), 4); QCOMPARE(map.objectAt(0), index10); QCOMPARE(map.objectAt(1), index0); QObject *index4 = map.objectAt(2); QVERIFY(index4); QObject *index15 = map.objectAt(3); QVERIFY(index15); QCOMPARE(map.indexOfObject(index10), 0); QCOMPARE(map.indexOfObject(index0), 1); QCOMPARE(map.indexOfObject(index4), 2); QCOMPARE(map.indexOfObject(index15), 3); // Remove 4 (10, 0, 15) map.removeEntry(4); QCOMPARE(map.count(), 3); QCOMPARE(map.objectAt(0), index10); QCOMPARE(map.objectAt(1), index0); QCOMPARE(map.objectAt(2), index15); // Remove 0 (10, 15) map.removeEntry(0); QCOMPARE(map.count(), 2); QCOMPARE(map.objectAt(0), index10); QCOMPARE(map.objectAt(1), index15); // Remove 15 (10) map.removeEntry(15); QCOMPARE(map.count(), 1); QCOMPARE(map.objectAt(0), index10); // Remove last () map.removeEntry(10); QCOMPARE(map.count(), 0); module_info_free(info); } void MapsTest::pendingRemovalsTest() { QObject p; ModuleMap map; pa_module_info *info = module_info_new(); info->index = 10; QCOMPARE(map.count(), 0); // 10 is not in map, should set pending removal map.removeEntry(10); // 10 is in pending removals, this should eat it and not add it into map map.updateEntry(info, &p); QCOMPARE(map.count(), 0); // No more pending removals, this should add it map.updateEntry(info, &p); QCOMPARE(map.count(), 1); module_info_free(info); } QTEST_MAIN(MapsTest) diff --git a/src/card.cpp b/src/card.cpp index 7cff602..98013e7 100644 --- a/src/card.cpp +++ b/src/card.cpp @@ -1,134 +1,134 @@ /* Copyright 2014-2015 Harald Sitter 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 "card.h" #include "card_p.h" #include "debug.h" +#include "cardport.h" #include "context.h" +#include "profile_p.h" #include "pulseobject.h" #include "pulseobject_p.h" -#include "cardport.h" -#include "profile_p.h" namespace PulseAudioQt { - Card::Card(QObject *parent) : PulseObject(parent) , d(new CardPrivate(this)) { } -Card::~Card(){ +Card::~Card() +{ delete d; } -CardPrivate::CardPrivate(Card* q) +CardPrivate::CardPrivate(Card *q) : q(q) { } CardPrivate::~CardPrivate() { } void CardPrivate::update(const pa_card_info *info) { q->PulseObject::d->updatePulseObject(info); QString infoName = QString::fromUtf8(info->name); if (m_name != infoName) { m_name = infoName; Q_EMIT q->nameChanged(); } QStringList newProfiles; for (auto **it = info->profiles2; it && *it != nullptr; ++it) { const QString name = QString::fromUtf8((*it)->name); newProfiles << name; if (!m_profiles.contains(name)) { - m_profiles[name] = new Profile(q); + m_profiles[name] = new Profile(q); } Profile *profile = m_profiles[name]; profile->d->setInfo(*it); if (info->active_profile2 == *it) { m_activeProfileIndex = m_profiles.size() - 1; } } const QList profileKeys = m_profiles.keys(); for (const QString &profileKey : profileKeys) { if (!newProfiles.contains(profileKey)) { delete m_profiles.take(profileKey); } } Q_EMIT q->profilesChanged(); Q_EMIT q->activeProfileIndexChanged(); QStringList newPorts; for (auto **it = info->ports; it && *it != nullptr; ++it) { const QString name = QString::fromUtf8((*it)->name); newPorts << name; if (!m_ports.contains(name)) { - m_ports[name] = new CardPort(q); + m_ports[name] = new CardPort(q); } CardPort *port = m_ports[name]; port->update(*it); } const QList portKeys = m_ports.keys(); for (const QString &portKey : profileKeys) { if (!newPorts.contains(portKey)) { delete m_ports.take(portKey); } } Q_EMIT q->portsChanged(); } QString Card::name() const { return d->m_name; } -QVector Card::profiles() const +QVector Card::profiles() const { - return QVector::fromList(d->m_profiles.values()); + return QVector::fromList(d->m_profiles.values()); } quint32 Card::activeProfileIndex() const { return d->m_activeProfileIndex; } void Card::setActiveProfileIndex(quint32 profileIndex) { const Profile *profile = qobject_cast(profiles().at(profileIndex)); context()->setCardProfile(index(), profile->name()); } -QVector Card::ports() const +QVector Card::ports() const { - return QVector::fromList(d->m_ports.values()); + return QVector::fromList(d->m_ports.values()); } } // PulseAudioQt diff --git a/src/card.h b/src/card.h index 6869462..148ca6e 100644 --- a/src/card.h +++ b/src/card.h @@ -1,66 +1,65 @@ /* Copyright 2014-2015 Harald Sitter 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 CARD_H #define CARD_H #include "pulseobject.h" struct pa_card_info; namespace PulseAudioQt { - class CardPort; class Profile; class Card : public PulseObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) - Q_PROPERTY(QVector profiles READ profiles NOTIFY profilesChanged) + Q_PROPERTY(QVector profiles READ profiles NOTIFY profilesChanged) Q_PROPERTY(quint32 activeProfileIndex READ activeProfileIndex WRITE setActiveProfileIndex NOTIFY activeProfileIndexChanged) - Q_PROPERTY(QVector ports READ ports NOTIFY portsChanged) + Q_PROPERTY(QVector ports READ ports NOTIFY portsChanged) public: ~Card(); QString name() const; - QVector profiles() const; + QVector profiles() const; quint32 activeProfileIndex() const; void setActiveProfileIndex(quint32 profileIndex); - QVector ports() const; + QVector ports() const; Q_SIGNALS: void nameChanged(); void profilesChanged(); void activeProfileIndexChanged(); void portsChanged(); private: explicit Card(QObject *parent); class CardPrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // CARD_H diff --git a/src/card_p.h b/src/card_p.h index 239e5a7..f4d8553 100644 --- a/src/card_p.h +++ b/src/card_p.h @@ -1,51 +1,49 @@ /* Copyright 2018 Nicolas Fella 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 CARD_P_H #define CARD_P_H #include "card.h" -#include "profile.h" #include "cardport.h" -#include +#include "profile.h" #include +#include #include namespace PulseAudioQt { - class CardPrivate { - public: explicit CardPrivate(Card *q); virtual ~CardPrivate(); Card *q; void update(const pa_card_info *info); QString m_name; - QHash m_profiles; + QHash m_profiles; quint32 m_activeProfileIndex; - QHash m_ports; + QHash m_ports; }; } #endif diff --git a/src/cardport.cpp b/src/cardport.cpp index 4b6503a..2bcaba7 100644 --- a/src/cardport.cpp +++ b/src/cardport.cpp @@ -1,61 +1,59 @@ /* Copyright 2018 Nicolas Fella 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 "cardport.h" #include "port_p.h" namespace PulseAudioQt { - CardPort::CardPort(QObject *parent) : Port(parent) { } CardPort::~CardPort() { } void CardPort::update(const pa_card_port_info *info) { - Port::d->setInfo(info); m_properties.clear(); void *it = nullptr; while (const char *key = pa_proplist_iterate(info->proplist, &it)) { Q_ASSERT(key); const char *value = pa_proplist_gets(info->proplist, key); if (!value) { qCDebug(PULSEAUDIOQT) << "property" << key << "not a string"; continue; } Q_ASSERT(value); m_properties.insert(QString::fromUtf8(key), QString::fromUtf8(value)); } - Q_EMIT propertiesChanged(); + Q_EMIT propertiesChanged(); } QVariantMap CardPort::properties() const { return m_properties; } -} //PulseAudioQt +} // PulseAudioQt diff --git a/src/cardport.h b/src/cardport.h index 4566204..6757f84 100644 --- a/src/cardport.h +++ b/src/cardport.h @@ -1,54 +1,53 @@ /* Copyright 2018 Nicolas Fella 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 CARDPORT_H #define CARDPORT_H #include "port.h" -#include #include "debug.h" +#include #include namespace PulseAudioQt { - class CardPort : public Port { Q_OBJECT Q_PROPERTY(QVariantMap properties READ properties NOTIFY propertiesChanged) public: ~CardPort(); void update(const pa_card_port_info *info); QVariantMap properties() const; private: explicit CardPort(QObject *parent); QVariantMap m_properties; friend class CardPrivate; }; } // PulseAudioQt #endif diff --git a/src/client.cpp b/src/client.cpp index a88bec0..f1c5794 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,62 +1,61 @@ /* Copyright 2014-2015 Harald Sitter 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 "client.h" #include "client_p.h" #include "debug.h" #include "pulseobject_p.h" namespace PulseAudioQt { - Client::Client(QObject *parent) : PulseObject(parent) , d(new ClientPrivate(this)) { } ClientPrivate::ClientPrivate(Client *q) : q(q) { } Client::~Client() { delete d; } void ClientPrivate::update(const pa_client_info *info) { q->PulseObject::d->updatePulseObject(info); QString infoName = QString::fromUtf8(info->name); if (m_name != infoName) { m_name = infoName; Q_EMIT q->nameChanged(); } } QString Client::name() const { return d->m_name; } } // PulseAudioQt diff --git a/src/client.h b/src/client.h index 2dbef9d..99c96d2 100644 --- a/src/client.h +++ b/src/client.h @@ -1,54 +1,53 @@ /* Copyright 2014-2015 Harald Sitter 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 CLIENT_H #define CLIENT_H #include "kf5pulseaudioqt_export.h" #include "pulseobject.h" struct pa_client_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Client : public PulseObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) public: ~Client(); QString name() const; Q_SIGNALS: void nameChanged(); private: explicit Client(QObject *parent); class ClientPrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // CLIENT_H diff --git a/src/client_p.h b/src/client_p.h index 740d472..a3444bd 100644 --- a/src/client_p.h +++ b/src/client_p.h @@ -1,42 +1,41 @@ /* Copyright 2018 Nicolas Fella 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 CLIENT_P_H #define CLIENT_P_H #include "client.h" #include namespace PulseAudioQt { - class ClientPrivate { public: ClientPrivate(Client *q); void update(const pa_client_info *info); Client *q; QString m_name; }; } // PulseAudioQt #endif diff --git a/src/context.cpp b/src/context.cpp index 6d850ff..37aa429 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1,829 +1,761 @@ /* Copyright 2014-2015 Harald Sitter 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 "context.h" #include "server.h" -#include #include "debug.h" -#include -#include +#include #include +#include +#include #include "card.h" #include "client.h" +#include "module.h" #include "sink.h" #include "sinkinput.h" #include "source.h" #include "sourceoutput.h" #include "streamrestore.h" -#include "module.h" #include "context_p.h" -#include "streamrestore_p.h" #include "server_p.h" +#include "streamrestore_p.h" namespace PulseAudioQt { - Context *s_context = nullptr; qint64 normalVolume() { return PA_VOLUME_NORM; } qint64 minimumVolume() { return 0; } qint64 maximumVolume() { return (PA_VOLUME_NORM / 100.0) * 150; } static bool isGoodState(int eol) { if (eol < 0) { // Error return false; } if (eol > 0) { // End of callback chain return false; } return true; } // -------------------------- static void sink_cb(pa_context *context, const pa_sink_info *info, int eol, void *data) { if (!isGoodState(eol)) return; Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->sinkCallback(info); + static_cast(data)->sinkCallback(info); } static void sink_input_callback(pa_context *context, const pa_sink_input_info *info, int eol, void *data) { if (!isGoodState(eol)) return; // pulsesink probe is used by gst-pulse only to query sink formats (not for playback) if (qstrcmp(info->name, "pulsesink probe") == 0) { return; } if (const char *id = pa_proplist_gets(info->proplist, "module-stream-restore.id")) { if (qstrcmp(id, "sink-input-by-media-role:event") == 0) { qCDebug(PULSEAUDIOQT) << "Ignoring event role sink input."; return; } } Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->sinkInputCallback(info); + static_cast(data)->sinkInputCallback(info); } static void source_cb(pa_context *context, const pa_source_info *info, int eol, void *data) { if (!isGoodState(eol)) return; // FIXME: This forces excluding monitors if (info->monitor_of_sink != PA_INVALID_INDEX) return; Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->sourceCallback(info); + static_cast(data)->sourceCallback(info); } static void source_output_cb(pa_context *context, const pa_source_output_info *info, int eol, void *data) { if (!isGoodState(eol)) return; // FIXME: This forces excluding these apps if (const char *app = pa_proplist_gets(info->proplist, PA_PROP_APPLICATION_ID)) { - if (strcmp(app, "org.PulseAudio.pavucontrol") == 0 - || strcmp(app, "org.gnome.VolumeControl") == 0 - || strcmp(app, "org.kde.kmixd") == 0) + if (strcmp(app, "org.PulseAudio.pavucontrol") == 0 || strcmp(app, "org.gnome.VolumeControl") == 0 || strcmp(app, "org.kde.kmixd") == 0) return; } Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->sourceOutputCallback(info); + static_cast(data)->sourceOutputCallback(info); } static void client_cb(pa_context *context, const pa_client_info *info, int eol, void *data) { if (!isGoodState(eol)) return; Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->clientCallback(info); + static_cast(data)->clientCallback(info); } static void card_cb(pa_context *context, const pa_card_info *info, int eol, void *data) { if (!isGoodState(eol)) return; Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->cardCallback(info); + static_cast(data)->cardCallback(info); } static void module_info_list_cb(pa_context *context, const pa_module_info *info, int eol, void *data) { if (!isGoodState(eol)) return; Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->moduleCallback(info); + static_cast(data)->moduleCallback(info); } static void server_cb(pa_context *context, const pa_server_info *info, void *data) { Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->serverCallback(info); + static_cast(data)->serverCallback(info); } static void context_state_callback(pa_context *context, void *data) { Q_ASSERT(data); - static_cast(data)->contextStateCallback(context); + static_cast(data)->contextStateCallback(context); } static void subscribe_cb(pa_context *context, pa_subscription_event_type_t type, uint32_t index, void *data) { Q_ASSERT(data); - static_cast(data)->subscribeCallback(context, type, index); + static_cast(data)->subscribeCallback(context, type, index); } static void ext_stream_restore_read_cb(pa_context *context, const pa_ext_stream_restore_info *info, int eol, void *data) { if (!isGoodState(eol)) { return; } Q_ASSERT(context); Q_ASSERT(data); - static_cast(data)->streamRestoreCallback(info); + static_cast(data)->streamRestoreCallback(info); } static void ext_stream_restore_subscribe_cb(pa_context *context, void *data) { Q_ASSERT(context); Q_ASSERT(data); if (!PAOperation(pa_ext_stream_restore_read(context, ext_stream_restore_read_cb, data))) { qCWarning(PULSEAUDIOQT) << "pa_ext_stream_restore_read() failed"; } } static void ext_stream_restore_change_sink_cb(pa_context *context, const pa_ext_stream_restore_info *info, int eol, void *data) { if (!isGoodState(eol)) { return; } Q_ASSERT(context); Q_ASSERT(data); if (qstrncmp(info->name, "sink-input-by", 13) == 0) { - ContextPrivate *contextp = static_cast(data); + ContextPrivate *contextp = static_cast(data); const QByteArray deviceData = contextp->m_newDefaultSink.toUtf8(); pa_ext_stream_restore_info newinfo; newinfo.name = info->name; newinfo.channel_map = info->channel_map; newinfo.volume = info->volume; newinfo.mute = info->mute; newinfo.device = deviceData.constData(); contextp->streamRestoreWrite(&newinfo); } } static void ext_stream_restore_change_source_cb(pa_context *context, const pa_ext_stream_restore_info *info, int eol, void *data) { if (!isGoodState(eol)) { return; } Q_ASSERT(context); Q_ASSERT(data); if (qstrncmp(info->name, "source-output-by", 16) == 0) { - ContextPrivate *contextp = static_cast(data); + ContextPrivate *contextp = static_cast(data); const QByteArray deviceData = contextp->m_newDefaultSource.toUtf8(); pa_ext_stream_restore_info newinfo; newinfo.name = info->name; newinfo.channel_map = info->channel_map; newinfo.volume = info->volume; newinfo.mute = info->mute; newinfo.device = deviceData.constData(); contextp->streamRestoreWrite(&newinfo); } } // -------------------------- Context::Context(QObject *parent) : QObject(parent) , d(new ContextPrivate(this)) { d->m_server = new Server(this); d->m_context = nullptr; d->m_mainloop = nullptr; d->m_references = 0; d->connectToDaemon(); - QDBusServiceWatcher* watcher = new QDBusServiceWatcher(QStringLiteral("org.pulseaudio.Server"), - QDBusConnection::sessionBus(), - QDBusServiceWatcher::WatchForRegistration, - this); - connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [this]{ - d->connectToDaemon(); - }); - - connect(&d->m_sinks, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT sinkAdded(static_cast(object)); - }); - connect(&d->m_sinks, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT sinkRemoved(static_cast(object)); - }); - - connect(&d->m_sinkInputs, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT sinkInputAdded(static_cast(object)); - }); - connect(&d->m_sinkInputs, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT sinkInputRemoved(static_cast(object)); - }); - - connect(&d->m_sources, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT sourceAdded(static_cast(object)); - }); - connect(&d->m_sources, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT sourceRemoved(static_cast(object)); - }); - - connect(&d->m_sourceOutputs, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT sourceOutputAdded(static_cast(object)); - }); - connect(&d->m_sourceOutputs, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT sourceOutputRemoved(static_cast(object)); - }); - - connect(&d->m_clients, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT clientAdded(static_cast(object)); - }); - connect(&d->m_clients, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT clientRemoved(static_cast(object)); - }); - - connect(&d->m_cards, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT cardAdded(static_cast(object)); - }); - connect(&d->m_cards, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT cardRemoved(static_cast(object)); - }); - - connect(&d->m_modules, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT moduleAdded(static_cast(object)); - }); - connect(&d->m_modules, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT moduleRemoved(static_cast(object)); - }); - - connect(&d->m_streamRestores, &MapBaseQObject::added, this, [this](int, QObject *object) { - Q_EMIT streamRestoreAdded(static_cast(object)); - }); - connect(&d->m_streamRestores, &MapBaseQObject::removed, this, [this](int, QObject *object) { - Q_EMIT streamRestoreRemoved(static_cast(object)); - }); + QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QStringLiteral("org.pulseaudio.Server"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); + connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [this] { d->connectToDaemon(); }); + + connect(&d->m_sinks, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT sinkAdded(static_cast(object)); }); + connect(&d->m_sinks, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT sinkRemoved(static_cast(object)); }); + + connect(&d->m_sinkInputs, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT sinkInputAdded(static_cast(object)); }); + connect(&d->m_sinkInputs, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT sinkInputRemoved(static_cast(object)); }); + + connect(&d->m_sources, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT sourceAdded(static_cast(object)); }); + connect(&d->m_sources, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT sourceRemoved(static_cast(object)); }); + + connect(&d->m_sourceOutputs, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT sourceOutputAdded(static_cast(object)); }); + connect(&d->m_sourceOutputs, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT sourceOutputRemoved(static_cast(object)); }); + + connect(&d->m_clients, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT clientAdded(static_cast(object)); }); + connect(&d->m_clients, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT clientRemoved(static_cast(object)); }); + + connect(&d->m_cards, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT cardAdded(static_cast(object)); }); + connect(&d->m_cards, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT cardRemoved(static_cast(object)); }); + + connect(&d->m_modules, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT moduleAdded(static_cast(object)); }); + connect(&d->m_modules, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT moduleRemoved(static_cast(object)); }); + + connect(&d->m_streamRestores, &MapBaseQObject::added, this, [this](int, QObject *object) { Q_EMIT streamRestoreAdded(static_cast(object)); }); + connect(&d->m_streamRestores, &MapBaseQObject::removed, this, [this](int, QObject *object) { Q_EMIT streamRestoreRemoved(static_cast(object)); }); } ContextPrivate::ContextPrivate(Context *q) - :q(q) + : q(q) { } Context::~Context() { delete d; } ContextPrivate::~ContextPrivate() { if (m_context) { pa_context_unref(m_context); m_context = nullptr; } if (m_mainloop) { pa_glib_mainloop_free(m_mainloop); m_mainloop = nullptr; } reset(); } Context *Context::instance() { if (!s_context) { s_context = new Context; } return s_context; } void Context::ref() { ++d->m_references; } void Context::unref() { if (--d->m_references == 0) { delete this; s_context = nullptr; } } void ContextPrivate::subscribeCallback(pa_context *context, pa_subscription_event_type_t type, uint32_t index) { Q_ASSERT(context == m_context); switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sinks.removeEntry(index); } else { if (!PAOperation(pa_context_get_sink_info_by_index(context, index, sink_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_sink_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sources.removeEntry(index); } else { if (!PAOperation(pa_context_get_source_info_by_index(context, index, source_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_source_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sinkInputs.removeEntry(index); } else { if (!PAOperation(pa_context_get_sink_input_info(context, index, sink_input_callback, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_sink_input_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_sourceOutputs.removeEntry(index); } else { if (!PAOperation(pa_context_get_source_output_info(context, index, source_output_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_sink_input_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_CLIENT: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_clients.removeEntry(index); } else { if (!PAOperation(pa_context_get_client_info(context, index, client_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_client_info() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_CARD: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_cards.removeEntry(index); } else { if (!PAOperation(pa_context_get_card_info_by_index(context, index, card_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_card_info_by_index() failed"; return; } } break; case PA_SUBSCRIPTION_EVENT_MODULE: if ((type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { m_modules.removeEntry(index); } else { if (!PAOperation(pa_context_get_module_info_list(context, module_info_list_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_module_info_list() failed"; return; } } break; - case PA_SUBSCRIPTION_EVENT_SERVER: if (!PAOperation(pa_context_get_server_info(context, server_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_server_info() failed"; return; } break; - } } void ContextPrivate::contextStateCallback(pa_context *c) { qCDebug(PULSEAUDIOQT) << "state callback"; pa_context_state_t state = pa_context_get_state(c); if (state == PA_CONTEXT_READY) { qCDebug(PULSEAUDIOQT) << "ready"; // 1. Register for the stream changes (except during probe) if (m_context == c) { pa_context_set_subscribe_callback(c, subscribe_cb, this); - if (!PAOperation(pa_context_subscribe(c, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE| - PA_SUBSCRIPTION_MASK_CLIENT| - PA_SUBSCRIPTION_MASK_SINK_INPUT| - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| - PA_SUBSCRIPTION_MASK_CARD| - PA_SUBSCRIPTION_MASK_MODULE| - PA_SUBSCRIPTION_MASK_SERVER), nullptr, nullptr))) { + if (!PAOperation(pa_context_subscribe(c, + (pa_subscription_mask_t)(PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_CLIENT | PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT | + PA_SUBSCRIPTION_MASK_CARD | PA_SUBSCRIPTION_MASK_MODULE | PA_SUBSCRIPTION_MASK_SERVER), + nullptr, + nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_context_subscribe() failed"; return; } } if (!PAOperation(pa_context_get_sink_info_list(c, sink_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_sink_info_list() failed"; return; } if (!PAOperation(pa_context_get_source_info_list(c, source_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_source_info_list() failed"; return; } if (!PAOperation(pa_context_get_client_info_list(c, client_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_client_info_list() failed"; return; } if (!PAOperation(pa_context_get_card_info_list(c, card_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_card_info_list() failed"; return; } if (!PAOperation(pa_context_get_sink_input_info_list(c, sink_input_callback, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_sink_input_info_list() failed"; return; } if (!PAOperation(pa_context_get_source_output_info_list(c, source_output_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_source_output_info_list() failed"; return; } if (!PAOperation(pa_context_get_module_info_list(c, module_info_list_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_module_info_list() failed"; return; } if (!PAOperation(pa_context_get_server_info(c, server_cb, this))) { qCWarning(PULSEAUDIOQT) << "pa_context_get_server_info() failed"; return; } if (PAOperation(pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, this))) { pa_ext_stream_restore_set_subscribe_cb(c, ext_stream_restore_subscribe_cb, this); PAOperation(pa_ext_stream_restore_subscribe(c, 1, nullptr, this)); } else { qCWarning(PULSEAUDIOQT) << "Failed to initialize stream_restore extension"; } } else if (!PA_CONTEXT_IS_GOOD(state)) { qCWarning(PULSEAUDIOQT) << "context kaput"; if (m_context) { pa_context_unref(m_context); m_context = nullptr; } reset(); - QTimer::singleShot(1000, q, [this]{ - connectToDaemon(); - }); + QTimer::singleShot(1000, q, [this] { connectToDaemon(); }); } } void ContextPrivate::sinkCallback(const pa_sink_info *info) { // This parenting here is a bit weird m_sinks.updateEntry(info, q); } void ContextPrivate::sinkInputCallback(const pa_sink_input_info *info) { m_sinkInputs.updateEntry(info, q); } void ContextPrivate::sourceCallback(const pa_source_info *info) { m_sources.updateEntry(info, q); } void ContextPrivate::sourceOutputCallback(const pa_source_output_info *info) { m_sourceOutputs.updateEntry(info, q); } void ContextPrivate::clientCallback(const pa_client_info *info) { m_clients.updateEntry(info, q); } void ContextPrivate::cardCallback(const pa_card_info *info) { m_cards.updateEntry(info, q); } void ContextPrivate::moduleCallback(const pa_module_info *info) { m_modules.updateEntry(info, q); } void ContextPrivate::streamRestoreCallback(const pa_ext_stream_restore_info *info) { if (qstrcmp(info->name, "sink-input-by-media-role:event") != 0) { return; } const int eventRoleIndex = 1; StreamRestore *obj = qobject_cast(m_streamRestores.data().value(eventRoleIndex)); if (!obj) { QVariantMap props; - props.insert(QStringLiteral("application.icon_name"), - QStringLiteral("preferences-desktop-notification")); + props.insert(QStringLiteral("application.icon_name"), QStringLiteral("preferences-desktop-notification")); obj = new StreamRestore(eventRoleIndex, props, q); obj->d->update(info); m_streamRestores.insert(obj); } else { obj->d->update(info); } } void ContextPrivate::serverCallback(const pa_server_info *info) { m_server->d->update(info); } void Context::setCardProfile(quint32 index, const QString &profile) { if (!d->m_context) { return; } qCDebug(PULSEAUDIOQT) << index << profile; - if (!PAOperation(pa_context_set_card_profile_by_index(d->m_context, - index, - profile.toUtf8().constData(), - nullptr, nullptr))) { + if (!PAOperation(pa_context_set_card_profile_by_index(d->m_context, index, profile.toUtf8().constData(), nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_context_set_card_profile_by_index failed"; return; } } void Context::setDefaultSink(const QString &name) { if (!d->m_context) { return; } const QByteArray nameData = name.toUtf8(); - if (!PAOperation(pa_context_set_default_sink(d->m_context, - nameData.constData(), - nullptr, - nullptr))) { + if (!PAOperation(pa_context_set_default_sink(d->m_context, nameData.constData(), nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_context_set_default_sink failed"; } // Change device for all entries in stream-restore database d->m_newDefaultSink = name; - if (!PAOperation(pa_ext_stream_restore_read(d->m_context, - ext_stream_restore_change_sink_cb, - d))) { + if (!PAOperation(pa_ext_stream_restore_read(d->m_context, ext_stream_restore_change_sink_cb, d))) { qCWarning(PULSEAUDIOQT) << "pa_ext_stream_restore_read failed"; } } void Context::setDefaultSource(const QString &name) { if (!d->m_context) { return; } const QByteArray nameData = name.toUtf8(); - if (!PAOperation(pa_context_set_default_source(d->m_context, - nameData.constData(), - nullptr, - nullptr))) { + if (!PAOperation(pa_context_set_default_source(d->m_context, nameData.constData(), nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_context_set_default_source failed"; } // Change device for all entries in stream-restore database d->m_newDefaultSource = name; - if (!PAOperation(pa_ext_stream_restore_read(d->m_context, - ext_stream_restore_change_source_cb, - d))) { + if (!PAOperation(pa_ext_stream_restore_read(d->m_context, ext_stream_restore_change_source_cb, d))) { qCWarning(PULSEAUDIOQT) << "pa_ext_stream_restore_read failed"; } } void ContextPrivate::streamRestoreWrite(const pa_ext_stream_restore_info *info) { if (!m_context) { return; } - if (!PAOperation(pa_ext_stream_restore_write(m_context, - PA_UPDATE_REPLACE, - info, - 1, - true, - nullptr, - nullptr))) { + if (!PAOperation(pa_ext_stream_restore_write(m_context, PA_UPDATE_REPLACE, info, 1, true, nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_ext_stream_restore_write failed"; } } void ContextPrivate::connectToDaemon() { if (m_context) { return; } // We require a glib event loop if (!QByteArray(QAbstractEventDispatcher::instance()->metaObject()->className()).contains("Glib")) { qCWarning(PULSEAUDIOQT) << "Disabling PulseAudio integration for lack of GLib event loop"; return; } - qCDebug(PULSEAUDIOQT) << "Attempting connection to PulseAudio sound daemon"; + qCDebug(PULSEAUDIOQT) << "Attempting connection to PulseAudio sound daemon"; if (!m_mainloop) { m_mainloop = pa_glib_mainloop_new(nullptr); Q_ASSERT(m_mainloop); } pa_mainloop_api *api = pa_glib_mainloop_get_api(m_mainloop); Q_ASSERT(api); m_context = pa_context_new(api, "QPulse"); Q_ASSERT(m_context); if (pa_context_connect(m_context, NULL, PA_CONTEXT_NOFAIL, nullptr) < 0) { pa_context_unref(m_context); pa_glib_mainloop_free(m_mainloop); m_context = nullptr; m_mainloop = nullptr; return; } pa_context_set_state_callback(m_context, &context_state_callback, this); } void ContextPrivate::reset() { m_sinks.reset(); m_sinkInputs.reset(); m_sources.reset(); m_sourceOutputs.reset(); m_clients.reset(); m_cards.reset(); m_modules.reset(); m_streamRestores.reset(); m_server->reset(); } bool Context::isValid() { return d->m_context && d->m_mainloop; } -QVector Context::sinks() const +QVector Context::sinks() const { return d->m_sinks.data(); } -QVector Context::sinkInputs() const +QVector Context::sinkInputs() const { return d->m_sinkInputs.data(); } -QVector Context::sources() const +QVector Context::sources() const { return d->m_sources.data(); } -QVector Context::sourceOutputs() const +QVector Context::sourceOutputs() const { return d->m_sourceOutputs.data(); } -QVector Context::clients() const +QVector Context::clients() const { return d->m_clients.data(); } -QVector Context::cards() const +QVector Context::cards() const { return d->m_cards.data(); } -QVector Context::modules() const +QVector Context::modules() const { return d->m_modules.data(); } -QVector Context::streamRestores() const +QVector Context::streamRestores() const { return d->m_streamRestores.data(); } Server *Context::server() const { return d->m_server; } -void ContextPrivate::setGenericVolume(quint32 index, int channel, qint64 newVolume, pa_cvolume cVolume, const std::function& pa_set_volume) +void ContextPrivate::setGenericVolume(quint32 index, int channel, qint64 newVolume, pa_cvolume cVolume, const std::function &pa_set_volume) { if (!m_context) { return; } newVolume = qBound(0, newVolume, PA_VOLUME_MAX); pa_cvolume newCVolume = cVolume; if (channel == -1) { // -1 all channels const qint64 diff = newVolume - pa_cvolume_max(&cVolume); for (int i = 0; i < newCVolume.channels; ++i) { newCVolume.values[i] = qBound(0, newCVolume.values[i] + diff, PA_VOLUME_MAX); } } else { Q_ASSERT(newCVolume.channels > channel); newCVolume.values[channel] = newVolume; } if (!pa_set_volume(m_context, index, &newCVolume, nullptr, nullptr)) { - qCWarning(PULSEAUDIOQT) << "pa_set_volume failed"; + qCWarning(PULSEAUDIOQT) << "pa_set_volume failed"; return; } } -void ContextPrivate::setGenericMute(quint32 index, bool mute, const std::function& pa_set_mute) +void ContextPrivate::setGenericMute(quint32 index, bool mute, const std::function &pa_set_mute) { if (!m_context) { return; } if (!PAOperation(pa_set_mute(m_context, index, mute, nullptr, nullptr))) { - qCWarning(PULSEAUDIOQT) << "pa_set_mute failed"; + qCWarning(PULSEAUDIOQT) << "pa_set_mute failed"; return; } } -void ContextPrivate::setGenericPort(quint32 index, const QString &portName, const std::function& pa_set_port) +void ContextPrivate::setGenericPort(quint32 index, const QString &portName, const std::function &pa_set_port) { if (!m_context) { return; } if (!PAOperation(pa_set_port(m_context, index, portName.toUtf8().constData(), nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_set_port failed"; return; } } -void ContextPrivate::setGenericDeviceForStream(quint32 streamIndex, quint32 deviceIndex, const std::function& pa_move_stream_to_device) +void ContextPrivate::setGenericDeviceForStream(quint32 streamIndex, quint32 deviceIndex, const std::function &pa_move_stream_to_device) { if (!m_context) { return; } if (!PAOperation(pa_move_stream_to_device(m_context, streamIndex, deviceIndex, nullptr, nullptr))) { qCWarning(PULSEAUDIOQT) << "pa_move_stream_to_device failed"; return; } } } // PulseAudioQt diff --git a/src/context.h b/src/context.h index 424c862..1196dbd 100644 --- a/src/context.h +++ b/src/context.h @@ -1,224 +1,223 @@ /* Copyright 2014-2015 Harald Sitter 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 CONTEXT_H #define CONTEXT_H -#include #include "kf5pulseaudioqt_export.h" +#include namespace PulseAudioQt { - class Card; class Client; class Sink; class SinkInput; class Source; class SourceOutput; class StreamRestore; class Module; class Server; KF5PULSEAUDIOQT_EXPORT qint64 normalVolume(); KF5PULSEAUDIOQT_EXPORT qint64 minimumVolume(); KF5PULSEAUDIOQT_EXPORT qint64 maximumVolume(); class KF5PULSEAUDIOQT_EXPORT Context : public QObject { Q_OBJECT public: ~Context(); static Context *instance(); void ref(); void unref(); bool isValid(); /** * Returns a list of all sinks. * * @return list of sinks */ - QVector sinks() const; + QVector sinks() const; /** * Returns a list of all sink inputs. * * @return list of sink inputs */ - QVector sinkInputs() const; + QVector sinkInputs() const; /** * Returns a list of all sources. * * @return list of sources */ - QVector sources() const; + QVector sources() const; /** * Returns a list of all source outputs. * * @return list of source outputs */ - QVector sourceOutputs() const; + QVector sourceOutputs() const; /** * Returns a list of all clients. * * @return list of clients */ - QVector clients() const; + QVector clients() const; /** * Returns a list of all cards. * * @return list of cards */ - QVector cards() const; + QVector cards() const; /** * Returns a list of all modules. * * @return list of modules */ - QVector modules() const; + QVector modules() const; /** * Returns a list of all stream restores. * * @return list of stream restores */ - QVector streamRestores() const; + QVector streamRestores() const; Server *server() const; void setCardProfile(quint32 index, const QString &profile); void setDefaultSink(const QString &name); void setDefaultSource(const QString &name); Q_SIGNALS: /** * Indicates that sink was added. */ void sinkAdded(PulseAudioQt::Sink *sink); /** * Indicates that sink was removed. */ void sinkRemoved(PulseAudioQt::Sink *sink); /** * Indicates that sink input was added. */ void sinkInputAdded(PulseAudioQt::SinkInput *sinkInput); /** * Indicates that sink input was removed. */ void sinkInputRemoved(PulseAudioQt::SinkInput *sinkInput); /** * Indicates that source was added. */ void sourceAdded(PulseAudioQt::Source *source); /** * Indicates that source was removed. */ void sourceRemoved(PulseAudioQt::Source *source); /** * Indicates that source output was added. */ void sourceOutputAdded(PulseAudioQt::SourceOutput *sourceOutput); /** * Indicates that source output was removed. */ void sourceOutputRemoved(PulseAudioQt::SourceOutput *sourceOutput); /** * Indicates that client was added. */ void clientAdded(PulseAudioQt::Client *client); /** * Indicates that client was removed. */ void clientRemoved(PulseAudioQt::Client *client); /** * Indicates that card was added. */ void cardAdded(PulseAudioQt::Card *card); /** * Indicates that card was removed. */ void cardRemoved(PulseAudioQt::Card *card); /** * Indicates that module was added. */ void moduleAdded(PulseAudioQt::Module *module); /** * Indicates that module was removed. */ void moduleRemoved(PulseAudioQt::Module *module); /** * Indicates that stream restore was added. */ void streamRestoreAdded(PulseAudioQt::StreamRestore *streamRestore); /** * Indicates that streamRestore was removed. */ void streamRestoreRemoved(PulseAudioQt::StreamRestore *streamRestore); private: explicit Context(QObject *parent = nullptr); class ContextPrivate *const d; friend class Sink; friend class SinkInput; friend class Source; friend class SourceOutput; friend class Stream; friend class StreamRestorePrivate; friend class Server; friend class SinkModel; friend class SinkInputModel; friend class SourceModel; friend class SourceOutputModel; friend class StreamRestoreModel; friend class CardModel; friend class ModuleModel; }; } // PulseAudioQt #endif // CONTEXT_H diff --git a/src/context_p.h b/src/context_p.h index 47fdf43..b60c17c 100644 --- a/src/context_p.h +++ b/src/context_p.h @@ -1,85 +1,82 @@ /* Copyright 2018 Nicolas Fella 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 CONTEXT_P_H #define CONTEXT_P_H -#include #include "maps.h" #include "operation.h" +#include #include -#include -#include #include #include +#include +#include namespace PulseAudioQt { - class ContextPrivate { public: - explicit ContextPrivate(Context *q); virtual ~ContextPrivate(); // Don't forget to add things to reset(). SinkMap m_sinks; SinkInputMap m_sinkInputs; SourceMap m_sources; SourceOutputMap m_sourceOutputs; ClientMap m_clients; CardMap m_cards; ModuleMap m_modules; StreamRestoreMap m_streamRestores; Server *m_server; pa_context *m_context; pa_glib_mainloop *m_mainloop; QString m_newDefaultSink; QString m_newDefaultSource; int m_references; void subscribeCallback(pa_context *context, pa_subscription_event_type_t type, uint32_t index); void contextStateCallback(pa_context *context); void sinkCallback(const pa_sink_info *info); void sinkInputCallback(const pa_sink_input_info *info); void sourceCallback(const pa_source_info *info); void sourceOutputCallback(const pa_source_output_info *info); void clientCallback(const pa_client_info *info); void cardCallback(const pa_card_info *info); void moduleCallback(const pa_module_info *info); void streamRestoreCallback(const pa_ext_stream_restore_info *info); void serverCallback(const pa_server_info *info); void streamRestoreWrite(const pa_ext_stream_restore_info *info); - void setGenericVolume(quint32 index, int channel, qint64 newVolume, pa_cvolume cVolume, const std::function& ); - void setGenericMute(quint32 index, bool mute, const std::function& ); - void setGenericPort(quint32 index, const QString &portName, const std::function& ); - void setGenericDeviceForStream(quint32 streamIndex, quint32 deviceIndex, const std::function& ); + void setGenericVolume(quint32 index, int channel, qint64 newVolume, pa_cvolume cVolume, const std::function &); + void setGenericMute(quint32 index, bool mute, const std::function &); + void setGenericPort(quint32 index, const QString &portName, const std::function &); + void setGenericDeviceForStream(quint32 streamIndex, quint32 deviceIndex, const std::function &); void reset(); void connectToDaemon(); Context *q; - }; } #endif diff --git a/src/device.cpp b/src/device.cpp index 5a7ef17..d32b865 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -1,92 +1,93 @@ /* Copyright 2014-2015 Harald Sitter 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 "device.h" #include "device_p.h" -namespace PulseAudioQt { - +namespace PulseAudioQt +{ Device::State Device::state() const { return d->m_state; } QString Device::name() const { return d->m_name; } QString Device::description() const { return d->m_description; } QString Device::formFactor() const { return d->m_formFactor; } quint32 Device::cardIndex() const { return d->m_cardIndex; } -QVector Device::ports() const +QVector Device::ports() const { - return QVector::fromList(d->m_ports.values()); + return QVector::fromList(d->m_ports.values()); } quint32 Device::activePortIndex() const { return d->m_activePortIndex; } Device::Device(QObject *parent) : VolumeObject(parent) , d(new DevicePrivate(this)) { } DevicePrivate::DevicePrivate(Device *q) : q(q) { } Device::State DevicePrivate::stateFromPaState(int value) const { switch (value) { case -1: // PA_X_INVALID_STATE return Device::InvalidState; - case 0: // PA_X_RUNNING + case 0: // PA_X_RUNNING return Device::RunningState; - case 1: // PA_X_IDLE + case 1: // PA_X_IDLE return Device::IdleState; - case 2: // PA_X_SUSPENDED + case 2: // PA_X_SUSPENDED return Device::SuspendedState; default: return Device::UnknownState; } } -Device::~Device(){ +Device::~Device() +{ delete d; } } // namespace PulseAudioQt diff --git a/src/device.h b/src/device.h index fc7ed4b..6d6ec55 100644 --- a/src/device.h +++ b/src/device.h @@ -1,90 +1,83 @@ /* Copyright 2014-2015 Harald Sitter 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 PA_DEVICE_H #define PA_DEVICE_H #include #include "volumeobject.h" namespace PulseAudioQt { - class Port; class DevicePrivate; class KF5PULSEAUDIOQT_EXPORT Device : public VolumeObject { Q_OBJECT Q_PROPERTY(State state READ state NOTIFY stateChanged) Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString description READ description NOTIFY descriptionChanged) Q_PROPERTY(QString formFactor READ formFactor NOTIFY formFactorChanged) Q_PROPERTY(quint32 cardIndex READ cardIndex NOTIFY cardIndexChanged) - Q_PROPERTY(QVector ports READ ports NOTIFY portsChanged) + Q_PROPERTY(QVector ports READ ports NOTIFY portsChanged) Q_PROPERTY(quint32 activePortIndex READ activePortIndex WRITE setActivePortIndex NOTIFY activePortIndexChanged) Q_PROPERTY(bool default READ isDefault WRITE setDefault NOTIFY defaultChanged) public: - enum State { - InvalidState = 0, - RunningState, - IdleState, - SuspendedState, - UnknownState - }; + enum State { InvalidState = 0, RunningState, IdleState, SuspendedState, UnknownState }; Q_ENUM(State); ~Device(); State state() const; QString name() const; QString description() const; QString formFactor() const; quint32 cardIndex() const; - QVector ports() const; + QVector ports() const; quint32 activePortIndex() const; virtual void setActivePortIndex(quint32 port_index) = 0; virtual bool isDefault() const = 0; virtual void setDefault(bool enable) = 0; Q_SIGNALS: void stateChanged(); void nameChanged(); void descriptionChanged(); void formFactorChanged(); void cardIndexChanged(); void portsChanged(); void activePortIndexChanged(); void defaultChanged(); protected: explicit Device(QObject *parent); DevicePrivate *d; private: friend class SinkPrivate; friend class SourcePrivate; }; } // PulseAudioQt #endif // DEVICE_H diff --git a/src/device_p.h b/src/device_p.h index 711f399..e3790d5 100644 --- a/src/device_p.h +++ b/src/device_p.h @@ -1,114 +1,110 @@ /* Copyright 2018 Nicolas Fella 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 DEVICE_P_H #define DEVICE_P_H #include -#include #include +#include #include "device.h" #include "port.h" #include "port_p.h" #include "volumeobject_p.h" namespace PulseAudioQt { - class DevicePrivate { - public: explicit DevicePrivate(Device *q); Device *q; QString m_name; QString m_description; QString m_formFactor; quint32 m_cardIndex = -1; - QHash m_ports; + QHash m_ports; quint32 m_activePortIndex = -1; Device::State m_state = Device::UnknownState; Device::State stateFromPaState(int value) const; - template - void updateDevice(const PAInfo *info) + template void updateDevice(const PAInfo *info) { q->VolumeObject::d->updateVolumeObject(info); if (m_name != info->name) { m_name = info->name; Q_EMIT q->nameChanged(); } if (m_description != info->description) { m_description = info->description; Q_EMIT q->descriptionChanged(); } const char *form_factor = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_FORM_FACTOR); if (form_factor) { QString formFactor = QString::fromUtf8(form_factor); if (m_formFactor != formFactor) { m_formFactor = formFactor; Q_EMIT q->formFactorChanged(); } } m_cardIndex = info->card; Q_EMIT q->cardIndexChanged(); QStringList newPorts; for (auto **it = info->ports; it && *it != nullptr; ++it) { const QString name = QString::fromUtf8((*it)->name); newPorts << name; if (!m_ports.contains(name)) { m_ports[name] = new Port(q); } Port *port = m_ports[name]; port->d->setInfo(*it); if (info->active_port == *it) { m_activePortIndex = m_ports.size() - 1; } } const QList keys = m_ports.keys(); for (const QString &portKey : keys) { if (!newPorts.contains(portKey)) { delete m_ports.take(portKey); } } Q_EMIT q->portsChanged(); Q_EMIT q->activePortIndexChanged(); Device::State infoState = stateFromPaState(info->state); if (infoState != m_state) { m_state = infoState; Q_EMIT q->stateChanged(); } } - - }; +}; } // namespace PulseAudioQt #endif diff --git a/src/maps.h b/src/maps.h index 9d7200a..2253dc7 100644 --- a/src/maps.h +++ b/src/maps.h @@ -1,175 +1,178 @@ /* Copyright 2014-2015 Harald Sitter Copyright 2018 David Rosca 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 . */ #pragma once -#include #include -#include #include +#include +#include -#include #include +#include -#include "sink_p.h" -#include "source_p.h" #include "card_p.h" +#include "client_p.h" +#include "module_p.h" +#include "sink_p.h" #include "sinkinput_p.h" +#include "source_p.h" #include "sourceoutput_p.h" -#include "client_p.h" #include "streamrestore_p.h" -#include "module_p.h" namespace PulseAudioQt { - // Used for typedefs. class Card; class Client; class Sink; class SinkInput; class Source; class SourceOutput; class StreamRestore; class Module; /** * @see MapBase * This class is nothing more than the QObject base since moc cannot handle * templates. */ class MapBaseQObject : public QObject { Q_OBJECT public: virtual int count() const = 0; virtual QObject *objectAt(int index) const = 0; virtual int indexOfObject(QObject *object) const = 0; Q_SIGNALS: void aboutToBeAdded(int index); void added(int index, QObject *object); void aboutToBeRemoved(int index); void removed(int index, QObject *object); }; /** * Maps a specific index to a specific object pointer. * This is used to give the unique arbitrary PulseAudio index of a PulseObject a * serialized list index. Namely it enables us to translate a discrete list * index to a pulse index to an object, and any permutation thereof. */ -template -class MapBase : public MapBaseQObject +template class MapBase : public MapBaseQObject { public: - virtual ~MapBase() {} + virtual ~MapBase() + { + } - const QVector &data() const { return m_data; } + const QVector &data() const + { + return m_data; + } int count() const override { return m_data.count(); } int indexOfObject(QObject *object) const override { - return m_data.indexOf(static_cast(object)); + return m_data.indexOf(static_cast(object)); } QObject *objectAt(int index) const override { return m_data.at(index); } void reset() { while (!m_hash.isEmpty()) { removeEntry(m_data.at(m_data.count() - 1)->index()); } m_pendingRemovals.clear(); } void insert(Type *object) { Q_ASSERT(!m_data.contains(object)); const int modelIndex = m_data.count(); Q_EMIT aboutToBeAdded(modelIndex); m_data.append(object); m_hash[object->index()] = object; Q_EMIT added(modelIndex, object); } // Context is passed in as parent because context needs to include the maps // so we'd cause a circular dep if we were to try to use the instance here. // Plus that's weird separation anyway. void updateEntry(const PAInfo *info, QObject *parent) { Q_ASSERT(info); if (m_pendingRemovals.remove(info->index)) { // Was already removed again. return; } auto *obj = m_hash.value(info->index); if (!obj) { obj = new Type(parent); obj->d->update(info); insert(obj); } else { obj->d->update(info); } } void removeEntry(quint32 index) { if (!m_hash.contains(index)) { m_pendingRemovals.insert(index); } else { const int modelIndex = m_data.indexOf(m_hash.value(index)); Q_EMIT aboutToBeRemoved(modelIndex); m_data.removeAt(modelIndex); - auto object = m_hash.take(index); + auto object = m_hash.take(index); Q_EMIT removed(modelIndex, object); delete object; } } protected: - QVector m_data; - QHash m_hash; + QVector m_data; + QHash m_hash; QSet m_pendingRemovals; }; typedef MapBase CardMap; typedef MapBase ClientMap; typedef MapBase SinkInputMap; typedef MapBase SinkMap; typedef MapBase SourceMap; typedef MapBase SourceOutputMap; typedef MapBase StreamRestoreMap; typedef MapBase ModuleMap; } // PulseAudioQt diff --git a/src/models.cpp b/src/models.cpp index a24506b..b62c00b 100644 --- a/src/models.cpp +++ b/src/models.cpp @@ -1,416 +1,409 @@ /* Copyright 2014-2015 Harald Sitter Copyright 2016 David Rosca 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 "models.h" -#include "maps.h" -#include "debug.h" #include "card.h" +#include "context.h" +#include "context_p.h" +#include "debug.h" +#include "maps.h" +#include "module.h" +#include "server.h" #include "sink.h" #include "sinkinput.h" #include "source.h" #include "sourceoutput.h" -#include "server.h" #include "streamrestore.h" -#include "module.h" -#include "context.h" -#include "context_p.h" -#include #include "models_p.h" +#include namespace PulseAudioQt { - AbstractModel::AbstractModel(const MapBaseQObject *map, QObject *parent) : QAbstractListModel(parent) , d(new AbstractModelPrivate(this, map)) { Context::instance()->ref(); - connect(d->m_map, &MapBaseQObject::aboutToBeAdded, this, [this](int index) { - beginInsertRows(QModelIndex(), index, index); - }); + connect(d->m_map, &MapBaseQObject::aboutToBeAdded, this, [this](int index) { beginInsertRows(QModelIndex(), index, index); }); connect(d->m_map, &MapBaseQObject::added, this, [this](int index) { onDataAdded(index); endInsertRows(); }); - connect(d->m_map, &MapBaseQObject::aboutToBeRemoved, this, [this](int index) { - beginRemoveRows(QModelIndex(), index, index); - }); + connect(d->m_map, &MapBaseQObject::aboutToBeRemoved, this, [this](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(d->m_map, &MapBaseQObject::removed, this, [this](int index) { Q_UNUSED(index); endRemoveRows(); }); } AbstractModel::~AbstractModel() { - //deref context after we've deleted this object - //see https://bugs.kde.org/show_bug.cgi?id=371215 + // deref context after we've deleted this object + // see https://bugs.kde.org/show_bug.cgi?id=371215 Context::instance()->unref(); delete d; } AbstractModelPrivate::AbstractModelPrivate(AbstractModel *q, const MapBaseQObject *map) : q(q) , m_map(map) { } AbstractModelPrivate::~AbstractModelPrivate() { } QHash AbstractModel::roleNames() const { if (!d->m_roles.empty()) { qCDebug(PULSEAUDIOQT) << "returning roles" << d->m_roles; return d->m_roles; } Q_UNREACHABLE(); return QHash(); } int AbstractModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return d->m_map->count(); } QVariant AbstractModel::data(const QModelIndex &index, int role) const { if (!hasIndex(index.row(), index.column())) { return QVariant(); } QObject *data = d->m_map->objectAt(index.row()); Q_ASSERT(data); if (role == PulseObjectRole) { return QVariant::fromValue(data); } else if (role == Qt::DisplayRole) { - return static_cast(data)->properties().value(QStringLiteral("name")).toString(); + return static_cast(data)->properties().value(QStringLiteral("name")).toString(); } int property = d->m_objectProperties.value(role, -1); if (property == -1) { return QVariant(); } return data->metaObject()->property(property).read(data); } bool AbstractModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!hasIndex(index.row(), index.column())) { return false; } int propertyIndex = d->m_objectProperties.value(role, -1); if (propertyIndex == -1) { return false; } QObject *data = d->m_map->objectAt(index.row()); auto property = data->metaObject()->property(propertyIndex); return property.write(data, value); } int AbstractModel::role(const QByteArray &roleName) const { qCDebug(PULSEAUDIOQT) << roleName << d->m_roles.key(roleName, -1); return d->m_roles.key(roleName, -1); } Context *AbstractModel::context() const { return Context::instance(); } void AbstractModel::initRoleNames(const QMetaObject &qobjectMetaObject) { d->m_roles[PulseObjectRole] = QByteArrayLiteral("PulseObject"); QMetaEnum enumerator; for (int i = 0; i < metaObject()->enumeratorCount(); ++i) { if (metaObject()->enumerator(i).name() == QLatin1String("ItemRole")) { enumerator = metaObject()->enumerator(i); break; } } for (int i = 0; i < enumerator.keyCount(); ++i) { // Clip the Role suffix and glue it in the hash. const int roleLength = 4; QByteArray key(enumerator.key(i)); // Enum values must end in Role or the enum is crap Q_ASSERT(key.right(roleLength) == QByteArrayLiteral("Role")); key.chop(roleLength); d->m_roles[enumerator.value(i)] = key; } int maxEnumValue = -1; for (auto it = d->m_roles.constBegin(); it != d->m_roles.constEnd(); ++it) { if (it.key() > maxEnumValue) { maxEnumValue = it.key(); } } Q_ASSERT(maxEnumValue != -1); auto mo = qobjectMetaObject; for (int i = 0; i < mo.propertyCount(); ++i) { QMetaProperty property = mo.property(i); QString name(property.name()); name.replace(0, 1, name.at(0).toUpper()); d->m_roles[++maxEnumValue] = name.toLatin1(); d->m_objectProperties.insert(maxEnumValue, i); if (!property.hasNotifySignal()) { continue; } d->m_signalIndexToProperties.insert(property.notifySignalIndex(), i); } qCDebug(PULSEAUDIOQT) << d->m_roles; // Connect to property changes also with objects already in model for (int i = 0; i < d->m_map->count(); ++i) { onDataAdded(i); } } void AbstractModel::propertyChanged() { if (!sender() || senderSignalIndex() == -1) { return; } int propertyIndex = d->m_signalIndexToProperties.value(senderSignalIndex(), -1); if (propertyIndex == -1) { return; } int role = d->m_objectProperties.key(propertyIndex, -1); if (role == -1) { return; } int index = d->m_map->indexOfObject(sender()); qCDebug(PULSEAUDIOQT) << "PROPERTY CHANGED (" << index << ") :: " << role << roleNames().value(role); Q_EMIT dataChanged(createIndex(index, 0), createIndex(index, 0), {role}); } void AbstractModel::onDataAdded(int index) { QObject *data = d->m_map->objectAt(index); const QMetaObject *mo = data->metaObject(); // We have all the data changed notify signals already stored auto keys = d->m_signalIndexToProperties.keys(); foreach (int index, keys) { QMetaMethod meth = mo->method(index); connect(data, meth, this, propertyChangedMetaMethod()); } } QMetaMethod AbstractModel::propertyChangedMetaMethod() const { auto mo = metaObject(); int methodIndex = mo->indexOfMethod("propertyChanged()"); if (methodIndex == -1) { return QMetaMethod(); } return mo->method(methodIndex); } SinkModel::SinkModel(QObject *parent) : AbstractModel(&context()->d->m_sinks, parent) , d(new SinkModelPrivate(this)) { initRoleNames(Sink::staticMetaObject); for (int i = 0; i < context()->d->m_sinks.count(); ++i) { sinkAdded(i); } connect(&context()->d->m_sinks, &MapBaseQObject::added, this, &SinkModel::sinkAdded); connect(&context()->d->m_sinks, &MapBaseQObject::removed, this, &SinkModel::sinkRemoved); connect(context()->server(), &Server::defaultSinkChanged, this, [this]() { updatePreferredSink(); Q_EMIT defaultSinkChanged(); }); } SinkModel::~SinkModel() { delete d; } - SinkModelPrivate::SinkModelPrivate(SinkModel *q) : q(q) , m_preferredSink(nullptr) { } SinkModelPrivate::~SinkModelPrivate() { } - Sink *SinkModel::defaultSink() const { return context()->server()->defaultSink(); } Sink *SinkModel::preferredSink() const { return d->m_preferredSink; } QVariant SinkModel::data(const QModelIndex &index, int role) const { if (role == SortByDefaultRole) { // Workaround QTBUG-1548 const QString pulseIndex = data(index, AbstractModel::role(QByteArrayLiteral("Index"))).toString(); const QString defaultDevice = data(index, AbstractModel::role(QByteArrayLiteral("Default"))).toString(); return defaultDevice + pulseIndex; } return AbstractModel::data(index, role); } void SinkModel::sinkAdded(int index) { Q_ASSERT(qobject_cast(context()->d->m_sinks.objectAt(index))); Sink *sink = static_cast(context()->d->m_sinks.objectAt(index)); connect(sink, &Sink::stateChanged, this, &SinkModel::updatePreferredSink); updatePreferredSink(); } void SinkModel::sinkRemoved(int index) { Q_UNUSED(index); updatePreferredSink(); } void SinkModel::updatePreferredSink() { Sink *sink = findPreferredSink(); if (sink != d->m_preferredSink) { qCDebug(PULSEAUDIOQT) << "Changing preferred sink to" << sink << (sink ? sink->name() : ""); d->m_preferredSink = sink; Q_EMIT preferredSinkChanged(); } } Sink *SinkModel::findPreferredSink() const { const auto &sinks = context()->d->m_sinks; // Only one sink is the preferred one if (sinks.count() == 1) { return static_cast(sinks.objectAt(0)); } auto lookForState = [&](Device::State state) { Sink *ret = nullptr; const auto data = sinks.data(); for (Sink *sink : data) { if (sink->state() != state) { continue; } if (!ret) { ret = sink; } else if (sink == defaultSink()) { ret = sink; break; } } return ret; }; Sink *preferred = nullptr; // Look for playing sinks + prefer default sink preferred = lookForState(Device::RunningState); if (preferred) { return preferred; } // Look for idle sinks + prefer default sink preferred = lookForState(Device::IdleState); if (preferred) { return preferred; } // Fallback to default sink return defaultSink(); } SourceModel::SourceModel(QObject *parent) : AbstractModel(&context()->d->m_sources, parent) { initRoleNames(Source::staticMetaObject); connect(context()->server(), &Server::defaultSourceChanged, this, &SourceModel::defaultSourceChanged); } Source *SourceModel::defaultSource() const { return context()->server()->defaultSource(); } QVariant SourceModel::data(const QModelIndex &index, int role) const { if (role == SortByDefaultRole) { // Workaround QTBUG-1548 const QString pulseIndex = data(index, AbstractModel::role(QByteArrayLiteral("Index"))).toString(); const QString defaultDevice = data(index, AbstractModel::role(QByteArrayLiteral("Default"))).toString(); return defaultDevice + pulseIndex; } return AbstractModel::data(index, role); } SinkInputModel::SinkInputModel(QObject *parent) : AbstractModel(&context()->d->m_sinkInputs, parent) { initRoleNames(SinkInput::staticMetaObject); } SourceOutputModel::SourceOutputModel(QObject *parent) : AbstractModel(&context()->d->m_sourceOutputs, parent) { initRoleNames(SourceOutput::staticMetaObject); } CardModel::CardModel(QObject *parent) : AbstractModel(&context()->d->m_cards, parent) { initRoleNames(Card::staticMetaObject); } StreamRestoreModel::StreamRestoreModel(QObject *parent) : AbstractModel(&context()->d->m_streamRestores, parent) { initRoleNames(StreamRestore::staticMetaObject); } ModuleModel::ModuleModel(QObject *parent) : AbstractModel(&context()->d->m_modules, parent) { initRoleNames(Module::staticMetaObject); } } // PulseAudioQt diff --git a/src/models.h b/src/models.h index 3b1a56d..4d47e08 100644 --- a/src/models.h +++ b/src/models.h @@ -1,172 +1,172 @@ /* Copyright 2014-2015 Harald Sitter Copyright 2016 David Rosca 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 PULSEAUDIO_H #define PULSEAUDIO_H #include #include "kf5pulseaudioqt_export.h" namespace PulseAudioQt { - class Context; class MapBaseQObject; class Sink; class Source; class AbstractModelPrivate; class SinkModelPrivate; class KF5PULSEAUDIOQT_EXPORT AbstractModel : public QAbstractListModel { Q_OBJECT public: - enum ItemRole { - PulseObjectRole = Qt::UserRole + 1 - }; + enum ItemRole { PulseObjectRole = Qt::UserRole + 1 }; ~AbstractModel() override; QHash roleNames() const final override; int rowCount(const QModelIndex &parent = QModelIndex()) const final override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) final override; int role(const QByteArray &roleName) const; protected: AbstractModel(const MapBaseQObject *map, QObject *parent); void initRoleNames(const QMetaObject &qobjectMetaObject); Context *context() const; private Q_SLOTS: void propertyChanged(); private: void onDataAdded(int index); void onDataRemoved(int index); QMetaMethod propertyChangedMetaMethod() const; AbstractModelPrivate *d; // Prevent leaf-classes from default constructing as we want to enforce // them passing us a context or explicit nullptrs. - AbstractModel() {} + AbstractModel() + { + } }; class KF5PULSEAUDIOQT_EXPORT CardModel : public AbstractModel { Q_OBJECT public: CardModel(QObject *parent = nullptr); + private: void *d; }; class KF5PULSEAUDIOQT_EXPORT SinkModel : public AbstractModel { Q_OBJECT Q_PROPERTY(PulseAudioQt::Sink *defaultSink READ defaultSink NOTIFY defaultSinkChanged) Q_PROPERTY(PulseAudioQt::Sink *preferredSink READ preferredSink NOTIFY preferredSinkChanged) public: - enum ItemRole { - SortByDefaultRole = PulseObjectRole + 1 - }; + enum ItemRole { SortByDefaultRole = PulseObjectRole + 1 }; Q_ENUM(ItemRole) SinkModel(QObject *parent = nullptr); virtual ~SinkModel(); Sink *defaultSink() const; Sink *preferredSink() const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Q_SIGNALS: void defaultSinkChanged(); void preferredSinkChanged(); private: void sinkAdded(int index); void sinkRemoved(int index); void updatePreferredSink(); Sink *findPreferredSink() const; SinkModelPrivate *d; }; class KF5PULSEAUDIOQT_EXPORT SinkInputModel : public AbstractModel { Q_OBJECT public: SinkInputModel(QObject *parent = nullptr); + private: void *d; }; class KF5PULSEAUDIOQT_EXPORT SourceModel : public AbstractModel { Q_OBJECT Q_PROPERTY(PulseAudioQt::Source *defaultSource READ defaultSource NOTIFY defaultSourceChanged) public: - enum ItemRole { - SortByDefaultRole = PulseObjectRole + 1 - }; + enum ItemRole { SortByDefaultRole = PulseObjectRole + 1 }; Q_ENUM(ItemRole) SourceModel(QObject *parent = nullptr); Source *defaultSource() const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Q_SIGNALS: void defaultSourceChanged(); private: void *d; }; class KF5PULSEAUDIOQT_EXPORT SourceOutputModel : public AbstractModel { Q_OBJECT public: SourceOutputModel(QObject *parent = nullptr); + private: void *d; }; class KF5PULSEAUDIOQT_EXPORT StreamRestoreModel : public AbstractModel { Q_OBJECT public: StreamRestoreModel(QObject *parent = nullptr); + private: void *d; }; class KF5PULSEAUDIOQT_EXPORT ModuleModel : public AbstractModel { Q_OBJECT public: ModuleModel(QObject *parent = nullptr); + private: void *d; }; } // PulseAudioQt #endif // PULSEAUDIO_H diff --git a/src/models_p.h b/src/models_p.h index fa481ae..b8b1dc9 100644 --- a/src/models_p.h +++ b/src/models_p.h @@ -1,51 +1,47 @@ /* Copyright 2018 Nicolas Fella 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 . */ #pragma once #include "maps.h" namespace PulseAudioQt { - class AbstractModelPrivate { public: - explicit AbstractModelPrivate(AbstractModel *q, const MapBaseQObject *map); virtual ~AbstractModelPrivate(); AbstractModel *q; const MapBaseQObject *m_map; QHash m_roles; QHash m_objectProperties; QHash m_signalIndexToProperties; - }; class SinkModelPrivate { public: explicit SinkModelPrivate(SinkModel *q); virtual ~SinkModelPrivate(); SinkModel *q; Sink *m_preferredSink; - }; } diff --git a/src/module.cpp b/src/module.cpp index 7ec67b5..9365396 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -1,77 +1,76 @@ /* Copyright 2017 David Rosca 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 "module.h" -#include "module_p.h" #include "debug.h" +#include "module_p.h" #include "context.h" #include "pulseobject_p.h" namespace PulseAudioQt { - Module::Module(QObject *parent) : PulseObject(parent) , d(new ModulePrivate(this)) { } ModulePrivate::ModulePrivate(Module *q) : q(q) { } ModulePrivate::~ModulePrivate() { } void ModulePrivate::update(const pa_module_info *info) { q->PulseObject::d->updatePulseObject(info); const QString infoName = QString::fromUtf8(info->name); if (m_name != infoName) { m_name = infoName; Q_EMIT q->nameChanged(); } const QString infoArgument = QString::fromUtf8(info->argument); if (m_argument != infoArgument) { m_argument = infoArgument; Q_EMIT q->argumentChanged(); } } Module::~Module() { delete d; } QString Module::name() const { return d->m_name; } QString Module::argument() const { return d->m_argument; } } // PulseAudioQt diff --git a/src/module.h b/src/module.h index 052d790..c3f1f22 100644 --- a/src/module.h +++ b/src/module.h @@ -1,57 +1,56 @@ /* Copyright 2017 David Rosca 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 MODULE_H #define MODULE_H -#include "pulseobject.h" #include "kf5pulseaudioqt_export.h" +#include "pulseobject.h" struct pa_module_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Module : public PulseObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString argument READ argument NOTIFY argumentChanged) public: ~Module(); QString name() const; QString argument() const; Q_SIGNALS: void nameChanged(); void argumentChanged(); private: explicit Module(QObject *parent); class ModulePrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // MODULE_H diff --git a/src/module_p.h b/src/module_p.h index 13d8967..1e58e71 100644 --- a/src/module_p.h +++ b/src/module_p.h @@ -1,47 +1,44 @@ /* Copyright 2018 Nicolas Fella 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 MODULE_P_H #define MODULE_P_H #include "module.h" #include namespace PulseAudioQt { - class ModulePrivate { - public: explicit ModulePrivate(Module *q); virtual ~ModulePrivate(); void update(const pa_module_info *info); Module *q; QString m_name; QString m_argument; - }; } // PulseAudioQt #endif diff --git a/src/operation.cpp b/src/operation.cpp index ad0570b..dc28d78 100644 --- a/src/operation.cpp +++ b/src/operation.cpp @@ -1,59 +1,58 @@ /* Copyright 2014-2015 Harald Sitter 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 "operation.h" namespace PulseAudioQt { - PAOperation::PAOperation(pa_operation *operation) : m_operation(operation) { } PAOperation::~PAOperation() { if (m_operation) { pa_operation_unref(m_operation); } } -PAOperation &PAOperation::operator =(pa_operation *operation) +PAOperation &PAOperation::operator=(pa_operation *operation) { m_operation = operation; return *this; } -bool PAOperation::operator !() +bool PAOperation::operator!() { return !m_operation; } -pa_operation *&PAOperation::operator *() +pa_operation *&PAOperation::operator*() { return m_operation; } PAOperation::operator bool() { return m_operation; } } // PulseAudioQt diff --git a/src/operation.h b/src/operation.h index 79e5f78..69bc8b1 100644 --- a/src/operation.h +++ b/src/operation.h @@ -1,71 +1,70 @@ /* Copyright 2014-2015 Harald Sitter 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 OPERATION_H #define OPERATION_H #include namespace PulseAudioQt { - /** * @brief The PAOperation class * Helps with management of pa_operations. pa_operations need to be expicitly * unref'd after use, so this class is essentially a fancy scoping helper where * destruction of an instance would also unref the held operation (if there is * one). */ class PAOperation { public: /** * @brief PAOperation * @param operation operation to manage the scope of */ PAOperation(pa_operation *operation = nullptr); ~PAOperation(); - PAOperation &operator =(pa_operation *operation); + PAOperation &operator=(pa_operation *operation); /** * @brief operator ! * @return whether or not there is an operation pointer */ - bool operator !(); + bool operator!(); /** * @brief operator bool representing whether there is an operation */ operator bool(); /** * @brief operator * * @return pointer to internal pa_operation object */ - pa_operation *&operator *(); + pa_operation *&operator*(); private: pa_operation *m_operation; }; } // PulseAudioQt #endif // OPERATION_H diff --git a/src/port.cpp b/src/port.cpp index ac845a7..46d2a01 100644 --- a/src/port.cpp +++ b/src/port.cpp @@ -1,45 +1,44 @@ /* Copyright 2014-2015 Harald Sitter 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 "port.h" #include "port_p.h" namespace PulseAudioQt { - Port::Port(QObject *parent) : Profile(parent) , d(new PortPrivate(this)) { } Port::~Port() { } PortPrivate::PortPrivate(Port *q) : q(q) { } PortPrivate::~PortPrivate() { } } // PulseAudioQt diff --git a/src/port.h b/src/port.h index 01e6f43..59594dc 100644 --- a/src/port.h +++ b/src/port.h @@ -1,46 +1,45 @@ /* Copyright 2014-2015 Harald Sitter 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 PORT_H #define PORT_H -#include "profile.h" #include "kf5pulseaudioqt_export.h" +#include "profile.h" namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Port : public Profile { Q_OBJECT public: ~Port(); protected: explicit Port(QObject *parent); class PortPrivate *const d; friend class DevicePrivate; }; } // PulseAudioQt #endif // PORT_H diff --git a/src/port_p.h b/src/port_p.h index 1b1d731..d93bf27 100644 --- a/src/port_p.h +++ b/src/port_p.h @@ -1,55 +1,53 @@ /* Copyright 2018 Nicolas Fella 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 . */ #pragma once #include "port.h" #include "profile_p.h" #include namespace PulseAudioQt { - class PortPrivate { public: explicit PortPrivate(Port *q); virtual ~PortPrivate(); Port *q; - template - void setInfo(const PAInfo *info) + template void setInfo(const PAInfo *info) { Profile::Availability newAvailability; - switch (info->available) { - case PA_PORT_AVAILABLE_NO: - newAvailability = Profile::Unavailable; - break; - case PA_PORT_AVAILABLE_YES: - newAvailability = Profile::Available; - break; - default: - newAvailability = Profile::Unknown; - } - q->Profile::d->setCommonInfo(info, newAvailability); + switch (info->available) { + case PA_PORT_AVAILABLE_NO: + newAvailability = Profile::Unavailable; + break; + case PA_PORT_AVAILABLE_YES: + newAvailability = Profile::Available; + break; + default: + newAvailability = Profile::Unknown; + } + q->Profile::d->setCommonInfo(info, newAvailability); } }; } diff --git a/src/profile.cpp b/src/profile.cpp index a92208a..5b01770 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -1,70 +1,69 @@ /* Copyright 2014-2015 Harald Sitter 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 "profile.h" #include "profile_p.h" namespace PulseAudioQt { - Profile::Profile(QObject *parent) : PulseObject(parent) , d(new ProfilePrivate(this)) { } Profile::~Profile() { } ProfilePrivate::ProfilePrivate(Profile *q) : q(q) , m_name() , m_description() , m_priority(0) , m_availability(Profile::Unknown) { } ProfilePrivate::~ProfilePrivate() { } QString Profile::name() const { return d->m_name; } QString Profile::description() const { return d->m_description; } quint32 Profile::priority() const { return d->m_priority; } Profile::Availability Profile::availability() const { return d->m_availability; } } // PulseAudioQt diff --git a/src/profile.h b/src/profile.h index d655ea5..7092fed 100644 --- a/src/profile.h +++ b/src/profile.h @@ -1,72 +1,67 @@ /* Copyright 2014-2015 Harald Sitter 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 PROFILE_H #define PROFILE_H -#include -#include #include "kf5pulseaudioqt_export.h" #include "pulseobject.h" +#include +#include namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Profile : public PulseObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString description READ description NOTIFY descriptionChanged) Q_PROPERTY(quint32 priority READ priority NOTIFY priorityChanged) Q_PROPERTY(Availability availability READ availability NOTIFY availabilityChanged) public: - enum Availability { - Unknown, - Available, - Unavailable - }; + enum Availability { Unknown, Available, Unavailable }; Q_ENUM(Availability) ~Profile(); QString name() const; QString description() const; quint32 priority() const; Availability availability() const; Q_SIGNALS: void nameChanged(); void descriptionChanged(); void priorityChanged(); void availabilityChanged(); protected: explicit Profile(QObject *parent); class ProfilePrivate *const d; friend class Device; friend class CardPrivate; friend class PortPrivate; }; } // PulseAudioQt #endif // PROFILE_H diff --git a/src/profile_p.h b/src/profile_p.h index e68de26..bb5da48 100644 --- a/src/profile_p.h +++ b/src/profile_p.h @@ -1,76 +1,72 @@ /* Copyright 2018 Nicolas Fella 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 . */ #pragma once #include "profile.h" namespace PulseAudioQt { - - class ProfilePrivate { public: explicit ProfilePrivate(Profile *q); virtual ~ProfilePrivate(); Profile *q; QString m_name; QString m_description; quint32 m_priority; Profile::Availability m_availability; - template - void setInfo(const PAInfo *info) + template void setInfo(const PAInfo *info) { setCommonInfo(info, info->available ? Profile::Available : Profile::Unavailable); } - template - void setCommonInfo(const PAInfo *info, Profile::Availability newAvailability) + template void setCommonInfo(const PAInfo *info, Profile::Availability newAvailability) { // Description is optional. Name not so much as we need some ID. Q_ASSERT(info->name); QString infoName = QString::fromUtf8(info->name); if (m_name != infoName) { m_name = infoName; Q_EMIT q->nameChanged(); } if (info->description) { QString infoDescription = QString::fromUtf8(info->description); if (m_description != infoDescription) { m_description = infoDescription; Q_EMIT q->descriptionChanged(); } } if (m_priority != info->priority) { m_priority = info->priority; Q_EMIT q->priorityChanged(); } if (m_availability != newAvailability) { m_availability = newAvailability; Q_EMIT q->availabilityChanged(); } } }; } diff --git a/src/pulseobject.cpp b/src/pulseobject.cpp index 085d2b3..4e21c0b 100644 --- a/src/pulseobject.cpp +++ b/src/pulseobject.cpp @@ -1,107 +1,106 @@ /* Copyright 2014-2015 Harald Sitter 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 "pulseobject.h" #include "pulseobject_p.h" #include "context.h" #include namespace PulseAudioQt { - PulseObject::PulseObject(QObject *parent) : QObject(parent) , d(new PulseObjectPrivate(this)) { } PulseObject::~PulseObject() { delete d; } PulseObjectPrivate::PulseObjectPrivate(PulseObject *q) : q(q) , m_index(0) { } PulseObjectPrivate::~PulseObjectPrivate() { } Context *PulseObject::context() const { return Context::instance(); } uint32_t PulseObject::index() const { return d->m_index; } QString PulseObject::iconName() const { QString name = d->m_properties.value(QStringLiteral("device.icon_name")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = d->m_properties.value(QStringLiteral("media.icon_name")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = d->m_properties.value(QStringLiteral("window.icon_name")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = d->m_properties.value(QStringLiteral("application.icon_name")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = d->m_properties.value(QStringLiteral("application.process.binary")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = d->m_properties.value(QStringLiteral("application.name")).toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } name = property("name").toString(); if (!name.isEmpty() && QIcon::hasThemeIcon(name)) { return name; } return QString(); } QVariantMap PulseObject::properties() const { return d->m_properties; } } // PulseAudioQt diff --git a/src/pulseobject.h b/src/pulseobject.h index 1415831..494f02e 100644 --- a/src/pulseobject.h +++ b/src/pulseobject.h @@ -1,70 +1,69 @@ /* Copyright 2014-2015 Harald Sitter 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 PULSEOBJECT_H #define PULSEOBJECT_H #include #include "kf5pulseaudioqt_export.h" namespace PulseAudioQt { - class Context; template class MapBase; class KF5PULSEAUDIOQT_EXPORT PulseObject : public QObject { Q_OBJECT Q_PROPERTY(quint32 index READ index CONSTANT) Q_PROPERTY(QString iconName READ iconName CONSTANT) Q_PROPERTY(QVariantMap properties READ properties NOTIFY propertiesChanged) public: ~PulseObject(); quint32 index() const; QString iconName() const; QVariantMap properties() const; Context *context() const; Q_SIGNALS: void propertiesChanged(); protected: explicit PulseObject(QObject *parent); class PulseObjectPrivate *const d; private: // Ensure that we get properly parented. PulseObject(); friend class ClientPrivate; friend class CardPrivate; friend class ModulePrivate; friend class VolumeObjectPrivate; }; } // PulseAudioQt #endif // PULSEOBJECT_H diff --git a/src/pulseobject_p.h b/src/pulseobject_p.h index 7b7694a..f48539b 100644 --- a/src/pulseobject_p.h +++ b/src/pulseobject_p.h @@ -1,65 +1,63 @@ /* Copyright 2018 Nicolas Fella 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 PULSEOBJECT_P_H #define PULSEOBJECT_P_H #include "debug.h" #include #include #include "context.h" namespace PulseAudioQt { - class PulseObjectPrivate { public: explicit PulseObjectPrivate(PulseObject *q); virtual ~PulseObjectPrivate(); PulseObject *q; quint32 m_index; QVariantMap m_properties; - template - void updatePulseObject(PAInfo *info) + template void updatePulseObject(PAInfo *info) { m_index = info->index; m_properties.clear(); void *it = nullptr; while (const char *key = pa_proplist_iterate(info->proplist, &it)) { Q_ASSERT(key); const char *value = pa_proplist_gets(info->proplist, key); if (!value) { qCDebug(PULSEAUDIOQT) << "property" << key << "not a string"; continue; } Q_ASSERT(value); m_properties.insert(QString::fromUtf8(key), QString::fromUtf8(value)); } Q_EMIT q->propertiesChanged(); } }; } #endif diff --git a/src/server.cpp b/src/server.cpp index 22b0ce5..fc7fa95 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1,138 +1,136 @@ /* Copyright 2016 David Rosca 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 "server.h" #include "server_p.h" #include "context.h" #include "context_p.h" +#include "debug.h" #include "sink.h" #include "source.h" -#include "debug.h" namespace PulseAudioQt { - Server::Server(Context *context) : QObject(context) , d(new ServerPrivate(this)) { Q_ASSERT(context); connect(&context->d->m_sinks, &MapBaseQObject::added, this, &Server::updateDefaultDevices); connect(&context->d->m_sinks, &MapBaseQObject::removed, this, &Server::updateDefaultDevices); connect(&context->d->m_sources, &MapBaseQObject::added, this, &Server::updateDefaultDevices); connect(&context->d->m_sources, &MapBaseQObject::removed, this, &Server::updateDefaultDevices); } Server::~Server() { } ServerPrivate::ServerPrivate(Server *q) : q(q) , m_defaultSink(nullptr) , m_defaultSource(nullptr) { } ServerPrivate::~ServerPrivate() { } Sink *Server::defaultSink() const { return d->m_defaultSink; } void Server::setDefaultSink(Sink *sink) { Q_ASSERT(sink); Context::instance()->setDefaultSink(sink->name()); } Source *Server::defaultSource() const { return d->m_defaultSource; } void Server::setDefaultSource(Source *source) { Q_ASSERT(source); Context::instance()->setDefaultSource(source->name()); } void Server::reset() { if (d->m_defaultSink) { d->m_defaultSink = nullptr; Q_EMIT defaultSinkChanged(d->m_defaultSink); } if (d->m_defaultSource) { d->m_defaultSource = nullptr; Q_EMIT defaultSourceChanged(d->m_defaultSource); } } void ServerPrivate::update(const pa_server_info *info) { m_defaultSinkName = QString::fromUtf8(info->default_sink_name); m_defaultSourceName = QString::fromUtf8(info->default_source_name); q->updateDefaultDevices(); } -template -static Type *findByName(const Vector &vector, const QString &name) +template static Type *findByName(const Vector &vector, const QString &name) { Type *out = nullptr; if (name.isEmpty()) { return out; } for (Type *t : vector) { out = t; if (out->name() == name) { return out; } } qCWarning(PULSEAUDIOQT) << "No object for name" << name; return out; } void Server::updateDefaultDevices() { Sink *sink = findByName(Context::instance()->d->m_sinks.data(), d->m_defaultSinkName); Source *source = findByName(Context::instance()->d->m_sources.data(), d->m_defaultSourceName); if (d->m_defaultSink != sink) { qCDebug(PULSEAUDIOQT) << "Default sink changed" << sink; d->m_defaultSink = sink; Q_EMIT defaultSinkChanged(d->m_defaultSink); } if (d->m_defaultSource != source) { qCDebug(PULSEAUDIOQT) << "Default source changed" << source; d->m_defaultSource = source; Q_EMIT defaultSourceChanged(d->m_defaultSource); } } } // PulseAudioQt diff --git a/src/server.h b/src/server.h index 1ad97ac..09eb137 100644 --- a/src/server.h +++ b/src/server.h @@ -1,67 +1,65 @@ /* Copyright 2016 David Rosca 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 SERVER_H #define SERVER_H -#include #include "kf5pulseaudioqt_export.h" +#include namespace PulseAudioQt { - class Sink; class Source; class Context; class KF5PULSEAUDIOQT_EXPORT Server : public QObject { Q_OBJECT public: ~Server(); Sink *defaultSink() const; void setDefaultSink(Sink *sink); Source *defaultSource() const; void setDefaultSource(Source *source); - Q_SIGNALS: void defaultSinkChanged(PulseAudioQt::Sink *sink); void defaultSourceChanged(PulseAudioQt::Source *source); private: explicit Server(Context *context); void reset(); void updateDefaultDevices(); class ServerPrivate *const d; friend class ServerPrivate; friend class Context; friend class ContextPrivate; }; } // PulseAudioQt #endif // CONTEXT_H diff --git a/src/server_p.h b/src/server_p.h index c80c845..6a666b9 100644 --- a/src/server_p.h +++ b/src/server_p.h @@ -1,43 +1,41 @@ /* Copyright 2018 Nicolas Fella 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 . */ #pragma once #include "server.h" #include namespace PulseAudioQt { - class ServerPrivate { - public: explicit ServerPrivate(Server *q); virtual ~ServerPrivate(); Server *q; QString m_defaultSinkName; QString m_defaultSourceName; Sink *m_defaultSink; Source *m_defaultSource; void update(const pa_server_info *info); }; } diff --git a/src/sink.cpp b/src/sink.cpp index 86b277f..37c02a9 100644 --- a/src/sink.cpp +++ b/src/sink.cpp @@ -1,93 +1,92 @@ /* Copyright 2014-2015 Harald Sitter 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 "sink.h" #include "sink_p.h" #include "context.h" #include "context_p.h" #include "server.h" #include "device_p.h" #include "volumeobject_p.h" namespace PulseAudioQt { - Sink::Sink(QObject *parent) : Device(parent) , d(new SinkPrivate(this)) { connect(context()->server(), &Server::defaultSinkChanged, this, &Sink::defaultChanged); } SinkPrivate::SinkPrivate(Sink *q) : q(q) { } Sink::~Sink() { delete d; } void SinkPrivate::update(const pa_sink_info *info) { q->Device::d->updateDevice(info); } void Sink::setVolume(qint64 volume) { context()->d->setGenericVolume(index(), -1, volume, VolumeObject::d->cvolume(), &pa_context_set_sink_volume_by_index); } void Sink::setMuted(bool muted) { context()->d->setGenericMute(index(), muted, &pa_context_set_sink_mute_by_index); } void Sink::setActivePortIndex(quint32 port_index) { Port *port = qobject_cast(ports().at(port_index)); if (!port) { qCWarning(PULSEAUDIOQT) << "invalid port set request" << port_index; return; } context()->d->setGenericPort(index(), port->name(), &pa_context_set_sink_port_by_index); } void Sink::setChannelVolume(int channel, qint64 volume) { context()->d->setGenericVolume(index(), channel, volume, VolumeObject::d->cvolume(), &pa_context_set_sink_volume_by_index); } bool Sink::isDefault() const { return context()->server()->defaultSink() == this; } void Sink::setDefault(bool enable) { if (!isDefault() && enable) { context()->server()->setDefaultSink(this); } } } // PulseAudioQt diff --git a/src/sink.h b/src/sink.h index 554917f..64174f0 100644 --- a/src/sink.h +++ b/src/sink.h @@ -1,55 +1,54 @@ /* Copyright 2014-2015 Harald Sitter 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 SINK_H #define SINK_H #include "device.h" struct pa_sink_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Sink : public Device { Q_OBJECT public: ~Sink(); void setVolume(qint64 volume) override; void setMuted(bool muted) override; void setActivePortIndex(quint32 port_index) override; void setChannelVolume(int channel, qint64 volume) override; bool isDefault() const override; void setDefault(bool enable) override; private: explicit Sink(QObject *parent); class SinkPrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // SINK_H diff --git a/src/sink_p.h b/src/sink_p.h index f6a6011..54c6fd3 100644 --- a/src/sink_p.h +++ b/src/sink_p.h @@ -1,41 +1,38 @@ /* Copyright 2018 Nicolas Fella 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 SINK_P_H #define SINK_P_H -#include "sink.h" #include "pulse/introspect.h" - +#include "sink.h" namespace PulseAudioQt { - class SinkPrivate { public: explicit SinkPrivate(Sink *q); void update(const pa_sink_info *info); Sink *q; }; } #endif - diff --git a/src/sinkinput.cpp b/src/sinkinput.cpp index 137fc76..7d79a7c 100644 --- a/src/sinkinput.cpp +++ b/src/sinkinput.cpp @@ -1,76 +1,75 @@ /* Copyright 2014-2015 Harald Sitter 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 "sinkinput.h" #include "sinkinput_p.h" #include "context.h" #include "context_p.h" #include "stream_p.h" namespace PulseAudioQt { - SinkInput::SinkInput(QObject *parent) : Stream(parent) , d(new SinkInputPrivate(this)) { } SinkInputPrivate::SinkInputPrivate(SinkInput *q) : q(q) { } SinkInput::~SinkInput() { delete d; } void SinkInputPrivate::update(const pa_sink_input_info *info) { q->Stream::d->updateStream(info); if (q->Stream::d->m_deviceIndex != info->sink) { q->Stream::d->m_deviceIndex = info->sink; Q_EMIT q->deviceIndexChanged(); } } void SinkInput::setDeviceIndex(quint32 deviceIndex) { context()->d->setGenericDeviceForStream(index(), deviceIndex, &pa_context_move_sink_input_by_index); } void SinkInput::setVolume(qint64 volume) { context()->d->setGenericVolume(index(), -1, volume, VolumeObject::d->cvolume(), &pa_context_set_sink_input_volume); } void SinkInput::setMuted(bool muted) { context()->d->setGenericMute(index(), muted, &pa_context_set_sink_input_mute); } void SinkInput::setChannelVolume(int channel, qint64 volume) { context()->d->setGenericVolume(index(), channel, volume, VolumeObject::d->cvolume(), &pa_context_set_sink_input_volume); } } // PulseAudioQt diff --git a/src/sinkinput.h b/src/sinkinput.h index c5f84e6..d3e2a33 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -1,54 +1,53 @@ /* Copyright 2014-2015 Harald Sitter 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 SINKINPUT_H #define SINKINPUT_H #include "stream.h" struct pa_sink_input_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT SinkInput : public Stream { Q_OBJECT public: ~SinkInput(); void setSinkIndex(quint32 sinkIndex); void setVolume(qint64 volume) override; void setMuted(bool muted) override; void setChannelVolume(int channel, qint64 volume) override; void setDeviceIndex(quint32 deviceIndex) override; private: SinkInput(QObject *parent); class SinkInputPrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // SINKINPUT_H diff --git a/src/sinkinput_p.h b/src/sinkinput_p.h index a5eb23c..1917d16 100644 --- a/src/sinkinput_p.h +++ b/src/sinkinput_p.h @@ -1,42 +1,39 @@ /* Copyright 2018 Nicolas Fella 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 SINKINPUT_P_H #define SINKINPUT_P_H #include "sinkinput.h" #include namespace PulseAudioQt { - class SinkInputPrivate { - public: explicit SinkInputPrivate(SinkInput *q); SinkInput *q; void update(const pa_sink_input_info *info); - }; } #endif diff --git a/src/source.cpp b/src/source.cpp index e6dbe91..500d86a 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -1,91 +1,90 @@ /* Copyright 2014-2015 Harald Sitter 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 "source.h" #include "source_p.h" #include "context.h" #include "context_p.h" -#include "server.h" #include "device_p.h" +#include "server.h" #include "volumeobject_p.h" namespace PulseAudioQt { - Source::Source(QObject *parent) : Device(parent) , d(new SourcePrivate(this)) { connect(context()->server(), &Server::defaultSourceChanged, this, &Source::defaultChanged); } SourcePrivate::SourcePrivate(Source *q) - :q(q) + : q(q) { } void SourcePrivate::update(const pa_source_info *info) { q->Device::d->updateDevice(info); } void Source::setVolume(qint64 volume) { context()->d->setGenericVolume(index(), -1, volume, VolumeObject::d->cvolume(), &pa_context_set_source_volume_by_index); } void Source::setMuted(bool muted) { context()->d->setGenericMute(index(), muted, &pa_context_set_source_mute_by_index); } void Source::setActivePortIndex(quint32 port_index) { Port *port = qobject_cast(ports().at(port_index)); if (!port) { qCWarning(PULSEAUDIOQT) << "invalid port set request" << port_index; return; } context()->d->setGenericPort(index(), port->name(), &pa_context_set_source_port_by_index); } void Source::setChannelVolume(int channel, qint64 volume) { context()->d->setGenericVolume(index(), channel, volume, VolumeObject::d->cvolume(), &pa_context_set_source_volume_by_index); } bool Source::isDefault() const { return context()->server()->defaultSource() == this; } void Source::setDefault(bool enable) { if (!isDefault() && enable) { context()->server()->setDefaultSource(this); } } Source::~Source() { delete d; } } // PulseAudioQt diff --git a/src/source.h b/src/source.h index 4c47b1d..dafd594 100644 --- a/src/source.h +++ b/src/source.h @@ -1,55 +1,54 @@ /* Copyright 2014-2015 Harald Sitter 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 SOURCE_H #define SOURCE_H #include "device.h" struct pa_source_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT Source : public Device { Q_OBJECT public: ~Source(); void setVolume(qint64 volume) override; void setMuted(bool muted) override; void setActivePortIndex(quint32 port_index) override; void setChannelVolume(int channel, qint64 volume) override; bool isDefault() const override; void setDefault(bool enable) override; private: explicit Source(QObject *parent); class SourcePrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // SOURCE_H diff --git a/src/source_p.h b/src/source_p.h index 19cfab4..dd1e18c 100644 --- a/src/source_p.h +++ b/src/source_p.h @@ -1,39 +1,38 @@ /* Copyright 2018 Nicolas Fella 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 SOURCE_P_H #define SOURCE_P_H -#include #include "source.h" +#include namespace PulseAudioQt { - class SourcePrivate { public: explicit SourcePrivate(Source *q); void update(const pa_source_info *info); Source *q; }; } #endif diff --git a/src/sourceoutput.cpp b/src/sourceoutput.cpp index 8342de0..3bede7a 100644 --- a/src/sourceoutput.cpp +++ b/src/sourceoutput.cpp @@ -1,75 +1,74 @@ /* Copyright 2014-2015 Harald Sitter 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 "sourceoutput.h" #include "sourceoutput_p.h" #include "context.h" #include "context_p.h" #include "stream_p.h" namespace PulseAudioQt { - SourceOutput::SourceOutput(QObject *parent) : Stream(parent) , d(new SourceOutputPrivate(this)) { } SourceOutput::~SourceOutput() { } SourceOutputPrivate::SourceOutputPrivate(SourceOutput *q) : q(q) { } void SourceOutputPrivate::update(const pa_source_output_info *info) { q->Stream::d->updateStream(info); if (q->Stream::d->m_deviceIndex != info->source) { q->Stream::d->m_deviceIndex = info->source; Q_EMIT q->deviceIndexChanged(); } } void SourceOutput::setDeviceIndex(quint32 deviceIndex) { context()->d->setGenericDeviceForStream(index(), deviceIndex, &pa_context_move_source_output_by_index); } void SourceOutput::setVolume(qint64 volume) { context()->d->setGenericVolume(index(), -1, volume, VolumeObject::d->cvolume(), &pa_context_set_source_output_volume); } void SourceOutput::setMuted(bool muted) { context()->d->setGenericMute(index(), muted, &pa_context_set_source_output_mute); } void SourceOutput::setChannelVolume(int channel, qint64 volume) { context()->d->setGenericVolume(index(), channel, volume, VolumeObject::d->cvolume(), &pa_context_set_source_output_volume); } } // PulseAudioQt diff --git a/src/sourceoutput.h b/src/sourceoutput.h index 3a16f0c..36d8ca6 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -1,52 +1,51 @@ /* Copyright 2014-2015 Harald Sitter 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 SOURCEOUTPUT_H #define SOURCEOUTPUT_H #include "stream.h" struct pa_source_output_info; namespace PulseAudioQt { - class SourceOutput : public Stream { Q_OBJECT public: ~SourceOutput(); void setVolume(qint64 volume) override; void setMuted(bool muted) override; void setChannelVolume(int channel, qint64 volume) override; void setDeviceIndex(quint32 deviceIndex) override; private: explicit SourceOutput(QObject *parent); class SourceOutputPrivate *const d; friend class MapBase; }; } // PulseAudioQt #endif // SOURCEOUTPUT_H diff --git a/src/sourceoutput_p.h b/src/sourceoutput_p.h index 44b5292..e4e40bf 100644 --- a/src/sourceoutput_p.h +++ b/src/sourceoutput_p.h @@ -1,42 +1,40 @@ /* Copyright 2018 Nicolas Fella 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 SOURCEOUTPUT_P_H #define SOURCEOUTPUT_P_H -#include #include "sourceoutput.h" +#include namespace PulseAudioQt { - class SourceOutputPrivate { - public: explicit SourceOutputPrivate(SourceOutput *q); void update(const pa_source_output_info *info); SourceOutput *q; }; } #endif diff --git a/src/stream.cpp b/src/stream.cpp index 010953f..845c27f 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -1,80 +1,79 @@ /* Copyright 2014-2015 Harald Sitter 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 "stream.h" +#include "context_p.h" #include "stream_p.h" #include "volumeobject_p.h" -#include "context_p.h" namespace PulseAudioQt { - Stream::Stream(QObject *parent) : VolumeObject(parent) , d(new StreamPrivate(this)) { VolumeObject::d->m_volumeWritable = false; VolumeObject::d->m_hasVolume = false; } Stream::~Stream() { delete d; } StreamPrivate::StreamPrivate(Stream *q) : q(q) , m_deviceIndex(PA_INVALID_INDEX) , m_clientIndex(PA_INVALID_INDEX) , m_virtualStream(false) , m_corked(false) { } StreamPrivate::~StreamPrivate() { } QString Stream::name() const { return d->m_name; } Client *Stream::client() const { return context()->d->m_clients.data().value(d->m_clientIndex, nullptr); } bool Stream::isVirtualStream() const { return d->m_virtualStream; } quint32 Stream::deviceIndex() const { return d->m_deviceIndex; } bool Stream::isCorked() const { return d->m_corked; } } // PulseAudioQt diff --git a/src/stream.h b/src/stream.h index 622b828..0ad2206 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,74 +1,73 @@ /* Copyright 2014-2015 Harald Sitter 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 STREAM_H #define STREAM_H #include #include "volumeobject.h" // Properties need fully qualified classes even with pointers. #include "client.h" namespace PulseAudioQt { - class StreamPrivate; class KF5PULSEAUDIOQT_EXPORT Stream : public VolumeObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(PulseAudioQt::Client *client READ client NOTIFY clientChanged) Q_PROPERTY(bool virtualStream READ isVirtualStream NOTIFY virtualStreamChanged) Q_PROPERTY(quint32 deviceIndex READ deviceIndex WRITE setDeviceIndex NOTIFY deviceIndexChanged) Q_PROPERTY(bool corked READ isCorked NOTIFY corkedChanged) public: ~Stream(); QString name() const; Client *client() const; bool isVirtualStream() const; quint32 deviceIndex() const; bool isCorked() const; virtual void setDeviceIndex(quint32 deviceIndex) = 0; Q_SIGNALS: void nameChanged(); void clientChanged(); void virtualStreamChanged(); void deviceIndexChanged(); void corkedChanged(); protected: explicit Stream(QObject *parent); class StreamPrivate *const d; friend class SinkInputPrivate; friend class SourceOutputPrivate; }; } // PulseAudioQt #endif // STREAM_H diff --git a/src/stream_p.h b/src/stream_p.h index 90dc645..0ca460a 100644 --- a/src/stream_p.h +++ b/src/stream_p.h @@ -1,77 +1,73 @@ /* Copyright 2018 Nicolas Fella 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 STREAM_P_H #define STREAM_P_H #include "stream.h" #include "volumeobject_p.h" namespace PulseAudioQt { - class StreamPrivate { public: explicit StreamPrivate(Stream *q); virtual ~StreamPrivate(); Stream *q; quint32 m_deviceIndex; QString m_name; quint32 m_clientIndex; bool m_virtualStream; bool m_corked; - - template - void updateStream(const PAInfo *info) + template void updateStream(const PAInfo *info) { q->VolumeObject::d->updateVolumeObject(info); if (m_name != QString::fromUtf8(info->name)) { m_name = QString::fromUtf8(info->name); Q_EMIT q->nameChanged(); } if (q->VolumeObject::d->m_hasVolume != info->has_volume) { q->VolumeObject::d->m_hasVolume = info->has_volume; Q_EMIT q->hasVolumeChanged(); } if (q->VolumeObject::d->m_volumeWritable != info->volume_writable) { q->VolumeObject::d->m_volumeWritable = info->volume_writable; Q_EMIT q->isVolumeWritableChanged(); } if (m_clientIndex != info->client) { m_clientIndex = info->client; Q_EMIT q->clientChanged(); } if (m_virtualStream != (info->client == PA_INVALID_INDEX)) { m_virtualStream = info->client == PA_INVALID_INDEX; Q_EMIT q->virtualStreamChanged(); } if (m_corked != info->corked) { m_corked = info->corked; Q_EMIT q->corkedChanged(); } } - }; } #endif diff --git a/src/streamrestore.cpp b/src/streamrestore.cpp index cff00bd..ed71dc7 100644 --- a/src/streamrestore.cpp +++ b/src/streamrestore.cpp @@ -1,219 +1,218 @@ /* Copyright 2016 David Rosca 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 "streamrestore.h" -#include "streamrestore_p.h" #include "context.h" #include "context_p.h" +#include "streamrestore_p.h" #include "debug.h" #include "pulseobject_p.h" namespace PulseAudioQt { - StreamRestore::StreamRestore(quint32 index, const QVariantMap &properties, QObject *parent) : PulseObject(parent) , d(new StreamRestorePrivate(this)) { memset(&d->m_volume, 0, sizeof(d->m_volume)); memset(&d->m_channelMap, 0, sizeof(d->m_channelMap)); d->m_muted = false; PulseObject::d->m_index = index; PulseObject::d->m_properties = properties; } StreamRestore::~StreamRestore() { } StreamRestorePrivate::StreamRestorePrivate(StreamRestore *q) - :q(q) + : q(q) { } StreamRestorePrivate::~StreamRestorePrivate() { } void StreamRestorePrivate::update(const pa_ext_stream_restore_info *info) { m_cache.valid = false; const QString infoName = QString::fromUtf8(info->name); if (m_name != infoName) { m_name = infoName; Q_EMIT q->nameChanged(); } const QString infoDevice = QString::fromUtf8(info->device); if (m_device != infoDevice) { m_device = infoDevice; Q_EMIT q->deviceChanged(); } if (m_muted != info->mute) { m_muted = info->mute; Q_EMIT q->mutedChanged(); } if (memcmp(&m_volume, &info->volume, sizeof(pa_cvolume)) != 0) { m_volume = info->volume; Q_EMIT q->volumeChanged(); Q_EMIT q->channelVolumesChanged(); } if (memcmp(&m_channelMap, &info->channel_map, sizeof(pa_channel_map)) != 0) { m_channels.clear(); m_channels.reserve(info->channel_map.channels); for (int i = 0; i < info->channel_map.channels; ++i) { m_channels << QString::fromUtf8(pa_channel_position_to_pretty_string(info->channel_map.map[i])); } m_channelMap = info->channel_map; Q_EMIT q->channelsChanged(); } } QString StreamRestore::name() const { return d->m_name; } QString StreamRestore::device() const { return d->m_device; } void StreamRestore::setDevice(const QString &device) { if (d->m_cache.valid) { if (d->m_cache.device != device) { d->writeChanges(d->m_cache.volume, d->m_cache.muted, device); } } else { if (d->m_device != device) { d->writeChanges(d->m_volume, d->m_muted, device); } } } qint64 StreamRestore::volume() const { return d->m_volume.values[0]; } void StreamRestore::setVolume(qint64 volume) { pa_cvolume vol = d->m_cache.valid ? d->m_cache.volume : d->m_volume; for (int i = 0; i < vol.channels; ++i) { vol.values[i] = volume; } if (d->m_cache.valid) { d->writeChanges(vol, d->m_cache.muted, d->m_cache.device); } else { d->writeChanges(vol, d->m_muted, d->m_device); } } bool StreamRestore::isMuted() const { return d->m_muted; } void StreamRestore::setMuted(bool muted) { if (d->m_cache.valid) { if (d->m_cache.muted != muted) { d->writeChanges(d->m_cache.volume, muted, d->m_cache.device); } } else { if (d->m_muted != muted) { d->writeChanges(d->m_volume, muted, d->m_device); } } } bool StreamRestore::hasVolume() const { return true; } bool StreamRestore::isVolumeWritable() const { return true; } QVector StreamRestore::channels() const { return d->m_channels; } QVector StreamRestore::channelVolumes() const { QVector ret; ret.reserve(d->m_volume.channels); for (int i = 0; i < d->m_volume.channels; ++i) { ret << d->m_volume.values[i]; } return ret; } void StreamRestore::setChannelVolume(int channel, qint64 volume) { Q_ASSERT(channel >= 0 && channel < d->m_volume.channels); pa_cvolume vol = d->m_cache.valid ? d->m_cache.volume : d->m_volume; vol.values[channel] = volume; if (d->m_cache.valid) { d->writeChanges(vol, d->m_cache.muted, d->m_cache.device); } else { d->writeChanges(vol, d->m_muted, d->m_device); } } quint32 StreamRestore::deviceIndex() const { return PA_INVALID_INDEX; } void StreamRestore::setDeviceIndex(quint32 deviceIndex) { Q_UNUSED(deviceIndex); qCWarning(PULSEAUDIOQT) << "Not implemented"; } void StreamRestorePrivate::writeChanges(const pa_cvolume &volume, bool muted, const QString &device) { const QByteArray nameData = m_name.toUtf8(); const QByteArray deviceData = device.toUtf8(); pa_ext_stream_restore_info info; info.name = nameData.constData(); info.channel_map = m_channelMap; info.volume = volume; info.device = deviceData.isEmpty() ? nullptr : deviceData.constData(); info.mute = muted; m_cache.valid = true; m_cache.volume = volume; m_cache.muted = muted; m_cache.device = device; q->context()->d->streamRestoreWrite(&info); } } // PulseAudioQt diff --git a/src/streamrestore.h b/src/streamrestore.h index 2f5f416..0e0d475 100644 --- a/src/streamrestore.h +++ b/src/streamrestore.h @@ -1,89 +1,88 @@ /* Copyright 2016 David Rosca 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 STREAMRESTORE_H #define STREAMRESTORE_H #include "pulseobject.h" struct pa_ext_stream_restore_info; namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT StreamRestore : public PulseObject { Q_OBJECT Q_PROPERTY(QString name READ name NOTIFY nameChanged) Q_PROPERTY(QString device READ device WRITE setDevice NOTIFY deviceChanged) Q_PROPERTY(qint64 volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) Q_PROPERTY(bool hasVolume READ hasVolume CONSTANT) Q_PROPERTY(bool volumeWritable READ isVolumeWritable CONSTANT) Q_PROPERTY(QVector channels READ channels NOTIFY channelsChanged) Q_PROPERTY(QVector channelVolumes READ channelVolumes NOTIFY channelVolumesChanged) Q_PROPERTY(quint32 deviceIndex READ deviceIndex WRITE setDeviceIndex NOTIFY deviceIndexChanged) public: ~StreamRestore(); QString name() const; QString device() const; void setDevice(const QString &device); qint64 volume() const; void setVolume(qint64 volume); bool isMuted() const; void setMuted(bool muted); bool hasVolume() const; bool isVolumeWritable() const; QVector channels() const; QVector channelVolumes() const; quint32 deviceIndex() const; void setDeviceIndex(quint32 deviceIndex); void setChannelVolume(int channel, qint64 volume); Q_SIGNALS: void nameChanged(); void deviceChanged(); void volumeChanged(); void mutedChanged(); void channelsChanged(); void channelVolumesChanged(); void deviceIndexChanged(); private: explicit StreamRestore(quint32 index, const QVariantMap &properties, QObject *parent); class StreamRestorePrivate *const d; friend class MapBase; friend class ContextPrivate; }; } // PulseAudioQt #endif // STREAMRESTORE_H diff --git a/src/streamrestore_p.h b/src/streamrestore_p.h index fe27d67..3d19f6c 100644 --- a/src/streamrestore_p.h +++ b/src/streamrestore_p.h @@ -1,60 +1,56 @@ /* Copyright 2018 Nicolas Fella 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 STREAMRESTORE_P_H #define STREAMRESTORE_P_H #include "streamrestore.h" #include #include namespace PulseAudioQt { - class StreamRestorePrivate { - public: explicit StreamRestorePrivate(StreamRestore *q); virtual ~StreamRestorePrivate(); void writeChanges(const pa_cvolume &volume, bool muted, const QString &device); void update(const pa_ext_stream_restore_info *info); StreamRestore *q; QString m_name; QString m_device; pa_cvolume m_volume; pa_channel_map m_channelMap; QVector m_channels; bool m_muted; struct { bool valid = false; pa_cvolume volume; bool muted; QString device; } m_cache; - - }; } #endif diff --git a/src/volumeobject.cpp b/src/volumeobject.cpp index 2a156e3..d6f6e3e 100644 --- a/src/volumeobject.cpp +++ b/src/volumeobject.cpp @@ -1,93 +1,92 @@ /* Copyright 2014-2015 Harald Sitter 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 #include "volumeobject.h" #include "volumeobject_p.h" namespace PulseAudioQt { - VolumeObject::VolumeObject(QObject *parent) : PulseObject(parent) , d(new VolumeObjectPrivate(this)) { } VolumeObjectPrivate::VolumeObjectPrivate(VolumeObject *q) : q(q) , m_muted(true) , m_hasVolume(true) , m_volumeWritable(true) { pa_cvolume_init(&m_volume); } VolumeObject::~VolumeObject() { } qint64 VolumeObject::volume() const { return pa_cvolume_max(&d->m_volume); } bool VolumeObject::isMuted() const { return d->m_muted; } pa_cvolume VolumeObjectPrivate::cvolume() const { return m_volume; } bool VolumeObject::hasVolume() const { return d->m_hasVolume; } bool VolumeObject::isVolumeWritable() const { return d->m_volumeWritable; } QVector VolumeObject::channels() const { return d->m_channels; } QStringList VolumeObject::rawChannels() const { return d->m_rawChannels; } QVector VolumeObject::channelVolumes() const { QVector ret; ret.reserve(d->m_volume.channels); for (int i = 0; i < d->m_volume.channels; ++i) { ret << d->m_volume.values[i]; } return ret; } } // PulseAudioQt diff --git a/src/volumeobject.h b/src/volumeobject.h index cf8c0d7..80641a6 100644 --- a/src/volumeobject.h +++ b/src/volumeobject.h @@ -1,76 +1,75 @@ /* Copyright 2014-2015 Harald Sitter 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 VOLUMEOBJECT_H #define VOLUMEOBJECT_H #include "pulseobject.h" namespace PulseAudioQt { - class KF5PULSEAUDIOQT_EXPORT VolumeObject : public PulseObject { Q_OBJECT Q_PROPERTY(qint64 volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) Q_PROPERTY(bool hasVolume READ hasVolume NOTIFY hasVolumeChanged) Q_PROPERTY(bool volumeWritable READ isVolumeWritable NOTIFY isVolumeWritableChanged) Q_PROPERTY(QVector channels READ channels NOTIFY channelsChanged) Q_PROPERTY(QVector channelVolumes READ channelVolumes NOTIFY channelVolumesChanged) Q_PROPERTY(QStringList rawChannels READ rawChannels NOTIFY rawChannelsChanged) public: ~VolumeObject(); qint64 volume() const; virtual void setVolume(qint64 volume) = 0; bool isMuted() const; virtual void setMuted(bool muted) = 0; bool hasVolume() const; bool isVolumeWritable() const; QVector channels() const; QStringList rawChannels() const; QVector channelVolumes() const; virtual void setChannelVolume(int channel, qint64 volume) = 0; Q_SIGNALS: void volumeChanged(); void mutedChanged(); void hasVolumeChanged(); void isVolumeWritableChanged(); void channelsChanged(); void rawChannelsChanged(); void channelVolumesChanged(); protected: explicit VolumeObject(QObject *parent); class VolumeObjectPrivate *const d; friend class DevicePrivate; friend class StreamPrivate; }; } // PulseAudioQt #endif // VOLUMEOBJECT_H diff --git a/src/volumeobject_p.h b/src/volumeobject_p.h index 693db25..6c99393 100644 --- a/src/volumeobject_p.h +++ b/src/volumeobject_p.h @@ -1,81 +1,80 @@ /* Copyright 2018 Nicolas Fella 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 VOLUMEOBJECT_P_H #define VOLUMEOBJECT_P_H #include -#include "volumeobject.h" #include "pulseobject_p.h" +#include "volumeobject.h" -namespace PulseAudioQt { - -class VolumeObjectPrivate { +namespace PulseAudioQt +{ +class VolumeObjectPrivate +{ public: explicit VolumeObjectPrivate(VolumeObject *q); VolumeObject *q; pa_channel_map foo; pa_cvolume m_volume; bool m_muted; bool m_hasVolume; bool m_volumeWritable; QVector m_channels; QStringList m_rawChannels; pa_cvolume cvolume() const; - template - void updateVolumeObject(PAInfo *info) + template void updateVolumeObject(PAInfo *info) { q->PulseObject::d->updatePulseObject(info); if (m_muted != info->mute) { m_muted = info->mute; Q_EMIT q->mutedChanged(); } if (!pa_cvolume_equal(&m_volume, &info->volume)) { m_volume = info->volume; Q_EMIT q->volumeChanged(); Q_EMIT q->channelVolumesChanged(); } QVector infoChannels; infoChannels.reserve(info->channel_map.channels); for (int i = 0; i < info->channel_map.channels; ++i) { infoChannels << QString::fromUtf8(pa_channel_position_to_pretty_string(info->channel_map.map[i])); } if (m_channels != infoChannels) { m_channels = infoChannels; Q_EMIT q->channelsChanged(); } QStringList infoRawChannels; infoRawChannels.reserve(info->channel_map.channels); for (int i = 0; i < info->channel_map.channels; ++i) { infoRawChannels << QString::fromUtf8(pa_channel_position_to_string(info->channel_map.map[i])); } if (m_rawChannels != infoRawChannels) { m_rawChannels = infoRawChannels; Q_EMIT q->rawChannelsChanged(); } } - }; } #endif