1 /*  This file is part of the KDE project
2     Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     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     later version accepted by the membership of KDE e.V. (or its
9     successor approved by the membership of KDE e.V.), Nokia Corporation
10     (or its successors, if any) and the KDE Free Qt Foundation, which shall
11     act as a proxy defined in Section 6 of version 3 of the license.
12 
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #include "globalconfig.h"
24 #include "globalconfig_p.h"
25 
26 #include "factory_p.h"
27 #include "phonondefs_p.h"
28 #include "platformplugin.h"
29 #include "backendinterface.h"
30 #include "qsettingsgroup_p.h"
31 #include "phononnamespace_p.h"
32 #include "phononnamespace.h"
33 #include "pulsesupport.h"
34 
35 #include <QtCore/QList>
36 #include <QtCore/QVariant>
37 
38 namespace Phonon
39 {
40 
GlobalConfigPrivate()41 GlobalConfigPrivate::GlobalConfigPrivate() : config(QLatin1String("kde.org"), QLatin1String("libphonon"))
42 {
43 }
44 
GlobalConfig()45 GlobalConfig::GlobalConfig()
46     : k_ptr(new GlobalConfigPrivate)
47 {
48 }
49 
~GlobalConfig()50 GlobalConfig::~GlobalConfig()
51 {
52     delete k_ptr;
53 }
54 
55 enum WhatToFilter {
56     FilterAdvancedDevices = 1,
57     FilterHardwareDevices = 2,
58     FilterUnavailableDevices = 4
59 };
60 
filter(ObjectDescriptionType type,BackendInterface * backendIface,QList<int> * list,int whatToFilter)61 static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
62 {
63     QMutableListIterator<int> it(*list);
64     while (it.hasNext()) {
65         QHash<QByteArray, QVariant> properties;
66         if (backendIface)
67             properties = backendIface->objectDescriptionProperties(type, it.next());
68         else
69             properties = PulseSupport::getInstance()->objectDescriptionProperties(type, it.next());
70         QVariant var;
71         if (whatToFilter & FilterAdvancedDevices) {
72             var = properties.value("isAdvanced");
73             if (var.isValid() && var.toBool()) {
74                 it.remove();
75                 continue;
76             }
77         }
78         if (whatToFilter & FilterHardwareDevices) {
79             var = properties.value("isHardwareDevice");
80             if (var.isValid() && var.toBool()) {
81                 it.remove();
82                 continue;
83             }
84         }
85         if (whatToFilter & FilterUnavailableDevices) {
86             var = properties.value("available");
87             if (var.isValid() && !var.toBool()) {
88                 it.remove();
89                 continue;
90             }
91         }
92     }
93 }
94 
95 #ifndef QT_NO_PHONON_SETTINGSGROUP
sortDevicesByCategoryPriority(const GlobalConfig * config,const QSettingsGroup * backendConfig,ObjectDescriptionType type,Category category,QList<int> & defaultList)96 static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Category category, QList<int> &defaultList)
97 {
98     Q_ASSERT(config); Q_UNUSED(config);
99     Q_ASSERT(backendConfig);
100     Q_ASSERT(type == AudioOutputDeviceType);
101 
102     if (defaultList.size() <= 1) {
103         // nothing to sort
104         return defaultList;
105     } else {
106         // make entries unique
107         QSet<int> seen;
108         QMutableListIterator<int> it(defaultList);
109         while (it.hasNext()) {
110             if (seen.contains(it.next())) {
111                 it.remove();
112             } else {
113                 seen.insert(it.value());
114             }
115         }
116     }
117 
118     QList<int> deviceList;
119     PulseSupport *pulse = PulseSupport::getInstance();
120     if (pulse->isUsed()) {
121         deviceList = pulse->objectIndexesByCategory(type, category);
122     } else {
123         QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
124         if (!backendConfig->hasKey(categoryKey)) {
125             // no list in config for the given category
126             categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(NoCategory));
127             if (!backendConfig->hasKey(categoryKey)) {
128                 // no list in config for NoCategory
129                 return defaultList;
130             }
131         }
132 
133         //Now the list from d->config
134         deviceList = backendConfig->value(categoryKey, QList<int>());
135     }
136 
137     //if there are devices in d->config that the backend doesn't report, remove them from the list
138     QMutableListIterator<int> i(deviceList);
139     while (i.hasNext()) {
140         if (0 == defaultList.removeAll(i.next())) {
141             i.remove();
142         }
143     }
144 
145     //if the backend reports more devices that are not in d->config append them to the list
146     deviceList += defaultList;
147 
148     return deviceList;
149 }
150 
sortDevicesByCategoryPriority(const GlobalConfig * config,const QSettingsGroup * backendConfig,ObjectDescriptionType type,CaptureCategory category,QList<int> & defaultList)151 static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, CaptureCategory category, QList<int> &defaultList)
152 {
153     Q_ASSERT(config); Q_UNUSED(config);
154     Q_ASSERT(backendConfig);
155     Q_ASSERT(type == AudioCaptureDeviceType || type == VideoCaptureDeviceType);
156 
157     if (defaultList.size() <= 1) {
158         // nothing to sort
159         return defaultList;
160     } else {
161         // make entries unique
162         QSet<int> seen;
163         QMutableListIterator<int> it(defaultList);
164         while (it.hasNext()) {
165             if (seen.contains(it.next())) {
166                 it.remove();
167             } else {
168                 seen.insert(it.value());
169             }
170         }
171     }
172 
173     QList<int> deviceList;
174     PulseSupport *pulse = PulseSupport::getInstance();
175     if (pulse->isUsed()) {
176         deviceList = pulse->objectIndexesByCategory(type, category);
177     } else {
178         QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
179         if (!backendConfig->hasKey(categoryKey)) {
180             // no list in config for the given category
181             categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(NoCategory));
182             if (!backendConfig->hasKey(categoryKey)) {
183                 // no list in config for NoCategory
184                 return defaultList;
185             }
186         }
187 
188         //Now the list from d->config
189         deviceList = backendConfig->value(categoryKey, QList<int>());
190     }
191 
192     //if there are devices in d->config that the backend doesn't report, remove them from the list
193     QMutableListIterator<int> i(deviceList);
194     while (i.hasNext()) {
195         if (0 == defaultList.removeAll(i.next())) {
196             i.remove();
197         }
198     }
199 
200     //if the backend reports more devices that are not in d->config append them to the list
201     deviceList += defaultList;
202 
203     return deviceList;
204 }
205 
hideAdvancedDevices() const206 bool GlobalConfig::hideAdvancedDevices() const
207 {
208     P_D(const GlobalConfig);
209     //The devices need to be stored independently for every backend
210     const QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
211     return generalGroup.value(QLatin1String("HideAdvancedDevices"), true);
212 }
213 
setHideAdvancedDevices(bool hide)214 void GlobalConfig::setHideAdvancedDevices(bool hide)
215 {
216     P_D(GlobalConfig);
217     QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
218     generalGroup.setValue(QLatin1String("HideAdvancedDevices"), hide);
219 }
220 #endif // QT_NO_PHONON_SETTINGSGROUP
221 
isHiddenAudioOutputDevice(const GlobalConfig * config,int i)222 static bool isHiddenAudioOutputDevice(const GlobalConfig *config, int i)
223 {
224     Q_ASSERT(config);
225 
226 #ifndef QT_NO_PHONON_SETTINGSGROUP
227     if (!config->hideAdvancedDevices())
228         return false;
229 #endif // QT_NO_PHONON_SETTINGSGROUP
230 
231     AudioOutputDevice ad = AudioOutputDevice::fromIndex(i);
232     const QVariant var = ad.property("isAdvanced");
233     return (var.isValid() && var.toBool());
234 }
235 
236 #ifndef PHONON_NO_AUDIOCAPTURE
isHiddenAudioCaptureDevice(const GlobalConfig * config,int i)237 static bool isHiddenAudioCaptureDevice(const GlobalConfig *config, int i)
238 {
239     Q_ASSERT(config);
240 
241 #ifndef QT_NO_PHONON_SETTINGSGROUP
242     if (!config->hideAdvancedDevices())
243         return false;
244 #endif // QT_NO_PHONON_SETTINGSGROUP
245 
246     AudioCaptureDevice ad = AudioCaptureDevice::fromIndex(i);
247     const QVariant var = ad.property("isAdvanced");
248     return (var.isValid() && var.toBool());
249 }
250 #endif
251 
252 #ifndef PHONON_NO_VIDEOCAPTURE
isHiddenVideoCaptureDevice(const GlobalConfig * config,int i)253 static bool isHiddenVideoCaptureDevice(const GlobalConfig *config, int i)
254 {
255     Q_ASSERT(config);
256 
257 #ifndef QT_NO_PHONON_SETTINGSGROUP
258     if (!config->hideAdvancedDevices())
259         return false;
260 #endif // QT_NO_PHONON_SETTINGSGROUP
261 
262     VideoCaptureDevice vd = VideoCaptureDevice::fromIndex(i);
263     const QVariant var = vd.property("isAdvanced");
264     return (var.isValid() && var.toBool());
265 }
266 #endif
267 
reindexList(const GlobalConfig * config,ObjectDescriptionType type,Category category,QList<int> newOrder)268 static QList<int> reindexList(const GlobalConfig *config, ObjectDescriptionType type, Category category, QList<int>newOrder)
269 {
270     Q_ASSERT(config);
271     Q_ASSERT(type == AudioOutputDeviceType);
272     Q_UNUSED(type);
273 
274     /*QString sb;
275     sb = QString("(Size %1)").arg(currentList.size());
276     foreach (int i, currentList)
277     sb += QString("%1, ").arg(i);
278     fprintf(stderr, "=== Reindex Current: %s\n", sb.toUtf8().constData());
279     sb = QString("(Size %1)").arg(newOrder.size());
280     foreach (int i, newOrder)
281     sb += QString("%1, ").arg(i);
282     fprintf(stderr, "=== Reindex Before : %s\n", sb.toUtf8().constData());*/
283 
284     int override = GlobalConfig::ShowUnavailableDevices | GlobalConfig::ShowAdvancedDevices;
285     QList<int> currentList = config->audioOutputDeviceListFor(category, override);
286 
287 
288     QList<int> newList;
289 
290     foreach (int i, newOrder) {
291         int found = currentList.indexOf(i);
292         if (found < 0) {
293             // It's not in the list, so something is odd (e.g. client error). Ignore it.
294             continue;
295         }
296 
297         // Iterate through the list from this point onward. If there are hidden devices
298         // immediately following, take them too.
299         newList.append(currentList.takeAt(found));
300 
301         while (found < currentList.size()) {
302             bool hidden = isHiddenAudioOutputDevice(config, currentList.at(found));
303             if (!hidden)
304                 break;
305 
306             newList.append(currentList.takeAt(found));
307         }
308     }
309 
310     // If there are any devices left in.. just tack them on the end.
311     if (currentList.size() > 0)
312         newList += currentList;
313 
314     /*sb = QString("(Size %1)").arg(newList.size());
315     foreach (int i, newList)
316     sb += QString("%1, ").arg(i);
317     fprintf(stderr, "=== Reindex After  : %s\n", sb.toUtf8().constData());*/
318     return newList;
319 }
320 
reindexList(const GlobalConfig * config,ObjectDescriptionType type,CaptureCategory category,QList<int> newOrder)321 static QList<int> reindexList(const GlobalConfig *config, ObjectDescriptionType type, CaptureCategory category, QList<int>newOrder)
322 {
323     Q_ASSERT(config);
324     Q_ASSERT(type == AudioCaptureDeviceType || type == VideoCaptureDeviceType);
325 
326     QList<int> currentList;
327     int override = GlobalConfig::ShowUnavailableDevices | GlobalConfig::ShowAdvancedDevices;
328 
329     switch (type) {
330 #ifndef PHONON_NO_AUDIOCAPTURE
331     case AudioCaptureDeviceType:
332         currentList = config->audioCaptureDeviceListFor(category, override);
333         break;
334 #endif
335 
336 #ifndef PHONON_NO_VIDEOCAPTURE
337     case VideoCaptureDeviceType:
338         currentList = config->videoCaptureDeviceListFor(category, override);
339         break;
340 #endif
341 
342     default: ;
343     }
344 
345     QList<int> newList;
346 
347     foreach (int i, newOrder) {
348         int found = currentList.indexOf(i);
349         if (found < 0) {
350             // It's not in the list, so something is odd (e.g. client error). Ignore it.
351             continue;
352         }
353 
354         // Iterate through the list from this point onward. If there are hidden devices
355         // immediately following, take them too.
356         newList.append(currentList.takeAt(found));
357 
358         while (found < currentList.size()) {
359             bool hidden = true;
360 
361             switch (type) {
362 #ifndef PHONON_NO_AUDIOCAPTURE
363             case AudioCaptureDeviceType:
364                 hidden = isHiddenAudioCaptureDevice(config, currentList.at(found));
365                 break;
366 #endif
367 
368 #ifndef PHONON_NO_VIDEOCAPTURE
369             case VideoCaptureDeviceType:
370                 hidden = isHiddenVideoCaptureDevice(config, currentList.at(found));
371                 break;
372 #endif
373 
374             default: ;
375             }
376 
377             if (!hidden)
378                 break;
379 
380             newList.append(currentList.takeAt(found));
381         }
382     }
383 
384     // If there are any devices left in.. just tack them on the end.
385     if (currentList.size() > 0)
386         newList += currentList;
387 
388     return newList;
389 }
390 
setAudioOutputDeviceListFor(Category category,QList<int> order)391 void GlobalConfig::setAudioOutputDeviceListFor(Category category, QList<int> order)
392 {
393     PulseSupport *pulse = PulseSupport::getInstance();
394     if (pulse->isUsed()) {
395         pulse->setOutputDevicePriorityForCategory(category, order);
396         return;
397     }
398 
399 #ifndef QT_NO_PHONON_SETTINGSGROUP
400     P_D(GlobalConfig);
401     QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
402 
403     order = reindexList(this, AudioOutputDeviceType, category, order);
404 
405     const QList<int> noCategoryOrder = audioOutputDeviceListFor(NoCategory, ShowUnavailableDevices|ShowAdvancedDevices);
406     if (category != NoCategory && order == noCategoryOrder) {
407         backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
408     } else {
409         backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
410     }
411 #endif //QT_NO_PHONON_SETTINGSGROUP
412 }
413 
audioOutputDeviceListFor(Category category,int override) const414 QList<int> GlobalConfig::audioOutputDeviceListFor(Category category, int override) const
415 {
416     P_D(const GlobalConfig);
417 
418 #ifndef QT_NO_PHONON_SETTINGSGROUP
419     const bool hide = ((override & AdvancedDevicesFromSettings)
420             ? hideAdvancedDevices()
421             : static_cast<bool>(override & HideAdvancedDevices));
422 #else
423     const bool hide = !((override & AdvancedDevicesFromSettings) && static_cast<bool>(override & HideAdvancedDevices));
424 #endif
425 
426     QList<int> defaultList;
427 
428     PulseSupport *pulse = PulseSupport::getInstance();
429     if (pulse->isUsed()) {
430         defaultList = pulse->objectDescriptionIndexes(AudioOutputDeviceType);
431         if (hide || (override & HideUnavailableDevices)) {
432             filter(AudioOutputDeviceType, NULL, &defaultList,
433                     (hide ? FilterAdvancedDevices : 0)
434                     | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
435                     );
436         }
437     } else {
438         BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
439 
440 #ifndef QT_NO_PHONON_PLATFORMPLUGIN
441         if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
442             // the platform plugin lists the audio devices for the platform
443             // this list already is in default order (as defined by the platform plugin)
444             defaultList = platformPlugin->objectDescriptionIndexes(AudioOutputDeviceType);
445             if (hide) {
446                 QMutableListIterator<int> it(defaultList);
447                 while (it.hasNext()) {
448                     AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
449                     const QVariant var = objDesc.property("isAdvanced");
450                     if (var.isValid() && var.toBool()) {
451                         it.remove();
452                     }
453                 }
454             }
455         }
456 #endif //QT_NO_PHONON_PLATFORMPLUGIN
457 
458         // lookup the available devices directly from the backend
459         if (backendIface) {
460             // this list already is in default order (as defined by the backend)
461             QList<int> list = backendIface->objectDescriptionIndexes(AudioOutputDeviceType);
462             if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
463                 filter(AudioOutputDeviceType, backendIface, &list,
464                         (hide ? FilterAdvancedDevices : 0)
465                         // the platform plugin maybe already provided the hardware devices?
466                         | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
467                         | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
468                         );
469             }
470             defaultList += list;
471         }
472     }
473 
474 #ifndef QT_NO_PHONON_SETTINGSGROUP
475     const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
476     return sortDevicesByCategoryPriority(this, &backendConfig, AudioOutputDeviceType, category, defaultList);
477 #else //QT_NO_PHONON_SETTINGSGROUP
478     return defaultList;
479 #endif //QT_NO_PHONON_SETTINGSGROUP
480 }
481 
482 
audioOutputDeviceFor(Category category,int override) const483 int GlobalConfig::audioOutputDeviceFor(Category category, int override) const
484 {
485 #ifndef QT_NO_PHONON_SETTINGSGROUP
486     QList<int> ret = audioOutputDeviceListFor(category, override);
487     if (!ret.isEmpty())
488         return ret.first();
489 #endif //QT_NO_PHONON_SETTINGSGROUP
490     return -1;
491 }
492 
audioOutputDeviceProperties(int index) const493 QHash<QByteArray, QVariant> GlobalConfig::audioOutputDeviceProperties(int index) const
494 {
495     return deviceProperties(AudioOutputDeviceType, index);
496 }
497 
498 
499 #ifndef PHONON_NO_AUDIOCAPTURE
setAudioCaptureDeviceListFor(CaptureCategory category,QList<int> order)500 void GlobalConfig::setAudioCaptureDeviceListFor(CaptureCategory category, QList<int> order)
501 {
502 
503     PulseSupport *pulse = PulseSupport::getInstance();
504     if (pulse->isUsed()) {
505         pulse->setCaptureDevicePriorityForCategory(category, order);
506         return;
507     }
508 
509 #ifndef QT_NO_PHONON_SETTINGSGROUP
510     P_D(GlobalConfig);
511     QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
512 
513     order = reindexList(this, AudioCaptureDeviceType, category, order);
514 
515     const QList<int> noCategoryOrder = audioCaptureDeviceListFor(NoCaptureCategory, ShowUnavailableDevices|ShowAdvancedDevices);
516     if (category != NoCaptureCategory && order == noCategoryOrder) {
517         backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
518     } else {
519         backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
520     }
521 #endif //QT_NO_PHONON_SETTINGSGROUP
522 }
523 
audioCaptureDeviceListFor(CaptureCategory category,int override) const524 QList<int> GlobalConfig::audioCaptureDeviceListFor(CaptureCategory category, int override) const
525 {
526     P_D(const GlobalConfig);
527 
528 #ifndef QT_NO_PHONON_SETTINGSGROUP
529     const bool hide = ((override & AdvancedDevicesFromSettings)
530         ? hideAdvancedDevices()
531         : static_cast<bool>(override & HideAdvancedDevices));
532 #else
533     const bool hide = !((override & AdvancedDevicesFromSettings) && static_cast<bool>(override & HideAdvancedDevices));
534 #endif
535 
536     QList<int> defaultList;
537 
538     PulseSupport *pulse = PulseSupport::getInstance();
539     if (pulse->isUsed()) {
540         defaultList = pulse->objectDescriptionIndexes(AudioCaptureDeviceType);
541         if (hide || (override & HideUnavailableDevices)) {
542             filter(AudioCaptureDeviceType, NULL, &defaultList,
543                     (hide ? FilterAdvancedDevices : 0)
544                     | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
545                     );
546         }
547     } else {
548         BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
549 
550 #ifndef QT_NO_PHONON_PLATFORMPLUGIN
551         if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
552             // the platform plugin lists the audio devices for the platform
553             // this list already is in default order (as defined by the platform plugin)
554             defaultList += platformPlugin->objectDescriptionIndexes(AudioCaptureDeviceType);
555             if (hide) {
556                 QMutableListIterator<int> it(defaultList);
557                 while (it.hasNext()) {
558                     AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
559                     const QVariant var = objDesc.property("isAdvanced");
560                     if (var.isValid() && var.toBool()) {
561                         it.remove();
562                     }
563                 }
564             }
565         }
566 #endif //QT_NO_PHONON_PLATFORMPLUGIN
567 
568         // lookup the available devices directly from the backend
569         if (backendIface) {
570             // this list already is in default order (as defined by the backend)
571             QList<int> list = backendIface->objectDescriptionIndexes(AudioCaptureDeviceType);
572             if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
573                 filter(AudioCaptureDeviceType, backendIface, &list,
574                         (hide ? FilterAdvancedDevices : 0)
575                         // the platform plugin maybe already provided the hardware devices?
576                         | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
577                         | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
578                         );
579             }
580             defaultList += list;
581         }
582     }
583 
584 #ifndef QT_NO_PHONON_SETTINGSGROUP
585     const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
586     return sortDevicesByCategoryPriority(this, &backendConfig, AudioCaptureDeviceType, category, defaultList);
587 #else //QT_NO_PHONON_SETTINGSGROUP
588 #ifndef QT_NO_PHONON_PLATFORMPLUGIN
589     return defaultList;
590 #else //QT_NO_PHONON_PLATFORMPLUGIN
591     return QList<int>();
592 #endif //QT_NO_PHONON_PLATFORMPLUGIN
593 #endif //QT_NO_PHONON_SETTINGSGROUP
594 }
595 
audioCaptureDeviceFor(CaptureCategory category,int override) const596 int GlobalConfig::audioCaptureDeviceFor(CaptureCategory category, int override) const
597 {
598     QList<int> ret = audioCaptureDeviceListFor(category, override);
599     if (ret.isEmpty())
600         return -1;
601     return ret.first();
602 }
603 
audioCaptureDeviceProperties(int index) const604 QHash<QByteArray, QVariant> GlobalConfig::audioCaptureDeviceProperties(int index) const
605 {
606     return deviceProperties(AudioCaptureDeviceType, index);
607 }
608 
setAudioCaptureDeviceListFor(Category category,QList<int> order)609 void GlobalConfig::setAudioCaptureDeviceListFor(Category category, QList<int> order)
610 {
611     CaptureCategory cat = categoryToCaptureCategory(category);
612     setAudioCaptureDeviceListFor(cat, order);
613 }
614 
audioCaptureDeviceListFor(Category category,int override) const615 QList<int> GlobalConfig::audioCaptureDeviceListFor(Category category, int override) const
616 {
617     CaptureCategory cat = categoryToCaptureCategory(category);
618     return audioCaptureDeviceListFor(cat, override);
619 }
620 
audioCaptureDeviceFor(Category category,int override) const621 int GlobalConfig::audioCaptureDeviceFor(Category category, int override) const
622 {
623     CaptureCategory cat = categoryToCaptureCategory(category);
624     return audioCaptureDeviceFor(cat, override);
625 }
626 
627 #endif //PHONON_NO_AUDIOCAPTURE
628 
629 
630 #ifndef PHONON_NO_VIDEOCAPTURE
setVideoCaptureDeviceListFor(CaptureCategory category,QList<int> order)631 void GlobalConfig::setVideoCaptureDeviceListFor(CaptureCategory category, QList<int> order)
632 {
633 #ifndef QT_NO_PHONON_SETTINGSGROUP
634     P_D(GlobalConfig);
635     QSettingsGroup backendConfig(&d->config, QLatin1String("VideoCaptureDevice")); // + Factory::identifier());
636 
637     order = reindexList(this, VideoCaptureDeviceType, category, order);
638 
639     const QList<int> noCategoryOrder = videoCaptureDeviceListFor(NoCaptureCategory, ShowUnavailableDevices|ShowAdvancedDevices);
640     if (category != NoCaptureCategory && order == noCategoryOrder) {
641         backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
642     } else {
643         backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
644     }
645 #endif //QT_NO_PHONON_SETTINGSGROUP
646 }
647 
videoCaptureDeviceListFor(CaptureCategory category,int override) const648 QList<int> GlobalConfig::videoCaptureDeviceListFor(CaptureCategory category, int override) const
649 {
650     P_D(const GlobalConfig);
651 
652 #ifndef QT_NO_PHONON_SETTINGSGROUP
653     const bool hide = ((override & AdvancedDevicesFromSettings)
654         ? hideAdvancedDevices()
655         : static_cast<bool>(override & HideAdvancedDevices));
656 #else
657     const bool hide = !((override & AdvancedDevicesFromSettings) && static_cast<bool>(override & HideAdvancedDevices));
658 #endif
659 
660     //First we lookup the available devices directly from the backend
661     BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
662     if (!backendIface) {
663         return QList<int>();
664     }
665 
666     // this list already is in default order (as defined by the backend)
667     QList<int> defaultList = backendIface->objectDescriptionIndexes(VideoCaptureDeviceType);
668 
669 #ifndef QT_NO_PHONON_PLATFORMPLUGIN
670     if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
671         // the platform plugin lists the video devices for the platform
672         // this list already is in default order (as defined by the platform plugin)
673         defaultList += platformPlugin->objectDescriptionIndexes(VideoCaptureDeviceType);
674         if (hide) {
675             QMutableListIterator<int> it(defaultList);
676             while (it.hasNext()) {
677                 VideoCaptureDevice objDesc = VideoCaptureDevice::fromIndex(it.next());
678                 const QVariant var = objDesc.property("isAdvanced");
679                 if (var.isValid() && var.toBool()) {
680                     it.remove();
681                 }
682             }
683         }
684     }
685 #endif //QT_NO_PHONON_PLATFORMPLUGIN
686 
687 #ifndef QT_NO_PHONON_SETTINGSGROUP
688     if (hideAdvancedDevices() || (override & HideUnavailableDevices)) {
689         filter(VideoCaptureDeviceType, backendIface, &defaultList,
690             (hideAdvancedDevices() ? FilterAdvancedDevices : 0) |
691             ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
692             );
693     }
694 
695     //The devices need to be stored independently for every backend
696     const QSettingsGroup backendConfig(&d->config, QLatin1String("VideoCaptureDevice")); // + Factory::identifier());
697     return sortDevicesByCategoryPriority(this, &backendConfig, VideoCaptureDeviceType, category, defaultList);
698 #else // QT_NO_PHONON_SETTINGSGROUP
699     return defaultList;
700 #endif // QT_NO_PHONON_SETTINGSGROUP
701 }
702 
videoCaptureDeviceFor(CaptureCategory category,int override) const703 int GlobalConfig::videoCaptureDeviceFor(CaptureCategory category, int override) const
704 {
705     QList<int> ret = videoCaptureDeviceListFor(category, override);
706     if (ret.isEmpty())
707         return -1;
708     return ret.first();
709 }
710 
videoCaptureDeviceProperties(int index) const711 QHash<QByteArray, QVariant> GlobalConfig::videoCaptureDeviceProperties(int index) const
712 {
713     return deviceProperties(VideoCaptureDeviceType, index);
714 }
715 
setVideoCaptureDeviceListFor(Category category,QList<int> order)716 void GlobalConfig::setVideoCaptureDeviceListFor(Category category, QList<int> order)
717 {
718     CaptureCategory cat = categoryToCaptureCategory(category);
719     setVideoCaptureDeviceListFor(cat, order);
720 }
721 
videoCaptureDeviceListFor(Category category,int override) const722 QList<int> GlobalConfig::videoCaptureDeviceListFor(Category category, int override) const
723 {
724     CaptureCategory cat = categoryToCaptureCategory(category);
725     return videoCaptureDeviceListFor(cat, override);
726 }
727 
videoCaptureDeviceFor(Category category,int override) const728 int GlobalConfig::videoCaptureDeviceFor(Category category, int override) const
729 {
730     CaptureCategory cat = categoryToCaptureCategory(category);
731     return videoCaptureDeviceFor(cat, override);
732 }
733 
734 #endif // PHONON_NO_VIDEOCAPTURE
735 
deviceProperties(ObjectDescriptionType deviceType,int index) const736 QHash<QByteArray, QVariant> GlobalConfig::deviceProperties(ObjectDescriptionType deviceType, int index) const
737 {
738     QList<int> indices;
739     QHash<QByteArray, QVariant> props;
740 
741     // Try a pulseaudio device
742     PulseSupport *pulse = PulseSupport::getInstance();
743     if (pulse->isUsed()) {
744         // Check the index before passing it to PulseSupport
745         indices = pulse->objectDescriptionIndexes(deviceType);
746         if (indices.contains(index))
747             props = pulse->objectDescriptionProperties(deviceType, index);
748     }
749     if (!props.isEmpty())
750         return props;
751 
752     #ifndef QT_NO_PHONON_PLATFORMPLUGIN
753     // Try a device from the platform
754     if (PlatformPlugin *platformPlugin = Factory::platformPlugin())
755         props = platformPlugin->objectDescriptionProperties(deviceType, index);
756     if (!props.isEmpty())
757         return props;
758     #endif //QT_NO_PHONON_PLATFORMPLUGIN
759 
760     // Try a device from the backend
761     BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
762     if (backendIface)
763         props = backendIface->objectDescriptionProperties(deviceType, index);
764     if (!props.isEmpty())
765         return props;
766 
767     return props;
768 }
769 
770 
771 } // namespace Phonon
772