From 90b68313d3a617e9ae89391e559e221ac22ec8d5 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Fri, 15 Sep 2017 14:43:48 +0200 Subject: Modernize the Audio Devices example Changed the style of member initialization. Provided small cleanup. Changed 0 to nullptr. Changed to new signal/slot style if possible. Task-number: QTBUG-60627 Change-Id: I995d62b8d3741c719565f5b203b1046e8701d238 Reviewed-by: Christian Stromme --- examples/multimedia/audiodevices/audiodevices.cpp | 100 ++++++++++------------ examples/multimedia/audiodevices/audiodevices.h | 9 +- 2 files changed, 48 insertions(+), 61 deletions(-) (limited to 'examples/multimedia') diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp index cf0947394..b447b809d 100644 --- a/examples/multimedia/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audiodevices/audiodevices.cpp @@ -88,18 +88,16 @@ AudioDevicesBase::~AudioDevicesBase() {} AudioTest::AudioTest(QWidget *parent) : AudioDevicesBase(parent) { - mode = QAudio::AudioOutput; - - connect(testButton, SIGNAL(clicked()), SLOT(test())); - connect(modeBox, SIGNAL(activated(int)), SLOT(modeChanged(int))); - connect(deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int))); - connect(sampleRateBox, SIGNAL(activated(int)), SLOT(sampleRateChanged(int))); - connect(channelsBox, SIGNAL(activated(int)), SLOT(channelChanged(int))); - connect(codecsBox, SIGNAL(activated(int)), SLOT(codecChanged(int))); - connect(sampleSizesBox, SIGNAL(activated(int)), SLOT(sampleSizeChanged(int))); - connect(sampleTypesBox, SIGNAL(activated(int)), SLOT(sampleTypeChanged(int))); - connect(endianBox, SIGNAL(activated(int)), SLOT(endianChanged(int))); - connect(populateTableButton, SIGNAL(clicked()), SLOT(populateTable())); + connect(testButton, &QPushButton::clicked, this, &AudioTest::test); + connect(modeBox, QOverload::of(&QComboBox::activated), this, &AudioTest::modeChanged); + connect(deviceBox, QOverload::of(&QComboBox::activated), this, &AudioTest::deviceChanged); + connect(sampleRateBox, QOverload::of(&QComboBox::activated), this, &AudioTest::sampleRateChanged); + connect(channelsBox, QOverload::of(&QComboBox::activated), this, &AudioTest::channelChanged); + connect(codecsBox, QOverload::of(&QComboBox::activated), this, &AudioTest::codecChanged); + connect(sampleSizesBox, QOverload::of(&QComboBox::activated), this, &AudioTest::sampleSizeChanged); + connect(sampleTypesBox, QOverload::of(&QComboBox::activated), this, &AudioTest::sampleTypeChanged); + connect(endianBox, QOverload::of(&QComboBox::activated), this, &AudioTest::endianChanged); + connect(populateTableButton, &QPushButton::clicked, this, &AudioTest::populateTable); modeBox->setCurrentIndex(0); modeChanged(0); @@ -107,17 +105,13 @@ AudioTest::AudioTest(QWidget *parent) deviceChanged(0); } -AudioTest::~AudioTest() -{ -} - void AudioTest::test() { // tries to set all the settings picked. testResult->clear(); - if (!deviceInfo.isNull()) { - if (deviceInfo.isFormatSupported(settings)) { + if (!m_deviceInfo.isNull()) { + if (m_deviceInfo.isFormatSupported(m_settings)) { testResult->setText(tr("Success")); nearestSampleRate->setText(""); nearestChannel->setText(""); @@ -126,7 +120,7 @@ void AudioTest::test() nearestSampleType->setText(""); nearestEndian->setText(""); } else { - QAudioFormat nearest = deviceInfo.nearestFormat(settings); + QAudioFormat nearest = m_deviceInfo.nearestFormat(m_settings); testResult->setText(tr("Failed")); nearestSampleRate->setText(QString("%1").arg(nearest.sampleRate())); nearestChannel->setText(QString("%1").arg(nearest.channelCount())); @@ -143,15 +137,9 @@ void AudioTest::test() void AudioTest::modeChanged(int idx) { testResult->clear(); - - // mode has changed - if (idx == 0) - mode = QAudio::AudioInput; - else - mode = QAudio::AudioOutput; - deviceBox->clear(); - foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(mode)) + const QAudio::Mode mode = idx == 0 ? QAudio::AudioInput : QAudio::AudioOutput; + for (auto &deviceInfo: QAudioDeviceInfo::availableDevices(mode)) deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); deviceBox->setCurrentIndex(0); @@ -166,52 +154,52 @@ void AudioTest::deviceChanged(int idx) return; // device has changed - deviceInfo = deviceBox->itemData(idx).value(); + m_deviceInfo = deviceBox->itemData(idx).value(); sampleRateBox->clear(); - QList sampleRatez = deviceInfo.supportedSampleRates(); + QList sampleRatez = m_deviceInfo.supportedSampleRates(); for (int i = 0; i < sampleRatez.size(); ++i) sampleRateBox->addItem(QString("%1").arg(sampleRatez.at(i))); if (sampleRatez.size()) - settings.setSampleRate(sampleRatez.at(0)); + m_settings.setSampleRate(sampleRatez.at(0)); channelsBox->clear(); - QList chz = deviceInfo.supportedChannelCounts(); + QList chz = m_deviceInfo.supportedChannelCounts(); for (int i = 0; i < chz.size(); ++i) channelsBox->addItem(QString("%1").arg(chz.at(i))); if (chz.size()) - settings.setChannelCount(chz.at(0)); + m_settings.setChannelCount(chz.at(0)); codecsBox->clear(); - QStringList codecs = deviceInfo.supportedCodecs(); + QStringList codecs = m_deviceInfo.supportedCodecs(); for (int i = 0; i < codecs.size(); ++i) codecsBox->addItem(QString("%1").arg(codecs.at(i))); if (codecs.size()) - settings.setCodec(codecs.at(0)); + m_settings.setCodec(codecs.at(0)); // Add false to create failed condition! codecsBox->addItem("audio/test"); sampleSizesBox->clear(); - QList sampleSizez = deviceInfo.supportedSampleSizes(); + QList sampleSizez = m_deviceInfo.supportedSampleSizes(); for (int i = 0; i < sampleSizez.size(); ++i) sampleSizesBox->addItem(QString("%1").arg(sampleSizez.at(i))); if (sampleSizez.size()) - settings.setSampleSize(sampleSizez.at(0)); + m_settings.setSampleSize(sampleSizez.at(0)); sampleTypesBox->clear(); - QList sampleTypez = deviceInfo.supportedSampleTypes(); + QList sampleTypez = m_deviceInfo.supportedSampleTypes(); for (int i = 0; i < sampleTypez.size(); ++i) sampleTypesBox->addItem(toString(sampleTypez.at(i))); if (sampleTypez.size()) - settings.setSampleType(sampleTypez.at(0)); + m_settings.setSampleType(sampleTypez.at(0)); endianBox->clear(); - QList endianz = deviceInfo.supportedByteOrders(); + QList endianz = m_deviceInfo.supportedByteOrders(); for (int i = 0; i < endianz.size(); ++i) endianBox->addItem(toString(endianz.at(i))); if (endianz.size()) - settings.setByteOrder(endianz.at(0)); + m_settings.setByteOrder(endianz.at(0)); allFormatsTable->clearContents(); } @@ -221,19 +209,19 @@ void AudioTest::populateTable() int row = 0; QAudioFormat format; - foreach (QString codec, deviceInfo.supportedCodecs()) { + for (auto codec: m_deviceInfo.supportedCodecs()) { format.setCodec(codec); - foreach (int sampleRate, deviceInfo.supportedSampleRates()) { + for (auto sampleRate: m_deviceInfo.supportedSampleRates()) { format.setSampleRate(sampleRate); - foreach (int channels, deviceInfo.supportedChannelCounts()) { + for (auto channels: m_deviceInfo.supportedChannelCounts()) { format.setChannelCount(channels); - foreach (QAudioFormat::SampleType sampleType, deviceInfo.supportedSampleTypes()) { + for (auto sampleType: m_deviceInfo.supportedSampleTypes()) { format.setSampleType(sampleType); - foreach (int sampleSize, deviceInfo.supportedSampleSizes()) { + for (auto sampleSize: m_deviceInfo.supportedSampleSizes()) { format.setSampleSize(sampleSize); - foreach (QAudioFormat::Endian endian, deviceInfo.supportedByteOrders()) { + for (auto endian: m_deviceInfo.supportedByteOrders()) { format.setByteOrder(endian); - if (deviceInfo.isFormatSupported(format)) { + if (m_deviceInfo.isFormatSupported(format)) { allFormatsTable->setRowCount(row + 1); QTableWidgetItem *codecItem = new QTableWidgetItem(format.codec()); @@ -267,35 +255,35 @@ void AudioTest::populateTable() void AudioTest::sampleRateChanged(int idx) { // sample rate has changed - settings.setSampleRate(sampleRateBox->itemText(idx).toInt()); + m_settings.setSampleRate(sampleRateBox->itemText(idx).toInt()); } void AudioTest::channelChanged(int idx) { - settings.setChannelCount(channelsBox->itemText(idx).toInt()); + m_settings.setChannelCount(channelsBox->itemText(idx).toInt()); } void AudioTest::codecChanged(int idx) { - settings.setCodec(codecsBox->itemText(idx)); + m_settings.setCodec(codecsBox->itemText(idx)); } void AudioTest::sampleSizeChanged(int idx) { - settings.setSampleSize(sampleSizesBox->itemText(idx).toInt()); + m_settings.setSampleSize(sampleSizesBox->itemText(idx).toInt()); } void AudioTest::sampleTypeChanged(int idx) { switch (sampleTypesBox->itemText(idx).toInt()) { case QAudioFormat::SignedInt: - settings.setSampleType(QAudioFormat::SignedInt); + m_settings.setSampleType(QAudioFormat::SignedInt); break; case QAudioFormat::UnSignedInt: - settings.setSampleType(QAudioFormat::UnSignedInt); + m_settings.setSampleType(QAudioFormat::UnSignedInt); break; case QAudioFormat::Float: - settings.setSampleType(QAudioFormat::Float); + m_settings.setSampleType(QAudioFormat::Float); } } @@ -303,9 +291,9 @@ void AudioTest::endianChanged(int idx) { switch (endianBox->itemText(idx).toInt()) { case QAudioFormat::LittleEndian: - settings.setByteOrder(QAudioFormat::LittleEndian); + m_settings.setByteOrder(QAudioFormat::LittleEndian); break; case QAudioFormat::BigEndian: - settings.setByteOrder(QAudioFormat::BigEndian); + m_settings.setByteOrder(QAudioFormat::BigEndian); } } diff --git a/examples/multimedia/audiodevices/audiodevices.h b/examples/multimedia/audiodevices/audiodevices.h index 2cc58eb6c..17f214a47 100644 --- a/examples/multimedia/audiodevices/audiodevices.h +++ b/examples/multimedia/audiodevices/audiodevices.h @@ -59,12 +59,11 @@ class AudioTest : public AudioDevicesBase Q_OBJECT public: - AudioTest(QWidget *parent = 0); - virtual ~AudioTest(); + explicit AudioTest(QWidget *parent = nullptr); - QAudioDeviceInfo deviceInfo; - QAudioFormat settings; - QAudio::Mode mode; +private: + QAudioDeviceInfo m_deviceInfo; + QAudioFormat m_settings; private slots: void modeChanged(int idx); -- cgit v1.2.3 From 1a8b30c10602aded40bd420614cbc6c7a3d3ba13 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Fri, 15 Sep 2017 17:04:50 +0200 Subject: Modernize the Audio Input example Removed unneeded defines. Removed unneeded members. Removed using QScopedPointer where is not needed. Changed some member functions to lambdas in signal/slot. Changed initialization style. Recoded toggleMode. Task-number: QTBUG-60627 Change-Id: Iaf6bb297bc0b87509fcda956bfd082e80a3226c4 Reviewed-by: Christian Stromme --- examples/multimedia/audioinput/audioinput.cpp | 168 +++++++++----------------- examples/multimedia/audioinput/audioinput.h | 40 +++--- 2 files changed, 75 insertions(+), 133 deletions(-) (limited to 'examples/multimedia') diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp index cdf56af99..e06df961e 100644 --- a/examples/multimedia/audioinput/audioinput.cpp +++ b/examples/multimedia/audioinput/audioinput.cpp @@ -38,6 +38,8 @@ ** ****************************************************************************/ +#include "audioinput.h" + #include #include @@ -49,21 +51,8 @@ #include #include -#include "audioinput.h" - -#define PUSH_MODE_LABEL "Enable push mode" -#define PULL_MODE_LABEL "Enable pull mode" -#define SUSPEND_LABEL "Suspend recording" -#define RESUME_LABEL "Resume recording" - -const int BufferSize = 4096; - -AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent) - : QIODevice(parent) - , m_format(format) - , m_maxAmplitude(0) - , m_level(0.0) - +AudioInfo::AudioInfo(const QAudioFormat &format) + : m_format(format) { switch (m_format.sampleSize()) { case 8: @@ -111,10 +100,6 @@ AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent) } } -AudioInfo::~AudioInfo() -{ -} - void AudioInfo::start() { open(QIODevice::WriteOnly); @@ -196,7 +181,6 @@ RenderArea::RenderArea(QWidget *parent) setBackgroundRole(QPalette::Base); setAutoFillBackground(true); - m_level = 0; setMinimumHeight(30); setMinimumWidth(200); } @@ -229,27 +213,16 @@ void RenderArea::setLevel(qreal value) InputTest::InputTest() - : m_canvas(0) - , m_modeButton(0) - , m_suspendResumeButton(0) - , m_deviceBox(0) - , m_device(QAudioDeviceInfo::defaultInputDevice()) - , m_audioInfo(0) - , m_audioInput(0) - , m_input(0) - , m_pullMode(true) - , m_buffer(BufferSize, 0) { initializeWindow(); - initializeAudio(); + initializeAudio(QAudioDeviceInfo::defaultInputDevice()); } -InputTest::~InputTest() {} void InputTest::initializeWindow() { - QScopedPointer window(new QWidget); - QScopedPointer layout(new QVBoxLayout); + QWidget *window = new QWidget; + QVBoxLayout *layout = new QVBoxLayout; m_canvas = new RenderArea(this); layout->addWidget(m_canvas); @@ -257,143 +230,120 @@ void InputTest::initializeWindow() m_deviceBox = new QComboBox(this); const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); m_deviceBox->addItem(defaultDeviceInfo.deviceName(), qVariantFromValue(defaultDeviceInfo)); - foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) { + for (auto &deviceInfo: QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) { if (deviceInfo != defaultDeviceInfo) m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); } - connect(m_deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int))); + connect(m_deviceBox, QOverload::of(&QComboBox::activated), this, &InputTest::deviceChanged); layout->addWidget(m_deviceBox); m_volumeSlider = new QSlider(Qt::Horizontal, this); m_volumeSlider->setRange(0, 100); m_volumeSlider->setValue(100); - connect(m_volumeSlider, SIGNAL(valueChanged(int)), SLOT(sliderChanged(int))); + connect(m_volumeSlider, &QSlider::valueChanged, this, &InputTest::sliderChanged); layout->addWidget(m_volumeSlider); m_modeButton = new QPushButton(this); - m_modeButton->setText(tr(PUSH_MODE_LABEL)); - connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode())); + connect(m_modeButton, &QPushButton::clicked, this, &InputTest::toggleMode); layout->addWidget(m_modeButton); m_suspendResumeButton = new QPushButton(this); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); - connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspend())); + connect(m_suspendResumeButton, &QPushButton::clicked, this, &InputTest::toggleSuspend); layout->addWidget(m_suspendResumeButton); - window->setLayout(layout.data()); - layout.take(); // ownership transferred + window->setLayout(layout); - setCentralWidget(window.data()); - QWidget *const windowPtr = window.take(); // ownership transferred - windowPtr->show(); + setCentralWidget(window); + window->show(); } -void InputTest::initializeAudio() +void InputTest::initializeAudio(const QAudioDeviceInfo &deviceInfo) { - m_format.setSampleRate(8000); - m_format.setChannelCount(1); - m_format.setSampleSize(16); - m_format.setSampleType(QAudioFormat::SignedInt); - m_format.setByteOrder(QAudioFormat::LittleEndian); - m_format.setCodec("audio/pcm"); - - QAudioDeviceInfo info(m_device); - if (!info.isFormatSupported(m_format)) { + QAudioFormat format; + format.setSampleRate(8000); + format.setChannelCount(1); + format.setSampleSize(16); + format.setSampleType(QAudioFormat::SignedInt); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setCodec("audio/pcm"); + + if (!deviceInfo.isFormatSupported(format)) { qWarning() << "Default format not supported - trying to use nearest"; - m_format = info.nearestFormat(m_format); + format = deviceInfo.nearestFormat(format); } - if (m_audioInfo) - delete m_audioInfo; - m_audioInfo = new AudioInfo(m_format, this); - connect(m_audioInfo, SIGNAL(update()), SLOT(refreshDisplay())); - - createAudioInput(); -} + m_audioInfo.reset(new AudioInfo(format)); + connect(m_audioInfo.data(), &AudioInfo::update, [this]() { + m_canvas->setLevel(m_audioInfo->level()); + }); -void InputTest::createAudioInput() -{ - m_audioInput = new QAudioInput(m_device, m_format, this); + m_audioInput.reset(new QAudioInput(deviceInfo, format)); qreal initialVolume = QAudio::convertVolume(m_audioInput->volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); m_volumeSlider->setValue(qRound(initialVolume * 100)); m_audioInfo->start(); - m_audioInput->start(m_audioInfo); -} - -void InputTest::readMore() -{ - if (!m_audioInput) - return; - qint64 len = m_audioInput->bytesReady(); - if (len > BufferSize) - len = BufferSize; - qint64 l = m_input->read(m_buffer.data(), len); - if (l > 0) - m_audioInfo->write(m_buffer.constData(), l); + toggleMode(); } void InputTest::toggleMode() { - // Change bewteen pull and push modes m_audioInput->stop(); + toggleSuspend(); + // Change bewteen pull and push modes if (m_pullMode) { - m_modeButton->setText(tr(PULL_MODE_LABEL)); - m_input = m_audioInput->start(); - connect(m_input, SIGNAL(readyRead()), SLOT(readMore())); - m_pullMode = false; + m_modeButton->setText(tr("Enable push mode")); + m_audioInput->start(m_audioInfo.data()); } else { - m_modeButton->setText(tr(PUSH_MODE_LABEL)); - m_pullMode = true; - m_audioInput->start(m_audioInfo); + m_modeButton->setText(tr("Enable pull mode")); + auto io = m_audioInput->start(); + connect(io, &QIODevice::readyRead, + [&, io]() { + qint64 len = m_audioInput->bytesReady(); + const int BufferSize = 4096; + if (len > BufferSize) + len = BufferSize; + + QByteArray buffer(len, 0); + qint64 l = io->read(buffer.data(), len); + if (l > 0) + m_audioInfo->write(buffer.constData(), l); + }); } - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_pullMode = !m_pullMode; } void InputTest::toggleSuspend() { // toggle suspend/resume - if (m_audioInput->state() == QAudio::SuspendedState) { + if (m_audioInput->state() == QAudio::SuspendedState || m_audioInput->state() == QAudio::StoppedState) { m_audioInput->resume(); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_suspendResumeButton->setText(tr("Suspend recording")); } else if (m_audioInput->state() == QAudio::ActiveState) { m_audioInput->suspend(); - m_suspendResumeButton->setText(tr(RESUME_LABEL)); - } else if (m_audioInput->state() == QAudio::StoppedState) { - m_audioInput->resume(); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_suspendResumeButton->setText(tr("Resume recording")); } else if (m_audioInput->state() == QAudio::IdleState) { // no-op } } -void InputTest::refreshDisplay() -{ - m_canvas->setLevel(m_audioInfo->level()); -} - void InputTest::deviceChanged(int index) { m_audioInfo->stop(); m_audioInput->stop(); m_audioInput->disconnect(this); - delete m_audioInput; - m_device = m_deviceBox->itemData(index).value(); - initializeAudio(); + initializeAudio(m_deviceBox->itemData(index).value()); } void InputTest::sliderChanged(int value) { - if (m_audioInput) { - qreal linearVolume = QAudio::convertVolume(value / qreal(100), - QAudio::LogarithmicVolumeScale, - QAudio::LinearVolumeScale); + qreal linearVolume = QAudio::convertVolume(value / qreal(100), + QAudio::LogarithmicVolumeScale, + QAudio::LinearVolumeScale); - m_audioInput->setVolume(linearVolume); - } + m_audioInput->setVolume(linearVolume); } diff --git a/examples/multimedia/audioinput/audioinput.h b/examples/multimedia/audioinput/audioinput.h index b6deb361c..cdfb6e69b 100644 --- a/examples/multimedia/audioinput/audioinput.h +++ b/examples/multimedia/audioinput/audioinput.h @@ -50,14 +50,14 @@ #include #include #include +#include class AudioInfo : public QIODevice { Q_OBJECT public: - AudioInfo(const QAudioFormat &format, QObject *parent); - ~AudioInfo(); + AudioInfo(const QAudioFormat &format); void start(); void stop(); @@ -69,8 +69,8 @@ public: private: const QAudioFormat m_format; - quint32 m_maxAmplitude; - qreal m_level; // 0.0 <= m_level <= 1.0 + quint32 m_maxAmplitude = 0; + qreal m_level = 0.0; // 0.0 <= m_level <= 1.0 signals: void update(); @@ -82,7 +82,7 @@ class RenderArea : public QWidget Q_OBJECT public: - RenderArea(QWidget *parent = 0); + explicit RenderArea(QWidget *parent = nullptr); void setLevel(qreal value); @@ -90,7 +90,7 @@ protected: void paintEvent(QPaintEvent *event) override; private: - qreal m_level; + qreal m_level = 0; QPixmap m_pixmap; }; @@ -101,16 +101,12 @@ class InputTest : public QMainWindow public: InputTest(); - ~InputTest(); private: void initializeWindow(); - void initializeAudio(); - void createAudioInput(); + void initializeAudio(const QAudioDeviceInfo &deviceInfo); private slots: - void refreshDisplay(); - void readMore(); void toggleMode(); void toggleSuspend(); void deviceChanged(int index); @@ -118,19 +114,15 @@ private slots: private: // Owned by layout - RenderArea *m_canvas; - QPushButton *m_modeButton; - QPushButton *m_suspendResumeButton; - QComboBox *m_deviceBox; - QSlider *m_volumeSlider; - - QAudioDeviceInfo m_device; - AudioInfo *m_audioInfo; - QAudioFormat m_format; - QAudioInput *m_audioInput; - QIODevice *m_input; - bool m_pullMode; - QByteArray m_buffer; + RenderArea *m_canvas = nullptr; + QPushButton *m_modeButton = nullptr; + QPushButton *m_suspendResumeButton = nullptr; + QComboBox *m_deviceBox = nullptr; + QSlider *m_volumeSlider = nullptr; + + QScopedPointer m_audioInfo; + QScopedPointer m_audioInput; + bool m_pullMode = true; }; #endif // AUDIOINPUT_H -- cgit v1.2.3 From cd39b3726db7df2d3d8b2ec2584f1aae6255e4aa Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Mon, 18 Sep 2017 11:42:32 +0200 Subject: Modernize the Audio Output example Changed initialization style. Recoded toggleMode. Removed unneeded defines, function members. Changed signal/slot connection style. Changed foreach to c++11 style. Fixed bug with wrong duration seconds. Task-number: QTBUG-60627 Change-Id: Ib62f7979f2a32d629482026e0d954612b2665d66 Reviewed-by: Christian Stromme --- examples/multimedia/audiooutput/audiooutput.cpp | 242 ++++++++++-------------- examples/multimedia/audiooutput/audiooutput.h | 36 ++-- 2 files changed, 113 insertions(+), 165 deletions(-) (limited to 'examples/multimedia') diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp index 3e9ec7377..543242a80 100644 --- a/examples/multimedia/audiooutput/audiooutput.cpp +++ b/examples/multimedia/audiooutput/audiooutput.cpp @@ -38,6 +38,8 @@ ** ****************************************************************************/ +#include "audiooutput.h" + #include #include #include @@ -45,36 +47,14 @@ #include #include -#include "audiooutput.h" - -#define PUSH_MODE_LABEL "Enable push mode" -#define PULL_MODE_LABEL "Enable pull mode" -#define SUSPEND_LABEL "Suspend playback" -#define RESUME_LABEL "Resume playback" -#define VOLUME_LABEL "Volume:" - -const int DurationSeconds = 1; -const int ToneSampleRateHz = 600; -const int DataSampleRateHz = 44100; -const int BufferSize = 32768; - - -Generator::Generator(const QAudioFormat &format, - qint64 durationUs, - int sampleRate, - QObject *parent) - : QIODevice(parent) - , m_pos(0) +Generator::Generator(const QAudioFormat &format + , qint64 durationUs + , int sampleRate) { if (format.isValid()) generateData(format, durationUs, sampleRate); } -Generator::~Generator() -{ - -} - void Generator::start() { open(QIODevice::ReadOnly); @@ -90,10 +70,8 @@ void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int { const int channelBytes = format.sampleSize() / 8; const int sampleBytes = format.channelCount() * channelBytes; - qint64 length = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)) - * durationUs / 100000; - + * durationUs / 1000000; Q_ASSERT(length % sampleBytes == 0); Q_UNUSED(sampleBytes) // suppress warning in release builds @@ -102,32 +80,36 @@ void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int int sampleIndex = 0; while (length) { - const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex % format.sampleRate()) / format.sampleRate()); + // Produces value (-1..1) + const qreal x = qSin(2 * M_PI * sampleRate * qreal(sampleIndex++ % format.sampleRate()) / format.sampleRate()); for (int i=0; i((1.0 + x) / 2 * 255); - *reinterpret_cast(ptr) = value; - } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) { - const qint8 value = static_cast(x * 127); - *reinterpret_cast(ptr) = value; - } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) { - quint16 value = static_cast((1.0 + x) / 2 * 65535); - if (format.byteOrder() == QAudioFormat::LittleEndian) - qToLittleEndian(value, ptr); - else - qToBigEndian(value, ptr); - } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) { - qint16 value = static_cast(x * 32767); - if (format.byteOrder() == QAudioFormat::LittleEndian) - qToLittleEndian(value, ptr); - else - qToBigEndian(value, ptr); + if (format.sampleSize() == 8) { + if (format.sampleType() == QAudioFormat::UnSignedInt) { + const quint8 value = static_cast((1.0 + x) / 2 * 255); + *reinterpret_cast(ptr) = value; + } else if (format.sampleType() == QAudioFormat::SignedInt) { + const qint8 value = static_cast(x * 127); + *reinterpret_cast(ptr) = value; + } + } else if (format.sampleSize() == 16) { + if (format.sampleType() == QAudioFormat::UnSignedInt) { + quint16 value = static_cast((1.0 + x) / 2 * 65535); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian(value, ptr); + else + qToBigEndian(value, ptr); + } else if (format.sampleType() == QAudioFormat::SignedInt) { + qint16 value = static_cast(x * 32767); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian(value, ptr); + else + qToBigEndian(value, ptr); + } } ptr += channelBytes; length -= channelBytes; } - ++sampleIndex; } } @@ -159,177 +141,149 @@ qint64 Generator::bytesAvailable() const } AudioTest::AudioTest() - : m_pushTimer(new QTimer(this)) - , m_modeButton(0) - , m_suspendResumeButton(0) - , m_deviceBox(0) - , m_device(QAudioDeviceInfo::defaultOutputDevice()) - , m_generator(0) - , m_audioOutput(0) - , m_output(0) - , m_pullMode(true) - , m_buffer(BufferSize, 0) + : m_pushTimer(new QTimer(this)) { initializeWindow(); - initializeAudio(); + initializeAudio(QAudioDeviceInfo::defaultOutputDevice()); +} + +AudioTest::~AudioTest() +{ + m_pushTimer->stop(); } void AudioTest::initializeWindow() { - QScopedPointer window(new QWidget); - QScopedPointer layout(new QVBoxLayout); + QWidget *window = new QWidget; + QVBoxLayout *layout = new QVBoxLayout; m_deviceBox = new QComboBox(this); const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultOutputDevice(); m_deviceBox->addItem(defaultDeviceInfo.deviceName(), qVariantFromValue(defaultDeviceInfo)); - foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { + for (auto &deviceInfo: QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { if (deviceInfo != defaultDeviceInfo) m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo)); } - connect(m_deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int))); + connect(m_deviceBox, QOverload::of(&QComboBox::activated), this, &AudioTest::deviceChanged); layout->addWidget(m_deviceBox); m_modeButton = new QPushButton(this); - m_modeButton->setText(tr(PUSH_MODE_LABEL)); - connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode())); + connect(m_modeButton, &QPushButton::clicked, this, &AudioTest::toggleMode); layout->addWidget(m_modeButton); m_suspendResumeButton = new QPushButton(this); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); - connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume())); + connect(m_suspendResumeButton, &QPushButton::clicked, this, &AudioTest::toggleSuspendResume); layout->addWidget(m_suspendResumeButton); QHBoxLayout *volumeBox = new QHBoxLayout; m_volumeLabel = new QLabel; - m_volumeLabel->setText(tr(VOLUME_LABEL)); + m_volumeLabel->setText(tr("Volume:")); m_volumeSlider = new QSlider(Qt::Horizontal); m_volumeSlider->setMinimum(0); m_volumeSlider->setMaximum(100); m_volumeSlider->setSingleStep(10); - connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); + connect(m_volumeSlider, &QSlider::valueChanged, this, &AudioTest::volumeChanged); volumeBox->addWidget(m_volumeLabel); volumeBox->addWidget(m_volumeSlider); layout->addLayout(volumeBox); - window->setLayout(layout.data()); - layout.take(); // ownership transferred + window->setLayout(layout); - setCentralWidget(window.data()); - QWidget *const windowPtr = window.take(); // ownership transferred - windowPtr->show(); + setCentralWidget(window); + window->show(); } -void AudioTest::initializeAudio() +void AudioTest::initializeAudio(const QAudioDeviceInfo &deviceInfo) { - connect(m_pushTimer, SIGNAL(timeout()), SLOT(pushTimerExpired())); - - m_format.setSampleRate(DataSampleRateHz); - m_format.setChannelCount(1); - m_format.setSampleSize(16); - m_format.setCodec("audio/pcm"); - m_format.setByteOrder(QAudioFormat::LittleEndian); - m_format.setSampleType(QAudioFormat::SignedInt); - - QAudioDeviceInfo info(m_device); - if (!info.isFormatSupported(m_format)) { + QAudioFormat format; + format.setSampleRate(44100); + format.setChannelCount(1); + format.setSampleSize(16); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setSampleType(QAudioFormat::SignedInt); + + if (!deviceInfo.isFormatSupported(format)) { qWarning() << "Default format not supported - trying to use nearest"; - m_format = info.nearestFormat(m_format); + format = deviceInfo.nearestFormat(format); } - if (m_generator) - delete m_generator; - m_generator = new Generator(m_format, DurationSeconds*1000000, ToneSampleRateHz, this); - - createAudioOutput(); -} - -void AudioTest::createAudioOutput() -{ - delete m_audioOutput; - m_audioOutput = 0; - m_audioOutput = new QAudioOutput(m_device, m_format, this); + const int durationSeconds = 1; + const int toneSampleRateHz = 600; + m_generator.reset(new Generator(format, durationSeconds * 1000000, toneSampleRateHz)); + m_audioOutput.reset(new QAudioOutput(deviceInfo, format)); m_generator->start(); - m_audioOutput->start(m_generator); qreal initialVolume = QAudio::convertVolume(m_audioOutput->volume(), QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); m_volumeSlider->setValue(qRound(initialVolume * 100)); -} - -AudioTest::~AudioTest() -{ - + toggleMode(); } void AudioTest::deviceChanged(int index) { - m_pushTimer->stop(); m_generator->stop(); m_audioOutput->stop(); m_audioOutput->disconnect(this); - m_device = m_deviceBox->itemData(index).value(); - initializeAudio(); + initializeAudio(m_deviceBox->itemData(index).value()); } void AudioTest::volumeChanged(int value) { - if (m_audioOutput) { - qreal linearVolume = QAudio::convertVolume(value / qreal(100), - QAudio::LogarithmicVolumeScale, - QAudio::LinearVolumeScale); + qreal linearVolume = QAudio::convertVolume(value / qreal(100), + QAudio::LogarithmicVolumeScale, + QAudio::LinearVolumeScale); - m_audioOutput->setVolume(linearVolume); - } -} - -void AudioTest::pushTimerExpired() -{ - if (m_audioOutput && m_audioOutput->state() != QAudio::StoppedState) { - int chunks = m_audioOutput->bytesFree()/m_audioOutput->periodSize(); - while (chunks) { - const qint64 len = m_generator->read(m_buffer.data(), m_audioOutput->periodSize()); - if (len) - m_output->write(m_buffer.data(), len); - if (len != m_audioOutput->periodSize()) - break; - --chunks; - } - } + m_audioOutput->setVolume(linearVolume); } void AudioTest::toggleMode() { m_pushTimer->stop(); m_audioOutput->stop(); + toggleSuspendResume(); if (m_pullMode) { + //switch to pull mode (QAudioOutput pulls from Generator as needed) + m_modeButton->setText(tr("Enable push mode")); + m_audioOutput->start(m_generator.data()); + } else { //switch to push mode (periodically push to QAudioOutput using a timer) - m_modeButton->setText(tr(PULL_MODE_LABEL)); - m_output = m_audioOutput->start(); - m_pullMode = false; + m_modeButton->setText(tr("Enable pull mode")); + auto io = m_audioOutput->start(); + m_pushTimer->disconnect(); + + connect(m_pushTimer, &QTimer::timeout, [this, io]() { + if (m_audioOutput->state() == QAudio::StoppedState) + return; + + QByteArray buffer(32768, 0); + int chunks = m_audioOutput->bytesFree() / m_audioOutput->periodSize(); + while (chunks) { + const qint64 len = m_generator->read(buffer.data(), m_audioOutput->periodSize()); + if (len) + io->write(buffer.data(), len); + if (len != m_audioOutput->periodSize()) + break; + --chunks; + } + }); + m_pushTimer->start(20); - } else { - //switch to pull mode (QAudioOutput pulls from Generator as needed) - m_modeButton->setText(tr(PUSH_MODE_LABEL)); - m_pullMode = true; - m_audioOutput->start(m_generator); } - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_pullMode = !m_pullMode; } void AudioTest::toggleSuspendResume() { - if (m_audioOutput->state() == QAudio::SuspendedState) { + if (m_audioOutput->state() == QAudio::SuspendedState || m_audioOutput->state() == QAudio::StoppedState) { m_audioOutput->resume(); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_suspendResumeButton->setText(tr("Suspend recording")); } else if (m_audioOutput->state() == QAudio::ActiveState) { m_audioOutput->suspend(); - m_suspendResumeButton->setText(tr(RESUME_LABEL)); - } else if (m_audioOutput->state() == QAudio::StoppedState) { - m_audioOutput->resume(); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_suspendResumeButton->setText(tr("Resume playback")); } else if (m_audioOutput->state() == QAudio::IdleState) { // no-op } diff --git a/examples/multimedia/audiooutput/audiooutput.h b/examples/multimedia/audiooutput/audiooutput.h index d5c2b4cc2..489624160 100644 --- a/examples/multimedia/audiooutput/audiooutput.h +++ b/examples/multimedia/audiooutput/audiooutput.h @@ -53,14 +53,14 @@ #include #include #include +#include class Generator : public QIODevice { Q_OBJECT public: - Generator(const QAudioFormat &format, qint64 durationUs, int sampleRate, QObject *parent); - ~Generator(); + Generator(const QAudioFormat &format, qint64 durationUs, int sampleRate); void start(); void stop(); @@ -73,7 +73,7 @@ private: void generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate); private: - qint64 m_pos; + qint64 m_pos = 0; QByteArray m_buffer; }; @@ -87,30 +87,24 @@ public: private: void initializeWindow(); - void initializeAudio(); - void createAudioOutput(); + void initializeAudio(const QAudioDeviceInfo &deviceInfo); private: - QTimer *m_pushTimer; + QTimer *m_pushTimer = nullptr; // Owned by layout - QPushButton *m_modeButton; - QPushButton *m_suspendResumeButton; - QComboBox *m_deviceBox; - QLabel *m_volumeLabel; - QSlider *m_volumeSlider; - - QAudioDeviceInfo m_device; - Generator *m_generator; - QAudioOutput *m_audioOutput; - QIODevice *m_output; // not owned - QAudioFormat m_format; - - bool m_pullMode; - QByteArray m_buffer; + QPushButton *m_modeButton = nullptr; + QPushButton *m_suspendResumeButton = nullptr; + QComboBox *m_deviceBox = nullptr; + QLabel *m_volumeLabel = nullptr; + QSlider *m_volumeSlider = nullptr; + + QScopedPointer m_generator; + QScopedPointer m_audioOutput; + + bool m_pullMode = true; private slots: - void pushTimerExpired(); void toggleMode(); void toggleSuspendResume(); void deviceChanged(int index); -- cgit v1.2.3 From bfcbd91c8548953434073b509a9053d88ec7ec54 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Mon, 18 Sep 2017 12:26:40 +0200 Subject: Modernize the Audio Recorder example Foreach to for. Changed initialization style. Renamed QAudioLevel -> AudiLevel. Changed connection signal/slot style. Task-number: QTBUG-60627 Change-Id: I3538433680086a2c4ee52ee22a5180c6d824b897 Reviewed-by: Christian Stromme --- examples/multimedia/audiorecorder/audiolevel.cpp | 69 +++++++++++++++ examples/multimedia/audiorecorder/audiolevel.h | 62 ++++++++++++++ .../multimedia/audiorecorder/audiorecorder.cpp | 99 ++++++++++------------ examples/multimedia/audiorecorder/audiorecorder.h | 15 ++-- .../multimedia/audiorecorder/audiorecorder.pro | 4 +- examples/multimedia/audiorecorder/qaudiolevel.cpp | 70 --------------- examples/multimedia/audiorecorder/qaudiolevel.h | 62 -------------- 7 files changed, 184 insertions(+), 197 deletions(-) create mode 100644 examples/multimedia/audiorecorder/audiolevel.cpp create mode 100644 examples/multimedia/audiorecorder/audiolevel.h delete mode 100644 examples/multimedia/audiorecorder/qaudiolevel.cpp delete mode 100644 examples/multimedia/audiorecorder/qaudiolevel.h (limited to 'examples/multimedia') diff --git a/examples/multimedia/audiorecorder/audiolevel.cpp b/examples/multimedia/audiorecorder/audiolevel.cpp new file mode 100644 index 000000000..5df137dd8 --- /dev/null +++ b/examples/multimedia/audiorecorder/audiolevel.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#include "audiolevel.h" +#include + +AudioLevel::AudioLevel(QWidget *parent) + : QWidget(parent) +{ + setMinimumHeight(15); + setMaximumHeight(50); +} + +void AudioLevel::setLevel(qreal level) +{ + if (m_level != level) { + m_level = level; + update(); + } +} + +void AudioLevel::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + // draw level + qreal widthLevel = m_level * width(); + painter.fillRect(0, 0, widthLevel, height(), Qt::red); + // clear the rest of the control + painter.fillRect(widthLevel, 0, width(), height(), Qt::black); +} diff --git a/examples/multimedia/audiorecorder/audiolevel.h b/examples/multimedia/audiorecorder/audiolevel.h new file mode 100644 index 000000000..ba6a76d90 --- /dev/null +++ b/examples/multimedia/audiorecorder/audiolevel.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#ifndef AUDIOLEVEL_H +#define AUDIOLEVEL_H + +#include + +class AudioLevel : public QWidget +{ + Q_OBJECT +public: + explicit AudioLevel(QWidget *parent = 0); + + // Using [0; 1.0] range + void setLevel(qreal level); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + qreal m_level = 0.0; +}; + +#endif // QAUDIOLEVEL_H diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp index 2fb41584e..9495085c8 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.cpp +++ b/examples/multimedia/audiorecorder/audiorecorder.cpp @@ -38,57 +38,55 @@ ** ****************************************************************************/ +#include "audiorecorder.h" +#include "audiolevel.h" + +#include "ui_audiorecorder.h" + #include #include #include #include #include -#include "audiorecorder.h" -#include "qaudiolevel.h" - -#include "ui_audiorecorder.h" - static qreal getPeakValue(const QAudioFormat &format); static QVector getBufferLevels(const QAudioBuffer &buffer); template static QVector getBufferLevels(const T *buffer, int frames, int channels); -AudioRecorder::AudioRecorder(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::AudioRecorder), - outputLocationSet(false) +AudioRecorder::AudioRecorder() + : ui(new Ui::AudioRecorder) { ui->setupUi(this); - audioRecorder = new QAudioRecorder(this); - probe = new QAudioProbe; - connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)), - this, SLOT(processBuffer(QAudioBuffer))); - probe->setSource(audioRecorder); + m_audioRecorder = new QAudioRecorder(this); + 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())); - foreach (const QString &device, audioRecorder->audioInputs()) { + for (auto &device: m_audioRecorder->audioInputs()) { ui->audioDeviceBox->addItem(device, QVariant(device)); } //audio codecs ui->audioCodecBox->addItem(tr("Default"), QVariant(QString())); - foreach (const QString &codecName, audioRecorder->supportedAudioCodecs()) { + for (auto &codecName: m_audioRecorder->supportedAudioCodecs()) { ui->audioCodecBox->addItem(codecName, QVariant(codecName)); } //containers ui->containerBox->addItem(tr("Default"), QVariant(QString())); - foreach (const QString &containerName, audioRecorder->supportedContainers()) { + for (auto &containerName: m_audioRecorder->supportedContainers()) { ui->containerBox->addItem(containerName, QVariant(containerName)); } //sample rate ui->sampleRateBox->addItem(tr("Default"), QVariant(0)); - foreach (int sampleRate, audioRecorder->supportedAudioSampleRates()) { + for (int sampleRate: m_audioRecorder->supportedAudioSampleRates()) { ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant( sampleRate)); } @@ -110,25 +108,16 @@ AudioRecorder::AudioRecorder(QWidget *parent) : ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000)); ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000)); - connect(audioRecorder, SIGNAL(durationChanged(qint64)), this, - SLOT(updateProgress(qint64))); - connect(audioRecorder, SIGNAL(statusChanged(QMediaRecorder::Status)), this, - SLOT(updateStatus(QMediaRecorder::Status))); - connect(audioRecorder, SIGNAL(stateChanged(QMediaRecorder::State)), - this, SLOT(onStateChanged(QMediaRecorder::State))); - connect(audioRecorder, SIGNAL(error(QMediaRecorder::Error)), this, - SLOT(displayErrorMessage())); -} - -AudioRecorder::~AudioRecorder() -{ - delete audioRecorder; - delete probe; + connect(m_audioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::updateProgress); + connect(m_audioRecorder, &QAudioRecorder::statusChanged, this, &AudioRecorder::updateStatus); + connect(m_audioRecorder, &QAudioRecorder::stateChanged, this, &AudioRecorder::onStateChanged); + connect(m_audioRecorder, QOverload::of(&QAudioRecorder::error), this, + &AudioRecorder::displayErrorMessage); } void AudioRecorder::updateProgress(qint64 duration) { - if (audioRecorder->error() != QMediaRecorder::NoError || duration < 2000) + if (m_audioRecorder->error() != QMediaRecorder::NoError || duration < 2000) return; ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000)); @@ -140,7 +129,7 @@ void AudioRecorder::updateStatus(QMediaRecorder::Status status) switch (status) { case QMediaRecorder::RecordingStatus: - statusMessage = tr("Recording to %1").arg(audioRecorder->actualLocation().toString()); + statusMessage = tr("Recording to %1").arg(m_audioRecorder->actualLocation().toString()); break; case QMediaRecorder::PausedStatus: clearAudioLevels(); @@ -154,7 +143,7 @@ void AudioRecorder::updateStatus(QMediaRecorder::Status status) break; } - if (audioRecorder->error() == QMediaRecorder::NoError) + if (m_audioRecorder->error() == QMediaRecorder::NoError) ui->statusbar->showMessage(statusMessage); } @@ -175,7 +164,7 @@ void AudioRecorder::onStateChanged(QMediaRecorder::State state) break; } - ui->pauseButton->setEnabled(audioRecorder->state() != QMediaRecorder::StoppedState); + ui->pauseButton->setEnabled(m_audioRecorder->state() != QMediaRecorder::StoppedState); } static QVariant boxValue(const QComboBox *box) @@ -189,8 +178,8 @@ static QVariant boxValue(const QComboBox *box) void AudioRecorder::toggleRecord() { - if (audioRecorder->state() == QMediaRecorder::StoppedState) { - audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString()); + if (m_audioRecorder->state() == QMediaRecorder::StoppedState) { + m_audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString()); QAudioEncoderSettings settings; settings.setCodec(boxValue(ui->audioCodecBox).toString()); @@ -204,38 +193,38 @@ void AudioRecorder::toggleRecord() QString container = boxValue(ui->containerBox).toString(); - audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container); - audioRecorder->record(); + m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container); + m_audioRecorder->record(); } else { - audioRecorder->stop(); + m_audioRecorder->stop(); } } void AudioRecorder::togglePause() { - if (audioRecorder->state() != QMediaRecorder::PausedState) - audioRecorder->pause(); + if (m_audioRecorder->state() != QMediaRecorder::PausedState) + m_audioRecorder->pause(); else - audioRecorder->record(); + m_audioRecorder->record(); } void AudioRecorder::setOutputLocation() { QString fileName = QFileDialog::getSaveFileName(); - audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName)); - outputLocationSet = true; + m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName)); + m_outputLocationSet = true; } void AudioRecorder::displayErrorMessage() { - ui->statusbar->showMessage(audioRecorder->errorString()); + ui->statusbar->showMessage(m_audioRecorder->errorString()); } void AudioRecorder::clearAudioLevels() { - for (int i = 0; i < audioLevels.size(); ++i) - audioLevels.at(i)->setLevel(0); + for (int i = 0; i < m_audioLevels.size(); ++i) + m_audioLevels.at(i)->setLevel(0); } // This function returns the maximum possible sample value for a given audio format @@ -346,17 +335,17 @@ QVector getBufferLevels(const T *buffer, int frames, int channels) void AudioRecorder::processBuffer(const QAudioBuffer& buffer) { - if (audioLevels.count() != buffer.format().channelCount()) { - qDeleteAll(audioLevels); - audioLevels.clear(); + if (m_audioLevels.count() != buffer.format().channelCount()) { + qDeleteAll(m_audioLevels); + m_audioLevels.clear(); for (int i = 0; i < buffer.format().channelCount(); ++i) { - QAudioLevel *level = new QAudioLevel(ui->centralwidget); - audioLevels.append(level); + AudioLevel *level = new AudioLevel(ui->centralwidget); + m_audioLevels.append(level); ui->levelsLayout->addWidget(level); } } QVector levels = getBufferLevels(buffer); for (int i = 0; i < levels.count(); ++i) - audioLevels.at(i)->setLevel(levels.at(i)); + m_audioLevels.at(i)->setLevel(levels.at(i)); } diff --git a/examples/multimedia/audiorecorder/audiorecorder.h b/examples/multimedia/audiorecorder/audiorecorder.h index 7c8040299..9df86cac4 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.h +++ b/examples/multimedia/audiorecorder/audiorecorder.h @@ -52,15 +52,14 @@ class QAudioProbe; class QAudioBuffer; QT_END_NAMESPACE -class QAudioLevel; +class AudioLevel; class AudioRecorder : public QMainWindow { Q_OBJECT public: - AudioRecorder(QWidget *parent = 0); - ~AudioRecorder(); + AudioRecorder(); public slots: void processBuffer(const QAudioBuffer&); @@ -78,12 +77,12 @@ private slots: private: void clearAudioLevels(); - Ui::AudioRecorder *ui; + Ui::AudioRecorder *ui = nullptr; - QAudioRecorder *audioRecorder; - QAudioProbe *probe; - QList audioLevels; - bool outputLocationSet; + QAudioRecorder *m_audioRecorder = nullptr; + QAudioProbe *m_probe = nullptr; + QList m_audioLevels; + bool m_outputLocationSet = false; }; diff --git a/examples/multimedia/audiorecorder/audiorecorder.pro b/examples/multimedia/audiorecorder/audiorecorder.pro index 593c30096..65eecc7b4 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.pro +++ b/examples/multimedia/audiorecorder/audiorecorder.pro @@ -7,12 +7,12 @@ win32:INCLUDEPATH += $$PWD HEADERS = \ audiorecorder.h \ - qaudiolevel.h + audiolevel.h SOURCES = \ main.cpp \ audiorecorder.cpp \ - qaudiolevel.cpp + audiolevel.cpp FORMS += audiorecorder.ui diff --git a/examples/multimedia/audiorecorder/qaudiolevel.cpp b/examples/multimedia/audiorecorder/qaudiolevel.cpp deleted file mode 100644 index 8dd172f30..000000000 --- a/examples/multimedia/audiorecorder/qaudiolevel.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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$ -** -****************************************************************************/ - -#include "qaudiolevel.h" -#include - -QAudioLevel::QAudioLevel(QWidget *parent) - : QWidget(parent) - , m_level(0.0) -{ - setMinimumHeight(15); - setMaximumHeight(50); -} - -void QAudioLevel::setLevel(qreal level) -{ - if (m_level != level) { - m_level = level; - update(); - } -} - -void QAudioLevel::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - - QPainter painter(this); - // draw level - qreal widthLevel = m_level * width(); - painter.fillRect(0, 0, widthLevel, height(), Qt::red); - // clear the rest of the control - painter.fillRect(widthLevel, 0, width(), height(), Qt::black); -} diff --git a/examples/multimedia/audiorecorder/qaudiolevel.h b/examples/multimedia/audiorecorder/qaudiolevel.h deleted file mode 100644 index f8e563adc..000000000 --- a/examples/multimedia/audiorecorder/qaudiolevel.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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$ -** -****************************************************************************/ - -#ifndef QAUDIOLEVEL_H -#define QAUDIOLEVEL_H - -#include - -class QAudioLevel : public QWidget -{ - Q_OBJECT -public: - explicit QAudioLevel(QWidget *parent = 0); - - // Using [0; 1.0] range - void setLevel(qreal level); - -protected: - void paintEvent(QPaintEvent *event) override; - -private: - qreal m_level; -}; - -#endif // QAUDIOLEVEL_H -- cgit v1.2.3 From 951393508a5068bd999c3225158cbb06872d881c Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Wed, 20 Sep 2017 10:37:06 +0200 Subject: Modernize the Declarative Radio example Added responsive UI. Added Button type. Task-number: QTBUG-60627 Change-Id: I69d10ad735706538b31c7bf1810e90d5a884a382 Reviewed-by: Christian Stromme --- examples/multimedia/declarative-radio/Button.qml | 71 +++++++++++ .../declarative-radio/declarative-radio.qrc | 1 + examples/multimedia/declarative-radio/main.cpp | 3 +- examples/multimedia/declarative-radio/view.qml | 142 ++++++--------------- 4 files changed, 116 insertions(+), 101 deletions(-) create mode 100644 examples/multimedia/declarative-radio/Button.qml (limited to 'examples/multimedia') diff --git a/examples/multimedia/declarative-radio/Button.qml b/examples/multimedia/declarative-radio/Button.qml new file mode 100644 index 000000000..c01c9d388 --- /dev/null +++ b/examples/multimedia/declarative-radio/Button.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + id: button + border.color: "black" + border.width: 1 + radius: 5 + + property string text + signal clicked + + width: d.buttonWidth + height: d.buttonHeight + + anchors { + margins: root.margins + top: parent.top + } + + Text { + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: button.text + } + + MouseArea { + anchors.fill: parent + onClicked: button.clicked(); + } +} diff --git a/examples/multimedia/declarative-radio/declarative-radio.qrc b/examples/multimedia/declarative-radio/declarative-radio.qrc index ed01a64f6..0f7859d78 100644 --- a/examples/multimedia/declarative-radio/declarative-radio.qrc +++ b/examples/multimedia/declarative-radio/declarative-radio.qrc @@ -1,6 +1,7 @@ view.qml +Button.qml diff --git a/examples/multimedia/declarative-radio/main.cpp b/examples/multimedia/declarative-radio/main.cpp index 0dfd4d2c9..6d7771e60 100644 --- a/examples/multimedia/declarative-radio/main.cpp +++ b/examples/multimedia/declarative-radio/main.cpp @@ -50,7 +50,8 @@ int main(int argc, char ** argv) QQuickView view; - view.setSource(QUrl("qrc:view.qml")); + view.setSource(QUrl("qrc:/view.qml")); + view.setMinimumSize(QSize(400, 100)); view.show(); return app.exec(); diff --git a/examples/multimedia/declarative-radio/view.qml b/examples/multimedia/declarative-radio/view.qml index 7ab35260a..4bc3fbc4a 100644 --- a/examples/multimedia/declarative-radio/view.qml +++ b/examples/multimedia/declarative-radio/view.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** - ** Copyright (C) 2015 The Qt Company Ltd. + ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. @@ -42,7 +42,16 @@ import QtQuick 2.0 import QtMultimedia 5.0 Rectangle { - width: 400; height: 300; + anchors.fill: parent + id: root + property int margins: 5 + property int spacing: 10 + + QtObject { + id: d + property int buttonHeight: root.height > root.width ? root.width / 3 : root.height / 3 + property int buttonWidth: (root.width - spacing * 4) / 4 + } Radio { id: radio @@ -51,25 +60,30 @@ Rectangle { Column { anchors.fill: parent - anchors.margins: 5 - spacing: 5 + anchors.margins: root.margins - Row { + Rectangle { + color: root.color + width: parent.width + height: root.height - d.buttonHeight - 40 Text { id: freq - - width: 150 - height: 200 - verticalAlignment: Text.AlignVCenter text: "" + radio.frequency / 1000 + " kHz" + anchors { + bottom: parent.bottom + margins: root.margins + } } Text { id: sig + anchors { + bottom: parent.bottom + right: parent.right + margins: root.margins - width: 200 - height: 200 + } verticalAlignment: Text.AlignVCenter text: (radio.availability == Radio.Available ? "No Signal " : "No Radio Found") @@ -80,112 +94,40 @@ Rectangle { spacing: 5 Rectangle { - width: 350 - height: 10 - + width: root.width - 10 + height: 20 color: "black" Rectangle { width: 5 - height: 10 + height: 20 color: "red" y: 0 x: (parent.width - 5) * ((radio.frequency - radio.minimumFrequency) / (radio.maximumFrequency - radio.minimumFrequency)) - } } } - - Row { - spacing: 5 - - Rectangle { - id: scanDownButton - border.color: "black" - border.width: 1 - radius: 2 - - width: 90 - height: 40 - - Text { - anchors.fill: parent - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: "Scan Down" - } - - MouseArea { - anchors.fill: parent - onClicked: radio.scanDown(); - } + spacing: root.spacing + Button { + text: "Scan Down" + onClicked: radio.scanDown() } - Rectangle { - id: freqDownButton - border.color: "black" - border.width: 1 - radius: 2 - - width: 90 - height: 40 - - Text { - anchors.fill: parent - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: "Freq Down" - } - - MouseArea { - anchors.fill: parent - onClicked: radio.tuneDown(); - } + Button { + text: "Freq Down" + onClicked: radio.tuneDown() } - Rectangle { - id: freqUpButton - border.color: "black" - border.width: 1 - radius: 2 - - width: 90 - height: 40 - - Text { - anchors.fill: parent - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: "Freq Up" - } - - MouseArea { - anchors.fill: parent - onClicked: radio.tuneUp(); - } + Button { + text: "Freq Up" + onClicked: radio.tuneUp() } - Rectangle { - id: scanUpButton - border.color: "black" - border.width: 1 - radius: 2 - - width: 90 - height: 40 - - Text { - anchors.fill: parent - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - text: "Scan Up" - } - - MouseArea { - anchors.fill: parent - onClicked: radio.scanUp(); - } + Button { + text: "Scan Up" + onClicked: radio.scanUp() } } } } + -- cgit v1.2.3