PulseAudio Qt Bindings

maps.h
1/*
2 SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org>
3 SPDX-FileCopyrightText: 2018 David Rosca <nowrep@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#pragma once
9
10#include <QHash>
11#include <QList>
12#include <QObject>
13#include <QSet>
14
15#include <pulse/ext-stream-restore.h>
16#include <pulse/pulseaudio.h>
17
18#include "card_p.h"
19#include "client_p.h"
20#include "module_p.h"
21#include "sink_p.h"
22#include "sinkinput_p.h"
23#include "source_p.h"
24#include "sourceoutput_p.h"
25#include "streamrestore_p.h"
26
27namespace PulseAudioQt
28{
29// Used for typedefs.
30class Card;
31class Client;
32class Sink;
33class SinkInput;
34class Source;
35class SourceOutput;
36class StreamRestore;
37class Module;
38
39/**
40 * @see MapBase
41 * This class is nothing more than the QObject base since moc cannot handle
42 * templates.
43 */
44class MapBaseQObject : public QObject
45{
47
48public:
49 virtual int count() const = 0;
50 virtual QObject *objectAt(int index) const = 0;
51 virtual int indexOfObject(QObject *object) const = 0;
52
53 void disconnectSignals()
54 {
55 disconnect(this, &MapBaseQObject::aboutToBeAdded, nullptr, nullptr);
56 disconnect(this, &MapBaseQObject::added, nullptr, nullptr);
57 disconnect(this, &MapBaseQObject::aboutToBeRemoved, nullptr, nullptr);
58 disconnect(this, &MapBaseQObject::removed, nullptr, nullptr);
59 };
60
62 void aboutToBeAdded(int index);
63 void added(int index, QObject *object);
64 void aboutToBeRemoved(int index);
65 void removed(int index, QObject *object);
66};
67
68/**
69 * Maps a specific index to a specific object pointer.
70 * This is used to give the unique arbitrary PulseAudio index of a PulseObject a
71 * serialized list index. Namely it enables us to translate a discrete list
72 * index to a pulse index to an object, and any permutation thereof.
73 */
74template<typename Type, typename PAInfo>
75class MapBase : public MapBaseQObject
76{
77public:
78 ~MapBase() override = default;
79
80 const QList<Type *> &data() const
81 {
82 return m_data;
83 }
84
85 int count() const override
86 {
87 return m_data.count();
88 }
89
90 int indexOfObject(QObject *object) const override
91 {
92 return m_data.indexOf(static_cast<Type *>(object));
93 }
94
95 QObject *objectAt(int index) const override
96 {
97 return m_data.at(index);
98 }
99
100 void reset()
101 {
102 while (!m_hash.isEmpty()) {
103 removeEntry(m_data.at(m_data.count() - 1)->index());
104 }
105 m_pendingRemovals.clear();
106 }
107
108 void insert(Type *object)
109 {
110 Q_ASSERT(!m_data.contains(object));
111
112 const int modelIndex = m_data.count();
113
114 Q_EMIT aboutToBeAdded(modelIndex);
115 m_data.append(object);
116 m_hash[object->index()] = object;
117 Q_EMIT added(modelIndex, object);
118 }
119
120 // Context is passed in as parent because context needs to include the maps
121 // so we'd cause a circular dep if we were to try to use the instance here.
122 // Plus that's weird separation anyway.
123 void updateEntry(const PAInfo *info, QObject *parent)
124 {
125 Q_ASSERT(info);
126
127 if (m_pendingRemovals.remove(info->index)) {
128 // Was already removed again.
129 return;
130 }
131
132 auto *obj = m_hash.value(info->index);
133 if (!obj) {
134 obj = new Type(parent);
135 obj->d->update(info);
136 insert(obj);
137 } else {
138 obj->d->update(info);
139 }
140 }
141
142 void removeEntry(quint32 index)
143 {
144 if (!m_hash.contains(index)) {
145 m_pendingRemovals.insert(index);
146 } else {
147 const int modelIndex = m_data.indexOf(m_hash.value(index));
148 Q_EMIT aboutToBeRemoved(modelIndex);
149 m_data.removeAt(modelIndex);
150 auto object = m_hash.take(index);
151 Q_EMIT removed(modelIndex, object);
152 delete object;
153 }
154 }
155
156protected:
157 QList<Type *> m_data;
159 QSet<quint32> m_pendingRemovals;
160};
161
162typedef MapBase<Card, pa_card_info> CardMap;
163typedef MapBase<Client, pa_client_info> ClientMap;
164typedef MapBase<SinkInput, pa_sink_input_info> SinkInputMap;
165typedef MapBase<Sink, pa_sink_info> SinkMap;
166typedef MapBase<Source, pa_source_info> SourceMap;
167typedef MapBase<SourceOutput, pa_source_output_info> SourceOutputMap;
168typedef MapBase<StreamRestore, pa_ext_stream_restore_info> StreamRestoreMap;
169typedef MapBase<Module, pa_module_info> ModuleMap;
170
171} // PulseAudioQt
Maps a specific index to a specific object pointer.
Definition pulseobject.h:19
The primary namespace of PulseAudioQt.
Definition card.cpp:17
bool contains(const Key &key) const const
bool isEmpty() const const
T take(const Key &key)
T value(const Key &key) const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
qsizetype count() const const
qsizetype indexOf(const AT &value, qsizetype from) const const
void removeAt(qsizetype i)
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
void clear()
iterator insert(const T &value)
bool remove(const T &value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:12:38 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.