1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qaudiodevicefactory_p.h"
41#include "qaudiosystem.h"
42#include "qaudiodeviceinfo.h"
43
44#include <QtCore/qmap.h>
45
46QT_BEGIN_NAMESPACE
47
48static void qRegisterAudioDeviceInfoMetaTypes()
49{
50 qRegisterMetaType<QAudioDeviceInfo>();
51}
52
53Q_CONSTRUCTOR_FUNCTION(qRegisterAudioDeviceInfoMetaTypes)
54
55class QAudioDeviceInfoPrivate : public QSharedData
56{
57public:
58 QAudioDeviceInfoPrivate()
59 : mode(QAudio::AudioOutput)
60 , info(nullptr)
61 {
62 }
63
64 QAudioDeviceInfoPrivate(const QString &r, const QByteArray &h, QAudio::Mode m):
65 realm(r), handle(h), mode(m)
66 {
67 if (!handle.isEmpty())
68 info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
69 else
70 info = nullptr;
71 }
72
73 QAudioDeviceInfoPrivate(const QAudioDeviceInfoPrivate &other):
74 QSharedData(other),
75 realm(other.realm), handle(other.handle), mode(other.mode)
76 {
77 info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
78 }
79
80 QAudioDeviceInfoPrivate& operator=(const QAudioDeviceInfoPrivate &other)
81 {
82 delete info;
83
84 realm = other.realm;
85 handle = other.handle;
86 mode = other.mode;
87 info = QAudioDeviceFactory::audioDeviceInfo(realm, handle, mode);
88 return *this;
89 }
90
91 ~QAudioDeviceInfoPrivate()
92 {
93 delete info;
94 }
95
96 QString realm;
97 QByteArray handle;
98 QAudio::Mode mode;
99 QAbstractAudioDeviceInfo* info;
100};
101
102
103/*!
104 \class QAudioDeviceInfo
105 \brief The QAudioDeviceInfo class provides an interface to query audio devices and their functionality.
106 \inmodule QtMultimedia
107 \ingroup multimedia
108 \ingroup multimedia_audio
109
110 QAudioDeviceInfo lets you query for audio devices--such as sound
111 cards and USB headsets--that are currently available on the system.
112 The audio devices available are dependent on the platform or audio plugins installed.
113
114 A QAudioDeviceInfo is used by Qt to construct
115 classes that communicate with the device--such as
116 QAudioInput, and QAudioOutput.
117
118 You can also query each device for the formats it supports. A
119 format in this context is a set consisting of a specific byte
120 order, channel, codec, frequency, sample rate, and sample type. A
121 format is represented by the QAudioFormat class.
122
123 The values supported by the device for each of these
124 parameters can be fetched with
125 supportedByteOrders(), supportedChannelCounts(), supportedCodecs(),
126 supportedSampleRates(), supportedSampleSizes(), and
127 supportedSampleTypes(). The combinations supported are dependent on the platform,
128 audio plugins installed and the audio device capabilities. If you need a
129 specific format, you can check if
130 the device supports it with isFormatSupported(), or fetch a
131 supported format that is as close as possible to the format with
132 nearestFormat(). For instance:
133
134 \snippet multimedia-snippets/audio.cpp Setting audio format
135
136 The static
137 functions defaultInputDevice(), defaultOutputDevice(), and
138 availableDevices() let you get a list of all available
139 devices. Devices are fetched according to the value of mode
140 this is specified by the \l {QAudio}::Mode enum.
141 The QAudioDeviceInfo returned are only valid for the \l {QAudio}::Mode.
142
143 For instance:
144
145 \snippet multimedia-snippets/audio.cpp Dumping audio formats
146
147 In this code sample, we loop through all devices that are able to output
148 sound, i.e., play an audio stream in a supported format. For each device we
149 find, we simply print the deviceName().
150
151 \sa QAudioOutput, QAudioInput
152*/
153
154/*!
155 Constructs an empty QAudioDeviceInfo object.
156*/
157QAudioDeviceInfo::QAudioDeviceInfo():
158 d(new QAudioDeviceInfoPrivate)
159{
160}
161
162/*!
163 Constructs a copy of \a other.
164*/
165QAudioDeviceInfo::QAudioDeviceInfo(const QAudioDeviceInfo& other):
166 d(other.d)
167{
168}
169
170/*!
171 Destroy this audio device info.
172*/
173QAudioDeviceInfo::~QAudioDeviceInfo()
174{
175}
176
177/*!
178 Sets the QAudioDeviceInfo object to be equal to \a other.
179*/
180QAudioDeviceInfo& QAudioDeviceInfo::operator=(const QAudioDeviceInfo &other)
181{
182 d = other.d;
183 return *this;
184}
185
186/*!
187 Returns true if this QAudioDeviceInfo class represents the
188 same audio device as \a other.
189*/
190bool QAudioDeviceInfo::operator ==(const QAudioDeviceInfo &other) const
191{
192 if (d == other.d)
193 return true;
194 if (d->realm == other.d->realm
195 && d->mode == other.d->mode
196 && d->handle == other.d->handle
197 && deviceName() == other.deviceName())
198 return true;
199 return false;
200}
201
202/*!
203 Returns true if this QAudioDeviceInfo class represents a
204 different audio device than \a other
205*/
206bool QAudioDeviceInfo::operator !=(const QAudioDeviceInfo &other) const
207{
208 return !operator==(other);
209}
210
211/*!
212 Returns whether this QAudioDeviceInfo object holds a valid device definition.
213*/
214bool QAudioDeviceInfo::isNull() const
215{
216 return d->info == nullptr;
217}
218
219/*!
220 Returns the human readable name of the audio device.
221
222 Device names vary depending on the platform/audio plugin being used.
223
224 They are a unique string identifier for the audio device.
225
226 eg. default, Intel, U0x46d0x9a4
227*/
228QString QAudioDeviceInfo::deviceName() const
229{
230 return isNull() ? QString() : d->info->deviceName();
231}
232
233/*!
234 Returns true if the supplied \a settings are supported by the audio
235 device described by this QAudioDeviceInfo.
236*/
237bool QAudioDeviceInfo::isFormatSupported(const QAudioFormat &settings) const
238{
239 return isNull() ? false : d->info->isFormatSupported(format: settings);
240}
241
242/*!
243 Returns the default audio format settings for this device.
244
245 These settings are provided by the platform/audio plugin being used.
246
247 They are also dependent on the \l {QAudio}::Mode being used.
248
249 A typical audio system would provide something like:
250 \list
251 \li Input settings: 8000Hz mono 8 bit.
252 \li Output settings: 44100Hz stereo 16 bit little endian.
253 \endlist
254*/
255QAudioFormat QAudioDeviceInfo::preferredFormat() const
256{
257 return isNull() ? QAudioFormat() : d->info->preferredFormat();
258}
259
260/*!
261 Returns the closest QAudioFormat to the supplied \a settings that the system supports.
262
263 These settings are provided by the platform/audio plugin being used.
264
265 They are also dependent on the \l {QAudio}::Mode being used.
266*/
267QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const
268{
269 if (isFormatSupported(settings))
270 return settings;
271
272 QAudioFormat nearest = settings;
273
274 QList<QString> testCodecs = supportedCodecs();
275 QList<int> testChannels = supportedChannelCounts();
276 QList<QAudioFormat::Endian> testByteOrders = supportedByteOrders();
277 QList<QAudioFormat::SampleType> testSampleTypes;
278 QList<QAudioFormat::SampleType> sampleTypesAvailable = supportedSampleTypes();
279 QMap<int,int> testSampleRates;
280 QList<int> sampleRatesAvailable = supportedSampleRates();
281 QMap<int,int> testSampleSizes;
282 QList<int> sampleSizesAvailable = supportedSampleSizes();
283
284 // Get sorted lists for checking
285 if (testCodecs.contains(t: settings.codec())) {
286 testCodecs.removeAll(t: settings.codec());
287 testCodecs.insert(i: 0, t: settings.codec());
288 }
289 testChannels.removeAll(t: settings.channelCount());
290 testChannels.insert(i: 0, t: settings.channelCount());
291 testByteOrders.removeAll(t: settings.byteOrder());
292 testByteOrders.insert(i: 0, t: settings.byteOrder());
293
294 if (sampleTypesAvailable.contains(t: settings.sampleType()))
295 testSampleTypes.append(t: settings.sampleType());
296 if (sampleTypesAvailable.contains(t: QAudioFormat::SignedInt))
297 testSampleTypes.append(t: QAudioFormat::SignedInt);
298 if (sampleTypesAvailable.contains(t: QAudioFormat::UnSignedInt))
299 testSampleTypes.append(t: QAudioFormat::UnSignedInt);
300 if (sampleTypesAvailable.contains(t: QAudioFormat::Float))
301 testSampleTypes.append(t: QAudioFormat::Float);
302
303 if (sampleSizesAvailable.contains(t: settings.sampleSize()))
304 testSampleSizes.insert(akey: 0,avalue: settings.sampleSize());
305 sampleSizesAvailable.removeAll(t: settings.sampleSize());
306 for (int size : qAsConst(t&: sampleSizesAvailable)) {
307 int larger = (size > settings.sampleSize()) ? size : settings.sampleSize();
308 int smaller = (size > settings.sampleSize()) ? settings.sampleSize() : size;
309 bool isMultiple = ( 0 == (larger % smaller));
310 int diff = larger - smaller;
311 testSampleSizes.insert(akey: (isMultiple ? diff : diff+100000), avalue: size);
312 }
313 if (sampleRatesAvailable.contains(t: settings.sampleRate()))
314 testSampleRates.insert(akey: 0,avalue: settings.sampleRate());
315 sampleRatesAvailable.removeAll(t: settings.sampleRate());
316 for (int sampleRate : qAsConst(t&: sampleRatesAvailable)) {
317 int larger = (sampleRate > settings.sampleRate()) ? sampleRate : settings.sampleRate();
318 int smaller = (sampleRate > settings.sampleRate()) ? settings.sampleRate() : sampleRate;
319 bool isMultiple = ( 0 == (larger % smaller));
320 int diff = larger - smaller;
321 testSampleRates.insert(akey: (isMultiple ? diff : diff+100000), avalue: sampleRate);
322 }
323
324 // Try to find nearest
325 for (const QString &codec : qAsConst(t&: testCodecs)) {
326 nearest.setCodec(codec);
327 for (QAudioFormat::Endian order : qAsConst(t&: testByteOrders)) {
328 nearest.setByteOrder(order);
329 for (QAudioFormat::SampleType sample : qAsConst(t&: testSampleTypes)) {
330 nearest.setSampleType(sample);
331 for (int sampleSize : qAsConst(t&: testSampleSizes)) {
332 nearest.setSampleSize(sampleSize);
333 for (int channel : qAsConst(t&: testChannels)) {
334 nearest.setChannelCount(channel);
335 for (int sampleRate : qAsConst(t&: testSampleRates)) {
336 nearest.setSampleRate(sampleRate);
337 if (isFormatSupported(settings: nearest))
338 return nearest;
339 }
340 }
341 }
342 }
343 }
344 }
345 //Fallback
346 return preferredFormat();
347}
348
349/*!
350 Returns a list of supported codecs.
351
352 All platform and plugin implementations should provide support for:
353
354 "audio/pcm" - Linear PCM
355
356 For writing plugins to support additional codecs refer to:
357
358 http://www.iana.org/assignments/media-types/audio/
359*/
360QStringList QAudioDeviceInfo::supportedCodecs() const
361{
362 return isNull() ? QStringList() : d->info->supportedCodecs();
363}
364
365/*!
366 Returns a list of supported sample rates (in Hertz).
367
368*/
369QList<int> QAudioDeviceInfo::supportedSampleRates() const
370{
371 return isNull() ? QList<int>() : d->info->supportedSampleRates();
372}
373
374/*!
375 Returns a list of supported channel counts.
376
377 This is typically 1 for mono sound, or 2 for stereo sound.
378
379*/
380QList<int> QAudioDeviceInfo::supportedChannelCounts() const
381{
382 return isNull() ? QList<int>() : d->info->supportedChannelCounts();
383}
384
385/*!
386 Returns a list of supported sample sizes (in bits).
387
388 Typically this will include 8 and 16 bit sample sizes.
389
390*/
391QList<int> QAudioDeviceInfo::supportedSampleSizes() const
392{
393 return isNull() ? QList<int>() : d->info->supportedSampleSizes();
394}
395
396/*!
397 Returns a list of supported byte orders.
398*/
399QList<QAudioFormat::Endian> QAudioDeviceInfo::supportedByteOrders() const
400{
401 return isNull() ? QList<QAudioFormat::Endian>() : d->info->supportedByteOrders();
402}
403
404/*!
405 Returns a list of supported sample types.
406*/
407QList<QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes() const
408{
409 return isNull() ? QList<QAudioFormat::SampleType>() : d->info->supportedSampleTypes();
410}
411
412/*!
413 Returns the information for the default input audio device.
414 All platform and audio plugin implementations provide a default audio device to use.
415*/
416QAudioDeviceInfo QAudioDeviceInfo::defaultInputDevice()
417{
418 return QAudioDeviceFactory::defaultDevice(mode: QAudio::AudioInput);
419}
420
421/*!
422 Returns the information for the default output audio device.
423 All platform and audio plugin implementations provide a default audio device to use.
424*/
425QAudioDeviceInfo QAudioDeviceInfo::defaultOutputDevice()
426{
427 return QAudioDeviceFactory::defaultDevice(mode: QAudio::AudioOutput);
428}
429
430/*!
431 Returns a list of audio devices that support \a mode.
432*/
433QList<QAudioDeviceInfo> QAudioDeviceInfo::availableDevices(QAudio::Mode mode)
434{
435 return QAudioDeviceFactory::availableDevices(mode);
436}
437
438
439/*!
440 \internal
441*/
442QAudioDeviceInfo::QAudioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode):
443 d(new QAudioDeviceInfoPrivate(realm, handle, mode))
444{
445}
446
447/*!
448 Returns the key that represents the audio plugin.
449
450 \since 5.14
451 \sa QAudioSystemPlugin
452*/
453QString QAudioDeviceInfo::realm() const
454{
455 return d->realm;
456}
457
458/*!
459 \internal
460*/
461QByteArray QAudioDeviceInfo::handle() const
462{
463 return d->handle;
464}
465
466
467/*!
468 \internal
469*/
470QAudio::Mode QAudioDeviceInfo::mode() const
471{
472 return d->mode;
473}
474
475QT_END_NAMESPACE
476
477

source code of qtmultimedia/src/multimedia/audio/qaudiodeviceinfo.cpp