Revision control

Copy as Markdown

// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformaudiodevices_p.h"
#include <QtMultimedia/private/qaudiosystem_p.h>
#include <QtMultimedia/qaudiodevice.h>
#include <QtMultimedia/qmediadevices.h>
#include <QtCore/private/qminimalflatset_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qvarlengtharray.h>
#if defined(Q_OS_ANDROID)
# include <QtMultimedia/private/qandroidaudiodevices_p.h>
#endif
#if QT_CONFIG(ohaudio)
# include <QtMultimedia/private/qohosaudiodevices_p.h>
#endif
#if defined(Q_OS_DARWIN)
# include <QtMultimedia/private/qcoreaudiodevices_p.h>
#endif
#if defined(Q_OS_WINDOWS)
# include <QtMultimedia/private/qwindowsaudiodevices_p.h>
#endif
#if QT_CONFIG(alsa)
# include <QtMultimedia/private/qalsaaudiodevices_p.h>
#endif
#if QT_CONFIG(pulseaudio)
# include <QtMultimedia/private/qpulseaudiodevices_p.h>
# include <QtMultimedia/private/qpulsehelpers_p.h>
#endif
#if QT_CONFIG(pipewire)
# include <QtMultimedia/private/qpipewire_audiodevices_p.h>
#endif
#if defined(Q_OS_QNX) && defined(QT_MM_QNX_IO_SND)
# include <QtMultimedia/private/qqnxsndaudiodevices_p.h>
#endif
#if defined(Q_OS_QNX) && defined(QT_MM_QNX_IO_AUDIO)
# include <QtMultimedia/private/qqnxaudiodevices_p.h>
#endif
#if defined(Q_OS_WASM)
# include <QtMultimedia/private/qwasmmediadevices_p.h>
#endif
QT_BEGIN_NAMESPACE
using namespace Qt::Literals;
std::unique_ptr<QPlatformAudioDevices> QPlatformAudioDevices::create()
{
#ifdef Q_OS_DARWIN
return std::make_unique<QCoreAudioDevices>();
#endif
#if defined(Q_OS_WINDOWS)
return std::make_unique<QWindowsAudioDevices>();
#endif
#if defined(Q_OS_ANDROID)
return std::make_unique<QAndroidAudioDevices>();
#endif
#if QT_CONFIG(ohaudio)
return std::make_unique<QOhosAudioDevices>();
#endif
#if QT_CONFIG(pipewire)
QByteArray requestedBackend = qgetenv("QT_AUDIO_BACKEND");
const bool pipewireRequested = requestedBackend == "pipewire"_ba;
# if QT_CONFIG(pulseaudio)
using namespace QPulseAudioInternal;
// Check if PulseAudio is actually the vanilla PulseAudio server, not PipeWire's PulseAudio server.
// Some funny still distros ship PipeWire and PulseAudio side by side. In that case, we should not
// use the PipeWire backend, as it might not report any audio devices.
auto skipPipewire = [&] {
if (pipewireRequested)
return false;
return requestedBackend.isNull()
&& pulseaudioDetectServerType() == PulseaudioServerType::Pulseaudio;
};
# else
auto skipPipewire = [] {
return false;
};
# endif
const bool considerPipewire = requestedBackend.isNull() || pipewireRequested;
if (considerPipewire && QtPipeWire::QAudioDevices::isSupported()) {
if (!skipPipewire())
return std::make_unique<QtPipeWire::QAudioDevices>();
}
if (pipewireRequested)
qDebug() << "PipeWire audio backend requested. not available. Using default backend";
#endif
#if QT_CONFIG(pulseaudio)
return std::make_unique<QPulseAudioDevices>();
#endif
#if QT_CONFIG(alsa)
return std::make_unique<QAlsaAudioDevices>();
#endif
#if defined(Q_OS_QNX) && defined(QT_MM_QNX_IO_SND)
return std::make_unique<QQnxSndAudioDevices>();
#endif
#if defined(Q_OS_QNX) && defined(QT_MM_QNX_IO_AUDIO)
return std::make_unique<QQnxAudioDevices>();
#endif
#if defined(Q_OS_WASM)
return std::make_unique<QWasmAudioDevices>();
#endif
return std::make_unique<QPlatformAudioDevices>();
}
QPlatformAudioDevices::QPlatformAudioDevices()
{
qRegisterMetaType<PrivateTag>(); // for the case of queued connections
}
QPlatformAudioDevices::~QPlatformAudioDevices() = default;
QList<QAudioDevice> QPlatformAudioDevices::audioInputs() const
{
return m_audioInputs.ensure([this]() {
return findAudioInputs();
});
}
QList<QAudioDevice> QPlatformAudioDevices::audioOutputs() const
{
return m_audioOutputs.ensure([this]() {
return findAudioOutputs();
});
}
void QPlatformAudioDevices::onAudioInputsChanged()
{
m_audioInputs.reset();
Q_EMIT audioInputsChanged(PrivateTag{});
}
void QPlatformAudioDevices::onAudioOutputsChanged()
{
m_audioOutputs.reset();
Q_EMIT audioOutputsChanged(PrivateTag{});
}
void QPlatformAudioDevices::updateAudioInputsCache()
{
if (m_audioInputs.update(findAudioInputs()))
Q_EMIT audioInputsChanged(PrivateTag{});
}
void QPlatformAudioDevices::updateAudioOutputsCache()
{
if (m_audioOutputs.update(findAudioOutputs()))
Q_EMIT audioOutputsChanged(PrivateTag{});
}
QPlatformAudioSource *QPlatformAudioDevices::createAudioSource(const QAudioDevice &,
const QAudioFormat &, QObject *)
{
return nullptr;
}
QPlatformAudioSink *QPlatformAudioDevices::createAudioSink(const QAudioDevice &,
const QAudioFormat &, QObject *)
{
return nullptr;
}
QPlatformAudioSource *QPlatformAudioDevices::audioInputDevice(QAudioFormat format,
const QAudioDevice &deviceInfo,
QObject *parent)
{
QAudioDevice device = deviceInfo;
if (device.isNull())
device = QMediaDevices::defaultAudioInput();
if (device.isNull())
return nullptr;
if (format == QAudioFormat{})
format = device.preferredFormat();
return createAudioSource(device, format, parent);
}
QPlatformAudioSink *QPlatformAudioDevices::audioOutputDevice(QAudioFormat format,
const QAudioDevice &deviceInfo,
QObject *parent)
{
QAudioDevice device = deviceInfo;
if (device.isNull())
device = QMediaDevices::defaultAudioOutput();
if (device.isNull())
return nullptr;
if (format == QAudioFormat{})
format = device.preferredFormat();
return createAudioSink(device, format, parent);
}
bool QPlatformAudioDevices::hasCallbackApi() const
{
return false;
}
QT_END_NAMESPACE
#include "moc_qplatformaudiodevices_p.cpp"