Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qaudiodevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtMultimedia/private/qaudiosystem_p.h>
7#include <QtMultimedia/private/qplatformaudiodevices_p.h>
8#include <QtMultimedia/private/qplatformmediaintegration_p.h>
9#include <QtCore/qmap.h>
10
12
13/*!
14 \class QAudioDevice
15 \brief The QAudioDevice class provides an information about audio devices and their
16 functionality.
17 \inmodule QtMultimedia
18 \ingroup multimedia
19 \ingroup multimedia_audio
20
21 QAudioDevice describes an audio device available in the system, either for input or for
22 playback.
23
24 A QAudioDevice is used by Qt to construct
25 classes that communicate with the device -- such as
26 QAudioSource, and QAudioSink. It is also used to determine the
27 input or output device to use in a capture session or during media playback.
28
29 \include qdevice-retains-properties.qdocinc {retains-properties} {QAudioDevice} {QMediaDevices}
30
31 You can also query each device for the formats it supports. A
32 format in this context is a set consisting of a channel count, sample rate, and sample type. A
33 format is represented by the QAudioFormat class.
34
35 The values supported by the device for each of these parameters can be
36 fetched with minimumChannelCount(), maximumChannelCount(),
37 minimumSampleRate(), maximumSampleRate() and supportedSampleFormats(). The
38 combinations supported are dependent on the audio device capabilities. If
39 you need a specific format, you can check if the device supports it with
40 isFormatSupported(). For instance:
41
42 \snippet multimedia-snippets/audio.cpp Audio output setup
43
44 The set of available devices can be retrieved from the QMediaDevices class.
45
46 For instance:
47
48 \snippet multimedia-snippets/audio.cpp Dumping audio formats
49
50 In this code sample, we loop through all devices that are able to output
51 sound, i.e., play an audio stream in a supported format. For each device we
52 find, we simply print the deviceName().
53
54 \sa QAudioSink, QAudioSource, QAudioFormat
55*/
56
57/*!
58 \qmlvaluetype audioDevice
59 \inqmlmodule QtMultimedia
60 \since 6.2
61 //! \nativetype QAudioDevice
62 \brief Describes an audio device.
63 \ingroup multimedia_qml
64 \ingroup multimedia_audio_qml
65 \ingroup qmlvaluetypes
67 The audioDevice value type describes the properties of an audio device that
68 is connected to the system.
69
70 \include qdevice-retains-properties.qdocinc {retains-properties} {audioDevice} {MediaDevices}
71
72 The list of audio input or output devices can be queried from the \l{MediaDevices}
73 type. To select a certain audio device for input or output set it as the device
74 on \l{AudioInput} or \l{AudioOutput}.
75
76 \qml
77 MediaPlayer {
78 audioOutput: AudioOutput {
79 device: mediaDevices.defaultAudioOutput
80 }
81 }
82 MediaDevices {
83 id: mediaDevices
84 }
85 \endqml
86*/
87
88/*!
89 Constructs a null QAudioDevice object.
90*/
91QAudioDevice::QAudioDevice() = default;
92
93/*!
94 Constructs a copy of \a other.
95*/
96QAudioDevice::QAudioDevice(const QAudioDevice &other) = default;
97
98/*!
99 \fn QAudioDevice::QAudioDevice(QAudioDevice &&other)
100
101 Move constructs from \a other.
102*/
103/*!
104 \fn void QAudioDevice::swap(QAudioDevice &other) noexcept
105
106 Swaps the audio device with the \a other.
107*/
108/*!
109 Destroy this audio device info.
110*/
111QAudioDevice::~QAudioDevice() = default;
112
113/*!
114 Sets the QAudioDevice object to be equal to \a other.
115*/
116QAudioDevice &QAudioDevice::operator=(const QAudioDevice &other) = default;
117
118/*!
119 \fn QAudioDevice& QAudioDevice::operator=(QAudioDevice &&other)
120
121 Moves \a other into this QAudioDevice object.
122*/
123
124/*!
125 Returns true if this QAudioDevice class represents the
126 same audio device as \a other.
127*/
128bool QAudioDevice::operator==(const QAudioDevice &other) const
129{
130 return mode() == other.mode() && id() == other.id();
131}
132
133/*!
134 Returns true if this QAudioDevice class represents a
135 different audio device than \a other
136*/
137bool QAudioDevice::operator!=(const QAudioDevice &other) const
138{
139 return !operator==(other);
140}
141
142/*!
143 Returns whether this QAudioDevice object holds a valid device definition.
144*/
145bool QAudioDevice::isNull() const
146{
147 return d == nullptr;
148}
149
150/*!
151 \qmlproperty string QtMultimedia::audioDevice::id
152
153 Holds an identifier for the audio device.
154
155 Device names vary depending on the platform/audio plugin being used.
156
157 They are a unique identifier for the audio device.
158*/
159
160/*!
161 \property QAudioDevice::id
162
163 Returns an identifier for the audio device.
164
165 Device names vary depending on the platform/audio plugin being used.
166
167 They are a unique identifier for the audio device.
168*/
169QByteArray QAudioDevice::id() const
170{
171 return isNull() ? QByteArray() : d->id;
172}
173
174/*!
175 \qmlproperty string QtMultimedia::audioDevice::description
176
177 Holds a human readable name of the audio device.
178
179 Use this string to present the device to the user.
180*/
181
182/*!
183 \property QAudioDevice::description
184
185 Returns a human readable name of the audio device.
186
187 Use this string to present the device to the user.
188*/
189QString QAudioDevice::description() const
190{
191 return isNull() ? QString() : d->description;
192}
193
194/*!
195 \qmlproperty bool QtMultimedia::audioDevice::isDefault
196
197 Is true if this is the default audio device.
198*/
199
200/*!
201 \property QAudioDevice::isDefault
202
203 Returns true if this is the default audio device.
204*/
205bool QAudioDevice::isDefault() const
206{
207 return d ? d->isDefault : false;
208}
209
210/*!
211 Returns true if the supplied \a settings are supported by the audio
212 device described by this QAudioDevice.
213*/
214bool QAudioDevice::isFormatSupported(const QAudioFormat &settings) const
215{
216 if (isNull())
217 return false;
218 auto result = d->isFormatSupported(settings);
219 return result ? *result : false;
220}
221
222/*!
223 Returns the default audio format settings for this device.
224
225 These settings are provided by the platform/audio plugin being used.
226
227 They are also dependent on the \l {QtAudio}::Mode being used.
228
229 A typical audio system would provide something like:
230 \list
231 \li Input settings: 48000Hz mono 16 bit.
232 \li Output settings: 48000Hz stereo 16 bit.
233 \endlist
234*/
235QAudioFormat QAudioDevice::preferredFormat() const
236{
237 if (isNull())
238 return QAudioFormat();
239 auto fmt = d->preferredFormat();
240 return fmt ? *fmt : QAudioFormat();
241}
242
243/*!
244 Returns the minimum supported sample rate (in Hertz).
245*/
246int QAudioDevice::minimumSampleRate() const
247{
248 if (isNull())
249 return 0;
250 auto rate = d->minimumSampleRate();
251 return rate ? *rate : 0;
252}
253
254/*!
255 Returns the maximum supported sample rate (in Hertz).
256*/
257int QAudioDevice::maximumSampleRate() const
258{
259 if (isNull())
260 return 0;
261 auto rate = d->maximumSampleRate();
262 return rate ? *rate : 0;
263}
264
265/*!
266 Returns the minimum number of supported channel counts.
267
268 This is typically 1 for mono sound, or 2 for stereo sound.
269*/
270int QAudioDevice::minimumChannelCount() const
271{
272 if (isNull())
273 return 0;
274 auto count = d->minimumChannelCount();
275 return count ? *count : 0;
276}
277
278/*!
279 Returns the maximum number of supported channel counts.
280
281 This is typically 1 for mono sound, or 2 for stereo sound.
282*/
283int QAudioDevice::maximumChannelCount() const
284{
285 if (isNull())
286 return 0;
287 auto count = d->maximumChannelCount();
288 return count ? *count : 0;
289}
290
291/*!
292 Returns a list of supported sample types.
293*/
294QList<QAudioFormat::SampleFormat> QAudioDevice::supportedSampleFormats() const
295{
296 if (isNull())
297 return QList<QAudioFormat::SampleFormat>();
298 auto formats = d->supportedSampleFormats();
299 return formats ? *formats : QList<QAudioFormat::SampleFormat>();
300}
301
302/*!
303 Returns the channel configuration of the device.
304*/
305QAudioFormat::ChannelConfig QAudioDevice::channelConfiguration() const
306{
307 if (isNull())
308 return QAudioFormat::ChannelConfigUnknown;
309 auto config = d->channelConfiguration();
310 return config ? *config : QAudioFormat::ChannelConfigUnknown;
311}
312
313/*!
314 \fn QAudioDevicePrivate QAudioDevice::handle() const
315 \internal
316*/
317/*!
318 \internal
319*/
320QAudioDevice::QAudioDevice(QAudioDevicePrivate *p) : d(p) { }
321
322/*!
323 \enum QAudioDevice::Mode
324
325 Describes the mode of this device.
326
327 \value Null
328 A null device.
329 \value Input
330 An input device.
331 \value Output
332 An output device.
333*/
334
335/*!
336 \qmlproperty enumeration QtMultimedia::audioDevice::mode
337 \qmlenumeratorsfrom [AudioDevice] QAudioDevice::Mode
338
339 Holds whether this device is an input or output device.
340
341 The returned value can be one of the following:
342*/
343
344/*!
345 \property QAudioDevice::mode
346
347 Returns whether this device is an input or output device.
348*/
349QAudioDevice::Mode QAudioDevice::mode() const
350{
351 return d ? d->mode : Null;
352}
353
354#ifndef QT_NO_DEBUG_STREAM
355QDebug operator<<(QDebug dbg, QAudioDevice::Mode mode)
356{
357 QDebugStateSaver saver(dbg);
358 dbg.nospace();
359 switch (mode) {
360 case QAudioDevice::Input:
361 dbg << "QAudioDevice::Input";
362 break;
363 case QAudioDevice::Output:
364 dbg << "QAudioDevice::Output";
365 break;
366 case QAudioDevice::Null:
367 dbg << "QAudioDevice::Null";
368 break;
369 }
370 return dbg;
371}
372#endif
373
374////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
375
377
378QAudioDevicePrivate::QAudioDevicePrivate(QByteArray i, QAudioDevice::Mode m, QString description,
379 bool isDefault, std::future<AudioDeviceFormat> format)
380 : id(std::move(i)),
381 mode(m),
382 description(std::move(description)),
383 isDefault(isDefault),
384 m_deviceFormat(std::move(format).share())
385{
386}
387
388namespace {
389
390std::future<QAudioDevicePrivate::AudioDeviceFormat>
391makeFuture(QAudioDevicePrivate::AudioDeviceFormat format)
392{
393 std::promise<QAudioDevicePrivate::AudioDeviceFormat> promise;
394 promise.set_value(std::move(format));
395 return promise.get_future();
396}
397
398} // namespace
399
400QAudioDevicePrivate::QAudioDevicePrivate(const QByteArray &i, QAudioDevice::Mode m,
401 QString description, bool isDefault,
402 AudioDeviceFormat format)
403 : QAudioDevicePrivate(i, m, std::move(description), isDefault, makeFuture(std::move(format)))
404{
405}
406
407QAudioDevicePrivate::~QAudioDevicePrivate() = default;
408
409template <typename F>
410QAudioDeviceExpected<std::invoke_result_t<F, const QAudioDevicePrivate::AudioDeviceFormat &>>
411QAudioDevicePrivate::doWithDeviceFormat(F &&f) const
412{
413 if (m_deviceFormat.valid()) {
414 auto status = m_deviceFormat.wait_for(formatProbeTimeout);
415 switch (status) {
416 case std::future_status::ready:
417 case std::future_status::deferred:
418 return f(m_deviceFormat.get());
419 case std::future_status::timeout:
420 return q23::unexpected{ QAudioDeviceFormatError::Timeout };
421 default:
422 Q_UNREACHABLE_RETURN(q23::unexpected{ QAudioDeviceFormatError::InvalidFuture });
423 }
424 }
425 return q23::unexpected{ QAudioDeviceFormatError::InvalidFuture };
426}
427
428QAudioDeviceExpected<QAudioDevicePrivate::AudioDeviceFormat> QAudioDevicePrivate::format() const
429{
430 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
431 return AudioDeviceFormat{ fmt };
432 });
433}
434
435QAudioDeviceExpected<QAudioFormat> QAudioDevicePrivate::preferredFormat() const
436{
437 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
438 return fmt.preferredFormat;
439 });
440}
441
442QAudioDeviceExpected<int> QAudioDevicePrivate::minimumSampleRate() const
443{
444 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
445 return fmt.minimumSampleRate;
446 });
447}
448
449QAudioDeviceExpected<int> QAudioDevicePrivate::maximumSampleRate() const
450{
451 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
452 return fmt.maximumSampleRate;
453 });
454}
455
456QAudioDeviceExpected<int> QAudioDevicePrivate::minimumChannelCount() const
457{
458 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
459 return fmt.minimumChannelCount;
460 });
461}
462
463QAudioDeviceExpected<int> QAudioDevicePrivate::maximumChannelCount() const
464{
465 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
466 return fmt.maximumChannelCount;
467 });
468}
469
470QAudioDeviceExpected<QList<QAudioFormat::SampleFormat>>
471QAudioDevicePrivate::supportedSampleFormats() const
472{
473 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
474 return fmt.supportedSampleFormats;
475 });
476}
477
478QAudioDeviceExpected<QAudioFormat::ChannelConfig> QAudioDevicePrivate::channelConfiguration() const
479{
480 return doWithDeviceFormat([](const AudioDeviceFormat &fmt) {
481 return fmt.channelConfiguration;
482 });
483}
484
485QAudioDeviceExpected<bool> QAudioDevicePrivate::isFormatSupported(const QAudioFormat &format) const
486{
487 return doWithDeviceFormat([&](const AudioDeviceFormat &deviceFormat) {
488 if (format.sampleRate() < deviceFormat.minimumSampleRate
489 || format.sampleRate() > deviceFormat.maximumSampleRate)
490 return false;
491 if (format.channelCount() < deviceFormat.minimumChannelCount
492 || format.channelCount() > deviceFormat.maximumChannelCount)
493 return false;
494 if (!deviceFormat.supportedSampleFormats.contains(format.sampleFormat()))
495 return false;
496 return true;
497 });
498}
499
500QAudioDevice
501QAudioDevicePrivate::createQAudioDevice(std::unique_ptr<QAudioDevicePrivate> devicePrivate)
502{
503 return QAudioDevice(devicePrivate.release());
504}
505
506const QAudioDevicePrivate *QAudioDevicePrivate::handle(const QAudioDevice &device)
507{
508 return device.d.get();
509}
510
511QAudioDevicePrivate *QAudioDevicePrivate::handle(QAudioDevice &device)
512{
513 return device.d.get();
514}
515
516QT_END_NAMESPACE
517
518#include "moc_qaudiodevice.cpp"
Combined button and popup list for selecting options.
QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2620