File indexing completed on 2024-04-21 04:43:25

0001 /*
0002     SPDX-FileCopyrightText: 2018 Nicolas Fella <nicolas.fella@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #ifndef DEVICE_P_H
0007 #define DEVICE_P_H
0008 
0009 #include <pulse/proplist.h>
0010 
0011 #include <QHash>
0012 #include <QVector>
0013 
0014 #include "device.h"
0015 #include "port.h"
0016 #include "port_p.h"
0017 #include "volumeobject_p.h"
0018 
0019 namespace PulseAudioQt
0020 {
0021 class DevicePrivate
0022 {
0023 public:
0024     explicit DevicePrivate(Device *q);
0025 
0026     Device *q;
0027 
0028     QString m_description;
0029     QString m_formFactor;
0030     quint32 m_cardIndex = -1;
0031     QList<Port *> m_ports;
0032     quint32 m_activePortIndex = -1;
0033     Device::State m_state = Device::UnknownState;
0034     qint64 m_baseVolume = -1;
0035     QVariantMap m_pulseProperties;
0036 
0037     Device::State stateFromPaState(int value) const;
0038 
0039     template<typename PAInfo>
0040     void updatePulseProperties(const PAInfo *info)
0041     {
0042         QVariantMap pulseProperties;
0043         void *state = nullptr;
0044         while (auto key = pa_proplist_iterate(info->proplist, &state)) {
0045             const auto value = pa_proplist_gets(info->proplist, key);
0046             pulseProperties.insert(key, QString::fromUtf8(value));
0047         }
0048         if (pulseProperties != m_pulseProperties) {
0049             m_pulseProperties = pulseProperties;
0050             Q_EMIT q->pulsePropertiesChanged();
0051         }
0052     }
0053 
0054     template<typename PAInfo>
0055     void updateDevice(const PAInfo *info)
0056     {
0057         q->VolumeObject::d->updateVolumeObject(info);
0058 
0059         if (m_description != info->description) {
0060             m_description = info->description;
0061             Q_EMIT q->descriptionChanged();
0062         }
0063         const char *form_factor = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_FORM_FACTOR);
0064         if (form_factor) {
0065             QString formFactor = QString::fromUtf8(form_factor);
0066             if (m_formFactor != formFactor) {
0067                 m_formFactor = formFactor;
0068                 Q_EMIT q->formFactorChanged();
0069             }
0070         }
0071 
0072         m_cardIndex = info->card;
0073         Q_EMIT q->cardIndexChanged();
0074 
0075         updatePulseProperties(info);
0076 
0077         QStringList newPorts;
0078         QStringList existingPorts;
0079 
0080         // Build list of existing ports
0081         for (const Port *port : qAsConst(m_ports)) {
0082             existingPorts << port->name();
0083         }
0084 
0085         // Add new ports from the updated port list and re/set port info
0086         for (auto **it = info->ports; it && *it != nullptr; ++it) {
0087             const QString name = QString::fromUtf8((*it)->name);
0088             newPorts << name;
0089 
0090             Port *port = nullptr;
0091 
0092             if (existingPorts.contains(name)) {
0093                 port = m_ports[existingPorts.indexOf(name)];
0094             } else {
0095                 port = new Port(q);
0096                 m_ports << port;
0097             }
0098 
0099             port->d->setInfo(*it);
0100         }
0101 
0102         // Remove ports that are not in the updated port list
0103         for (Port *port : qAsConst(m_ports)) {
0104             if (!newPorts.contains(port->name())) {
0105                 m_ports.removeOne(port);
0106                 delete port;
0107             }
0108         }
0109 
0110         // Set active port
0111         for (Port *port : qAsConst(m_ports)) {
0112             if (info->active_port->name == port->name()) {
0113                 m_activePortIndex = m_ports.indexOf(port);
0114             }
0115         }
0116 
0117         Q_EMIT q->portsChanged();
0118         Q_EMIT q->activePortIndexChanged();
0119 
0120         Device::State infoState = stateFromPaState(info->state);
0121         if (infoState != m_state) {
0122             m_state = infoState;
0123             Q_EMIT q->stateChanged();
0124         }
0125 
0126         if (m_baseVolume != info->base_volume) {
0127             m_baseVolume = info->base_volume;
0128             Q_EMIT q->baseVolumeChanged();
0129         }
0130     }
0131 };
0132 
0133 } // namespace PulseAudioQt
0134 
0135 #endif