Changeset View
Changeset View
Standalone View
Standalone View
src/pulseaudio.cpp
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | Copyright 2014-2015 Harald Sitter <sitter@kde.org> | 2 | Copyright 2014-2015 Harald Sitter <sitter@kde.org> | ||
3 | Copyright 2016 David Rosca <nowrep@gmail.com> | ||||
3 | 4 | | |||
4 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | 6 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | 7 | License as published by the Free Software Foundation; either | ||
7 | version 2.1 of the License, or (at your option) version 3, or any | 8 | version 2.1 of the License, or (at your option) version 3, or any | ||
8 | later version accepted by the membership of KDE e.V. (or its | 9 | later version accepted by the membership of KDE e.V. (or its | ||
9 | successor approved by the membership of KDE e.V.), which shall | 10 | successor approved by the membership of KDE e.V.), which shall | ||
10 | act as a proxy defined in Section 6 of version 3 of the license. | 11 | act as a proxy defined in Section 6 of version 3 of the license. | ||
11 | 12 | | |||
12 | This library is distributed in the hope that it will be useful, | 13 | This library is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | Lesser General Public License for more details. | 16 | Lesser General Public License for more details. | ||
16 | 17 | | |||
17 | You should have received a copy of the GNU Lesser General Public | 18 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | 19 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | 20 | */ | ||
20 | 21 | | |||
21 | #include "pulseaudio.h" | 22 | #include "pulseaudio.h" | ||
22 | 23 | | |||
23 | #include "debug.h" | 24 | #include "debug.h" | ||
24 | #include <QMetaEnum> | | |||
25 | | ||||
26 | #include "card.h" | 25 | #include "card.h" | ||
27 | #include "client.h" | | |||
28 | #include "sink.h" | 26 | #include "sink.h" | ||
29 | #include "sinkinput.h" | 27 | #include "sinkinput.h" | ||
30 | #include "source.h" | 28 | #include "source.h" | ||
31 | #include "sourceoutput.h" | 29 | #include "sourceoutput.h" | ||
32 | #include "server.h" | 30 | #include "server.h" | ||
33 | 31 | | |||
34 | namespace QPulseAudio | 32 | #include <QMetaEnum> | ||
35 | { | | |||
36 | | ||||
37 | ClientModel::ClientModel(QObject *parent) | | |||
38 | : AbstractModel(&context()->clients(), parent) | | |||
39 | { | | |||
40 | initRoleNames(Client::staticMetaObject); | | |||
41 | } | | |||
42 | | ||||
43 | int ClientModel::rowCount(const QModelIndex &parent) const | | |||
44 | { | | |||
45 | Q_UNUSED(parent); | | |||
46 | if (!context()) | | |||
47 | return 0; | | |||
48 | return context()->clients().data().count(); | | |||
49 | } | | |||
50 | | ||||
51 | QVariant ClientModel::data(const QModelIndex &index, int role) const | | |||
52 | { | | |||
53 | Client *data = context()->clients().data().values().at(index.row()); | | |||
54 | Q_ASSERT(data); | | |||
55 | switch(static_cast<ItemRole>(role)){ | | |||
56 | case NameRole: | | |||
57 | return data->name(); | | |||
58 | case PulseObjectRole: | | |||
59 | return QVariant::fromValue(data); | | |||
60 | } | | |||
61 | return dataForRole(data, role); | | |||
62 | } | | |||
63 | | ||||
64 | SinkInputModel::SinkInputModel(QObject *parent) | | |||
65 | : AbstractModel(&context()->sinkInputs(), parent) | | |||
66 | { | | |||
67 | initRoleNames(SinkInput::staticMetaObject); | | |||
68 | } | | |||
69 | | ||||
70 | int AbstractModel::role(const QByteArray &roleName) const | | |||
71 | { | | |||
72 | qCDebug(PLASMAPA) << roleName << m_roles.key(roleName, -1); | | |||
73 | return m_roles.key(roleName, -1); | | |||
74 | } | | |||
75 | 33 | | |||
76 | int SinkInputModel::rowCount(const QModelIndex &parent) const | 34 | namespace QPulseAudio | ||
77 | { | 35 | { | ||
78 | Q_UNUSED(parent); | | |||
79 | if (!context()) | | |||
80 | return 0; | | |||
81 | return context()->sinkInputs().data().count(); | | |||
82 | } | | |||
83 | 36 | | |||
84 | QVariant SinkInputModel::data(const QModelIndex &index, int role) const | 37 | AbstractModel::AbstractModel(const MapBaseQObject *map, QObject *parent) | ||
38 | : QAbstractListModel(parent) | ||||
39 | , m_map(map) | ||||
85 | { | 40 | { | ||
86 | SinkInput *data = context()->sinkInputs().data().values().at(index.row()); | 41 | connect(m_map, &MapBaseQObject::added, this, &AbstractModel::onDataAdded); | ||
87 | Q_ASSERT(data); | 42 | connect(m_map, &MapBaseQObject::removed, this, &AbstractModel::onDataRemoved); | ||
88 | switch ((ItemRole) role) { | | |||
89 | case IndexRole: | | |||
90 | return data->index(); | | |||
91 | case PulseObjectRole: | | |||
92 | return QVariant::fromValue(data); | | |||
93 | } | | |||
94 | return dataForRole(data, role); | | |||
95 | } | 43 | } | ||
96 | 44 | | |||
97 | QHash<int, QByteArray> AbstractModel::roleNames() const | 45 | QHash<int, QByteArray> AbstractModel::roleNames() const | ||
98 | { | 46 | { | ||
99 | if (!m_roles.empty()) { | 47 | if (!m_roles.empty()) { | ||
100 | qCDebug(PLASMAPA) << "returning roles" << m_roles; | 48 | qCDebug(PLASMAPA) << "returning roles" << m_roles; | ||
101 | return m_roles; | 49 | return m_roles; | ||
102 | } | 50 | } | ||
103 | Q_ASSERT(false); | 51 | Q_UNREACHABLE(); | ||
104 | return QHash<int, QByteArray>(); | 52 | return QHash<int, QByteArray>(); | ||
105 | } | 53 | } | ||
106 | 54 | | |||
107 | SinkModel::SinkModel(QObject *parent) | 55 | int AbstractModel::rowCount(const QModelIndex &parent) const | ||
108 | : AbstractModel(&context()->sinks(), parent) | | |||
109 | { | | |||
110 | initRoleNames(Sink::staticMetaObject); | | |||
111 | | ||||
112 | connect(&context()->sinks(), &SinkMap::added, this, &SinkModel::sinksChanged); | | |||
113 | connect(&context()->sinks(), &SinkMap::updated, this, &SinkModel::sinksChanged); | | |||
114 | connect(&context()->sinks(), &SinkMap::removed, this, &SinkModel::sinksChanged); | | |||
115 | connect(context()->server(), &Server::defaultSinkChanged, this, &SinkModel::defaultSinkChanged); | | |||
116 | | ||||
117 | emit sinksChanged(); | | |||
118 | } | | |||
119 | | ||||
120 | Sink *SinkModel::defaultSink() const | | |||
121 | { | | |||
122 | return context()->server()->defaultSink(); | | |||
123 | } | | |||
124 | | ||||
125 | int SinkModel::rowCount(const QModelIndex &parent) const | | |||
126 | { | 56 | { | ||
127 | Q_UNUSED(parent); | 57 | Q_UNUSED(parent); | ||
128 | if (!context()) | 58 | return m_map->count(); | ||
129 | return 0; | | |||
130 | return context()->sinks().data().count(); | | |||
131 | } | 59 | } | ||
132 | 60 | | |||
133 | QVariant SinkModel::data(const QModelIndex &index, int role) const | 61 | QVariant AbstractModel::data(const QModelIndex &index, int role) const | ||
134 | { | 62 | { | ||
135 | Sink *data = context()->sinks().data().values().at(index.row()); | 63 | QObject *data = m_map->objectAt(index.row()); | ||
136 | Q_ASSERT(data); | 64 | Q_ASSERT(data); | ||
137 | switch(static_cast<ItemRole>(role)) { | 65 | if (role == PulseObjectRole) { | ||
138 | case IndexRole: | | |||
139 | return data->index(); | | |||
140 | case PulseObjectRole: | | |||
141 | return QVariant::fromValue(data); | 66 | return QVariant::fromValue(data); | ||
142 | } | 67 | } | ||
143 | return dataForRole(data, role); | 68 | int property = m_objectProperties.value(role, -1); | ||
69 | if (property == -1) { | ||||
70 | return QVariant(); | ||||
71 | } | ||||
72 | return data->metaObject()->property(property).read(data); | ||||
144 | } | 73 | } | ||
145 | 74 | | |||
146 | bool SinkModel::setData(const QModelIndex &index, const QVariant &value, int role) | 75 | bool AbstractModel::setData(const QModelIndex &index, const QVariant &value, int role) | ||
147 | { | 76 | { | ||
148 | int propertyIndex = m_objectProperties.value(role, -1); | 77 | int propertyIndex = m_objectProperties.value(role, -1); | ||
149 | if (propertyIndex == -1) | 78 | if (propertyIndex == -1) { | ||
150 | return false; | 79 | return false; | ||
151 | Sink *data = context()->sinks().data().values().at(index.row()); | 80 | } | ||
81 | QObject *data = m_map->objectAt(index.row()); | ||||
152 | auto property = data->metaObject()->property(propertyIndex); | 82 | auto property = data->metaObject()->property(propertyIndex); | ||
153 | return property.write(data, value); | 83 | return property.write(data, value); | ||
154 | } | 84 | } | ||
155 | 85 | | |||
156 | void SinkModel::onDataAdded(quint32 index) | 86 | int AbstractModel::role(const QByteArray &roleName) const | ||
157 | { | | |||
158 | beginInsertRows(QModelIndex(), index, index); | | |||
159 | Sink *data = context()->sinks().data().values().at(index); | | |||
160 | const QMetaObject *mo = data->metaObject(); | | |||
161 | // We have all the data changed notify signals already stored | | |||
162 | auto keys = m_signalIndexToProperties.keys(); | | |||
163 | foreach(int index, keys){ | | |||
164 | QMetaMethod meth = mo->method(index); | | |||
165 | connect(data, meth, this, propertyChangedMetaMethod()); | | |||
166 | } | | |||
167 | endInsertRows(); | | |||
168 | } | | |||
169 | | ||||
170 | void SinkModel::onDataRemoved(quint32 index) | | |||
171 | { | | |||
172 | beginRemoveRows(QModelIndex(), index, index); | | |||
173 | endRemoveRows(); | | |||
174 | } | | |||
175 | | ||||
176 | void SinkModel::propertyChanged() | | |||
177 | { | | |||
178 | if (!sender() || senderSignalIndex() == -1) | | |||
179 | return; | | |||
180 | int propertyIndex = m_signalIndexToProperties.value(senderSignalIndex(), -1); | | |||
181 | if (propertyIndex == -1) | | |||
182 | return; | | |||
183 | int role = m_objectProperties.key(propertyIndex, -1); | | |||
184 | if (role == -1) | | |||
185 | return; | | |||
186 | int index = context()->sinks().modelIndexForQObject(sender()); | | |||
187 | qCDebug(PLASMAPA) << "PROPERTY CHANGED (" << index << ") :: " << role << roleNames().value(role); | | |||
188 | emit dataChanged(createIndex(index, 0), createIndex(index, 0), QVector<int>() << role); | | |||
189 | } | | |||
190 | | ||||
191 | QMetaMethod SinkModel::propertyChangedMetaMethod() const | | |||
192 | { | | |||
193 | auto mo = metaObject(); | | |||
194 | int methodIndex = mo->indexOfMethod(QMetaObject::normalizedSignature("propertyChanged()").data()); | | |||
195 | if(methodIndex == -1){ | | |||
196 | return QMetaMethod(); | | |||
197 | } | | |||
198 | return mo->method(methodIndex); | | |||
199 | } | | |||
200 | | ||||
201 | void AbstractModel::onDataAdded(quint32 index) | | |||
202 | { | | |||
203 | beginInsertRows(QModelIndex(), index, index); | | |||
204 | endInsertRows(); | | |||
205 | } | | |||
206 | | ||||
207 | void AbstractModel::onDataUpdated(quint32 index) | | |||
208 | { | | |||
209 | emit dataChanged(createIndex(index, 0), createIndex(index, 0)); | | |||
210 | } | | |||
211 | | ||||
212 | void AbstractModel::onDataRemoved(quint32 index) | | |||
213 | { | | |||
214 | beginRemoveRows(QModelIndex(), index, index); | | |||
215 | endRemoveRows(); | | |||
216 | } | | |||
217 | | ||||
218 | AbstractModel::AbstractModel(const MapBaseQObject *map, QObject *parent) | | |||
219 | : QAbstractListModel(parent) | | |||
220 | { | 87 | { | ||
221 | connect(map, &MapBaseQObject::added, this, &AbstractModel::onDataAdded); | 88 | qCDebug(PLASMAPA) << roleName << m_roles.key(roleName, -1); | ||
222 | connect(map, &MapBaseQObject::updated, this, &AbstractModel::onDataUpdated); | 89 | return m_roles.key(roleName, -1); | ||
223 | connect(map, &MapBaseQObject::removed, this, &AbstractModel::onDataRemoved); | | |||
224 | } | 90 | } | ||
225 | 91 | | |||
226 | void AbstractModel::initRoleNames(const QMetaObject &qobjectMetaObject) | 92 | void AbstractModel::initRoleNames(const QMetaObject &qobjectMetaObject) | ||
227 | { | 93 | { | ||
228 | QMetaEnum enumerator; | 94 | m_roles[PulseObjectRole] = QByteArrayLiteral("PulseObject"); | ||
229 | for (int i = 0; i < metaObject()->enumeratorCount(); ++i) { | 95 | int maxEnumValue = PulseObjectRole; | ||
230 | if (metaObject()->enumerator(i).name() == QLatin1Literal("ItemRole")) { | | |||
231 | enumerator = metaObject()->enumerator(i); | | |||
232 | break; | | |||
233 | } | | |||
234 | } | | |||
235 | 96 | | |||
236 | Q_ASSERT(enumerator.scope() == metaObject()->className()); | | |||
237 | // No valid enum found, leaf probably doesn't implement ItemRole (correctly). | | |||
238 | Q_ASSERT(enumerator.isValid()); | | |||
239 | | ||||
240 | for (int i = 0; i < enumerator.keyCount(); ++i) { | | |||
241 | // Clip the Role suffix and glue it in the hash. | | |||
242 | static int roleLength = strlen("Role"); | | |||
243 | QByteArray key(enumerator.key(i)); | | |||
244 | // Enum values must end in Role or the enum is crap | | |||
245 | Q_ASSERT(key.right(roleLength) == QByteArray("Role")); | | |||
246 | key.chop(roleLength); | | |||
247 | m_roles[enumerator.value(i)] = key; | | |||
248 | } | | |||
249 | | ||||
250 | int maxEnumValue = -1; | | |||
251 | for (auto it = m_roles.constBegin(); it != m_roles.constEnd(); ++it) { | | |||
252 | if (it.key() > maxEnumValue) | | |||
253 | maxEnumValue = it.key(); | | |||
254 | } | | |||
255 | Q_ASSERT(maxEnumValue != -1); | | |||
256 | auto mo = qobjectMetaObject; | 97 | auto mo = qobjectMetaObject; | ||
257 | for (int i = 0; i < mo.propertyCount(); ++i) { | 98 | for (int i = 0; i < mo.propertyCount(); ++i) { | ||
258 | QMetaProperty property = mo.property(i); | 99 | QMetaProperty property = mo.property(i); | ||
259 | QString name(property.name()); | 100 | QString name(property.name()); | ||
260 | name.replace(0, 1, name.at(0).toUpper()); | 101 | name.replace(0, 1, name.at(0).toUpper()); | ||
261 | m_roles[++maxEnumValue] = name.toLatin1(); | 102 | m_roles[++maxEnumValue] = name.toLatin1(); | ||
262 | m_objectProperties.insert(maxEnumValue, i); | 103 | m_objectProperties.insert(maxEnumValue, i); | ||
263 | if (!property.hasNotifySignal()) | 104 | if (!property.hasNotifySignal()) { | ||
264 | continue; | 105 | continue; | ||
106 | } | ||||
265 | m_signalIndexToProperties.insert(property.notifySignalIndex(), i); | 107 | m_signalIndexToProperties.insert(property.notifySignalIndex(), i); | ||
266 | } | 108 | } | ||
267 | qCDebug(PLASMAPA) << m_roles; | 109 | qCDebug(PLASMAPA) << m_roles; | ||
268 | } | 110 | } | ||
269 | 111 | | |||
270 | QVariant AbstractModel::dataForRole(QObject *obj, int role) const | 112 | void AbstractModel::propertyChanged() | ||
271 | { | | |||
272 | int property = m_objectProperties.value(role, -1); | | |||
273 | if (property == -1) { | | |||
274 | return QVariant(); | | |||
275 | } | | |||
276 | return obj->metaObject()->property(property).read(obj); | | |||
277 | } | | |||
278 | | ||||
279 | ReverseFilterModel::ReverseFilterModel(QObject *parent) | | |||
280 | : QSortFilterProxyModel(parent) | | |||
281 | { | | |||
282 | setDynamicSortFilter(true); | | |||
283 | setFilterKeyColumn(0); | | |||
284 | } | | |||
285 | | ||||
286 | void ReverseFilterModel::initialSort() | | |||
287 | { | | |||
288 | QSortFilterProxyModel::sort(0, Qt::DescendingOrder); | | |||
289 | } | | |||
290 | | ||||
291 | SourceModel::SourceModel(QObject *parent) | | |||
292 | : AbstractModel(&context()->sources(), parent) | | |||
293 | { | 113 | { | ||
294 | initRoleNames(Source::staticMetaObject); | 114 | if (!sender() || senderSignalIndex() == -1) { | ||
295 | 115 | return; | |||
296 | connect(&context()->sources(), &SourceMap::added, this, &SourceModel::sourcesChanged); | | |||
297 | connect(&context()->sources(), &SourceMap::updated, this, &SourceModel::sourcesChanged); | | |||
298 | connect(&context()->sources(), &SourceMap::removed, this, &SourceModel::sourcesChanged); | | |||
299 | connect(context()->server(), &Server::defaultSourceChanged, this, &SourceModel::defaultSourceChanged); | | |||
300 | | ||||
301 | emit sourcesChanged(); | | |||
302 | } | | |||
303 | | ||||
304 | Source *SourceModel::defaultSource() const | | |||
305 | { | | |||
306 | return context()->server()->defaultSource(); | | |||
307 | } | | |||
308 | | ||||
309 | int SourceModel::rowCount(const QModelIndex &parent) const | | |||
310 | { | | |||
311 | Q_UNUSED(parent); | | |||
312 | if (!context()) | | |||
313 | return 0; | | |||
314 | return context()->sources().data().count(); | | |||
315 | } | 116 | } | ||
316 | 117 | int propertyIndex = m_signalIndexToProperties.value(senderSignalIndex(), -1); | |||
317 | QVariant SourceModel::data(const QModelIndex &index, int role) const | 118 | if (propertyIndex == -1) { | ||
318 | { | 119 | return; | ||
319 | Source *data = context()->sources().data().values().at(index.row()); | | |||
320 | Q_ASSERT(data); | | |||
321 | switch(static_cast<ItemRole>(role)) { | | |||
322 | case IndexRole: | | |||
323 | return data->index(); | | |||
324 | case PulseObjectRole: | | |||
325 | return QVariant::fromValue(data); | | |||
326 | } | 120 | } | ||
327 | return dataForRole(data, role); | 121 | int role = m_objectProperties.key(propertyIndex, -1); | ||
122 | if (role == -1) { | ||||
123 | return; | ||||
328 | } | 124 | } | ||
329 | 125 | int index = m_map->indexOfObject(sender()); | |||
330 | bool SourceModel::setData(const QModelIndex &index, const QVariant &value, int role) | 126 | qCDebug(PLASMAPA) << "PROPERTY CHANGED (" << index << ") :: " << role << roleNames().value(role); | ||
331 | { | 127 | emit dataChanged(createIndex(index, 0), createIndex(index, 0), {role}); | ||
332 | int propertyIndex = m_objectProperties.value(role, -1); | | |||
333 | if (propertyIndex == -1) | | |||
334 | return false; | | |||
335 | Source *data = context()->sources().data().values().at(index.row()); | | |||
336 | auto property = data->metaObject()->property(propertyIndex); | | |||
337 | return property.write(data, value); | | |||
338 | } | 128 | } | ||
339 | 129 | | |||
340 | void SourceModel::onDataAdded(quint32 index) | 130 | void AbstractModel::onDataAdded(int index) | ||
341 | { | 131 | { | ||
342 | beginInsertRows(QModelIndex(), index, index); | 132 | beginInsertRows(QModelIndex(), index, index); | ||
343 | Source *data = context()->sources().data().values().at(index); | 133 | QObject *data = m_map->objectAt(index); | ||
344 | const QMetaObject *mo = data->metaObject(); | 134 | const QMetaObject *mo = data->metaObject(); | ||
345 | // We have all the data changed notify signals already stored | 135 | // We have all the data changed notify signals already stored | ||
346 | auto keys = m_signalIndexToProperties.keys(); | 136 | auto keys = m_signalIndexToProperties.keys(); | ||
347 | foreach(int index, keys){ | 137 | foreach (int index, keys) { | ||
348 | QMetaMethod meth = mo->method(index); | 138 | QMetaMethod meth = mo->method(index); | ||
349 | connect(data, meth, this, propertyChangedMetaMethod()); | 139 | connect(data, meth, this, propertyChangedMetaMethod()); | ||
350 | } | 140 | } | ||
351 | endInsertRows(); | 141 | endInsertRows(); | ||
352 | } | 142 | } | ||
353 | 143 | | |||
354 | void SourceModel::onDataRemoved(quint32 index) | 144 | void AbstractModel::onDataRemoved(int index) | ||
355 | { | 145 | { | ||
356 | beginRemoveRows(QModelIndex(), index, index); | 146 | beginRemoveRows(QModelIndex(), index, index); | ||
357 | endRemoveRows(); | 147 | endRemoveRows(); | ||
358 | } | 148 | } | ||
359 | 149 | | |||
360 | void SourceModel::propertyChanged() | 150 | QMetaMethod AbstractModel::propertyChangedMetaMethod() const | ||
361 | { | | |||
362 | if (!sender() || senderSignalIndex() == -1) | | |||
363 | return; | | |||
364 | int propertyIndex = m_signalIndexToProperties.value(senderSignalIndex(), -1); | | |||
365 | if (propertyIndex == -1) | | |||
366 | return; | | |||
367 | int role = m_objectProperties.key(propertyIndex, -1); | | |||
368 | if (role == -1) | | |||
369 | return; | | |||
370 | int index = context()->sources().modelIndexForQObject(sender()); | | |||
371 | qCDebug(PLASMAPA) << "PROPERTY CHANGED (" << index << ") :: " << role << roleNames().value(role); | | |||
372 | emit dataChanged(createIndex(index, 0), createIndex(index, 0), QVector<int>() << role); | | |||
373 | } | | |||
374 | | ||||
375 | QMetaMethod SourceModel::propertyChangedMetaMethod() const | | |||
376 | { | 151 | { | ||
377 | auto mo = metaObject(); | 152 | auto mo = metaObject(); | ||
378 | int methodIndex = mo->indexOfMethod(QMetaObject::normalizedSignature("propertyChanged()").data()); | 153 | int methodIndex = mo->indexOfMethod("propertyChanged()"); | ||
379 | if(methodIndex == -1){ | 154 | if (methodIndex == -1) { | ||
380 | return QMetaMethod(); | 155 | return QMetaMethod(); | ||
381 | } | 156 | } | ||
382 | return mo->method(methodIndex); | 157 | return mo->method(methodIndex); | ||
383 | } | 158 | } | ||
384 | 159 | | |||
385 | SourceOutputModel::SourceOutputModel(QObject *parent) | 160 | SinkModel::SinkModel(QObject *parent) | ||
386 | : AbstractModel(&context()->sourceOutputs(), parent) | 161 | : AbstractModel(&context()->sinks(), parent) | ||
387 | { | 162 | { | ||
388 | initRoleNames(SourceOutput::staticMetaObject); | 163 | initRoleNames(Sink::staticMetaObject); | ||
164 | | ||||
165 | connect(context()->server(), &Server::defaultSinkChanged, this, &SinkModel::defaultSinkChanged); | ||||
389 | } | 166 | } | ||
390 | 167 | | |||
391 | int SourceOutputModel::rowCount(const QModelIndex &parent) const | 168 | Sink *SinkModel::defaultSink() const | ||
392 | { | 169 | { | ||
393 | Q_UNUSED(parent); | 170 | return context()->server()->defaultSink(); | ||
394 | if (!context()) | | |||
395 | return 0; | | |||
396 | return context()->sourceOutputs().data().count(); | | |||
397 | } | 171 | } | ||
398 | 172 | | |||
399 | QVariant SourceOutputModel::data(const QModelIndex &index, int role) const | 173 | SourceModel::SourceModel(QObject *parent) | ||
174 | : AbstractModel(&context()->sources(), parent) | ||||
400 | { | 175 | { | ||
401 | SourceOutput *data = context()->sourceOutputs().data().values().at(index.row()); | 176 | initRoleNames(Source::staticMetaObject); | ||
402 | Q_ASSERT(data); | 177 | | ||
403 | switch ((ItemRole) role) { | 178 | connect(context()->server(), &Server::defaultSourceChanged, this, &SourceModel::defaultSourceChanged); | ||
404 | case IndexRole: | | |||
405 | return data->index(); | | |||
406 | case PulseObjectRole: | | |||
407 | return QVariant::fromValue(data); | | |||
408 | } | | |||
409 | return dataForRole(data, role); | | |||
410 | } | 179 | } | ||
411 | 180 | | |||
412 | CardModel::CardModel(QObject *parent) | 181 | Source *SourceModel::defaultSource() const | ||
413 | : AbstractModel(&context()->cards(), parent) | | |||
414 | { | 182 | { | ||
415 | initRoleNames(Card::staticMetaObject); | 183 | return context()->server()->defaultSource(); | ||
416 | } | 184 | } | ||
417 | 185 | | |||
418 | int CardModel::rowCount(const QModelIndex &parent) const | 186 | SinkInputModel::SinkInputModel(QObject *parent) | ||
187 | : AbstractModel(&context()->sinkInputs(), parent) | ||||
419 | { | 188 | { | ||
420 | Q_UNUSED(parent); | 189 | initRoleNames(SinkInput::staticMetaObject); | ||
421 | if (!context()) | | |||
422 | return 0; | | |||
423 | return context()->cards().data().count(); | | |||
424 | } | 190 | } | ||
425 | 191 | | |||
426 | QVariant CardModel::data(const QModelIndex &index, int role) const | 192 | SourceOutputModel::SourceOutputModel(QObject *parent) | ||
193 | : AbstractModel(&context()->sourceOutputs(), parent) | ||||
427 | { | 194 | { | ||
428 | Card *data = context()->cards().data().values().at(index.row()); | 195 | initRoleNames(SourceOutput::staticMetaObject); | ||
429 | Q_ASSERT(data); | | |||
430 | switch ((ItemRole) role) { | | |||
431 | case IndexRole: | | |||
432 | return data->index(); | | |||
433 | case PulseObjectRole: | | |||
434 | return QVariant::fromValue(data); | | |||
435 | } | 196 | } | ||
436 | return dataForRole(data, role); | 197 | | ||
198 | CardModel::CardModel(QObject *parent) | ||||
199 | : AbstractModel(&context()->cards(), parent) | ||||
200 | { | ||||
201 | initRoleNames(Card::staticMetaObject); | ||||
437 | } | 202 | } | ||
438 | 203 | | |||
439 | } // QPulseAudio | 204 | } // QPulseAudio |