File indexing completed on 2024-12-08 10:59:34

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 
0012 #include <pulse/volume.h>
0013 
0014 #include "port.h"
0015 #include "pulseobject.h"
0016 #include "volumeobject.h"
0017 
0018 namespace QPulseAudio
0019 {
0020 class Device : public VolumeObject
0021 {
0022     Q_OBJECT
0023     Q_PROPERTY(State state READ state NOTIFY stateChanged)
0024     Q_PROPERTY(QString name READ name NOTIFY nameChanged)
0025     Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
0026     Q_PROPERTY(QString formFactor READ formFactor NOTIFY formFactorChanged)
0027     Q_PROPERTY(quint32 cardIndex READ cardIndex NOTIFY cardIndexChanged)
0028     Q_PROPERTY(QList<QObject *> ports READ ports NOTIFY portsChanged)
0029     Q_PROPERTY(quint32 activePortIndex READ activePortIndex WRITE setActivePortIndex NOTIFY activePortIndexChanged)
0030     Q_PROPERTY(bool default READ isDefault WRITE setDefault NOTIFY defaultChanged)
0031     Q_PROPERTY(bool virtualDevice READ isVirtualDevice NOTIFY virtualDeviceChanged)
0032 public:
0033     enum State {
0034         InvalidState = 0,
0035         RunningState,
0036         IdleState,
0037         SuspendedState,
0038         UnknownState,
0039     };
0040     Q_ENUMS(State)
0041 
0042     ~Device() override = default;
0043 
0044     template<typename PAInfo>
0045     void updateDevice(const PAInfo *info)
0046     {
0047         updateVolumeObject(info);
0048 
0049         if (m_name != info->name) {
0050             m_name = info->name;
0051             Q_EMIT nameChanged();
0052         }
0053         if (m_description != info->description) {
0054             m_description = info->description;
0055             Q_EMIT descriptionChanged();
0056         }
0057         const char *form_factor = pa_proplist_gets(info->proplist, PA_PROP_DEVICE_FORM_FACTOR);
0058         if (form_factor) {
0059             QString formFactor = QString::fromUtf8(form_factor);
0060             if (m_formFactor != formFactor) {
0061                 m_formFactor = formFactor;
0062                 Q_EMIT formFactorChanged();
0063             }
0064         }
0065 
0066         if (m_cardIndex != info->card) {
0067             m_cardIndex = info->card;
0068             Q_EMIT cardIndexChanged();
0069         }
0070 
0071         const quint32 oldActivePortIndex = m_activePortIndex;
0072         bool portsHaveChanged = false;
0073         int i = 0;
0074         for (auto **ports = info->ports; ports && *ports != nullptr; ++ports) {
0075             if (i < m_ports.count()) {
0076                 Port *port = static_cast<Port *>(m_ports.at(i));
0077                 portsHaveChanged |= port->setInfo(*ports);
0078             } else {
0079                 Port *port = new Port(this);
0080                 port->setInfo(*ports);
0081                 m_ports.append(port);
0082                 portsHaveChanged = true;
0083             }
0084             if (info->active_port == *ports) {
0085                 m_activePortIndex = i;
0086             }
0087             ++i;
0088         }
0089 
0090         while (m_ports.count() > i) {
0091             delete m_ports.takeLast();
0092             portsHaveChanged = true;
0093         }
0094 
0095         if (portsHaveChanged) {
0096             Q_EMIT portsChanged();
0097         }
0098         if (portsHaveChanged || m_activePortIndex != oldActivePortIndex) {
0099             Q_EMIT activePortIndexChanged();
0100         }
0101 
0102         State infoState = stateFromPaState(info->state);
0103         if (infoState != m_state) {
0104             m_state = infoState;
0105             Q_EMIT stateChanged();
0106         }
0107 
0108         const bool isVirtual = !(info->flags & 4); // PA_X_HARDWARE
0109         if (m_virtualDevice != isVirtual) {
0110             m_virtualDevice = isVirtual;
0111             Q_EMIT virtualDeviceChanged();
0112         }
0113     }
0114 
0115     State state() const;
0116     QString name() const;
0117     QString description() const;
0118     QString formFactor() const;
0119     quint32 cardIndex() const;
0120     QList<QObject *> ports() const;
0121     quint32 activePortIndex() const;
0122     virtual void setActivePortIndex(quint32 port_index) = 0;
0123     virtual bool isDefault() const = 0;
0124     virtual void setDefault(bool enable) = 0;
0125     bool isVirtualDevice() const;
0126 
0127     virtual Q_INVOKABLE void switchStreams() = 0;
0128 
0129 Q_SIGNALS:
0130     void stateChanged();
0131     void nameChanged();
0132     void descriptionChanged();
0133     void formFactorChanged();
0134     void cardIndexChanged();
0135     void portsChanged();
0136     void activePortIndexChanged();
0137     void defaultChanged();
0138     void virtualDeviceChanged();
0139 
0140 protected:
0141     explicit Device(QObject *parent);
0142 
0143 private:
0144     State stateFromPaState(int value) const;
0145 
0146     QString m_name;
0147     QString m_description;
0148     QString m_formFactor;
0149     quint32 m_cardIndex = -1;
0150     QList<QObject *> m_ports;
0151     quint32 m_activePortIndex = -1;
0152     State m_state = UnknownState;
0153     bool m_virtualDevice = false;
0154 };
0155 
0156 } // QPulseAudio
0157 
0158 #endif // DEVICE_H