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 "debug_object.h"
21#include "module_p.h"
22#include "pulseobject_p.h"
23#include "sink_p.h"
24#include "sinkinput_p.h"
25#include "source_p.h"
26#include "sourceoutput_p.h"
27#include "streamrestore_p.h"
28
29namespace PulseAudioQt
30{
31// Used for typedefs.
32class Card;
33class Client;
34class Sink;
35class SinkInput;
36class Source;
37class SourceOutput;
38class StreamRestore;
39class Module;
40
41/**
42 * @see MapBase
43 * This class is nothing more than the QObject base since moc cannot handle
44 * templates.
45 */
46class MapBaseQObject : public QObject
47{
49
50public:
51 virtual int count() const = 0;
52 virtual QObject *objectAt(int index) const = 0;
53 virtual int indexOfObject(QObject *object) const = 0;
54
55 void disconnectSignals()
56 {
57 disconnect(this, &MapBaseQObject::aboutToBeAdded, nullptr, nullptr);
58 disconnect(this, &MapBaseQObject::added, nullptr, nullptr);
59 disconnect(this, &MapBaseQObject::aboutToBeRemoved, nullptr, nullptr);
60 disconnect(this, &MapBaseQObject::removed, nullptr, nullptr);
61 };
62
64 void aboutToBeAdded(int index);
65 void added(int index, QObject *object);
66 void aboutToBeRemoved(int index);
67 void removed(int index, QObject *object);
68};
69
70/**
71 * Maps a specific index to a specific object pointer.
72 * This is used to give the unique arbitrary PulseAudio index of a PulseObject a
73 * serialized list index. Namely it enables us to translate a discrete list
74 * index to a pulse index to an object, and any permutation thereof.
75 */
76template<typename Type, typename PAInfo>
77class MapBase : public MapBaseQObject
78{
79public:
80 ~MapBase() override = default;
81
82 const QList<Type *> &data() const
83 {
84 return m_data;
85 }
86
87 int count() const override
88 {
89 return m_data.count();
90 }
91
92 int indexOfObject(QObject *object) const override
93 {
94 return m_data.indexOf(static_cast<Type *>(object));
95 }
96
97 QObject *objectAt(int index) const override
98 {
99 return m_data.at(index);
100 }
101
102 void reset()
103 {
104 while (!m_hash.isEmpty()) {
105 removeEntry(m_data.at(m_data.count() - 1)->index());
106 }
107 m_pendingRemovals.clear();
108 }
109
110 void insert(Type *object)
111 {
112 Q_ASSERT(!m_data.contains(object));
113
114 const int modelIndex = m_data.count();
115
116 Q_EMIT aboutToBeAdded(modelIndex);
117 m_data.append(object);
118 m_hash[object->index()] = object;
119 Q_EMIT added(modelIndex, object);
120 }
121
122 // Context is passed in as parent because context needs to include the maps
123 // so we'd cause a circular dep if we were to try to use the instance here.
124 // Plus that's weird separation anyway.
125 void updateEntry(const PAInfo *info, QObject *parent)
126 {
127 Q_ASSERT(info);
128
129 if (m_pendingRemovals.remove(info->index)) {
130 // Was already removed again.
131 return;
132 }
133
134 auto *obj = m_hash.value(info->index);
135 auto type = QLatin1String("create");
136 if (!obj) {
137 obj = new Type(parent);
138 obj->d->update(info);
139 insert(obj);
140 } else {
141 type = QLatin1String("update");
142 obj->d->update(info);
143 }
144
145#if !defined(UNDER_TEST)
146 qCDebug(PAOBJECT).noquote() << type << qobject_cast<PulseObject *>(obj)->d.get();
147#endif
148 }
149
150 void removeEntry(quint32 index)
151 {
152 if (!m_hash.contains(index)) {
153 m_pendingRemovals.insert(index);
154 } else {
155 const int modelIndex = m_data.indexOf(m_hash.value(index));
156 Q_EMIT aboutToBeRemoved(modelIndex);
157 m_data.removeAt(modelIndex);
158 auto object = m_hash.take(index);
159 Q_EMIT removed(modelIndex, object);
160 delete object;
161 }
162 }
163
164protected:
165 QList<Type *> m_data;
167 QSet<quint32> m_pendingRemovals;
168};
169
170typedef MapBase<Card, pa_card_info> CardMap;
171typedef MapBase<Client, pa_client_info> ClientMap;
172typedef MapBase<SinkInput, pa_sink_input_info> SinkInputMap;
173typedef MapBase<Sink, pa_sink_info> SinkMap;
174typedef MapBase<Source, pa_source_info> SourceMap;
175typedef MapBase<SourceOutput, pa_source_output_info> SourceOutputMap;
176typedef MapBase<StreamRestore, pa_ext_stream_restore_info> StreamRestoreMap;
177typedef MapBase<Module, pa_module_info> ModuleMap;
178
179} // PulseAudioQt
Maps a specific index to a specific object pointer.
Definition pulseobject.h:19
Type type(const QSqlDatabase &db)
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 Mon Nov 18 2024 12:18:01 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.