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