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