File indexing completed on 2024-04-21 04:56:55

0001 /**
0002  * SPDX-FileCopyrightText: 2017 Nicolas Fella <nicolas.fella@gmx.de>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "systemvolumeplugin-pulse.h"
0008 
0009 #include <KPluginFactory>
0010 
0011 #include <QDebug>
0012 #include <QJsonArray>
0013 #include <QJsonDocument>
0014 #include <QJsonObject>
0015 #include <QProcess>
0016 
0017 #include <core/device.h>
0018 
0019 #include "plugin_systemvolume_debug.h"
0020 #include <PulseAudioQt/Context>
0021 #include <PulseAudioQt/Sink>
0022 
0023 K_PLUGIN_CLASS_WITH_JSON(SystemvolumePlugin, "kdeconnect_systemvolume.json")
0024 
0025 SystemvolumePlugin::SystemvolumePlugin(QObject *parent, const QVariantList &args)
0026     : KdeConnectPlugin(parent, args)
0027     , sinksMap()
0028 {
0029 }
0030 
0031 void SystemvolumePlugin::receivePacket(const NetworkPacket &np)
0032 {
0033     if (!PulseAudioQt::Context::instance()->isValid())
0034         return;
0035 
0036     if (np.has(QStringLiteral("requestSinks"))) {
0037         sendSinkList();
0038     } else {
0039         QString name = np.get<QString>(QStringLiteral("name"));
0040 
0041         PulseAudioQt::Sink *sink = sinksMap.value(name);
0042         if (sink) {
0043             if (np.has(QStringLiteral("volume"))) {
0044                 int volume = np.get<int>(QStringLiteral("volume"));
0045                 sink->setVolume(volume);
0046                 sink->setMuted(false);
0047             }
0048             if (np.has(QStringLiteral("muted"))) {
0049                 sink->setMuted(np.get<bool>(QStringLiteral("muted")));
0050             }
0051             if (np.has(QStringLiteral("enabled"))) {
0052                 sink->setDefault(np.get<bool>(QStringLiteral("enabled")));
0053             }
0054         }
0055     }
0056 }
0057 
0058 void SystemvolumePlugin::sendSinkList()
0059 {
0060     QJsonDocument document;
0061     QJsonArray array;
0062 
0063     sinksMap.clear();
0064 
0065     const auto sinks = PulseAudioQt::Context::instance()->sinks();
0066     for (PulseAudioQt::Sink *sink : sinks) {
0067         sinksMap.insert(sink->name(), sink);
0068 
0069         connect(sink, &PulseAudioQt::Sink::volumeChanged, this, [this, sink] {
0070             NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME);
0071             np.set<int>(QStringLiteral("volume"), sink->volume());
0072             np.set<QString>(QStringLiteral("name"), sink->name());
0073             sendPacket(np);
0074         });
0075 
0076         connect(sink, &PulseAudioQt::Sink::mutedChanged, this, [this, sink] {
0077             NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME);
0078             np.set<bool>(QStringLiteral("muted"), sink->isMuted());
0079             np.set<QString>(QStringLiteral("name"), sink->name());
0080             sendPacket(np);
0081         });
0082 
0083         connect(sink, &PulseAudioQt::Sink::defaultChanged, this, [this, sink] {
0084             NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME);
0085             np.set<bool>(QStringLiteral("enabled"), sink->isDefault());
0086             np.set<QString>(QStringLiteral("name"), sink->name());
0087             sendPacket(np);
0088         });
0089 
0090         QJsonObject sinkObject{{QStringLiteral("name"), sink->name()},
0091                                {QStringLiteral("muted"), sink->isMuted()},
0092                                {QStringLiteral("description"), sink->description()},
0093                                {QStringLiteral("volume"), sink->volume()},
0094                                {QStringLiteral("maxVolume"), PulseAudioQt::normalVolume()},
0095                                {QStringLiteral("enabled"), sink->isDefault()}};
0096 
0097         array.append(sinkObject);
0098     }
0099 
0100     document.setArray(array);
0101 
0102     NetworkPacket np(PACKET_TYPE_SYSTEMVOLUME);
0103     np.set<QJsonDocument>(QStringLiteral("sinkList"), document);
0104     sendPacket(np);
0105 }
0106 
0107 void SystemvolumePlugin::connected()
0108 {
0109     connect(PulseAudioQt::Context::instance(), &PulseAudioQt::Context::sinkAdded, this, [this] {
0110         sendSinkList();
0111     });
0112 
0113     connect(PulseAudioQt::Context::instance(), &PulseAudioQt::Context::sinkRemoved, this, [this] {
0114         sendSinkList();
0115     });
0116 
0117     const auto sinks = PulseAudioQt::Context::instance()->sinks();
0118     for (PulseAudioQt::Sink *sink : sinks) {
0119         sinksMap.insert(sink->name(), sink);
0120     }
0121 }
0122 
0123 #include "moc_systemvolumeplugin-pulse.cpp"
0124 #include "systemvolumeplugin-pulse.moc"