Changeset View
Changeset View
Standalone View
Standalone View
src/pulseaudio.cpp
Show First 20 Lines • Show All 183 Lines • ▼ Show 20 Line(s) | 181 | { | |||
---|---|---|---|---|---|
184 | if (methodIndex == -1) { | 184 | if (methodIndex == -1) { | ||
185 | return QMetaMethod(); | 185 | return QMetaMethod(); | ||
186 | } | 186 | } | ||
187 | return mo->method(methodIndex); | 187 | return mo->method(methodIndex); | ||
188 | } | 188 | } | ||
189 | 189 | | |||
190 | SinkModel::SinkModel(QObject *parent) | 190 | SinkModel::SinkModel(QObject *parent) | ||
191 | : AbstractModel(&context()->sinks(), parent) | 191 | : AbstractModel(&context()->sinks(), parent) | ||
192 | , m_preferredSink(nullptr) | ||||
192 | { | 193 | { | ||
193 | initRoleNames(Sink::staticMetaObject); | 194 | initRoleNames(Sink::staticMetaObject); | ||
194 | 195 | | |||
195 | connect(context()->server(), &Server::defaultSinkChanged, this, &SinkModel::defaultSinkChanged); | 196 | for (int i = 0; i < context()->sinks().count(); ++i) { | ||
197 | sinkAdded(i); | ||||
198 | } | ||||
199 | | ||||
200 | connect(&context()->sinks(), &MapBaseQObject::added, this, &SinkModel::sinkAdded); | ||||
201 | connect(&context()->sinks(), &MapBaseQObject::removed, this, &SinkModel::sinkRemoved); | ||||
202 | | ||||
203 | connect(context()->server(), &Server::defaultSinkChanged, this, [this]() { | ||||
204 | updatePreferredSink(); | ||||
205 | emit defaultSinkChanged(); | ||||
206 | }); | ||||
196 | } | 207 | } | ||
197 | 208 | | |||
198 | Sink *SinkModel::defaultSink() const | 209 | Sink *SinkModel::defaultSink() const | ||
199 | { | 210 | { | ||
200 | return context()->server()->defaultSink(); | 211 | return context()->server()->defaultSink(); | ||
201 | } | 212 | } | ||
202 | 213 | | |||
214 | Sink *SinkModel::preferredSink() const | ||||
215 | { | ||||
216 | return m_preferredSink; | ||||
217 | } | ||||
218 | | ||||
203 | QVariant SinkModel::data(const QModelIndex &index, int role) const | 219 | QVariant SinkModel::data(const QModelIndex &index, int role) const | ||
204 | { | 220 | { | ||
205 | if (role == SortByDefaultRole) { | 221 | if (role == SortByDefaultRole) { | ||
206 | // Workaround QTBUG-1548 | 222 | // Workaround QTBUG-1548 | ||
207 | const QString pulseIndex = data(index, AbstractModel::role(QByteArrayLiteral("Index"))).toString(); | 223 | const QString pulseIndex = data(index, AbstractModel::role(QByteArrayLiteral("Index"))).toString(); | ||
208 | const QString defaultDevice = data(index, AbstractModel::role(QByteArrayLiteral("Default"))).toString(); | 224 | const QString defaultDevice = data(index, AbstractModel::role(QByteArrayLiteral("Default"))).toString(); | ||
209 | return defaultDevice + pulseIndex; | 225 | return defaultDevice + pulseIndex; | ||
210 | } | 226 | } | ||
211 | return AbstractModel::data(index, role); | 227 | return AbstractModel::data(index, role); | ||
212 | } | 228 | } | ||
213 | 229 | | |||
230 | void SinkModel::sinkAdded(int index) | ||||
231 | { | ||||
232 | Q_ASSERT(qobject_cast<Sink *>(context()->sinks().objectAt(index))); | ||||
233 | Sink *sink = static_cast<Sink *>(context()->sinks().objectAt(index)); | ||||
234 | connect(sink, &Sink::stateChanged, this, &SinkModel::updatePreferredSink); | ||||
235 | | ||||
236 | updatePreferredSink(); | ||||
237 | } | ||||
238 | | ||||
239 | void SinkModel::sinkRemoved(int index) | ||||
240 | { | ||||
241 | Q_UNUSED(index); | ||||
242 | | ||||
243 | updatePreferredSink(); | ||||
244 | } | ||||
245 | | ||||
246 | void SinkModel::updatePreferredSink() | ||||
247 | { | ||||
248 | Sink *sink = findPreferredSink(); | ||||
249 | | ||||
250 | if (sink != m_preferredSink) { | ||||
251 | qCDebug(PLASMAPA) << "Changing preferred sink to" << sink << (sink ? sink->name() : ""); | ||||
252 | m_preferredSink = sink; | ||||
253 | emit preferredSinkChanged(); | ||||
254 | } | ||||
255 | } | ||||
256 | | ||||
257 | Sink *SinkModel::findPreferredSink() const | ||||
258 | { | ||||
259 | const auto &sinks = context()->sinks(); | ||||
260 | | ||||
261 | // Only one sink is the preferred one | ||||
262 | if (sinks.count() == 1) { | ||||
263 | return static_cast<Sink *>(sinks.objectAt(0)); | ||||
264 | } | ||||
265 | | ||||
266 | auto lookForState = [this](Device::State state) { | ||||
267 | Sink *ret = nullptr; | ||||
268 | QMapIterator<quint32, Sink *> it(context()->sinks().data()); | ||||
269 | while (it.hasNext()) { | ||||
270 | it.next(); | ||||
271 | if (it.value()->state() != state) { | ||||
272 | continue; | ||||
273 | } | ||||
274 | if (!ret) { | ||||
275 | ret = it.value(); | ||||
276 | } else if (it.value() == defaultSink()) { | ||||
277 | ret = it.value(); | ||||
278 | break; | ||||
279 | } | ||||
280 | } | ||||
281 | return ret; | ||||
282 | }; | ||||
283 | | ||||
284 | Sink *preferred = nullptr; | ||||
285 | | ||||
286 | // Look for playing sinks + prefer default sink | ||||
287 | preferred = lookForState(Device::RunningState); | ||||
288 | if (preferred) { | ||||
289 | return preferred; | ||||
290 | } | ||||
291 | | ||||
292 | // Look for idle sinks + prefer default sink | ||||
293 | preferred = lookForState(Device::IdleState); | ||||
294 | if (preferred) { | ||||
295 | return preferred; | ||||
296 | } | ||||
297 | | ||||
298 | // Fallback to default sink | ||||
299 | return defaultSink(); | ||||
300 | } | ||||
301 | | ||||
214 | SourceModel::SourceModel(QObject *parent) | 302 | SourceModel::SourceModel(QObject *parent) | ||
215 | : AbstractModel(&context()->sources(), parent) | 303 | : AbstractModel(&context()->sources(), parent) | ||
216 | { | 304 | { | ||
217 | initRoleNames(Source::staticMetaObject); | 305 | initRoleNames(Source::staticMetaObject); | ||
218 | 306 | | |||
219 | connect(context()->server(), &Server::defaultSourceChanged, this, &SourceModel::defaultSourceChanged); | 307 | connect(context()->server(), &Server::defaultSourceChanged, this, &SourceModel::defaultSourceChanged); | ||
220 | } | 308 | } | ||
221 | 309 | | |||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |