diff options
Diffstat (limited to 'examples/multimedia/audiorecorder/audiorecorder.cpp')
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.cpp | 218 |
1 files changed, 110 insertions, 108 deletions
diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp index 992e0a486..4131d5d51 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.cpp +++ b/examples/multimedia/audiorecorder/audiorecorder.cpp @@ -1,125 +1,103 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "audiorecorder.h" #include "audiolevel.h" - #include "ui_audiorecorder.h" -#include <QMediaRecorder> +#include <QAudioBuffer> +#include <QAudioDevice> +#include <QAudioInput> #include <QDir> #include <QFileDialog> +#include <QImageCapture> +#include <QMediaDevices> +#include <QMediaFormat> #include <QMediaRecorder> -#include <QStandardPaths> -#include <qmediadevices.h> -#include <qmediaformat.h> -#include <qaudiodevice.h> -#include <qaudiobuffer.h> -#include <qaudioinput.h> -#include <qimagecapture.h> #include <QMimeType> +#include <QStandardPaths> + +#if QT_CONFIG(permissions) + #include <QPermission> +#endif static QList<qreal> getBufferLevels(const QAudioBuffer &buffer); -AudioRecorder::AudioRecorder() - : ui(new Ui::AudioRecorder) +AudioRecorder::AudioRecorder() : ui(new Ui::AudioRecorder) { ui->setupUi(this); - m_audioRecorder = new QMediaRecorder(this); - m_captureSession.setRecorder(m_audioRecorder); - m_captureSession.setAudioInput(new QAudioInput(this)); - // ### replace with a monitoring output once we have it. -// m_probe = new QAudioProbe(this); -// connect(m_probe, &QAudioProbe::audioBufferProbed, -// this, &AudioRecorder::processBuffer); -// m_probe->setSource(m_audioRecorder); - - //audio devices - ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString())); - for (auto device: QMediaDevices::audioInputs()) { - auto name = device.description(); - ui->audioDeviceBox->addItem(name, QVariant::fromValue(device)); - } - - //audio codecs and container formats - updateFormats(); - connect(ui->audioCodecBox, &QComboBox::currentIndexChanged, this, &AudioRecorder::updateFormats); - connect(ui->containerBox, &QComboBox::currentIndexChanged, this, &AudioRecorder::updateFormats); - - //sample rate - ui->sampleRateBox->setRange(m_captureSession.audioInput()->device().minimumSampleRate(), - m_captureSession.audioInput()->device().maximumSampleRate()); - ui->sampleRateBox->setValue(qBound(m_captureSession.audioInput()->device().minimumSampleRate(), 44100, - m_captureSession.audioInput()->device().maximumSampleRate())); - - //channels + // channels ui->channelsBox->addItem(tr("Default"), QVariant(-1)); ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1)); ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2)); ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4)); - //quality + // quality ui->qualitySlider->setRange(0, int(QImageCapture::VeryHighQuality)); ui->qualitySlider->setValue(int(QImageCapture::NormalQuality)); - //bit rates: + // bit rates: ui->bitrateBox->addItem(tr("Default"), QVariant(0)); ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000)); ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000)); ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000)); ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000)); - connect(m_audioRecorder, &QMediaRecorder::durationChanged, this, &AudioRecorder::updateProgress); - connect(m_audioRecorder, &QMediaRecorder::recorderStateChanged, this, &AudioRecorder::onStateChanged); - connect(m_audioRecorder, &QMediaRecorder::errorChanged, this, &AudioRecorder::displayErrorMessage); + // audio input initialization + init(); +} + +void AudioRecorder::init() +{ +#if QT_CONFIG(permissions) + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &AudioRecorder::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif + + m_audioRecorder = new QMediaRecorder(this); + m_captureSession.setRecorder(m_audioRecorder); + m_captureSession.setAudioInput(new QAudioInput(this)); + // ### replace with a monitoring output once we have it. + // m_probe = new QAudioProbe(this); + // connect(m_probe, &QAudioProbe::audioBufferProbed, + // this, &AudioRecorder::processBuffer); + // m_probe->setSource(m_audioRecorder); + + // audio devices + m_mediaDevices = new QMediaDevices(this); + connect(m_mediaDevices, &QMediaDevices::audioInputsChanged, this, + &AudioRecorder::updateDevices); + updateDevices(); + + // audio codecs and container formats + updateFormats(); + connect(ui->audioCodecBox, &QComboBox::currentIndexChanged, this, + &AudioRecorder::updateFormats); + connect(ui->containerBox, &QComboBox::currentIndexChanged, this, &AudioRecorder::updateFormats); + + // sample rate + ui->sampleRateBox->setRange(m_captureSession.audioInput()->device().minimumSampleRate(), + m_captureSession.audioInput()->device().maximumSampleRate()); + ui->sampleRateBox->setValue( + qBound(m_captureSession.audioInput()->device().minimumSampleRate(), 44100, + m_captureSession.audioInput()->device().maximumSampleRate())); + + connect(m_audioRecorder, &QMediaRecorder::durationChanged, this, + &AudioRecorder::updateProgress); + connect(m_audioRecorder, &QMediaRecorder::recorderStateChanged, this, + &AudioRecorder::onStateChanged); + connect(m_audioRecorder, &QMediaRecorder::errorChanged, this, + &AudioRecorder::displayErrorMessage); } void AudioRecorder::updateProgress(qint64 duration) @@ -171,20 +149,20 @@ static QVariant boxValue(const QComboBox *box) void AudioRecorder::toggleRecord() { if (m_audioRecorder->recorderState() == QMediaRecorder::StoppedState) { - m_captureSession.audioInput()->setDevice(boxValue(ui->audioDeviceBox).value<QAudioDevice>()); + m_captureSession.audioInput()->setDevice( + boxValue(ui->audioDeviceBox).value<QAudioDevice>()); m_audioRecorder->setMediaFormat(selectedMediaFormat()); m_audioRecorder->setAudioSampleRate(ui->sampleRateBox->value()); m_audioRecorder->setAudioBitRate(boxValue(ui->bitrateBox).toInt()); m_audioRecorder->setAudioChannelCount(boxValue(ui->channelsBox).toInt()); m_audioRecorder->setQuality(QMediaRecorder::Quality(ui->qualitySlider->value())); - m_audioRecorder->setEncodingMode(ui->constantQualityRadioButton->isChecked() ? - QMediaRecorder::ConstantQualityEncoding : - QMediaRecorder::ConstantBitRateEncoding); + m_audioRecorder->setEncodingMode(ui->constantQualityRadioButton->isChecked() + ? QMediaRecorder::ConstantQualityEncoding + : QMediaRecorder::ConstantBitRateEncoding); m_audioRecorder->record(); - } - else { + } else { m_audioRecorder->stop(); } } @@ -200,9 +178,9 @@ void AudioRecorder::togglePause() void AudioRecorder::setOutputLocation() { #ifdef Q_OS_ANDROID - QString fileName = QFileDialog::getSaveFileName(this, tr("Save Recording"), - "output." - + selectedMediaFormat().mimeType().preferredSuffix()); + QString fileName = QFileDialog::getSaveFileName( + this, tr("Save Recording"), + "output." + selectedMediaFormat().mimeType().preferredSuffix()); #else QString fileName = QFileDialog::getSaveFileName(); #endif @@ -215,6 +193,25 @@ void AudioRecorder::displayErrorMessage() ui->statusbar->showMessage(m_audioRecorder->errorString()); } +void AudioRecorder::updateDevices() +{ + const auto currentDevice = boxValue(ui->audioDeviceBox).value<QAudioDevice>(); + int currentDeviceIndex = 0; + + ui->audioDeviceBox->clear(); + + ui->audioDeviceBox->addItem(tr("Default"), {}); + for (const auto &device : m_mediaDevices->audioInputs()) { + const auto name = device.description(); + ui->audioDeviceBox->addItem(name, QVariant::fromValue(device)); + + if (device.id() == currentDevice.id()) + currentDeviceIndex = ui->audioDeviceBox->count() - 1; + } + + ui->audioDeviceBox->setCurrentIndex(currentDeviceIndex); +} + void AudioRecorder::updateFormats() { if (m_updatingFormats) @@ -229,23 +226,27 @@ void AudioRecorder::updateFormats() int currentIndex = 0; ui->audioCodecBox->clear(); - ui->audioCodecBox->addItem(tr("Default audio codec"), QVariant::fromValue(QMediaFormat::AudioCodec::Unspecified)); + ui->audioCodecBox->addItem(tr("Default audio codec"), + QVariant::fromValue(QMediaFormat::AudioCodec::Unspecified)); for (auto codec : format.supportedAudioCodecs(QMediaFormat::Encode)) { if (codec == format.audioCodec()) currentIndex = ui->audioCodecBox->count(); - ui->audioCodecBox->addItem(QMediaFormat::audioCodecDescription(codec), QVariant::fromValue(codec)); + ui->audioCodecBox->addItem(QMediaFormat::audioCodecDescription(codec), + QVariant::fromValue(codec)); } ui->audioCodecBox->setCurrentIndex(currentIndex); currentIndex = 0; ui->containerBox->clear(); - ui->containerBox->addItem(tr("Default file format"), QVariant::fromValue(QMediaFormat::UnspecifiedFormat)); + ui->containerBox->addItem(tr("Default file format"), + QVariant::fromValue(QMediaFormat::UnspecifiedFormat)); for (auto container : format.supportedFileFormats(QMediaFormat::Encode)) { if (container < QMediaFormat::Mpeg4Audio) // Skip video formats continue; if (container == format.fileFormat()) currentIndex = ui->containerBox->count(); - ui->containerBox->addItem(QMediaFormat::fileFormatDescription(container), QVariant::fromValue(container)); + ui->containerBox->addItem(QMediaFormat::fileFormatDescription(container), + QVariant::fromValue(container)); } ui->containerBox->setCurrentIndex(currentIndex); @@ -254,7 +255,7 @@ void AudioRecorder::updateFormats() void AudioRecorder::clearAudioLevels() { - for (auto m_audioLevel : qAsConst(m_audioLevels)) + for (auto m_audioLevel : std::as_const(m_audioLevels)) m_audioLevel->setLevel(0); } @@ -295,7 +296,7 @@ QList<qreal> getBufferLevels(const QAudioBuffer &buffer) return max_values; } -void AudioRecorder::processBuffer(const QAudioBuffer& buffer) +void AudioRecorder::processBuffer(const QAudioBuffer &buffer) { if (m_audioLevels.count() != buffer.format().channelCount()) { qDeleteAll(m_audioLevels); @@ -311,3 +312,4 @@ void AudioRecorder::processBuffer(const QAudioBuffer& buffer) for (int i = 0; i < levels.count(); ++i) m_audioLevels.at(i)->setLevel(levels.at(i)); } + |