File indexing completed on 2024-04-28 05:34:14
0001 /* 0002 SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef DEVICE_H 0008 #define DEVICE_H 0009 0010 #include <QString> 0011 #include <QVariantMap> 0012 0013 #include <pulse/volume.h> 0014 0015 #include "port.h" 0016 #include "pulseobject.h" 0017 #include "volumeobject.h" 0018 0019 namespace QPulseAudio 0020 { 0021 class Device : public VolumeObject 0022 { 0023 Q_OBJECT 0024 Q_PROPERTY(State state READ state NOTIFY stateChanged) 0025 Q_PROPERTY(QString name READ name NOTIFY nameChanged) 0026 Q_PROPERTY(QString description READ description NOTIFY descriptionChanged) 0027 Q_PROPERTY(QString formFactor READ formFactor NOTIFY formFactorChanged) 0028 Q_PROPERTY(quint32 cardIndex READ cardIndex NOTIFY cardIndexChanged) 0029 Q_PROPERTY(QList<QObject *> ports READ ports NOTIFY portsChanged) 0030 Q_PROPERTY(quint32 activePortIndex READ activePortIndex WRITE setActivePortIndex NOTIFY activePortIndexChanged) 0031 Q_PROPERTY(bool default READ isDefault WRITE setDefault NOTIFY defaultChanged) 0032 Q_PROPERTY(bool virtualDevice READ isVirtualDevice NOTIFY virtualDeviceChanged) 0033 Q_PROPERTY(QVariantMap pulseProperties READ pulseProperties NOTIFY pulsePropertiesChanged) 0034 public: 0035 enum State { 0036 InvalidState = 0, 0037 RunningState, 0038 IdleState, 0039 SuspendedState, 0040 UnknownState, 0041 }; 0042 Q_ENUMS(State) 0043 0044 ~Device() override = default; 0045 0046 template<typename PAInfo> 0047 void updatePulseProperties(const PAInfo *info) 0048 { 0049 QVariantMap pulseProperties; 0050 void *state = nullptr; 0051 while (auto key = pa_proplist_iterate(info->proplist, &state)) { 0052 const auto value = pa_proplist_gets(info->proplist, key); 0053 pulseProperties.insert(key, QString::fromUtf8(value)); 0054 } 0055 if (pulseProperties != m_pulseProperties) { 0056 m_pulseProperties = pulseProperties; 0057 Q_EMIT pulsePropertiesChanged(); 0058 } 0059 } 0060 0061 template<typename PAInfo> 0062 void updateDevice(const PAInfo *info) 0063 { 0064 updateVolumeObject(info); 0065 0066 if (m_name != info->name) { 0067 m_name = info->name; 0068 Q_EMIT nameChanged(); 0069 } 0070 if (m_description != info->description) { 0071 m_description = info->description; 0072 Q_EMIT descriptionChanged(); 0073 } 0074 const char *form_factor = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_FORM_FACTOR); 0075 if (form_factor) { 0076 QString formFactor = QString::fromUtf8(form_factor); 0077 if (m_formFactor != formFactor) { 0078 m_formFactor = formFactor; 0079 Q_EMIT formFactorChanged(); 0080 } 0081 } 0082 0083 updatePulseProperties(info); 0084 0085 if (m_cardIndex != info->card) { 0086 m_cardIndex = info->card; 0087 Q_EMIT cardIndexChanged(); 0088 } 0089 0090 const quint32 oldActivePortIndex = m_activePortIndex; 0091 bool portsHaveChanged = false; 0092 int i = 0; 0093 for (auto **ports = info->ports; ports && *ports != nullptr; ++ports) { 0094 if (i < m_ports.count()) { 0095 Port *port = static_cast<Port *>(m_ports.at(i)); 0096 portsHaveChanged |= port->setInfo(*ports); 0097 } else { 0098 Port *port = new Port(this); 0099 port->setInfo(*ports); 0100 m_ports.append(port); 0101 portsHaveChanged = true; 0102 } 0103 if (info->active_port == *ports) { 0104 m_activePortIndex = i; 0105 } 0106 ++i; 0107 } 0108 0109 while (m_ports.count() > i) { 0110 delete m_ports.takeLast(); 0111 portsHaveChanged = true; 0112 } 0113 0114 if (portsHaveChanged) { 0115 Q_EMIT portsChanged(); 0116 } 0117 if (portsHaveChanged || m_activePortIndex != oldActivePortIndex) { 0118 Q_EMIT activePortIndexChanged(); 0119 } 0120 0121 State infoState = stateFromPaState(info->state); 0122 if (infoState != m_state) { 0123 m_state = infoState; 0124 Q_EMIT stateChanged(); 0125 } 0126 0127 const bool isVirtual = !(info->flags & 4); // PA_X_HARDWARE 0128 if (m_virtualDevice != isVirtual) { 0129 m_virtualDevice = isVirtual; 0130 Q_EMIT virtualDeviceChanged(); 0131 } 0132 } 0133 0134 State state() const; 0135 QString name() const; 0136 QString description() const; 0137 QString formFactor() const; 0138 quint32 cardIndex() const; 0139 QList<QObject *> ports() const; 0140 quint32 activePortIndex() const; 0141 virtual void setActivePortIndex(quint32 port_index) = 0; 0142 virtual bool isDefault() const = 0; 0143 virtual void setDefault(bool enable) = 0; 0144 bool isVirtualDevice() const; 0145 [[nodiscard]] QVariantMap pulseProperties() const; 0146 0147 virtual Q_INVOKABLE void switchStreams() = 0; 0148 0149 Q_SIGNALS: 0150 void stateChanged(); 0151 void nameChanged(); 0152 void descriptionChanged(); 0153 void formFactorChanged(); 0154 void cardIndexChanged(); 0155 void portsChanged(); 0156 void activePortIndexChanged(); 0157 void defaultChanged(); 0158 void virtualDeviceChanged(); 0159 void pulsePropertiesChanged(); 0160 0161 protected: 0162 explicit Device(QObject *parent); 0163 0164 private: 0165 State stateFromPaState(int value) const; 0166 0167 QString m_name; 0168 QString m_description; 0169 QString m_formFactor; 0170 quint32 m_cardIndex = -1; 0171 QList<QObject *> m_ports; 0172 quint32 m_activePortIndex = -1; 0173 State m_state = UnknownState; 0174 bool m_virtualDevice = false; 0175 QVariantMap m_pulseProperties; 0176 }; 0177 0178 } // QPulseAudio 0179 0180 #endif // DEVICE_H