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
qplatformaudiodevices.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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/qaudiodevice.h>
8#include <QtMultimedia/qmediadevices.h>
9#include <QtCore/private/qminimalflatset_p.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qvarlengtharray.h>
12
13#if defined(Q_OS_ANDROID)
14# include <QtMultimedia/private/qandroidaudiodevices_p.h>
15#endif
16#if defined(Q_OS_DARWIN)
17# include <QtMultimedia/private/qcoreaudiodevices_p.h>
18#endif
19#if defined(Q_OS_WINDOWS)
20# include <QtMultimedia/private/qwindowsaudiodevices_p.h>
21#endif
22#if QT_CONFIG(alsa)
23# include <QtMultimedia/private/qalsaaudiodevices_p.h>
24#endif
25#if QT_CONFIG(pulseaudio)
26# include <QtMultimedia/private/qpulseaudiodevices_p.h>
27# include <QtMultimedia/private/qpulsehelpers_p.h>
28#endif
29#if QT_CONFIG(pipewire)
30# include <QtMultimedia/private/qpipewire_audiodevices_p.h>
31#endif
32#if defined(Q_OS_QNX) && defined(QT_MM_QNX_QSA)
33# include <QtMultimedia/private/qqnxaudiodevices_p.h>
34#endif
35#if defined(Q_OS_WASM)
36# include <QtMultimedia/private/qwasmmediadevices_p.h>
37#endif
38
40
41using namespace Qt::Literals;
42
43std::unique_ptr<QPlatformAudioDevices> QPlatformAudioDevices::create()
44{
45#ifdef Q_OS_DARWIN
46 return std::make_unique<QCoreAudioDevices>();
47#endif
48#if defined(Q_OS_WINDOWS)
49 return std::make_unique<QWindowsAudioDevices>();
50#endif
51#if defined(Q_OS_ANDROID)
52 return std::make_unique<QAndroidAudioDevices>();
53#endif
54#if QT_CONFIG(pipewire)
55 QByteArray requestedBackend = qgetenv("QT_AUDIO_BACKEND");
56 const bool pipewireRequested = requestedBackend == "pipewire"_ba;
57
58# if QT_CONFIG(pulseaudio)
59 using namespace QPulseAudioInternal;
60 // Check if PulseAudio is actually the vanilla PulseAudio server, not PipeWire's PulseAudio server.
61 // Some funny still distros ship PipeWire and PulseAudio side by side. In that case, we should not
62 // use the PipeWire backend, as it might not report any audio devices.
63 auto skipPipewire = [&] {
64 if (pipewireRequested)
65 return false;
66 return requestedBackend.isNull()
67 && pulseaudioDetectServerType() == PulseaudioServerType::Pulseaudio;
68 };
69# else
70 auto skipPipewire = [] {
71 return false;
72 };
73# endif
74
75 const bool considerPipewire = requestedBackend.isNull() || pipewireRequested;
76
77 if (considerPipewire && QtPipeWire::QAudioDevices::isSupported()) {
78 if (!skipPipewire())
79 return std::make_unique<QtPipeWire::QAudioDevices>();
80 }
81
82 if (pipewireRequested)
83 qDebug() << "PipeWire audio backend requested. not available. Using default backend";
84
85#endif
86#if QT_CONFIG(pulseaudio)
87 return std::make_unique<QPulseAudioDevices>();
88#endif
89#if QT_CONFIG(alsa)
90 return std::make_unique<QAlsaAudioDevices>();
91#endif
92#if defined(Q_OS_QNX) && defined(QT_MM_QNX_QSA)
93 return std::make_unique<QQnxAudioDevices>();
94#endif
95#if defined(Q_OS_WASM)
96 return std::make_unique<QWasmAudioDevices>();
97#endif
98 return std::make_unique<QPlatformAudioDevices>();
99}
100
101QPlatformAudioDevices::QPlatformAudioDevices()
102{
103 qRegisterMetaType<PrivateTag>(); // for the case of queued connections
104}
105
106QPlatformAudioDevices::~QPlatformAudioDevices() = default;
107
108QList<QAudioDevice> QPlatformAudioDevices::audioInputs() const
109{
110 return m_audioInputs.ensure([this]() {
111 return findAudioInputs();
112 });
113}
114
115QList<QAudioDevice> QPlatformAudioDevices::audioOutputs() const
116{
117 return m_audioOutputs.ensure([this]() {
118 return findAudioOutputs();
119 });
120}
121
122void QPlatformAudioDevices::onAudioInputsChanged()
123{
124 m_audioInputs.reset();
125 emit audioInputsChanged(PrivateTag{});
126}
127
128void QPlatformAudioDevices::onAudioOutputsChanged()
129{
130 m_audioOutputs.reset();
131 emit audioOutputsChanged(PrivateTag{});
132}
133
134void QPlatformAudioDevices::updateAudioInputsCache()
135{
136 if (m_audioInputs.update(findAudioInputs()))
137 emit audioInputsChanged(PrivateTag{});
138}
139
140void QPlatformAudioDevices::updateAudioOutputsCache()
141{
142 if (m_audioOutputs.update(findAudioOutputs()))
143 emit audioOutputsChanged(PrivateTag{});
144}
145
146QPlatformAudioSource *QPlatformAudioDevices::createAudioSource(const QAudioDevice &,
147 const QAudioFormat &, QObject *)
148{
149 return nullptr;
150}
151QPlatformAudioSink *QPlatformAudioDevices::createAudioSink(const QAudioDevice &,
152 const QAudioFormat &, QObject *)
153{
154 return nullptr;
155}
156
157QPlatformAudioSource *QPlatformAudioDevices::audioInputDevice(QAudioFormat format,
158 const QAudioDevice &deviceInfo,
159 QObject *parent)
160{
161 QAudioDevice device = deviceInfo;
162 if (device.isNull())
163 device = QMediaDevices::defaultAudioInput();
164
165 if (device.isNull())
166 return nullptr;
167
168 if (format == QAudioFormat{})
169 format = device.preferredFormat();
170
171 return createAudioSource(device, format, parent);
172}
173
174QPlatformAudioSink *QPlatformAudioDevices::audioOutputDevice(QAudioFormat format,
175 const QAudioDevice &deviceInfo,
176 QObject *parent)
177{
178 QAudioDevice device = deviceInfo;
179 if (device.isNull())
180 device = QMediaDevices::defaultAudioOutput();
181
182 if (device.isNull())
183 return nullptr;
184
185 if (format == QAudioFormat{})
186 format = device.preferredFormat();
187
188 return createAudioSink(device, format, parent);
189}
190
191bool QPlatformAudioDevices::hasCallbackApi() const
192{
193 return false;
194}
195
196QT_END_NAMESPACE
197
198#include "moc_qplatformaudiodevices_p.cpp"
Combined button and popup list for selecting options.