File indexing completed on 2024-03-24 04:59:46

0001 /**
0002  * SPDX-FileCopyrightText: 2018 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 "remotesinksmodel.h"
0008 #include "interfaces_debug.h"
0009 
0010 #include <QDebug>
0011 
0012 #include <dbushelper.h>
0013 
0014 RemoteSinksModel::RemoteSinksModel(QObject *parent)
0015     : QAbstractListModel(parent)
0016     , m_dbusInterface(nullptr)
0017 {
0018     connect(this, &QAbstractItemModel::rowsInserted, this, &RemoteSinksModel::rowsChanged);
0019     connect(this, &QAbstractItemModel::rowsRemoved, this, &RemoteSinksModel::rowsChanged);
0020 
0021     QDBusServiceWatcher *watcher =
0022         new QDBusServiceWatcher(DaemonDbusInterface::activatedService(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this);
0023     connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &RemoteSinksModel::refreshSinkList);
0024     connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &RemoteSinksModel::refreshSinkList);
0025 }
0026 
0027 QHash<int, QByteArray> RemoteSinksModel::roleNames() const
0028 {
0029     // Role names for QML
0030     QHash<int, QByteArray> names = QAbstractItemModel::roleNames();
0031     names.insert(NameRole, "name");
0032     names.insert(DescriptionRole, "description");
0033     names.insert(MaxVolumeRole, "maxVolume");
0034     names.insert(VolumeRole, "volume");
0035     names.insert(MutedRole, "muted");
0036 
0037     return names;
0038 }
0039 
0040 RemoteSinksModel::~RemoteSinksModel()
0041 {
0042 }
0043 
0044 QString RemoteSinksModel::deviceId() const
0045 {
0046     return m_deviceId;
0047 }
0048 
0049 void RemoteSinksModel::setDeviceId(const QString &deviceId)
0050 {
0051     m_deviceId = deviceId;
0052 
0053     if (m_dbusInterface) {
0054         delete m_dbusInterface;
0055     }
0056 
0057     m_dbusInterface = new RemoteSystemVolumeDbusInterface(deviceId, this);
0058 
0059     connect(m_dbusInterface, &OrgKdeKdeconnectDeviceRemotesystemvolumeInterface::sinksChanged, this, &RemoteSinksModel::refreshSinkList);
0060 
0061     connect(m_dbusInterface, &OrgKdeKdeconnectDeviceRemotesystemvolumeInterface::volumeChanged, this, [this](const QString &name, int volume) {
0062         auto iter = std::find_if(m_sinkList.begin(), m_sinkList.end(), [&name](const Sink &s) {
0063             return s.name == name;
0064         });
0065         if (iter != m_sinkList.end()) {
0066             iter->volume = volume;
0067             int i = std::distance(m_sinkList.begin(), iter);
0068             Q_EMIT dataChanged(index(i, 0), index(i, 0), {VolumeRole});
0069         }
0070     });
0071 
0072     connect(m_dbusInterface, &OrgKdeKdeconnectDeviceRemotesystemvolumeInterface::mutedChanged, this, [this](const QString &name, bool muted) {
0073         auto iter = std::find_if(m_sinkList.begin(), m_sinkList.end(), [&name](const Sink &s) {
0074             return s.name == name;
0075         });
0076         if (iter != m_sinkList.cend()) {
0077             iter->muted = muted;
0078             int i = std::distance(m_sinkList.begin(), iter);
0079             Q_EMIT dataChanged(index(i, 0), index(i, 0), {MutedRole});
0080         }
0081     });
0082 
0083     refreshSinkList();
0084 
0085     Q_EMIT deviceIdChanged(deviceId);
0086 }
0087 
0088 void RemoteSinksModel::refreshSinkList()
0089 {
0090     if (!m_dbusInterface) {
0091         return;
0092     }
0093 
0094     if (!m_dbusInterface->isValid()) {
0095         qCWarning(KDECONNECT_INTERFACES) << "dbus interface not valid";
0096         return;
0097     }
0098 
0099     beginResetModel();
0100     m_sinkList.clear();
0101 
0102     const auto cmds = QJsonDocument::fromJson(m_dbusInterface->sinks()).array();
0103     for (const QJsonValue &cmd : cmds) {
0104         const QJsonObject cont = cmd.toObject();
0105         Sink sink;
0106         sink.name = cont.value(QStringLiteral("name")).toString();
0107         sink.description = cont.value(QStringLiteral("description")).toString();
0108         sink.maxVolume = cont.value(QStringLiteral("maxVolume")).toInt();
0109         sink.volume = cont.value(QStringLiteral("volume")).toInt();
0110         sink.muted = cont.value(QStringLiteral("muted")).toBool();
0111         m_sinkList.append(sink);
0112     }
0113 
0114     endResetModel();
0115 }
0116 
0117 QVariant RemoteSinksModel::data(const QModelIndex &index, int role) const
0118 {
0119     if (!index.isValid() || index.row() < 0 || index.row() >= m_sinkList.count()) {
0120         return QVariant();
0121     }
0122 
0123     if (!m_dbusInterface || !m_dbusInterface->isValid()) {
0124         return QVariant();
0125     }
0126 
0127     const Sink &sink = m_sinkList[index.row()];
0128 
0129     switch (role) {
0130     case NameRole:
0131         return sink.name;
0132     case DescriptionRole:
0133         return sink.description;
0134     case MaxVolumeRole:
0135         return sink.maxVolume;
0136     case VolumeRole:
0137         return sink.volume;
0138     case MutedRole:
0139         return sink.muted;
0140     default:
0141         return QVariant();
0142     }
0143 }
0144 
0145 bool RemoteSinksModel::setData(const QModelIndex &index, const QVariant &value, int role)
0146 {
0147     if (!index.isValid() || index.row() < 0 || index.row() >= m_sinkList.count()) {
0148         return false;
0149     }
0150 
0151     if (!m_dbusInterface || !m_dbusInterface->isValid()) {
0152         return false;
0153     }
0154 
0155     const QString sinkName = m_sinkList[index.row()].name;
0156     switch (role) {
0157     case VolumeRole:
0158         m_dbusInterface->sendVolume(sinkName, value.toInt());
0159         return true;
0160     case MutedRole:
0161         m_dbusInterface->sendMuted(sinkName, value.toBool());
0162         return true;
0163     default:
0164         return false;
0165     }
0166 }
0167 
0168 int RemoteSinksModel::rowCount(const QModelIndex &parent) const
0169 {
0170     if (parent.isValid()) {
0171         // Return size 0 if we are a child because this is not a tree
0172         return 0;
0173     }
0174 
0175     return m_sinkList.count();
0176 }
0177 
0178 #include "moc_remotesinksmodel.cpp"