File indexing completed on 2024-12-01 04:21:38
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