qt6-bb10/qtmultimedia/examples/multimedia/audiodevices/audiodevices.cpp

210 lines
6.9 KiB
C++

// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "audiodevices.h"
#include <QCameraDevice>
#include <QMediaDevices>
#include <QMediaFormat>
#if QT_CONFIG(permissions)
#include <QPermission>
#endif
// Utility functions for converting QAudioFormat fields into text
static QString toString(QAudioFormat::SampleFormat sampleFormat)
{
switch (sampleFormat) {
case QAudioFormat::UInt8:
return "Unsigned 8 bit";
case QAudioFormat::Int16:
return "Signed 16 bit";
case QAudioFormat::Int32:
return "Signed 32 bit";
case QAudioFormat::Float:
return "Float";
default:
return "Unknown";
}
}
AudioDevicesBase::AudioDevicesBase(QWidget *parent) : QMainWindow(parent)
{
setupUi(this);
}
AudioDevicesBase::~AudioDevicesBase() = default;
AudioTest::AudioTest(QWidget *parent) : AudioDevicesBase(parent), m_devices(new QMediaDevices(this))
{
init();
}
void AudioTest::init()
{
#if QT_CONFIG(permissions)
// camera
QCameraPermission cameraPermission;
switch (qApp->checkPermission(cameraPermission)) {
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(cameraPermission, this, &AudioTest::init);
return;
case Qt::PermissionStatus::Denied:
qWarning("Camera permission is not granted!");
return;
case Qt::PermissionStatus::Granted:
break;
}
// microphone
QMicrophonePermission microphonePermission;
switch (qApp->checkPermission(microphonePermission)) {
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(microphonePermission, this, &AudioTest::init);
return;
case Qt::PermissionStatus::Denied:
qWarning("Microphone permission is not granted!");
return;
case Qt::PermissionStatus::Granted:
break;
}
#endif
m_devices->videoInputs();
QMediaFormat().supportedFileFormats(QMediaFormat::Encode);
connect(testButton, &QPushButton::clicked, this, &AudioTest::test);
connect(modeBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::modeChanged);
connect(deviceBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::deviceChanged);
connect(sampleRateSpinBox, &QSpinBox::valueChanged, this, &AudioTest::sampleRateChanged);
connect(channelsSpinBox, &QSpinBox::valueChanged, this, &AudioTest::channelChanged);
connect(sampleFormatBox, QOverload<int>::of(&QComboBox::activated), this,
&AudioTest::sampleFormatChanged);
connect(populateTableButton, &QPushButton::clicked, this, &AudioTest::populateTable);
connect(m_devices, &QMediaDevices::audioInputsChanged, this, &AudioTest::updateAudioDevices);
connect(m_devices, &QMediaDevices::audioOutputsChanged, this, &AudioTest::updateAudioDevices);
modeBox->setCurrentIndex(0);
modeChanged(0);
deviceBox->setCurrentIndex(0);
deviceChanged(0);
}
void AudioTest::test()
{
// tries to set all the settings picked.
testResult->clear();
if (!m_deviceInfo.isNull()) {
if (m_deviceInfo.isFormatSupported(m_settings)) {
testResult->setText(tr("Success"));
nearestSampleRate->setText("");
nearestChannel->setText("");
nearestSampleFormat->setText("");
} else {
QAudioFormat nearest = m_deviceInfo.preferredFormat();
testResult->setText(tr("Failed"));
nearestSampleRate->setText(QStringLiteral("%1").arg(nearest.sampleRate()));
nearestChannel->setText(QStringLiteral("%1").arg(nearest.channelCount()));
nearestSampleFormat->setText(toString(nearest.sampleFormat()));
}
} else
testResult->setText(tr("No Device"));
}
void AudioTest::updateAudioDevices()
{
deviceBox->clear();
const auto devices =
m_mode == QAudioDevice::Input ? m_devices->audioInputs() : m_devices->audioOutputs();
for (auto &deviceInfo : devices)
deviceBox->addItem(deviceInfo.description(), QVariant::fromValue(deviceInfo));
}
void AudioTest::modeChanged(int idx)
{
testResult->clear();
m_mode = idx == 0 ? QAudioDevice::Input : QAudioDevice::Output;
updateAudioDevices();
deviceBox->setCurrentIndex(0);
deviceChanged(0);
}
void AudioTest::deviceChanged(int idx)
{
testResult->clear();
if (deviceBox->count() == 0)
return;
// device has changed
m_deviceInfo = deviceBox->itemData(idx).value<QAudioDevice>();
sampleRateSpinBox->clear();
sampleRateSpinBox->setMinimum(m_deviceInfo.minimumSampleRate());
sampleRateSpinBox->setMaximum(m_deviceInfo.maximumSampleRate());
int sampleValue =
qBound(m_deviceInfo.minimumSampleRate(), 48000, m_deviceInfo.maximumSampleRate());
sampleRateSpinBox->setValue(sampleValue);
m_settings.setSampleRate(sampleValue);
channelsSpinBox->clear();
channelsSpinBox->setMinimum(m_deviceInfo.minimumChannelCount());
channelsSpinBox->setMaximum(m_deviceInfo.maximumChannelCount());
int channelValue =
qBound(m_deviceInfo.minimumChannelCount(), 2, m_deviceInfo.maximumChannelCount());
channelsSpinBox->setValue(channelValue);
sampleFormatBox->clear();
const QList<QAudioFormat::SampleFormat> sampleFormats = m_deviceInfo.supportedSampleFormats();
for (auto sampleFormat : sampleFormats)
sampleFormatBox->addItem(toString(sampleFormat));
if (sampleFormats.size())
m_settings.setSampleFormat(sampleFormats.at(0));
allFormatsTable->clearContents();
}
void AudioTest::populateTable()
{
int row = 0;
for (auto sampleFormat : m_deviceInfo.supportedSampleFormats()) {
allFormatsTable->setRowCount(row + 1);
QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(sampleFormat));
allFormatsTable->setItem(row, 0, sampleTypeItem);
QTableWidgetItem *sampleRateItem =
new QTableWidgetItem(QStringLiteral("%1 - %2")
.arg(m_deviceInfo.minimumSampleRate())
.arg(m_deviceInfo.maximumSampleRate()));
allFormatsTable->setItem(row, 1, sampleRateItem);
QTableWidgetItem *channelsItem =
new QTableWidgetItem(QStringLiteral("%1 - %2")
.arg(m_deviceInfo.minimumChannelCount())
.arg(m_deviceInfo.maximumChannelCount()));
allFormatsTable->setItem(row, 2, channelsItem);
++row;
}
}
void AudioTest::sampleRateChanged(int value)
{
// sample rate has changed
m_settings.setSampleRate(value);
}
void AudioTest::channelChanged(int channels)
{
m_settings.setChannelCount(channels);
}
void AudioTest::sampleFormatChanged(int idx)
{
auto formats = m_deviceInfo.supportedSampleFormats();
m_settings.setSampleFormat(formats.at(idx));
}
#include "moc_audiodevices.cpp"