diff options
104 files changed, 1831 insertions, 1361 deletions
diff --git a/.qmake.conf b/.qmake.conf index 2108ac6fd..138038d54 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.9.3 +MODULE_VERSION = 5.10.0 diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp index 7d5824f65..468dbc659 100644 --- a/examples/multimedia/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audiodevices/audiodevices.cpp @@ -98,18 +98,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<int>::of(&QComboBox::activated), this, &AudioTest::modeChanged); + connect(deviceBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::deviceChanged); + connect(sampleRateBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleRateChanged); + connect(channelsBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::channelChanged); + connect(codecsBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::codecChanged); + connect(sampleSizesBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleSizeChanged); + connect(sampleTypesBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::sampleTypeChanged); + connect(endianBox, QOverload<int>::of(&QComboBox::activated), this, &AudioTest::endianChanged); + connect(populateTableButton, &QPushButton::clicked, this, &AudioTest::populateTable); modeBox->setCurrentIndex(0); modeChanged(0); @@ -117,17 +115,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(""); @@ -136,7 +130,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())); @@ -153,15 +147,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); @@ -176,52 +164,52 @@ void AudioTest::deviceChanged(int idx) return; // device has changed - deviceInfo = deviceBox->itemData(idx).value<QAudioDeviceInfo>(); + m_deviceInfo = deviceBox->itemData(idx).value<QAudioDeviceInfo>(); sampleRateBox->clear(); - QList<int> sampleRatez = deviceInfo.supportedSampleRates(); + QList<int> 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<int> chz = deviceInfo.supportedChannelCounts(); + QList<int> 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<int> sampleSizez = deviceInfo.supportedSampleSizes(); + QList<int> 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<QAudioFormat::SampleType> sampleTypez = deviceInfo.supportedSampleTypes(); + QList<QAudioFormat::SampleType> 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<QAudioFormat::Endian> endianz = deviceInfo.supportedByteOrders(); + QList<QAudioFormat::Endian> 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(); } @@ -231,19 +219,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()); @@ -277,35 +265,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); } } @@ -313,9 +301,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 6b73b31e2..85ea828ef 100644 --- a/examples/multimedia/audiodevices/audiodevices.h +++ b/examples/multimedia/audiodevices/audiodevices.h @@ -69,12 +69,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); diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp index 3d670ed62..ec6088780 100644 --- a/examples/multimedia/audioinput/audioinput.cpp +++ b/examples/multimedia/audioinput/audioinput.cpp @@ -48,6 +48,8 @@ ** ****************************************************************************/ +#include "audioinput.h" + #include <stdlib.h> #include <math.h> @@ -59,21 +61,8 @@ #include <QAudioInput> #include <qendian.h> -#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: @@ -121,10 +110,6 @@ AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent) } } -AudioInfo::~AudioInfo() -{ -} - void AudioInfo::start() { open(QIODevice::WriteOnly); @@ -206,7 +191,6 @@ RenderArea::RenderArea(QWidget *parent) setBackgroundRole(QPalette::Base); setAutoFillBackground(true); - m_level = 0; setMinimumHeight(30); setMinimumWidth(200); } @@ -239,27 +223,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<QWidget> window(new QWidget); - QScopedPointer<QVBoxLayout> layout(new QVBoxLayout); + QWidget *window = new QWidget; + QVBoxLayout *layout = new QVBoxLayout; m_canvas = new RenderArea(this); layout->addWidget(m_canvas); @@ -267,143 +240,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<int>::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<QAudioDeviceInfo>(); - initializeAudio(); + initializeAudio(m_deviceBox->itemData(index).value<QAudioDeviceInfo>()); } 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 a57054be9..33ddd51af 100644 --- a/examples/multimedia/audioinput/audioinput.h +++ b/examples/multimedia/audioinput/audioinput.h @@ -60,14 +60,14 @@ #include <QPushButton> #include <QSlider> #include <QWidget> +#include <QScopedPointer> class AudioInfo : public QIODevice { Q_OBJECT public: - AudioInfo(const QAudioFormat &format, QObject *parent); - ~AudioInfo(); + AudioInfo(const QAudioFormat &format); void start(); void stop(); @@ -79,8 +79,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(); @@ -92,7 +92,7 @@ class RenderArea : public QWidget Q_OBJECT public: - RenderArea(QWidget *parent = 0); + explicit RenderArea(QWidget *parent = nullptr); void setLevel(qreal value); @@ -100,7 +100,7 @@ protected: void paintEvent(QPaintEvent *event) override; private: - qreal m_level; + qreal m_level = 0; QPixmap m_pixmap; }; @@ -111,16 +111,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); @@ -128,19 +124,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<AudioInfo> m_audioInfo; + QScopedPointer<QAudioInput> m_audioInput; + bool m_pullMode = true; }; #endif // AUDIOINPUT_H diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp index d469c8901..229727422 100644 --- a/examples/multimedia/audiooutput/audiooutput.cpp +++ b/examples/multimedia/audiooutput/audiooutput.cpp @@ -48,6 +48,8 @@ ** ****************************************************************************/ +#include "audiooutput.h" + #include <QAudioDeviceInfo> #include <QAudioOutput> #include <QDebug> @@ -55,36 +57,14 @@ #include <qmath.h> #include <qendian.h> -#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); @@ -100,10 +80,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 @@ -112,32 +90,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<format.channelCount(); ++i) { - if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) { - const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255); - *reinterpret_cast<quint8*>(ptr) = value; - } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) { - const qint8 value = static_cast<qint8>(x * 127); - *reinterpret_cast<quint8*>(ptr) = value; - } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) { - quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535); - if (format.byteOrder() == QAudioFormat::LittleEndian) - qToLittleEndian<quint16>(value, ptr); - else - qToBigEndian<quint16>(value, ptr); - } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) { - qint16 value = static_cast<qint16>(x * 32767); - if (format.byteOrder() == QAudioFormat::LittleEndian) - qToLittleEndian<qint16>(value, ptr); - else - qToBigEndian<qint16>(value, ptr); + if (format.sampleSize() == 8) { + if (format.sampleType() == QAudioFormat::UnSignedInt) { + const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255); + *reinterpret_cast<quint8 *>(ptr) = value; + } else if (format.sampleType() == QAudioFormat::SignedInt) { + const qint8 value = static_cast<qint8>(x * 127); + *reinterpret_cast<qint8 *>(ptr) = value; + } + } else if (format.sampleSize() == 16) { + if (format.sampleType() == QAudioFormat::UnSignedInt) { + quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian<quint16>(value, ptr); + else + qToBigEndian<quint16>(value, ptr); + } else if (format.sampleType() == QAudioFormat::SignedInt) { + qint16 value = static_cast<qint16>(x * 32767); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian<qint16>(value, ptr); + else + qToBigEndian<qint16>(value, ptr); + } } ptr += channelBytes; length -= channelBytes; } - ++sampleIndex; } } @@ -169,177 +151,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<QWidget> window(new QWidget); - QScopedPointer<QVBoxLayout> 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<int>::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<QAudioDeviceInfo>(); - initializeAudio(); + initializeAudio(m_deviceBox->itemData(index).value<QAudioDeviceInfo>()); } 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 ddfbfe7d8..c17f47727 100644 --- a/examples/multimedia/audiooutput/audiooutput.h +++ b/examples/multimedia/audiooutput/audiooutput.h @@ -63,14 +63,14 @@ #include <QPushButton> #include <QSlider> #include <QTimer> +#include <QScopedPointer> 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(); @@ -83,7 +83,7 @@ private: void generateData(const QAudioFormat &format, qint64 durationUs, int sampleRate); private: - qint64 m_pos; + qint64 m_pos = 0; QByteArray m_buffer; }; @@ -97,30 +97,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<Generator> m_generator; + QScopedPointer<QAudioOutput> m_audioOutput; + + bool m_pullMode = true; private slots: - void pushTimerExpired(); void toggleMode(); void toggleSuspendResume(); void deviceChanged(int index); diff --git a/examples/multimedia/audiorecorder/qaudiolevel.cpp b/examples/multimedia/audiorecorder/audiolevel.cpp index 9eeecad91..b13e7fbc8 100644 --- a/examples/multimedia/audiorecorder/qaudiolevel.cpp +++ b/examples/multimedia/audiorecorder/audiolevel.cpp @@ -48,18 +48,17 @@ ** ****************************************************************************/ -#include "qaudiolevel.h" +#include "audiolevel.h" #include <QPainter> -QAudioLevel::QAudioLevel(QWidget *parent) +AudioLevel::AudioLevel(QWidget *parent) : QWidget(parent) - , m_level(0.0) { setMinimumHeight(15); setMaximumHeight(50); } -void QAudioLevel::setLevel(qreal level) +void AudioLevel::setLevel(qreal level) { if (m_level != level) { m_level = level; @@ -67,7 +66,7 @@ void QAudioLevel::setLevel(qreal level) } } -void QAudioLevel::paintEvent(QPaintEvent *event) +void AudioLevel::paintEvent(QPaintEvent *event) { Q_UNUSED(event); diff --git a/examples/multimedia/audiorecorder/qaudiolevel.h b/examples/multimedia/audiorecorder/audiolevel.h index 5c8a23772..3c71264c5 100644 --- a/examples/multimedia/audiorecorder/qaudiolevel.h +++ b/examples/multimedia/audiorecorder/audiolevel.h @@ -48,16 +48,16 @@ ** ****************************************************************************/ -#ifndef QAUDIOLEVEL_H -#define QAUDIOLEVEL_H +#ifndef AUDIOLEVEL_H +#define AUDIOLEVEL_H #include <QWidget> -class QAudioLevel : public QWidget +class AudioLevel : public QWidget { Q_OBJECT public: - explicit QAudioLevel(QWidget *parent = 0); + explicit AudioLevel(QWidget *parent = 0); // Using [0; 1.0] range void setLevel(qreal level); @@ -66,7 +66,7 @@ protected: void paintEvent(QPaintEvent *event) override; private: - qreal m_level; + qreal m_level = 0.0; }; #endif // QAUDIOLEVEL_H diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp index 250d2dc16..312b2d2aa 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.cpp +++ b/examples/multimedia/audiorecorder/audiorecorder.cpp @@ -48,57 +48,55 @@ ** ****************************************************************************/ +#include "audiorecorder.h" +#include "audiolevel.h" + +#include "ui_audiorecorder.h" + #include <QAudioProbe> #include <QAudioRecorder> #include <QDir> #include <QFileDialog> #include <QMediaRecorder> -#include "audiorecorder.h" -#include "qaudiolevel.h" - -#include "ui_audiorecorder.h" - static qreal getPeakValue(const QAudioFormat &format); static QVector<qreal> getBufferLevels(const QAudioBuffer &buffer); template <class T> static QVector<qreal> 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)); } @@ -120,25 +118,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<QMediaRecorder::Error>::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)); @@ -150,7 +139,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(); @@ -164,7 +153,7 @@ void AudioRecorder::updateStatus(QMediaRecorder::Status status) break; } - if (audioRecorder->error() == QMediaRecorder::NoError) + if (m_audioRecorder->error() == QMediaRecorder::NoError) ui->statusbar->showMessage(statusMessage); } @@ -185,7 +174,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) @@ -199,8 +188,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()); @@ -214,38 +203,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 @@ -356,17 +345,17 @@ QVector<qreal> 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<qreal> 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 7d6aec115..6818dba90 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.h +++ b/examples/multimedia/audiorecorder/audiorecorder.h @@ -62,15 +62,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&); @@ -88,12 +87,12 @@ private slots: private: void clearAudioLevels(); - Ui::AudioRecorder *ui; + Ui::AudioRecorder *ui = nullptr; - QAudioRecorder *audioRecorder; - QAudioProbe *probe; - QList<QAudioLevel*> audioLevels; - bool outputLocationSet; + QAudioRecorder *m_audioRecorder = nullptr; + QAudioProbe *m_probe = nullptr; + QList<AudioLevel*> 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/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 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource> <file>view.qml</file> +<file>Button.qml</file> </qresource> </RCC> diff --git a/examples/multimedia/declarative-radio/main.cpp b/examples/multimedia/declarative-radio/main.cpp index 526cda6f4..3ed6f1950 100644 --- a/examples/multimedia/declarative-radio/main.cpp +++ b/examples/multimedia/declarative-radio/main.cpp @@ -60,7 +60,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 ef7b65d99..ab173a737 100644 --- a/examples/multimedia/declarative-radio/view.qml +++ b/examples/multimedia/declarative-radio/view.qml @@ -52,7 +52,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 @@ -61,25 +70,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") @@ -90,112 +104,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() } } } } + diff --git a/examples/multimedia/spectrum/app/engine.cpp b/examples/multimedia/spectrum/app/engine.cpp index 07e82bb4a..eb289ca6c 100644 --- a/examples/multimedia/spectrum/app/engine.cpp +++ b/examples/multimedia/spectrum/app/engine.cpp @@ -113,6 +113,23 @@ Engine::Engine(QObject *parent) this, SLOT(spectrumChanged(FrequencySpectrum))); + // This code might misinterpret things like "-something -category". But + // it's unlikely that that needs to be supported so we'll let it go. + QStringList arguments = QCoreApplication::instance()->arguments(); + for (int i = 0; i < arguments.count(); ++i) { + if (arguments.at(i) == QStringLiteral("--")) + break; + + if (arguments.at(i) == QStringLiteral("-category") + || arguments.at(i) == QStringLiteral("--category")) { + ++i; + if (i < arguments.count()) + m_audioOutputCategory = arguments.at(i); + else + --i; + } + } + initialize(); #ifdef DUMP_DATA @@ -504,6 +521,7 @@ bool Engine::initialize() } m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this); m_audioOutput->setNotifyInterval(NotifyIntervalMs); + m_audioOutput->setCategory(m_audioOutputCategory); } } else { if (m_file) @@ -518,6 +536,7 @@ bool Engine::initialize() ENGINE_DEBUG << "Engine::initialize" << "m_bufferLength" << m_bufferLength; ENGINE_DEBUG << "Engine::initialize" << "m_dataLength" << m_dataLength; ENGINE_DEBUG << "Engine::initialize" << "format" << m_format; + ENGINE_DEBUG << "Engine::initialize" << "m_audioOutputCategory" << m_audioOutputCategory; return result; } diff --git a/examples/multimedia/spectrum/app/engine.h b/examples/multimedia/spectrum/app/engine.h index 3fc1afe68..ff56d7c8b 100644 --- a/examples/multimedia/spectrum/app/engine.h +++ b/examples/multimedia/spectrum/app/engine.h @@ -297,6 +297,7 @@ private: const QList<QAudioDeviceInfo> m_availableAudioOutputDevices; QAudioDeviceInfo m_audioOutputDevice; QAudioOutput* m_audioOutput; + QString m_audioOutputCategory; qint64 m_playPosition; QBuffer m_audioOutputIODevice; diff --git a/examples/multimedia/spectrum/app/mainwidget.cpp b/examples/multimedia/spectrum/app/mainwidget.cpp index 9186320cd..6585fec94 100644 --- a/examples/multimedia/spectrum/app/mainwidget.cpp +++ b/examples/multimedia/spectrum/app/mainwidget.cpp @@ -119,7 +119,9 @@ void MainWidget::stateChanged(QAudio::Mode mode, QAudio::State state) updateButtonStates(); - if (QAudio::ActiveState != state && QAudio::SuspendedState != state) { + if (QAudio::ActiveState != state && + QAudio::SuspendedState != state && + QAudio::InterruptedState != state) { m_levelMeter->reset(); m_spectrograph->reset(); } @@ -428,7 +430,8 @@ void MainWidget::updateButtonStates() const bool playEnabled = (/*m_engine->dataLength() &&*/ (QAudio::AudioOutput != m_engine->mode() || (QAudio::ActiveState != m_engine->state() && - QAudio::IdleState != m_engine->state()))); + QAudio::IdleState != m_engine->state() && + QAudio::InterruptedState != m_engine->state()))); m_playButton->setEnabled(playEnabled); } diff --git a/examples/multimediawidgets/camera/camera.cpp b/examples/multimediawidgets/camera/camera.cpp index 4d18b0519..85fe0f0bb 100644 --- a/examples/multimediawidgets/camera/camera.cpp +++ b/examples/multimediawidgets/camera/camera.cpp @@ -66,9 +66,7 @@ Q_DECLARE_METATYPE(QCameraInfo) -Camera::Camera(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::Camera) +Camera::Camera() : ui(new Ui::Camera) { ui->setupUi(this); @@ -93,57 +91,46 @@ Camera::Camera(QWidget *parent) : setCamera(QCameraInfo::defaultCamera()); } -Camera::~Camera() -{ - delete mediaRecorder; - delete imageCapture; - delete camera; -} - void Camera::setCamera(const QCameraInfo &cameraInfo) { - delete imageCapture; - delete mediaRecorder; - delete camera; - - camera = new QCamera(cameraInfo); + m_camera.reset(new QCamera(cameraInfo)); - connect(camera, &QCamera::stateChanged, this, &Camera::updateCameraState); - connect(camera, QOverload<QCamera::Error>::of(&QCamera::error), this, &Camera::displayCameraError); + connect(m_camera.data(), &QCamera::stateChanged, this, &Camera::updateCameraState); + connect(m_camera.data(), QOverload<QCamera::Error>::of(&QCamera::error), this, &Camera::displayCameraError); - mediaRecorder = new QMediaRecorder(camera); - connect(mediaRecorder, &QMediaRecorder::stateChanged, this, &Camera::updateRecorderState); + m_mediaRecorder.reset(new QMediaRecorder(m_camera.data())); + connect(m_mediaRecorder.data(), &QMediaRecorder::stateChanged, this, &Camera::updateRecorderState); - imageCapture = new QCameraImageCapture(camera); + m_imageCapture.reset(new QCameraImageCapture(m_camera.data())); - connect(mediaRecorder, &QMediaRecorder::durationChanged, this, &Camera::updateRecordTime); - connect(mediaRecorder, QOverload<QMediaRecorder::Error>::of(&QMediaRecorder::error), + connect(m_mediaRecorder.data(), &QMediaRecorder::durationChanged, this, &Camera::updateRecordTime); + connect(m_mediaRecorder.data(), QOverload<QMediaRecorder::Error>::of(&QMediaRecorder::error), this, &Camera::displayRecorderError); - mediaRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title"))); + m_mediaRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title"))); connect(ui->exposureCompensation, &QAbstractSlider::valueChanged, this, &Camera::setExposureCompensation); - camera->setViewfinder(ui->viewfinder); + m_camera->setViewfinder(ui->viewfinder); - updateCameraState(camera->state()); - updateLockStatus(camera->lockStatus(), QCamera::UserRequest); - updateRecorderState(mediaRecorder->state()); + updateCameraState(m_camera->state()); + updateLockStatus(m_camera->lockStatus(), QCamera::UserRequest); + updateRecorderState(m_mediaRecorder->state()); - connect(imageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &Camera::readyForCapture); - connect(imageCapture, &QCameraImageCapture::imageCaptured, this, &Camera::processCapturedImage); - connect(imageCapture, &QCameraImageCapture::imageSaved, this, &Camera::imageSaved); - connect(imageCapture, QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error), + connect(m_imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, this, &Camera::readyForCapture); + connect(m_imageCapture.data(), &QCameraImageCapture::imageCaptured, this, &Camera::processCapturedImage); + connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &Camera::imageSaved); + connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error), this, &Camera::displayCaptureError); - connect(camera, QOverload<QCamera::LockStatus, QCamera::LockChangeReason>::of(&QCamera::lockStatusChanged), + connect(m_camera.data(), QOverload<QCamera::LockStatus, QCamera::LockChangeReason>::of(&QCamera::lockStatusChanged), this, &Camera::updateLockStatus); - ui->captureWidget->setTabEnabled(0, (camera->isCaptureModeSupported(QCamera::CaptureStillImage))); - ui->captureWidget->setTabEnabled(1, (camera->isCaptureModeSupported(QCamera::CaptureVideo))); + ui->captureWidget->setTabEnabled(0, (m_camera->isCaptureModeSupported(QCamera::CaptureStillImage))); + ui->captureWidget->setTabEnabled(1, (m_camera->isCaptureModeSupported(QCamera::CaptureVideo))); updateCaptureMode(); - camera->start(); + m_camera->start(); } void Camera::keyPressEvent(QKeyEvent * event) @@ -154,14 +141,14 @@ void Camera::keyPressEvent(QKeyEvent * event) switch (event->key()) { case Qt::Key_CameraFocus: displayViewfinder(); - camera->searchAndLock(); + m_camera->searchAndLock(); event->accept(); break; case Qt::Key_Camera: - if (camera->captureMode() == QCamera::CaptureStillImage) { + if (m_camera->captureMode() == QCamera::CaptureStillImage) { takeImage(); } else { - if (mediaRecorder->state() == QMediaRecorder::RecordingState) + if (m_mediaRecorder->state() == QMediaRecorder::RecordingState) stop(); else record(); @@ -180,7 +167,7 @@ void Camera::keyReleaseEvent(QKeyEvent *event) switch (event->key()) { case Qt::Key_CameraFocus: - camera->unlock(); + m_camera->unlock(); break; default: QMainWindow::keyReleaseEvent(event); @@ -189,7 +176,7 @@ void Camera::keyReleaseEvent(QKeyEvent *event) void Camera::updateRecordTime() { - QString str = QString("Recorded %1 sec").arg(mediaRecorder->duration()/1000); + QString str = QString("Recorded %1 sec").arg(m_mediaRecorder->duration()/1000); ui->statusbar->showMessage(str); } @@ -209,7 +196,7 @@ void Camera::processCapturedImage(int requestId, const QImage& img) void Camera::configureCaptureSettings() { - switch (camera->captureMode()) { + switch (m_camera->captureMode()) { case QCamera::CaptureStillImage: configureImageSettings(); break; @@ -223,68 +210,68 @@ void Camera::configureCaptureSettings() void Camera::configureVideoSettings() { - VideoSettings settingsDialog(mediaRecorder); + VideoSettings settingsDialog(m_mediaRecorder.data()); settingsDialog.setWindowFlags(settingsDialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - settingsDialog.setAudioSettings(audioSettings); - settingsDialog.setVideoSettings(videoSettings); - settingsDialog.setFormat(videoContainerFormat); + settingsDialog.setAudioSettings(m_audioSettings); + settingsDialog.setVideoSettings(m_videoSettings); + settingsDialog.setFormat(m_videoContainerFormat); if (settingsDialog.exec()) { - audioSettings = settingsDialog.audioSettings(); - videoSettings = settingsDialog.videoSettings(); - videoContainerFormat = settingsDialog.format(); - - mediaRecorder->setEncodingSettings( - audioSettings, - videoSettings, - videoContainerFormat); + m_audioSettings = settingsDialog.audioSettings(); + m_videoSettings = settingsDialog.videoSettings(); + m_videoContainerFormat = settingsDialog.format(); + + m_mediaRecorder->setEncodingSettings( + m_audioSettings, + m_videoSettings, + m_videoContainerFormat); } } void Camera::configureImageSettings() { - ImageSettings settingsDialog(imageCapture); + ImageSettings settingsDialog(m_imageCapture.data()); settingsDialog.setWindowFlags(settingsDialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - settingsDialog.setImageSettings(imageSettings); + settingsDialog.setImageSettings(m_imageSettings); if (settingsDialog.exec()) { - imageSettings = settingsDialog.imageSettings(); - imageCapture->setEncodingSettings(imageSettings); + m_imageSettings = settingsDialog.imageSettings(); + m_imageCapture->setEncodingSettings(m_imageSettings); } } void Camera::record() { - mediaRecorder->record(); + m_mediaRecorder->record(); updateRecordTime(); } void Camera::pause() { - mediaRecorder->pause(); + m_mediaRecorder->pause(); } void Camera::stop() { - mediaRecorder->stop(); + m_mediaRecorder->stop(); } void Camera::setMuted(bool muted) { - mediaRecorder->setMuted(muted); + m_mediaRecorder->setMuted(muted); } void Camera::toggleLock() { - switch (camera->lockStatus()) { + switch (m_camera->lockStatus()) { case QCamera::Searching: case QCamera::Locked: - camera->unlock(); + m_camera->unlock(); break; case QCamera::Unlocked: - camera->searchAndLock(); + m_camera->searchAndLock(); } } @@ -317,8 +304,8 @@ void Camera::updateLockStatus(QCamera::LockStatus status, QCamera::LockChangeRea void Camera::takeImage() { - isCapturingImage = true; - imageCapture->capture(); + m_isCapturingImage = true; + m_imageCapture->capture(); } void Camera::displayCaptureError(int id, const QCameraImageCapture::Error error, const QString &errorString) @@ -326,17 +313,17 @@ void Camera::displayCaptureError(int id, const QCameraImageCapture::Error error, Q_UNUSED(id); Q_UNUSED(error); QMessageBox::warning(this, tr("Image Capture Error"), errorString); - isCapturingImage = false; + m_isCapturingImage = false; } void Camera::startCamera() { - camera->start(); + m_camera->start(); } void Camera::stopCamera() { - camera->stop(); + m_camera->stop(); } void Camera::updateCaptureMode() @@ -344,8 +331,8 @@ void Camera::updateCaptureMode() int tabIndex = ui->captureWidget->currentIndex(); QCamera::CaptureModes captureMode = tabIndex == 0 ? QCamera::CaptureStillImage : QCamera::CaptureVideo; - if (camera->isCaptureModeSupported(captureMode)) - camera->setCaptureMode(captureMode); + if (m_camera->isCaptureModeSupported(captureMode)) + m_camera->setCaptureMode(captureMode); } void Camera::updateCameraState(QCamera::State state) @@ -389,17 +376,17 @@ void Camera::updateRecorderState(QMediaRecorder::State state) void Camera::setExposureCompensation(int index) { - camera->exposure()->setExposureCompensation(index*0.5); + m_camera->exposure()->setExposureCompensation(index*0.5); } void Camera::displayRecorderError() { - QMessageBox::warning(this, tr("Capture Error"), mediaRecorder->errorString()); + QMessageBox::warning(this, tr("Capture Error"), m_mediaRecorder->errorString()); } void Camera::displayCameraError() { - QMessageBox::warning(this, tr("Camera Error"), camera->errorString()); + QMessageBox::warning(this, tr("Camera Error"), m_camera->errorString()); } void Camera::updateCameraDevice(QAction *action) @@ -427,16 +414,16 @@ void Camera::imageSaved(int id, const QString &fileName) Q_UNUSED(id); ui->statusbar->showMessage(tr("Captured \"%1\"").arg(QDir::toNativeSeparators(fileName))); - isCapturingImage = false; - if (applicationExiting) + m_isCapturingImage = false; + if (m_applicationExiting) close(); } void Camera::closeEvent(QCloseEvent *event) { - if (isCapturingImage) { + if (m_isCapturingImage) { setEnabled(false); - applicationExiting = true; + m_applicationExiting = true; event->ignore(); } else { event->accept(); diff --git a/examples/multimediawidgets/camera/camera.h b/examples/multimediawidgets/camera/camera.h index 11a4d0e44..d06c770f6 100644 --- a/examples/multimediawidgets/camera/camera.h +++ b/examples/multimediawidgets/camera/camera.h @@ -54,6 +54,7 @@ #include <QCamera> #include <QCameraImageCapture> #include <QMediaRecorder> +#include <QScopedPointer> #include <QMainWindow> @@ -66,8 +67,7 @@ class Camera : public QMainWindow Q_OBJECT public: - explicit Camera(QWidget *parent = nullptr); - ~Camera(); + Camera(); private slots: void setCamera(const QCameraInfo &cameraInfo); @@ -117,16 +117,16 @@ protected: private: Ui::Camera *ui; - QCamera *camera = nullptr; - QCameraImageCapture *imageCapture = nullptr; - QMediaRecorder* mediaRecorder = nullptr; + QScopedPointer<QCamera> m_camera; + QScopedPointer<QCameraImageCapture> m_imageCapture; + QScopedPointer<QMediaRecorder> m_mediaRecorder; - QImageEncoderSettings imageSettings; - QAudioEncoderSettings audioSettings; - QVideoEncoderSettings videoSettings; - QString videoContainerFormat; - bool isCapturingImage = false; - bool applicationExiting = false; + QImageEncoderSettings m_imageSettings; + QAudioEncoderSettings m_audioSettings; + QVideoEncoderSettings m_videoSettings; + QString m_videoContainerFormat; + bool m_isCapturingImage = false; + bool m_applicationExiting = false; }; #endif diff --git a/examples/multimediawidgets/player/histogramwidget.cpp b/examples/multimediawidgets/player/histogramwidget.cpp index a7bc83757..a0de8516a 100644 --- a/examples/multimediawidgets/player/histogramwidget.cpp +++ b/examples/multimediawidgets/player/histogramwidget.cpp @@ -59,7 +59,7 @@ class QAudioLevel : public QWidget { Q_OBJECT public: - explicit QAudioLevel(QWidget *parent = 0); + explicit QAudioLevel(QWidget *parent = nullptr); // Using [0; 1.0] range void setLevel(qreal level); @@ -68,12 +68,11 @@ protected: void paintEvent(QPaintEvent *event); private: - qreal m_level; + qreal m_level = 0; }; QAudioLevel::QAudioLevel(QWidget *parent) - : QWidget(parent) - , m_level(0.0) + : QWidget(parent) { setMinimumHeight(15); setMaximumHeight(50); @@ -101,12 +100,10 @@ void QAudioLevel::paintEvent(QPaintEvent *event) HistogramWidget::HistogramWidget(QWidget *parent) : QWidget(parent) - , m_levels(128) - , m_isBusy(false) { m_processor.moveToThread(&m_processorThread); - qRegisterMetaType<QVector<qreal> >("QVector<qreal>"); - connect(&m_processor, SIGNAL(histogramReady(QVector<qreal>)), SLOT(setHistogram(QVector<qreal>))); + qRegisterMetaType<QVector<qreal>>("QVector<qreal>"); + connect(&m_processor, &FrameProcessor::histogramReady, this, &HistogramWidget::setHistogram); m_processorThread.start(QThread::LowestPriority); setLayout(new QHBoxLayout); } @@ -117,7 +114,7 @@ HistogramWidget::~HistogramWidget() m_processorThread.wait(10000); } -void HistogramWidget::processFrame(QVideoFrame frame) +void HistogramWidget::processFrame(const QVideoFrame &frame) { if (m_isBusy && frame.isValid()) return; //drop frame @@ -236,24 +233,24 @@ QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels) return max_values; } -void HistogramWidget::processBuffer(QAudioBuffer buffer) +void HistogramWidget::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(this); - audioLevels.append(level); + m_audioLevels.append(level); layout()->addWidget(level); } } QVector<qreal> 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)); } -void HistogramWidget::setHistogram(QVector<qreal> histogram) +void HistogramWidget::setHistogram(const QVector<qreal> &histogram) { m_isBusy = false; m_histogram = histogram; @@ -264,7 +261,7 @@ void HistogramWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); - if (!audioLevels.isEmpty()) + if (!m_audioLevels.isEmpty()) return; QPainter painter(this); @@ -276,7 +273,7 @@ void HistogramWidget::paintEvent(QPaintEvent *event) qreal barWidth = width() / (qreal)m_histogram.size(); - for (int i = 0; i < m_histogram.size(); i++) { + for (int i = 0; i < m_histogram.size(); ++i) { qreal h = m_histogram[i] * height(); // draw level painter.fillRect(barWidth * i, height() - h, barWidth * (i + 1), height(), Qt::red); @@ -300,7 +297,7 @@ void FrameProcessor::processFrame(QVideoFrame frame, int levels) frame.pixelFormat() == QVideoFrame::Format_NV12) { // Process YUV data uchar *b = frame.bits(); - for (int y = 0; y < frame.height(); y++) { + for (int y = 0; y < frame.height(); ++y) { uchar *lastPixel = b + frame.width(); for (uchar *curPixel = b; curPixel < lastPixel; curPixel++) histogram[(*curPixel * levels) >> 8] += 1.0; @@ -314,7 +311,7 @@ void FrameProcessor::processFrame(QVideoFrame frame, int levels) image = image.convertToFormat(QImage::Format_RGB32); const QRgb* b = (const QRgb*)image.bits(); - for (int y = 0; y < image.height(); y++) { + for (int y = 0; y < image.height(); ++y) { const QRgb *lastPixel = b + frame.width(); for (const QRgb *curPixel = b; curPixel < lastPixel; curPixel++) histogram[(qGray(*curPixel) * levels) >> 8] += 1.0; diff --git a/examples/multimediawidgets/player/histogramwidget.h b/examples/multimediawidgets/player/histogramwidget.h index a130477f8..a5c697dfb 100644 --- a/examples/multimediawidgets/player/histogramwidget.h +++ b/examples/multimediawidgets/player/histogramwidget.h @@ -66,7 +66,7 @@ public slots: void processFrame(QVideoFrame frame, int levels); signals: - void histogramReady(QVector<qreal> histogram); + void histogramReady(const QVector<qreal> &histogram); }; class HistogramWidget : public QWidget @@ -74,25 +74,25 @@ class HistogramWidget : public QWidget Q_OBJECT public: - explicit HistogramWidget(QWidget *parent = 0); + explicit HistogramWidget(QWidget *parent = nullptr); ~HistogramWidget(); void setLevels(int levels) { m_levels = levels; } public slots: - void processFrame(QVideoFrame frame); - void processBuffer(QAudioBuffer buffer); - void setHistogram(QVector<qreal> histogram); + void processFrame(const QVideoFrame &frame); + void processBuffer(const QAudioBuffer &buffer); + void setHistogram(const QVector<qreal> &histogram); protected: void paintEvent(QPaintEvent *event) override; private: QVector<qreal> m_histogram; - int m_levels; + int m_levels = 128; FrameProcessor m_processor; QThread m_processorThread; - bool m_isBusy; - QVector<QAudioLevel *> audioLevels; + bool m_isBusy = false; + QVector<QAudioLevel *> m_audioLevels; }; #endif // HISTOGRAMWIDGET_H diff --git a/examples/multimediawidgets/player/main.cpp b/examples/multimediawidgets/player/main.cpp index f936fe09d..9e6d9358c 100644 --- a/examples/multimediawidgets/player/main.cpp +++ b/examples/multimediawidgets/player/main.cpp @@ -73,16 +73,11 @@ int main(int argc, char *argv[]) if (!parser.positionalArguments().isEmpty() && player.isPlayerAvailable()) { QList<QUrl> urls; - foreach (const QString &a, parser.positionalArguments()) + for (auto &a: parser.positionalArguments()) urls.append(QUrl::fromUserInput(a, QDir::currentPath(), QUrl::AssumeLocalFile)); player.addToPlaylist(urls); } -#if defined(Q_WS_SIMULATOR) - player.setAttribute(Qt::WA_LockLandscapeOrientation); - player.showMaximized(); -#else player.show(); -#endif return app.exec(); } diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp index 5c30b7906..8113df70e 100644 --- a/examples/multimediawidgets/player/player.cpp +++ b/examples/multimediawidgets/player/player.cpp @@ -53,6 +53,7 @@ #include "playercontrols.h" #include "playlistmodel.h" #include "histogramwidget.h" +#include "videowidget.h" #include <QMediaService> #include <QMediaPlaylist> @@ -63,101 +64,98 @@ Player::Player(QWidget *parent) : QWidget(parent) - , videoWidget(0) - , coverLabel(0) - , slider(0) - , colorDialog(0) { //! [create-objs] - player = new QMediaPlayer(this); + m_player = new QMediaPlayer(this); + m_player->setAudioRole(QAudio::VideoRole); + qInfo() << "Supported audio roles:"; + for (QAudio::Role role : m_player->supportedAudioRoles()) + qInfo() << " " << role; // owned by PlaylistModel - playlist = new QMediaPlaylist(); - player->setPlaylist(playlist); + m_playlist = new QMediaPlaylist(); + m_player->setPlaylist(m_playlist); //! [create-objs] - connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64))); - connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64))); - connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged())); - connect(playlist, SIGNAL(currentIndexChanged(int)), SLOT(playlistPositionChanged(int))); - connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), - this, SLOT(statusChanged(QMediaPlayer::MediaStatus))); - connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int))); - connect(player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(videoAvailableChanged(bool))); - connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(displayErrorMessage())); - connect(player, &QMediaPlayer::stateChanged, this, &Player::stateChanged); + connect(m_player, &QMediaPlayer::durationChanged, this, &Player::durationChanged); + connect(m_player, &QMediaPlayer::positionChanged, this, &Player::positionChanged); + connect(m_player, QOverload<>::of(&QMediaPlayer::metaDataChanged), this, &Player::metaDataChanged); + connect(m_playlist, &QMediaPlaylist::currentIndexChanged, this, &Player::playlistPositionChanged); + connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &Player::statusChanged); + connect(m_player, &QMediaPlayer::bufferStatusChanged, this, &Player::bufferingProgress); + connect(m_player, &QMediaPlayer::videoAvailableChanged, this, &Player::videoAvailableChanged); + connect(m_player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, &Player::displayErrorMessage); + connect(m_player, &QMediaPlayer::stateChanged, this, &Player::stateChanged); //! [2] - videoWidget = new VideoWidget(this); - player->setVideoOutput(videoWidget); + m_videoWidget = new VideoWidget(this); + m_player->setVideoOutput(m_videoWidget); - playlistModel = new PlaylistModel(this); - playlistModel->setPlaylist(playlist); + m_playlistModel = new PlaylistModel(this); + m_playlistModel->setPlaylist(m_playlist); //! [2] - playlistView = new QListView(this); - playlistView->setModel(playlistModel); - playlistView->setCurrentIndex(playlistModel->index(playlist->currentIndex(), 0)); + m_playlistView = new QListView(this); + m_playlistView->setModel(m_playlistModel); + m_playlistView->setCurrentIndex(m_playlistModel->index(m_playlist->currentIndex(), 0)); - connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex))); + connect(m_playlistView, &QAbstractItemView::activated, this, &Player::jump); - slider = new QSlider(Qt::Horizontal, this); - slider->setRange(0, player->duration() / 1000); + m_slider = new QSlider(Qt::Horizontal, this); + m_slider->setRange(0, m_player->duration() / 1000); - labelDuration = new QLabel(this); - connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int))); + m_labelDuration = new QLabel(this); + connect(m_slider, &QSlider::sliderMoved, this, &Player::seek); - labelHistogram = new QLabel(this); - labelHistogram->setText("Histogram:"); - videoHistogram = new HistogramWidget(this); - audioHistogram = new HistogramWidget(this); + m_labelHistogram = new QLabel(this); + m_labelHistogram->setText("Histogram:"); + m_videoHistogram = new HistogramWidget(this); + m_audioHistogram = new HistogramWidget(this); QHBoxLayout *histogramLayout = new QHBoxLayout; - histogramLayout->addWidget(labelHistogram); - histogramLayout->addWidget(videoHistogram, 1); - histogramLayout->addWidget(audioHistogram, 2); + histogramLayout->addWidget(m_labelHistogram); + histogramLayout->addWidget(m_videoHistogram, 1); + histogramLayout->addWidget(m_audioHistogram, 2); - videoProbe = new QVideoProbe(this); - connect(videoProbe, SIGNAL(videoFrameProbed(QVideoFrame)), videoHistogram, SLOT(processFrame(QVideoFrame))); - videoProbe->setSource(player); + m_videoProbe = new QVideoProbe(this); + connect(m_videoProbe, &QVideoProbe::videoFrameProbed, m_videoHistogram, &HistogramWidget::processFrame); + m_videoProbe->setSource(m_player); - audioProbe = new QAudioProbe(this); - connect(audioProbe, SIGNAL(audioBufferProbed(QAudioBuffer)), audioHistogram, SLOT(processBuffer(QAudioBuffer))); - audioProbe->setSource(player); + m_audioProbe = new QAudioProbe(this); + connect(m_audioProbe, &QAudioProbe::audioBufferProbed, m_audioHistogram, &HistogramWidget::processBuffer); + m_audioProbe->setSource(m_player); QPushButton *openButton = new QPushButton(tr("Open"), this); - connect(openButton, SIGNAL(clicked()), this, SLOT(open())); + connect(openButton, &QPushButton::clicked, this, &Player::open); PlayerControls *controls = new PlayerControls(this); - controls->setState(player->state()); - controls->setVolume(player->volume()); + controls->setState(m_player->state()); + controls->setVolume(m_player->volume()); controls->setMuted(controls->isMuted()); - connect(controls, SIGNAL(play()), player, SLOT(play())); - connect(controls, SIGNAL(pause()), player, SLOT(pause())); - connect(controls, SIGNAL(stop()), player, SLOT(stop())); - connect(controls, SIGNAL(next()), playlist, SLOT(next())); - connect(controls, SIGNAL(previous()), this, SLOT(previousClicked())); - connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int))); - connect(controls, SIGNAL(changeMuting(bool)), player, SLOT(setMuted(bool))); - connect(controls, SIGNAL(changeRate(qreal)), player, SLOT(setPlaybackRate(qreal))); + connect(controls, &PlayerControls::play, m_player, &QMediaPlayer::play); + connect(controls, &PlayerControls::pause, m_player, &QMediaPlayer::pause); + connect(controls, &PlayerControls::stop, m_player, &QMediaPlayer::stop); + connect(controls, &PlayerControls::next, m_playlist, &QMediaPlaylist::next); + connect(controls, &PlayerControls::previous, this, &Player::previousClicked); + connect(controls, &PlayerControls::changeVolume, m_player, &QMediaPlayer::setVolume); + connect(controls, &PlayerControls::changeMuting, m_player, &QMediaPlayer::setMuted); + connect(controls, &PlayerControls::changeRate, m_player, &QMediaPlayer::setPlaybackRate); + connect(controls, &PlayerControls::stop, m_videoWidget, QOverload<>::of(&QVideoWidget::update)); - connect(controls, SIGNAL(stop()), videoWidget, SLOT(update())); + connect(m_player, &QMediaPlayer::stateChanged, controls, &PlayerControls::setState); + connect(m_player, &QMediaPlayer::volumeChanged, controls, &PlayerControls::setVolume); + connect(m_player, &QMediaPlayer::mutedChanged, controls, &PlayerControls::setMuted); - connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), - controls, SLOT(setState(QMediaPlayer::State))); - connect(player, SIGNAL(volumeChanged(int)), controls, SLOT(setVolume(int))); - connect(player, SIGNAL(mutedChanged(bool)), controls, SLOT(setMuted(bool))); + m_fullScreenButton = new QPushButton(tr("FullScreen"), this); + m_fullScreenButton->setCheckable(true); - fullScreenButton = new QPushButton(tr("FullScreen"), this); - fullScreenButton->setCheckable(true); - - colorButton = new QPushButton(tr("Color Options..."), this); - colorButton->setEnabled(false); - connect(colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog())); + m_colorButton = new QPushButton(tr("Color Options..."), this); + m_colorButton->setEnabled(false); + connect(m_colorButton, &QPushButton::clicked, this, &Player::showColorDialog); QBoxLayout *displayLayout = new QHBoxLayout; - displayLayout->addWidget(videoWidget, 2); - displayLayout->addWidget(playlistView); + displayLayout->addWidget(m_videoWidget, 2); + displayLayout->addWidget(m_playlistView); QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); @@ -165,14 +163,14 @@ Player::Player(QWidget *parent) controlLayout->addStretch(1); controlLayout->addWidget(controls); controlLayout->addStretch(1); - controlLayout->addWidget(fullScreenButton); - controlLayout->addWidget(colorButton); + controlLayout->addWidget(m_fullScreenButton); + controlLayout->addWidget(m_colorButton); QBoxLayout *layout = new QVBoxLayout; layout->addLayout(displayLayout); QHBoxLayout *hLayout = new QHBoxLayout; - hLayout->addWidget(slider); - hLayout->addWidget(labelDuration); + hLayout->addWidget(m_slider); + hLayout->addWidget(m_labelDuration); layout->addLayout(hLayout); layout->addLayout(controlLayout); layout->addLayout(histogramLayout); @@ -185,10 +183,10 @@ Player::Player(QWidget *parent) "Please check the media service plugins are installed.")); controls->setEnabled(false); - playlistView->setEnabled(false); + m_playlistView->setEnabled(false); openButton->setEnabled(false); - colorButton->setEnabled(false); - fullScreenButton->setEnabled(false); + m_colorButton->setEnabled(false); + m_fullScreenButton->setEnabled(false); } metaDataChanged(); @@ -200,7 +198,7 @@ Player::~Player() bool Player::isPlayerAvailable() const { - return player->isAvailable(); + return m_player->isAvailable(); } void Player::open() @@ -208,7 +206,7 @@ void Player::open() QFileDialog fileDialog(this); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setWindowTitle(tr("Open Files")); - QStringList supportedMimeTypes = player->supportedMimeTypes(); + QStringList supportedMimeTypes = m_player->supportedMimeTypes(); if (!supportedMimeTypes.isEmpty()) { supportedMimeTypes.append("audio/x-m3u"); // MP3 playlists fileDialog.setMimeTypeFilters(supportedMimeTypes); @@ -226,41 +224,41 @@ static bool isPlaylist(const QUrl &url) // Check for ".m3u" playlists. return fileInfo.exists() && !fileInfo.suffix().compare(QLatin1String("m3u"), Qt::CaseInsensitive); } -void Player::addToPlaylist(const QList<QUrl> urls) +void Player::addToPlaylist(const QList<QUrl> &urls) { - foreach (const QUrl &url, urls) { + for (auto &url: urls) { if (isPlaylist(url)) - playlist->load(url); + m_playlist->load(url); else - playlist->addMedia(url); + m_playlist->addMedia(url); } } void Player::durationChanged(qint64 duration) { - this->duration = duration/1000; - slider->setMaximum(duration / 1000); + m_duration = duration / 1000; + m_slider->setMaximum(m_duration); } void Player::positionChanged(qint64 progress) { - if (!slider->isSliderDown()) { - slider->setValue(progress / 1000); - } + if (!m_slider->isSliderDown()) + m_slider->setValue(progress / 1000); + updateDurationInfo(progress / 1000); } void Player::metaDataChanged() { - if (player->isMetaDataAvailable()) { + if (m_player->isMetaDataAvailable()) { setTrackInfo(QString("%1 - %2") - .arg(player->metaData(QMediaMetaData::AlbumArtist).toString()) - .arg(player->metaData(QMediaMetaData::Title).toString())); + .arg(m_player->metaData(QMediaMetaData::AlbumArtist).toString()) + .arg(m_player->metaData(QMediaMetaData::Title).toString())); - if (coverLabel) { - QUrl url = player->metaData(QMediaMetaData::CoverArtUrlLarge).value<QUrl>(); + if (m_coverLabel) { + QUrl url = m_player->metaData(QMediaMetaData::CoverArtUrlLarge).value<QUrl>(); - coverLabel->setPixmap(!url.isEmpty() + m_coverLabel->setPixmap(!url.isEmpty() ? QPixmap(url.toString()) : QPixmap()); } @@ -271,29 +269,29 @@ void Player::previousClicked() { // Go to previous track if we are within the first 5 seconds of playback // Otherwise, seek to the beginning. - if(player->position() <= 5000) - playlist->previous(); + if (m_player->position() <= 5000) + m_playlist->previous(); else - player->setPosition(0); + m_player->setPosition(0); } void Player::jump(const QModelIndex &index) { if (index.isValid()) { - playlist->setCurrentIndex(index.row()); - player->play(); + m_playlist->setCurrentIndex(index.row()); + m_player->play(); } } void Player::playlistPositionChanged(int currentItem) { clearHistogram(); - playlistView->setCurrentIndex(playlistModel->index(currentItem, 0)); + m_playlistView->setCurrentIndex(m_playlistModel->index(currentItem, 0)); } void Player::seek(int seconds) { - player->setPosition(seconds * 1000); + m_player->setPosition(seconds * 1000); } void Player::statusChanged(QMediaPlayer::MediaStatus status) @@ -350,86 +348,84 @@ void Player::bufferingProgress(int progress) void Player::videoAvailableChanged(bool available) { if (!available) { - disconnect(fullScreenButton, SIGNAL(clicked(bool)), - videoWidget, SLOT(setFullScreen(bool))); - disconnect(videoWidget, SIGNAL(fullScreenChanged(bool)), - fullScreenButton, SLOT(setChecked(bool))); - videoWidget->setFullScreen(false); + disconnect(m_fullScreenButton, &QPushButton::clicked, m_videoWidget, &QVideoWidget::setFullScreen); + disconnect(m_videoWidget, &QVideoWidget::fullScreenChanged, m_fullScreenButton, &QPushButton::setChecked); + m_videoWidget->setFullScreen(false); } else { - connect(fullScreenButton, SIGNAL(clicked(bool)), - videoWidget, SLOT(setFullScreen(bool))); - connect(videoWidget, SIGNAL(fullScreenChanged(bool)), - fullScreenButton, SLOT(setChecked(bool))); + connect(m_fullScreenButton, &QPushButton::clicked, m_videoWidget, &QVideoWidget::setFullScreen); + connect(m_videoWidget, &QVideoWidget::fullScreenChanged, m_fullScreenButton, &QPushButton::setChecked); - if (fullScreenButton->isChecked()) - videoWidget->setFullScreen(true); + if (m_fullScreenButton->isChecked()) + m_videoWidget->setFullScreen(true); } - colorButton->setEnabled(available); + m_colorButton->setEnabled(available); } void Player::setTrackInfo(const QString &info) { - trackInfo = info; - if (!statusInfo.isEmpty()) - setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo)); + m_trackInfo = info; + if (!m_statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); else - setWindowTitle(trackInfo); + setWindowTitle(m_trackInfo); } void Player::setStatusInfo(const QString &info) { - statusInfo = info; - if (!statusInfo.isEmpty()) - setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo)); + m_statusInfo = info; + if (!m_statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); else - setWindowTitle(trackInfo); + setWindowTitle(m_trackInfo); } void Player::displayErrorMessage() { - setStatusInfo(player->errorString()); + setStatusInfo(m_player->errorString()); } void Player::updateDurationInfo(qint64 currentInfo) { QString tStr; - if (currentInfo || duration) { - QTime currentTime((currentInfo/3600)%60, (currentInfo/60)%60, currentInfo%60, (currentInfo*1000)%1000); - QTime totalTime((duration/3600)%60, (duration/60)%60, duration%60, (duration*1000)%1000); + if (currentInfo || m_duration) { + QTime currentTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60, + currentInfo % 60, (currentInfo * 1000) % 1000); + QTime totalTime((m_duration / 3600) % 60, (m_duration / 60) % 60, + m_duration % 60, (m_duration * 1000) % 1000); QString format = "mm:ss"; - if (duration > 3600) + if (m_duration > 3600) format = "hh:mm:ss"; tStr = currentTime.toString(format) + " / " + totalTime.toString(format); } - labelDuration->setText(tStr); + m_labelDuration->setText(tStr); } void Player::showColorDialog() { - if (!colorDialog) { + if (!m_colorDialog) { QSlider *brightnessSlider = new QSlider(Qt::Horizontal); brightnessSlider->setRange(-100, 100); - brightnessSlider->setValue(videoWidget->brightness()); - connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setBrightness(int))); - connect(videoWidget, SIGNAL(brightnessChanged(int)), brightnessSlider, SLOT(setValue(int))); + brightnessSlider->setValue(m_videoWidget->brightness()); + connect(brightnessSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setBrightness); + connect(m_videoWidget, &QVideoWidget::brightnessChanged, brightnessSlider, &QSlider::setValue); QSlider *contrastSlider = new QSlider(Qt::Horizontal); contrastSlider->setRange(-100, 100); - contrastSlider->setValue(videoWidget->contrast()); - connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setContrast(int))); - connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider, SLOT(setValue(int))); + contrastSlider->setValue(m_videoWidget->contrast()); + connect(contrastSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setContrast); + connect(m_videoWidget, &QVideoWidget::contrastChanged, contrastSlider, &QSlider::setValue); QSlider *hueSlider = new QSlider(Qt::Horizontal); hueSlider->setRange(-100, 100); - hueSlider->setValue(videoWidget->hue()); - connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setHue(int))); - connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider, SLOT(setValue(int))); + hueSlider->setValue(m_videoWidget->hue()); + connect(hueSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setHue); + connect(m_videoWidget, &QVideoWidget::hueChanged, hueSlider, &QSlider::setValue); QSlider *saturationSlider = new QSlider(Qt::Horizontal); saturationSlider->setRange(-100, 100); - saturationSlider->setValue(videoWidget->saturation()); - connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setSaturation(int))); - connect(videoWidget, SIGNAL(saturationChanged(int)), saturationSlider, SLOT(setValue(int))); + saturationSlider->setValue(m_videoWidget->saturation()); + connect(saturationSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setSaturation); + connect(m_videoWidget, &QVideoWidget::saturationChanged, saturationSlider, &QSlider::setValue); QFormLayout *layout = new QFormLayout; layout->addRow(tr("Brightness"), brightnessSlider); @@ -440,17 +436,17 @@ void Player::showColorDialog() QPushButton *button = new QPushButton(tr("Close")); layout->addRow(button); - colorDialog = new QDialog(this); - colorDialog->setWindowTitle(tr("Color Options")); - colorDialog->setLayout(layout); + m_colorDialog = new QDialog(this); + m_colorDialog->setWindowTitle(tr("Color Options")); + m_colorDialog->setLayout(layout); - connect(button, SIGNAL(clicked()), colorDialog, SLOT(close())); + connect(button, &QPushButton::clicked, m_colorDialog, &QDialog::close); } - colorDialog->show(); + m_colorDialog->show(); } void Player::clearHistogram() { - QMetaObject::invokeMethod(videoHistogram, "processFrame", Qt::QueuedConnection, Q_ARG(QVideoFrame, QVideoFrame())); - QMetaObject::invokeMethod(audioHistogram, "processBuffer", Qt::QueuedConnection, Q_ARG(QAudioBuffer, QAudioBuffer())); + QMetaObject::invokeMethod(m_videoHistogram, "processFrame", Qt::QueuedConnection, Q_ARG(QVideoFrame, QVideoFrame())); + QMetaObject::invokeMethod(m_audioHistogram, "processBuffer", Qt::QueuedConnection, Q_ARG(QAudioBuffer, QAudioBuffer())); } diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h index a13c9dbc4..1b30204f9 100644 --- a/examples/multimediawidgets/player/player.h +++ b/examples/multimediawidgets/player/player.h @@ -51,8 +51,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "videowidget.h" - #include <QWidget> #include <QMediaPlayer> #include <QMediaPlaylist> @@ -77,12 +75,12 @@ class Player : public QWidget Q_OBJECT public: - Player(QWidget *parent = 0); + explicit Player(QWidget *parent = nullptr); ~Player(); bool isPlayerAvailable() const; - void addToPlaylist(const QList<QUrl> urls); + void addToPlaylist(const QList<QUrl> &urls); signals: void fullScreenChanged(bool fullScreen); @@ -115,27 +113,27 @@ private: void handleCursor(QMediaPlayer::MediaStatus status); void updateDurationInfo(qint64 currentInfo); - QMediaPlayer *player; - QMediaPlaylist *playlist; - VideoWidget *videoWidget; - QLabel *coverLabel; - QSlider *slider; - QLabel *labelDuration; - QPushButton *fullScreenButton; - QPushButton *colorButton; - QDialog *colorDialog; - - QLabel *labelHistogram; - HistogramWidget *videoHistogram; - HistogramWidget *audioHistogram; - QVideoProbe *videoProbe; - QAudioProbe *audioProbe; - - PlaylistModel *playlistModel; - QAbstractItemView *playlistView; - QString trackInfo; - QString statusInfo; - qint64 duration; + QMediaPlayer *m_player = nullptr; + QMediaPlaylist *m_playlist = nullptr; + QVideoWidget *m_videoWidget = nullptr; + QLabel *m_coverLabel = nullptr; + QSlider *m_slider = nullptr; + QLabel *m_labelDuration = nullptr; + QPushButton *m_fullScreenButton = nullptr; + QPushButton *m_colorButton = nullptr; + QDialog *m_colorDialog = nullptr; + + QLabel *m_labelHistogram = nullptr; + HistogramWidget *m_videoHistogram = nullptr; + HistogramWidget *m_audioHistogram = nullptr; + QVideoProbe *m_videoProbe = nullptr; + QAudioProbe *m_audioProbe = nullptr; + + PlaylistModel *m_playlistModel = nullptr; + QAbstractItemView *m_playlistView = nullptr; + QString m_trackInfo; + QString m_statusInfo; + qint64 m_duration; }; #endif // PLAYER_H diff --git a/examples/multimediawidgets/player/playercontrols.cpp b/examples/multimediawidgets/player/playercontrols.cpp index e91f09460..2a1869b93 100644 --- a/examples/multimediawidgets/player/playercontrols.cpp +++ b/examples/multimediawidgets/player/playercontrols.cpp @@ -59,89 +59,80 @@ PlayerControls::PlayerControls(QWidget *parent) : QWidget(parent) - , playerState(QMediaPlayer::StoppedState) - , playerMuted(false) - , playButton(0) - , stopButton(0) - , nextButton(0) - , previousButton(0) - , muteButton(0) - , volumeSlider(0) - , rateBox(0) { - playButton = new QToolButton(this); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_playButton = new QToolButton(this); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); - connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked())); + connect(m_playButton, &QAbstractButton::clicked, this, &PlayerControls::playClicked); - stopButton = new QToolButton(this); - stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); - stopButton->setEnabled(false); + m_stopButton = new QToolButton(this); + m_stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); + m_stopButton->setEnabled(false); - connect(stopButton, SIGNAL(clicked()), this, SIGNAL(stop())); + connect(m_stopButton, &QAbstractButton::clicked, this, &PlayerControls::stop); - nextButton = new QToolButton(this); - nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward)); + m_nextButton = new QToolButton(this); + m_nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward)); - connect(nextButton, SIGNAL(clicked()), this, SIGNAL(next())); + connect(m_nextButton, &QAbstractButton::clicked, this, &PlayerControls::next); - previousButton = new QToolButton(this); - previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward)); + m_previousButton = new QToolButton(this); + m_previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward)); - connect(previousButton, SIGNAL(clicked()), this, SIGNAL(previous())); + connect(m_previousButton, &QAbstractButton::clicked, this, &PlayerControls::previous); - muteButton = new QToolButton(this); - muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume)); + m_muteButton = new QToolButton(this); + m_muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume)); - connect(muteButton, SIGNAL(clicked()), this, SLOT(muteClicked())); + connect(m_muteButton, &QAbstractButton::clicked, this, &PlayerControls::muteClicked); - volumeSlider = new QSlider(Qt::Horizontal, this); - volumeSlider->setRange(0, 100); + m_volumeSlider = new QSlider(Qt::Horizontal, this); + m_volumeSlider->setRange(0, 100); - connect(volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(onVolumeSliderValueChanged())); + connect(m_volumeSlider, &QSlider::valueChanged, this, &PlayerControls::onVolumeSliderValueChanged); - rateBox = new QComboBox(this); - rateBox->addItem("0.5x", QVariant(0.5)); - rateBox->addItem("1.0x", QVariant(1.0)); - rateBox->addItem("2.0x", QVariant(2.0)); - rateBox->setCurrentIndex(1); + m_rateBox = new QComboBox(this); + m_rateBox->addItem("0.5x", QVariant(0.5)); + m_rateBox->addItem("1.0x", QVariant(1.0)); + m_rateBox->addItem("2.0x", QVariant(2.0)); + m_rateBox->setCurrentIndex(1); - connect(rateBox, SIGNAL(activated(int)), SLOT(updateRate())); + connect(m_rateBox, QOverload<int>::of(&QComboBox::activated), this, &PlayerControls::updateRate); QBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); - layout->addWidget(stopButton); - layout->addWidget(previousButton); - layout->addWidget(playButton); - layout->addWidget(nextButton); - layout->addWidget(muteButton); - layout->addWidget(volumeSlider); - layout->addWidget(rateBox); + layout->addWidget(m_stopButton); + layout->addWidget(m_previousButton); + layout->addWidget(m_playButton); + layout->addWidget(m_nextButton); + layout->addWidget(m_muteButton); + layout->addWidget(m_volumeSlider); + layout->addWidget(m_rateBox); setLayout(layout); } QMediaPlayer::State PlayerControls::state() const { - return playerState; + return m_playerState; } void PlayerControls::setState(QMediaPlayer::State state) { - if (state != playerState) { - playerState = state; + if (state != m_playerState) { + m_playerState = state; switch (state) { case QMediaPlayer::StoppedState: - stopButton->setEnabled(false); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_stopButton->setEnabled(false); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); break; case QMediaPlayer::PlayingState: - stopButton->setEnabled(true); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + m_stopButton->setEnabled(true); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); break; case QMediaPlayer::PausedState: - stopButton->setEnabled(true); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_stopButton->setEnabled(true); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); break; } } @@ -149,7 +140,7 @@ void PlayerControls::setState(QMediaPlayer::State state) int PlayerControls::volume() const { - qreal linearVolume = QAudio::convertVolume(volumeSlider->value() / qreal(100), + qreal linearVolume = QAudio::convertVolume(m_volumeSlider->value() / qreal(100), QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale); @@ -162,20 +153,20 @@ void PlayerControls::setVolume(int volume) QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale); - volumeSlider->setValue(qRound(logarithmicVolume * 100)); + m_volumeSlider->setValue(qRound(logarithmicVolume * 100)); } bool PlayerControls::isMuted() const { - return playerMuted; + return m_playerMuted; } void PlayerControls::setMuted(bool muted) { - if (muted != playerMuted) { - playerMuted = muted; + if (muted != m_playerMuted) { + m_playerMuted = muted; - muteButton->setIcon(style()->standardIcon(muted + m_muteButton->setIcon(style()->standardIcon(muted ? QStyle::SP_MediaVolumeMuted : QStyle::SP_MediaVolume)); } @@ -183,7 +174,7 @@ void PlayerControls::setMuted(bool muted) void PlayerControls::playClicked() { - switch (playerState) { + switch (m_playerState) { case QMediaPlayer::StoppedState: case QMediaPlayer::PausedState: emit play(); @@ -196,25 +187,25 @@ void PlayerControls::playClicked() void PlayerControls::muteClicked() { - emit changeMuting(!playerMuted); + emit changeMuting(!m_playerMuted); } qreal PlayerControls::playbackRate() const { - return rateBox->itemData(rateBox->currentIndex()).toDouble(); + return m_rateBox->itemData(m_rateBox->currentIndex()).toDouble(); } void PlayerControls::setPlaybackRate(float rate) { - for (int i = 0; i < rateBox->count(); ++i) { - if (qFuzzyCompare(rate, float(rateBox->itemData(i).toDouble()))) { - rateBox->setCurrentIndex(i); + for (int i = 0; i < m_rateBox->count(); ++i) { + if (qFuzzyCompare(rate, float(m_rateBox->itemData(i).toDouble()))) { + m_rateBox->setCurrentIndex(i); return; } } - rateBox->addItem(QString("%1x").arg(rate), QVariant(rate)); - rateBox->setCurrentIndex(rateBox->count() - 1); + m_rateBox->addItem(QString("%1x").arg(rate), QVariant(rate)); + m_rateBox->setCurrentIndex(m_rateBox->count() - 1); } void PlayerControls::updateRate() diff --git a/examples/multimediawidgets/player/playercontrols.h b/examples/multimediawidgets/player/playercontrols.h index 6e8f7d7b7..bf1f676c1 100644 --- a/examples/multimediawidgets/player/playercontrols.h +++ b/examples/multimediawidgets/player/playercontrols.h @@ -65,7 +65,7 @@ class PlayerControls : public QWidget Q_OBJECT public: - PlayerControls(QWidget *parent = 0); + explicit PlayerControls(QWidget *parent = nullptr); QMediaPlayer::State state() const; int volume() const; @@ -95,15 +95,15 @@ private slots: void onVolumeSliderValueChanged(); private: - QMediaPlayer::State playerState; - bool playerMuted; - QAbstractButton *playButton; - QAbstractButton *stopButton; - QAbstractButton *nextButton; - QAbstractButton *previousButton; - QAbstractButton *muteButton; - QAbstractSlider *volumeSlider; - QComboBox *rateBox; + QMediaPlayer::State m_playerState = QMediaPlayer::StoppedState; + bool m_playerMuted = false; + QAbstractButton *m_playButton = nullptr; + QAbstractButton *m_stopButton = nullptr; + QAbstractButton *m_nextButton = nullptr; + QAbstractButton *m_previousButton = nullptr; + QAbstractButton *m_muteButton = nullptr; + QAbstractSlider *m_volumeSlider = nullptr; + QComboBox *m_rateBox = nullptr; }; #endif // PLAYERCONTROLS_H diff --git a/examples/multimediawidgets/player/playlistmodel.cpp b/examples/multimediawidgets/player/playlistmodel.cpp index 8811cb0cf..e5246bc37 100644 --- a/examples/multimediawidgets/player/playlistmodel.cpp +++ b/examples/multimediawidgets/player/playlistmodel.cpp @@ -56,7 +56,10 @@ PlaylistModel::PlaylistModel(QObject *parent) : QAbstractItemModel(parent) - , m_playlist(0) +{ +} + +PlaylistModel::~PlaylistModel() { } @@ -102,28 +105,28 @@ QVariant PlaylistModel::data(const QModelIndex &index, int role) const QMediaPlaylist *PlaylistModel::playlist() const { - return m_playlist; + return m_playlist.data(); } void PlaylistModel::setPlaylist(QMediaPlaylist *playlist) { if (m_playlist) { - disconnect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int))); - disconnect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems())); - disconnect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int))); - disconnect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems())); - disconnect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int))); + disconnect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeInserted, this, &PlaylistModel::beginInsertItems); + disconnect(m_playlist.data(), &QMediaPlaylist::mediaInserted, this, &PlaylistModel::endInsertItems); + disconnect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeRemoved, this, &PlaylistModel::beginRemoveItems); + disconnect(m_playlist.data(), &QMediaPlaylist::mediaRemoved, this, &PlaylistModel::endRemoveItems); + disconnect(m_playlist.data(), &QMediaPlaylist::mediaChanged, this, &PlaylistModel::changeItems); } beginResetModel(); - m_playlist = playlist; + m_playlist.reset(playlist); if (m_playlist) { - connect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int))); - connect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems())); - connect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int))); - connect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems())); - connect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int))); + connect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeInserted, this, &PlaylistModel::beginInsertItems); + connect(m_playlist.data(), &QMediaPlaylist::mediaInserted, this, &PlaylistModel::endInsertItems); + connect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeRemoved, this, &PlaylistModel::beginRemoveItems); + connect(m_playlist.data(), &QMediaPlaylist::mediaRemoved, this, &PlaylistModel::endRemoveItems); + connect(m_playlist.data(), &QMediaPlaylist::mediaChanged, this, &PlaylistModel::changeItems); } endResetModel(); diff --git a/examples/multimediawidgets/player/playlistmodel.h b/examples/multimediawidgets/player/playlistmodel.h index ebd0727e8..a0df0e9e7 100644 --- a/examples/multimediawidgets/player/playlistmodel.h +++ b/examples/multimediawidgets/player/playlistmodel.h @@ -52,6 +52,7 @@ #define PLAYLISTMODEL_H #include <QAbstractItemModel> +#include <QScopedPointer> QT_BEGIN_NAMESPACE class QMediaPlaylist; @@ -68,7 +69,8 @@ public: ColumnCount }; - PlaylistModel(QObject *parent = 0); + explicit PlaylistModel(QObject *parent = nullptr); + ~PlaylistModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; @@ -91,7 +93,7 @@ private slots: void changeItems(int start, int end); private: - QMediaPlaylist *m_playlist; + QScopedPointer<QMediaPlaylist> m_playlist; QMap<QModelIndex, QVariant> m_data; }; diff --git a/examples/multimediawidgets/player/videowidget.h b/examples/multimediawidgets/player/videowidget.h index 7cda4c7c5..c01632e7b 100644 --- a/examples/multimediawidgets/player/videowidget.h +++ b/examples/multimediawidgets/player/videowidget.h @@ -58,7 +58,7 @@ class VideoWidget : public QVideoWidget Q_OBJECT public: - VideoWidget(QWidget *parent = 0); + explicit VideoWidget(QWidget *parent = nullptr); protected: void keyPressEvent(QKeyEvent *event) override; diff --git a/examples/multimediawidgets/videographicsitem/videoplayer.cpp b/examples/multimediawidgets/videographicsitem/videoplayer.cpp index 89a3e0ab1..995c86d3e 100644 --- a/examples/multimediawidgets/videographicsitem/videoplayer.cpp +++ b/examples/multimediawidgets/videographicsitem/videoplayer.cpp @@ -51,24 +51,20 @@ #include "videoplayer.h" #include <QtWidgets> -#include <QVideoSurfaceFormat> #include <QGraphicsVideoItem> VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent) - , mediaPlayer(0, QMediaPlayer::VideoSurface) - , videoItem(0) - , playButton(0) - , positionSlider(0) { + m_mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); const QRect screenGeometry = QApplication::desktop()->screenGeometry(this); - videoItem = new QGraphicsVideoItem; - videoItem->setSize(QSizeF(screenGeometry.width() / 3, screenGeometry.height() / 2)); + m_videoItem = new QGraphicsVideoItem; + m_videoItem->setSize(QSizeF(screenGeometry.width() / 3, screenGeometry.height() / 2)); QGraphicsScene *scene = new QGraphicsScene(this); QGraphicsView *graphicsView = new QGraphicsView(scene); - scene->addItem(videoItem); + scene->addItem(m_videoItem); QSlider *rotateSlider = new QSlider(Qt::Horizontal); rotateSlider->setToolTip(tr("Rotate Video")); @@ -81,34 +77,34 @@ VideoPlayer::VideoPlayer(QWidget *parent) QAbstractButton *openButton = new QPushButton(tr("Open...")); connect(openButton, &QAbstractButton::clicked, this, &VideoPlayer::openFile); - playButton = new QPushButton; - playButton->setEnabled(false); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_playButton = new QPushButton; + m_playButton->setEnabled(false); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); - connect(playButton, &QAbstractButton::clicked, this, &VideoPlayer::play); + connect(m_playButton, &QAbstractButton::clicked, this, &VideoPlayer::play); - positionSlider = new QSlider(Qt::Horizontal); - positionSlider->setRange(0, 0); + m_positionSlider = new QSlider(Qt::Horizontal); + m_positionSlider->setRange(0, 0); - connect(positionSlider, &QAbstractSlider::sliderMoved, + connect(m_positionSlider, &QAbstractSlider::sliderMoved, this, &VideoPlayer::setPosition); QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); controlLayout->addWidget(openButton); - controlLayout->addWidget(playButton); - controlLayout->addWidget(positionSlider); + controlLayout->addWidget(m_playButton); + controlLayout->addWidget(m_positionSlider); QBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(graphicsView); layout->addWidget(rotateSlider); layout->addLayout(controlLayout); - mediaPlayer.setVideoOutput(videoItem); - connect(&mediaPlayer, &QMediaPlayer::stateChanged, + m_mediaPlayer->setVideoOutput(m_videoItem); + connect(m_mediaPlayer, &QMediaPlayer::stateChanged, this, &VideoPlayer::mediaStateChanged); - connect(&mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged); - connect(&mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged); + connect(m_mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged); + connect(m_mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged); } VideoPlayer::~VideoPlayer() @@ -117,12 +113,12 @@ VideoPlayer::~VideoPlayer() QSize VideoPlayer::sizeHint() const { - return (videoItem->size() * qreal(3) / qreal(2)).toSize(); + return (m_videoItem->size() * qreal(3) / qreal(2)).toSize(); } bool VideoPlayer::isPlayerAvailable() const { - return mediaPlayer.isAvailable(); + return m_mediaPlayer->isAvailable(); } void VideoPlayer::openFile() @@ -130,7 +126,7 @@ void VideoPlayer::openFile() QFileDialog fileDialog(this); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setWindowTitle(tr("Open Movie")); - const QStringList supportedMimeTypes = mediaPlayer.supportedMimeTypes(); + const QStringList supportedMimeTypes = m_mediaPlayer->supportedMimeTypes(); if (!supportedMimeTypes.isEmpty()) fileDialog.setMimeTypeFilters(supportedMimeTypes); fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath())); @@ -140,18 +136,18 @@ void VideoPlayer::openFile() void VideoPlayer::load(const QUrl &url) { - mediaPlayer.setMedia(url); - playButton->setEnabled(true); + m_mediaPlayer->setMedia(url); + m_playButton->setEnabled(true); } void VideoPlayer::play() { - switch(mediaPlayer.state()) { + switch (m_mediaPlayer->state()) { case QMediaPlayer::PlayingState: - mediaPlayer.pause(); + m_mediaPlayer->pause(); break; default: - mediaPlayer.play(); + m_mediaPlayer->play(); break; } } @@ -160,34 +156,34 @@ void VideoPlayer::mediaStateChanged(QMediaPlayer::State state) { switch(state) { case QMediaPlayer::PlayingState: - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); break; default: - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); break; } } void VideoPlayer::positionChanged(qint64 position) { - positionSlider->setValue(position); + m_positionSlider->setValue(position); } void VideoPlayer::durationChanged(qint64 duration) { - positionSlider->setRange(0, duration); + m_positionSlider->setRange(0, duration); } void VideoPlayer::setPosition(int position) { - mediaPlayer.setPosition(position); + m_mediaPlayer->setPosition(position); } void VideoPlayer::rotateVideo(int angle) { //rotate around the center of video element - qreal x = videoItem->boundingRect().width() / 2.0; - qreal y = videoItem->boundingRect().height() / 2.0; - videoItem->setTransform(QTransform().translate(x, y).rotate(angle).translate(-x, -y)); + qreal x = m_videoItem->boundingRect().width() / 2.0; + qreal y = m_videoItem->boundingRect().height() / 2.0; + m_videoItem->setTransform(QTransform().translate(x, y).rotate(angle).translate(-x, -y)); } diff --git a/examples/multimediawidgets/videographicsitem/videoplayer.h b/examples/multimediawidgets/videographicsitem/videoplayer.h index 86545088f..87c20c804 100644 --- a/examples/multimediawidgets/videographicsitem/videoplayer.h +++ b/examples/multimediawidgets/videographicsitem/videoplayer.h @@ -52,7 +52,6 @@ #define VIDEOPLAYER_H #include <QMediaPlayer> -#include <QMovie> #include <QWidget> QT_BEGIN_NAMESPACE @@ -66,7 +65,7 @@ class VideoPlayer : public QWidget Q_OBJECT public: - VideoPlayer(QWidget *parent = 0); + VideoPlayer(QWidget *parent = nullptr); ~VideoPlayer(); void load(const QUrl &url); @@ -86,10 +85,10 @@ private slots: void rotateVideo(int angle); private: - QMediaPlayer mediaPlayer; - QGraphicsVideoItem *videoItem; - QAbstractButton *playButton; - QSlider *positionSlider; + QMediaPlayer *m_mediaPlayer = nullptr; + QGraphicsVideoItem *m_videoItem = nullptr; + QAbstractButton *m_playButton = nullptr; + QSlider *m_positionSlider = nullptr; }; #endif diff --git a/examples/multimediawidgets/videowidget/videoplayer.cpp b/examples/multimediawidgets/videowidget/videoplayer.cpp index d5083afcf..e7ad670fa 100644 --- a/examples/multimediawidgets/videowidget/videoplayer.cpp +++ b/examples/multimediawidgets/videowidget/videoplayer.cpp @@ -51,57 +51,52 @@ #include "videoplayer.h" #include <QtWidgets> -#include <qvideowidget.h> -#include <qvideosurfaceformat.h> +#include <QVideoWidget> VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent) - , mediaPlayer(0, QMediaPlayer::VideoSurface) - , playButton(0) - , positionSlider(0) - , errorLabel(0) { + m_mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); QVideoWidget *videoWidget = new QVideoWidget; QAbstractButton *openButton = new QPushButton(tr("Open...")); connect(openButton, &QAbstractButton::clicked, this, &VideoPlayer::openFile); - playButton = new QPushButton; - playButton->setEnabled(false); - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_playButton = new QPushButton; + m_playButton->setEnabled(false); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); - connect(playButton, &QAbstractButton::clicked, + connect(m_playButton, &QAbstractButton::clicked, this, &VideoPlayer::play); - positionSlider = new QSlider(Qt::Horizontal); - positionSlider->setRange(0, 0); + m_positionSlider = new QSlider(Qt::Horizontal); + m_positionSlider->setRange(0, 0); - connect(positionSlider, &QAbstractSlider::sliderMoved, + connect(m_positionSlider, &QAbstractSlider::sliderMoved, this, &VideoPlayer::setPosition); - errorLabel = new QLabel; - errorLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + m_errorLabel = new QLabel; + m_errorLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); controlLayout->addWidget(openButton); - controlLayout->addWidget(playButton); - controlLayout->addWidget(positionSlider); + controlLayout->addWidget(m_playButton); + controlLayout->addWidget(m_positionSlider); QBoxLayout *layout = new QVBoxLayout; layout->addWidget(videoWidget); layout->addLayout(controlLayout); - layout->addWidget(errorLabel); + layout->addWidget(m_errorLabel); setLayout(layout); - mediaPlayer.setVideoOutput(videoWidget); - connect(&mediaPlayer, &QMediaPlayer::stateChanged, + m_mediaPlayer->setVideoOutput(videoWidget); + connect(m_mediaPlayer, &QMediaPlayer::stateChanged, this, &VideoPlayer::mediaStateChanged); - connect(&mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged); - connect(&mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged); - typedef void (QMediaPlayer::*ErrorSignal)(QMediaPlayer::Error); - connect(&mediaPlayer, static_cast<ErrorSignal>(&QMediaPlayer::error), + connect(m_mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged); + connect(m_mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged); + connect(m_mediaPlayer, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, &VideoPlayer::handleError); } @@ -114,7 +109,7 @@ void VideoPlayer::openFile() QFileDialog fileDialog(this); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setWindowTitle(tr("Open Movie")); - QStringList supportedMimeTypes = mediaPlayer.supportedMimeTypes(); + QStringList supportedMimeTypes = m_mediaPlayer->supportedMimeTypes(); if (!supportedMimeTypes.isEmpty()) fileDialog.setMimeTypeFilters(supportedMimeTypes); fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath())); @@ -124,20 +119,20 @@ void VideoPlayer::openFile() void VideoPlayer::setUrl(const QUrl &url) { - errorLabel->setText(QString()); + m_errorLabel->setText(QString()); setWindowFilePath(url.isLocalFile() ? url.toLocalFile() : QString()); - mediaPlayer.setMedia(url); - playButton->setEnabled(true); + m_mediaPlayer->setMedia(url); + m_playButton->setEnabled(true); } void VideoPlayer::play() { - switch(mediaPlayer.state()) { + switch (m_mediaPlayer->state()) { case QMediaPlayer::PlayingState: - mediaPlayer.pause(); + m_mediaPlayer->pause(); break; default: - mediaPlayer.play(); + m_mediaPlayer->play(); break; } } @@ -146,37 +141,37 @@ void VideoPlayer::mediaStateChanged(QMediaPlayer::State state) { switch(state) { case QMediaPlayer::PlayingState: - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); break; default: - playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); break; } } void VideoPlayer::positionChanged(qint64 position) { - positionSlider->setValue(position); + m_positionSlider->setValue(position); } void VideoPlayer::durationChanged(qint64 duration) { - positionSlider->setRange(0, duration); + m_positionSlider->setRange(0, duration); } void VideoPlayer::setPosition(int position) { - mediaPlayer.setPosition(position); + m_mediaPlayer->setPosition(position); } void VideoPlayer::handleError() { - playButton->setEnabled(false); - const QString errorString = mediaPlayer.errorString(); + m_playButton->setEnabled(false); + const QString errorString = m_mediaPlayer->errorString(); QString message = "Error: "; if (errorString.isEmpty()) - message += " #" + QString::number(int(mediaPlayer.error())); + message += " #" + QString::number(int(m_mediaPlayer->error())); else message += errorString; - errorLabel->setText(message); + m_errorLabel->setText(message); } diff --git a/examples/multimediawidgets/videowidget/videoplayer.h b/examples/multimediawidgets/videowidget/videoplayer.h index 7ccbb40f0..62260d167 100644 --- a/examples/multimediawidgets/videowidget/videoplayer.h +++ b/examples/multimediawidgets/videowidget/videoplayer.h @@ -51,10 +51,8 @@ #ifndef VIDEOPLAYER_H #define VIDEOPLAYER_H -#include <qmediaplayer.h> - -#include <QtGui/QMovie> -#include <QtWidgets/QWidget> +#include <QMediaPlayer> +#include <QWidget> QT_BEGIN_NAMESPACE class QAbstractButton; @@ -67,7 +65,7 @@ class VideoPlayer : public QWidget { Q_OBJECT public: - VideoPlayer(QWidget *parent = 0); + VideoPlayer(QWidget *parent = nullptr); ~VideoPlayer(); void setUrl(const QUrl &url); @@ -84,10 +82,10 @@ private slots: void handleError(); private: - QMediaPlayer mediaPlayer; - QAbstractButton *playButton; - QSlider *positionSlider; - QLabel *errorLabel; + QMediaPlayer* m_mediaPlayer; + QAbstractButton *m_playButton; + QSlider *m_positionSlider; + QLabel *m_errorLabel; }; #endif diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index edbf603e3..f5e3fd96f 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -1,7 +1,6 @@ -TEMPLATE = lib - -TARGET = qgsttools_p -QPRO_PWD = $$PWD +TARGET = QtMultimediaGstTools +MODULE = multimediagsttools +CONFIG += internal_module QT = core-private multimedia-private gui-private @@ -36,7 +35,8 @@ PRIVATE_HEADERS += \ qgstreamervideoprobecontrol_p.h \ qgstreameraudioprobecontrol_p.h \ qgstreamervideowindow_p.h \ - qgstreamervideooverlay_p.h + qgstreamervideooverlay_p.h \ + qgsttools_global_p.h SOURCES += \ qgstreamerbushelper.cpp \ @@ -101,7 +101,4 @@ qtConfig(gstreamer_app) { HEADERS += $$PRIVATE_HEADERS -DESTDIR = $$QT.multimedia.libs -target.path = $$[QT_INSTALL_LIBS] - -INSTALLS += target +load(qt_module) diff --git a/src/gsttools/qgstcodecsinfo.cpp b/src/gsttools/qgstcodecsinfo.cpp index 230dc581b..a05ee92aa 100644 --- a/src/gsttools/qgstcodecsinfo.cpp +++ b/src/gsttools/qgstcodecsinfo.cpp @@ -156,7 +156,7 @@ void QGstCodecsInfo::updateCodecs(ElementType elementType) GstRank rank = GstRank(gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(factory))); // If two elements provide the same codec, use the highest ranked one - QMap<QString, CodecInfo>::const_iterator it = m_codecInfo.find(codec); + QMap<QString, CodecInfo>::const_iterator it = m_codecInfo.constFind(codec); if (it == m_codecInfo.constEnd() || it->rank < rank) { if (it == m_codecInfo.constEnd()) m_codecs.append(codec); diff --git a/src/gsttools/qgstreameraudioinputselector.cpp b/src/gsttools/qgstreameraudioinputselector.cpp index 6d74feb1b..72d079cbc 100644 --- a/src/gsttools/qgstreameraudioinputselector.cpp +++ b/src/gsttools/qgstreameraudioinputselector.cpp @@ -104,7 +104,7 @@ void QGstreamerAudioInputSelector::update() m_descriptions.clear(); //use autoaudiosrc as the first default device - m_names.append("default:"); + m_names.append(QLatin1String("default:")); m_descriptions.append(tr("System default device")); updatePulseDevices(); @@ -150,12 +150,12 @@ void QGstreamerAudioInputSelector::updateAlsaDevices() void QGstreamerAudioInputSelector::updateOssDevices() { - QDir devDir("/dev"); + QDir devDir(QStringLiteral("/dev")); devDir.setFilter(QDir::System); - const QFileInfoList entries = devDir.entryInfoList(QStringList() << "dsp*"); + const QFileInfoList entries = devDir.entryInfoList(QStringList() << QLatin1String("dsp*")); for (const QFileInfo& entryInfo : entries) { m_names.append(QLatin1String("oss:")+entryInfo.filePath()); - m_descriptions.append(QString("OSS device %1").arg(entryInfo.fileName())); + m_descriptions.append(QString::fromLatin1("OSS device %1").arg(entryInfo.fileName())); } } @@ -163,8 +163,8 @@ void QGstreamerAudioInputSelector::updatePulseDevices() { GstElementFactory *factory = gst_element_factory_find("pulsesrc"); if (factory) { - m_names.append("pulseaudio:"); - m_descriptions.append("PulseAudio device."); + m_names.append(QLatin1String("pulseaudio:")); + m_descriptions.append(QLatin1String("PulseAudio device.")); gst_object_unref(GST_OBJECT(factory)); } } diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index 06181403e..6a573fa78 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -471,16 +471,16 @@ void QGstUtils::initializeGst() namespace { const char* getCodecAlias(const QString &codec) { - if (codec.startsWith("avc1.")) + if (codec.startsWith(QLatin1String("avc1."))) return "video/x-h264"; - if (codec.startsWith("mp4a.")) + if (codec.startsWith(QLatin1String("mp4a."))) return "audio/mpeg4"; - if (codec.startsWith("mp4v.20.")) + if (codec.startsWith(QLatin1String("mp4v.20."))) return "video/mpeg4"; - if (codec == "samr") + if (codec == QLatin1String("samr")) return "audio/amr"; return 0; @@ -488,14 +488,14 @@ namespace { const char* getMimeTypeAlias(const QString &mimeType) { - if (mimeType == "video/mp4") + if (mimeType == QLatin1String("video/mp4")) return "video/mpeg4"; - if (mimeType == "audio/mp4") + if (mimeType == QLatin1String("audio/mp4")) return "audio/mpeg4"; - if (mimeType == "video/ogg" - || mimeType == "audio/ogg") + if (mimeType == QLatin1String("video/ogg") + || mimeType == QLatin1String("audio/ogg")) return "application/ogg"; return 0; @@ -513,12 +513,12 @@ QMultimedia::SupportEstimate QGstUtils::hasSupport(const QString &mimeType, bool containsMimeType = supportedMimeTypeSet.contains(mimeTypeLowcase); if (!containsMimeType) { const char* mimeTypeAlias = getMimeTypeAlias(mimeTypeLowcase); - containsMimeType = supportedMimeTypeSet.contains(mimeTypeAlias); + containsMimeType = supportedMimeTypeSet.contains(QLatin1String(mimeTypeAlias)); if (!containsMimeType) { - containsMimeType = supportedMimeTypeSet.contains("video/" + mimeTypeLowcase) - || supportedMimeTypeSet.contains("video/x-" + mimeTypeLowcase) - || supportedMimeTypeSet.contains("audio/" + mimeTypeLowcase) - || supportedMimeTypeSet.contains("audio/x-" + mimeTypeLowcase); + containsMimeType = supportedMimeTypeSet.contains(QLatin1String("video/") + mimeTypeLowcase) + || supportedMimeTypeSet.contains(QLatin1String("video/x-") + mimeTypeLowcase) + || supportedMimeTypeSet.contains(QLatin1String("audio/") + mimeTypeLowcase) + || supportedMimeTypeSet.contains(QLatin1String("audio/x-") + mimeTypeLowcase); } } @@ -527,12 +527,12 @@ QMultimedia::SupportEstimate QGstUtils::hasSupport(const QString &mimeType, QString codecLowcase = codec.toLower(); const char* codecAlias = getCodecAlias(codecLowcase); if (codecAlias) { - if (supportedMimeTypeSet.contains(codecAlias)) + if (supportedMimeTypeSet.contains(QLatin1String(codecAlias))) supportedCodecCount++; - } else if (supportedMimeTypeSet.contains("video/" + codecLowcase) - || supportedMimeTypeSet.contains("video/x-" + codecLowcase) - || supportedMimeTypeSet.contains("audio/" + codecLowcase) - || supportedMimeTypeSet.contains("audio/x-" + codecLowcase)) { + } else if (supportedMimeTypeSet.contains(QLatin1String("video/") + codecLowcase) + || supportedMimeTypeSet.contains(QLatin1String("video/x-") + codecLowcase) + || supportedMimeTypeSet.contains(QLatin1String("audio/") + codecLowcase) + || supportedMimeTypeSet.contains(QLatin1String("audio/x-") + codecLowcase)) { supportedCodecCount++; } } @@ -769,8 +769,8 @@ QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac GstElementFactory *factory; if (GST_IS_TYPE_FIND_FACTORY(feature)) { - QString name(gst_plugin_feature_get_name(feature)); - if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type + QString name(QLatin1String(gst_plugin_feature_get_name(feature))); + if (name.contains(QLatin1Char('/'))) //filter out any string without '/' which is obviously not a mime type supportedMimeTypes.insert(name.toLower()); continue; } else if (!GST_IS_ELEMENT_FACTORY (feature) @@ -788,18 +788,18 @@ QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac if (gst_caps_is_any(caps) || gst_caps_is_empty(caps)) { } else for (guint i = 0; i < gst_caps_get_size(caps); i++) { GstStructure *structure = gst_caps_get_structure(caps, i); - QString nameLowcase = QString(gst_structure_get_name(structure)).toLower(); + QString nameLowcase = QString::fromLatin1(gst_structure_get_name(structure)).toLower(); supportedMimeTypes.insert(nameLowcase); - if (nameLowcase.contains("mpeg")) { + if (nameLowcase.contains(QLatin1String("mpeg"))) { //Because mpeg version number is only included in the detail //description, it is necessary to manually extract this information //in order to match the mime type of mpeg4. const GValue *value = gst_structure_get_value(structure, "mpegversion"); if (value) { gchar *str = gst_value_serialize(value); - QString versions(str); - const QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts); + QString versions = QLatin1String(str); + const QStringList elements = versions.split(QRegExp(QLatin1String("\\D+")), QString::SkipEmptyParts); for (const QString &e : elements) supportedMimeTypes.insert(nameLowcase + e); g_free(str); @@ -1239,7 +1239,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant QMapIterator<QByteArray, QVariant> it(data); while (it.hasNext()) { it.next(); - const QString tagName = it.key(); + const QString tagName = QString::fromLatin1(it.key()); const QVariant tagValue = it.value(); switch (tagValue.type()) { @@ -1439,26 +1439,26 @@ QString QGstUtils::fileExtensionForMimeType(const QString &mimeType) { if (fileExtensionMap->isEmpty()) { //extension for containers hard to guess from mimetype - fileExtensionMap->insert("video/x-matroska", "mkv"); - fileExtensionMap->insert("video/quicktime", "mov"); - fileExtensionMap->insert("video/x-msvideo", "avi"); - fileExtensionMap->insert("video/msvideo", "avi"); - fileExtensionMap->insert("audio/mpeg", "mp3"); - fileExtensionMap->insert("application/x-shockwave-flash", "swf"); - fileExtensionMap->insert("application/x-pn-realmedia", "rm"); + fileExtensionMap->insert(QStringLiteral("video/x-matroska"), QLatin1String("mkv")); + fileExtensionMap->insert(QStringLiteral("video/quicktime"), QLatin1String("mov")); + fileExtensionMap->insert(QStringLiteral("video/x-msvideo"), QLatin1String("avi")); + fileExtensionMap->insert(QStringLiteral("video/msvideo"), QLatin1String("avi")); + fileExtensionMap->insert(QStringLiteral("audio/mpeg"), QLatin1String("mp3")); + fileExtensionMap->insert(QStringLiteral("application/x-shockwave-flash"), QLatin1String("swf")); + fileExtensionMap->insert(QStringLiteral("application/x-pn-realmedia"), QLatin1String("rm")); } //for container names like avi instead of video/x-msvideo, use it as extension - if (!mimeType.contains('/')) + if (!mimeType.contains(QLatin1Char('/'))) return mimeType; - QString format = mimeType.left(mimeType.indexOf(',')); + QString format = mimeType.left(mimeType.indexOf(QLatin1Char(','))); QString extension = fileExtensionMap->value(format); if (!extension.isEmpty() || format.isEmpty()) return extension; - QRegExp rx("[-/]([\\w]+)$"); + QRegExp rx(QStringLiteral("[-/]([\\w]+)$")); if (rx.indexIn(format) != -1) extension = rx.cap(1); diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.cpp b/src/imports/audioengine/qdeclarative_playvariation_p.cpp index 36ffca668..e6d3697d0 100644 --- a/src/imports/audioengine/qdeclarative_playvariation_p.cpp +++ b/src/imports/audioengine/qdeclarative_playvariation_p.cpp @@ -41,6 +41,7 @@ #include "qdeclarative_audioengine_p.h" #include "qsoundinstance_p.h" #include "qdebug.h" +#include "qrandom.h" #define DEBUG_AUDIOENGINE @@ -272,7 +273,7 @@ void QDeclarativePlayVariation::setSampleObject(QDeclarativeAudioSample *sampleO void QDeclarativePlayVariation::applyParameters(QSoundInstance *soundInstance) { - qreal pitch = qreal(qrand() % 1001) * 0.001f * (m_maxPitch - m_minPitch) + m_minPitch; - qreal gain = qreal(qrand() % 1001) * 0.001f * (m_maxGain - m_minGain) + m_minGain; + qreal pitch = QRandomGenerator::global()->bounded(1001 * 0.001f) * (m_maxPitch - m_minPitch) + m_minPitch; + qreal gain = QRandomGenerator::global()->bounded(1001 * 0.001f) * (m_maxGain - m_minGain) + m_minGain; soundInstance->updateVariationParameters(pitch, gain, m_looping); } diff --git a/src/imports/audioengine/qdeclarative_sound_p.cpp b/src/imports/audioengine/qdeclarative_sound_p.cpp index 0849215be..a11490cea 100644 --- a/src/imports/audioengine/qdeclarative_sound_p.cpp +++ b/src/imports/audioengine/qdeclarative_sound_p.cpp @@ -43,6 +43,7 @@ #include "qdeclarative_soundinstance_p.h" #include "qdeclarative_audioengine_p.h" #include "qdebug.h" +#include "qrandom.h" #define DEBUG_AUDIOENGINE @@ -316,7 +317,7 @@ int QDeclarativeSound::genVariationIndex(int oldVariationIndex) case QDeclarativeSound::Random: { if (oldVariationIndex < 0) oldVariationIndex = 0; - return (oldVariationIndex + (qrand() % (m_playlist.count() + 1))) % m_playlist.count(); + return (oldVariationIndex + (QRandomGenerator::global()->bounded(m_playlist.count() + 1))) % m_playlist.count(); } default: return (oldVariationIndex + 1) % m_playlist.count(); diff --git a/src/multimedia/audio/qaudio.cpp b/src/multimedia/audio/qaudio.cpp index d4f89e898..dea9a05a5 100644 --- a/src/multimedia/audio/qaudio.cpp +++ b/src/multimedia/audio/qaudio.cpp @@ -79,13 +79,18 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterAudioMetaTypes) /*! \enum QAudio::State - \value ActiveState Audio data is being processed, this state is set after start() is called - and while audio data is available to be processed. - \value SuspendedState The audio device is in a suspended state, this state will only be entered - after suspend() is called. - \value StoppedState The audio device is closed, and is not processing any audio data - \value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state - is set after start() is called and while no audio data is available to be processed. + \value ActiveState Audio data is being processed, this state is set after start() is called + and while audio data is available to be processed. + \value SuspendedState The audio stream is in a suspended state. Entered after suspend() is called + or when another stream takes control of the audio device. In the later case, + a call to resume will return control of the audio device to this stream. This + should usually only be done upon user request. + \value StoppedState The audio device is closed, and is not processing any audio data + \value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state + is set after start() is called and while no audio data is available to be processed. + \value InterruptedState This stream is in a suspended state because another higher priority stream currently + has control of the audio device. Playback cannot resume until the higher priority + stream relinquishes control of the audio device. */ /*! @@ -285,6 +290,9 @@ QDebug operator<<(QDebug dbg, QAudio::State state) case QAudio::IdleState: dbg << "IdleState"; break; + case QAudio::InterruptedState: + dbg << "InterruptedState"; + break; } return dbg; } diff --git a/src/multimedia/audio/qaudio.h b/src/multimedia/audio/qaudio.h index 1c38e9f35..2603d71d1 100644 --- a/src/multimedia/audio/qaudio.h +++ b/src/multimedia/audio/qaudio.h @@ -55,7 +55,7 @@ class QString; namespace QAudio { enum Error { NoError, OpenError, IOError, UnderrunError, FatalError }; - enum State { ActiveState, SuspendedState, StoppedState, IdleState }; + enum State { ActiveState, SuspendedState, StoppedState, IdleState, InterruptedState }; enum Mode { AudioInput, AudioOutput }; enum Role { diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 1e9204598..bf647ea1f 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -73,20 +73,23 @@ inline pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format) spec.rate = format.sampleRate(); spec.channels = format.channelCount(); - - if (format.sampleSize() == 8) - spec.format = PA_SAMPLE_U8; - else if (format.sampleSize() == 16) { - switch (format.byteOrder()) { - case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S16BE; break; - case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S16LE; break; - } - } - else if (format.sampleSize() == 32) { - switch (format.byteOrder()) { - case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S32BE; break; - case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S32LE; break; + spec.format = PA_SAMPLE_INVALID; + const bool isBigEndian = (format.byteOrder() == QAudioFormat::BigEndian); + + if (format.sampleType() == QAudioFormat::UnSignedInt) { + if (format.sampleSize() == 8) + spec.format = PA_SAMPLE_U8; + } else if (format.sampleType() == QAudioFormat::SignedInt) { + if (format.sampleSize() == 16) { + spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; + } else if (format.sampleSize() == 24) { + spec.format = isBigEndian ? PA_SAMPLE_S24BE : PA_SAMPLE_S24LE; + } else if (format.sampleSize() == 32) { + spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; } + } else if (format.sampleType() == QAudioFormat::Float) { + if (format.sampleSize() == 32) + spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; } return spec; @@ -190,7 +193,11 @@ private Q_SLOTS: pa_context_set_state_callback(m_context, context_state_callback, this); - if (pa_context_connect(m_context, 0, (pa_context_flags_t)0, 0) < 0) { + const QByteArray srvStrEnv = qgetenv("QT_PULSE_SERVER_STRING"); + const char *srvStr = srvStrEnv.isNull() ? 0 : srvStrEnv.constData(); + pa_context_flags_t flags = qEnvironmentVariableIsSet("QT_PULSE_NOAUTOSPAWN") ? PA_CONTEXT_NOAUTOSPAWN : (pa_context_flags_t)0; + + if (pa_context_connect(m_context, srvStr, flags, 0) < 0) { qWarning("PulseAudioService: pa_context_connect() failed"); pa_context_unref(m_context); unlock(); diff --git a/src/multimedia/camera/qcamera.h b/src/multimedia/camera/qcamera.h index 685298905..aebd1c013 100644 --- a/src/multimedia/camera/qcamera.h +++ b/src/multimedia/camera/qcamera.h @@ -262,7 +262,10 @@ QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator==(const QCamera::FrameRateRange &r1, const QCamera::FrameRateRange &r2) Q_DECL_NOTHROW -{ return r1.minimumFrameRate == r2.minimumFrameRate && r1.maximumFrameRate == r2.maximumFrameRate; } +{ + return qFuzzyCompare(r1.minimumFrameRate, r2.minimumFrameRate) + && qFuzzyCompare(r1.maximumFrameRate, r2.maximumFrameRate); +} QT_WARNING_POP diff --git a/src/multimedia/gsttools_headers/gstvideoconnector_p.h b/src/multimedia/gsttools_headers/gstvideoconnector_p.h index 4fa1456c8..a38ca2e65 100644 --- a/src/multimedia/gsttools_headers/gstvideoconnector_p.h +++ b/src/multimedia/gsttools_headers/gstvideoconnector_p.h @@ -51,6 +51,8 @@ // We mean it. // +#include <private/qgsttools_global_p.h> + #include <gst/gst.h> G_BEGIN_DECLS @@ -69,7 +71,7 @@ G_BEGIN_DECLS typedef struct _GstVideoConnector GstVideoConnector; typedef struct _GstVideoConnectorClass GstVideoConnectorClass; -struct _GstVideoConnector { +struct Q_GSTTOOLS_EXPORT _GstVideoConnector { GstElement element; GstPad *srcpad; @@ -81,14 +83,14 @@ struct _GstVideoConnector { GstBuffer *latest_buffer; }; -struct _GstVideoConnectorClass { +struct Q_GSTTOOLS_EXPORT _GstVideoConnectorClass { GstElementClass parent_class; /* action signal to resend new segment */ void (*resend_new_segment) (GstElement * element, gboolean emitFailedSignal); }; -GType gst_video_connector_get_type (void); +GType Q_GSTTOOLS_EXPORT gst_video_connector_get_type (void); G_END_DECLS diff --git a/src/multimedia/gsttools_headers/qgstappsrc_p.h b/src/multimedia/gsttools_headers/qgstappsrc_p.h index e50915231..c7e87037d 100644 --- a/src/multimedia/gsttools_headers/qgstappsrc_p.h +++ b/src/multimedia/gsttools_headers/qgstappsrc_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <QtCore/qobject.h> #include <QtCore/qiodevice.h> @@ -63,7 +64,7 @@ QT_BEGIN_NAMESPACE -class QGstAppSrc : public QObject +class Q_GSTTOOLS_EXPORT QGstAppSrc : public QObject { Q_OBJECT public: diff --git a/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h b/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h index e03da1ab5..45e573262 100644 --- a/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h +++ b/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qabstractvideobuffer.h> #include <qvideosurfaceformat.h> #include <QtCore/qobject.h> @@ -65,7 +66,7 @@ const QLatin1String QGstBufferPoolPluginKey("bufferpool"); /*! Abstract interface for video buffers allocation. */ -class QGstBufferPoolInterface +class Q_GSTTOOLS_EXPORT QGstBufferPoolInterface { public: virtual ~QGstBufferPoolInterface() {} diff --git a/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h b/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h index af1a4486f..33ab3de4b 100644 --- a/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h +++ b/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <QtCore/qmap.h> #include <QtCore/qstringlist.h> @@ -58,7 +59,7 @@ QT_BEGIN_NAMESPACE -class QGstCodecsInfo +class Q_GSTTOOLS_EXPORT QGstCodecsInfo { public: enum ElementType { AudioEncoder, VideoEncoder, Muxer }; diff --git a/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h b/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h index 1a961c6d9..0c193fda9 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h @@ -51,12 +51,13 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qaudioinputselectorcontrol.h> #include <QtCore/qstringlist.h> QT_BEGIN_NAMESPACE -class QGstreamerAudioInputSelector : public QAudioInputSelectorControl +class Q_GSTTOOLS_EXPORT QGstreamerAudioInputSelector : public QAudioInputSelectorControl { Q_OBJECT public: diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h index bacf8c71d..4fc5c7704 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <gst/gst.h> #include <qmediaaudioprobecontrol.h> #include <QtCore/qmutex.h> @@ -61,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QGstreamerAudioProbeControl +class Q_GSTTOOLS_EXPORT QGstreamerAudioProbeControl : public QMediaAudioProbeControl , public QGstreamerBufferProbe , public QSharedData diff --git a/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h b/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h index f7ba2bbd9..35644f934 100644 --- a/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h +++ b/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h @@ -51,13 +51,15 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <gst/gst.h> #include <QtCore/qglobal.h> + QT_BEGIN_NAMESPACE -class QGstreamerBufferProbe +class Q_GSTTOOLS_EXPORT QGstreamerBufferProbe { public: enum Flags diff --git a/src/multimedia/gsttools_headers/qgstreamerbushelper_p.h b/src/multimedia/gsttools_headers/qgstreamerbushelper_p.h index 3216c07da..c7d06faf8 100644 --- a/src/multimedia/gsttools_headers/qgstreamerbushelper_p.h +++ b/src/multimedia/gsttools_headers/qgstreamerbushelper_p.h @@ -51,9 +51,11 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <QObject> #include "qgstreamermessage_p.h" + #include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -78,7 +80,7 @@ Q_DECLARE_INTERFACE(QGstreamerBusMessageFilter, QGstreamerBusMessageFilter_iid) class QGstreamerBusHelperPrivate; -class QGstreamerBusHelper : public QObject +class Q_GSTTOOLS_EXPORT QGstreamerBusHelper : public QObject { Q_OBJECT friend class QGstreamerBusHelperPrivate; diff --git a/src/multimedia/gsttools_headers/qgstreamermessage_p.h b/src/multimedia/gsttools_headers/qgstreamermessage_p.h index 5d832ccfa..2f9d1745c 100644 --- a/src/multimedia/gsttools_headers/qgstreamermessage_p.h +++ b/src/multimedia/gsttools_headers/qgstreamermessage_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <QMetaType> #include <gst/gst.h> @@ -60,7 +61,7 @@ QT_BEGIN_NAMESPACE // Required for QDoc workaround class QString; -class QGstreamerMessage +class Q_GSTTOOLS_EXPORT QGstreamerMessage { public: QGstreamerMessage(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h index e1ac453c7..b660cc7b3 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qvideodeviceselectorcontrol.h> #include <QtCore/qstringlist.h> @@ -59,7 +60,7 @@ QT_BEGIN_NAMESPACE -class QGstreamerVideoInputDeviceControl : public QVideoDeviceSelectorControl +class Q_GSTTOOLS_EXPORT QGstreamerVideoInputDeviceControl : public QVideoDeviceSelectorControl { Q_OBJECT public: diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h index b599b0e78..b15b6099c 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <gst/gst.h> #include <gst/video/video.h> #include <qmediavideoprobecontrol.h> @@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE -class QGstreamerVideoProbeControl +class Q_GSTTOOLS_EXPORT QGstreamerVideoProbeControl : public QMediaVideoProbeControl , public QGstreamerBufferProbe , public QSharedData diff --git a/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h b/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h index 1d22e1125..2f0b80d45 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qvideorenderercontrol.h> #include <private/qvideosurfacegstsink_p.h> #include <qabstractvideosurface.h> @@ -59,7 +60,7 @@ QT_BEGIN_NAMESPACE -class QGstreamerVideoRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface +class Q_GSTTOOLS_EXPORT QGstreamerVideoRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface { Q_OBJECT Q_INTERFACES(QGstreamerVideoRendererInterface) diff --git a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h index b2dfece60..3e3240725 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qvideowidgetcontrol.h> #include "qgstreamervideorendererinterface_p.h" @@ -59,9 +60,9 @@ QT_BEGIN_NAMESPACE -class QGstreamerVideoWidget; +class Q_GSTTOOLS_EXPORT QGstreamerVideoWidget; -class QGstreamerVideoWidgetControl +class Q_GSTTOOLS_EXPORT QGstreamerVideoWidgetControl : public QVideoWidgetControl , public QGstreamerVideoRendererInterface , public QGstreamerSyncMessageFilter diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h index b489650f9..5f893f10e 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qvideowindowcontrol.h> #include "qgstreamervideorendererinterface_p.h" @@ -61,7 +62,7 @@ QT_BEGIN_NAMESPACE class QAbstractVideoSurface; -class QGstreamerVideoWindow : +class Q_GSTTOOLS_EXPORT QGstreamerVideoWindow : public QVideoWindowControl, public QGstreamerVideoRendererInterface, public QGstreamerSyncMessageFilter, diff --git a/src/multimedia/gsttools_headers/qgsttools_global_p.h b/src/multimedia/gsttools_headers/qgsttools_global_p.h new file mode 100644 index 000000000..babcd3aaf --- /dev/null +++ b/src/multimedia/gsttools_headers/qgsttools_global_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTTOOLS_GLOBAL_H +#define QGSTTOOLS_GLOBAL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_MULTIMEDIAGSTTOOLS_LIB) +# define Q_GSTTOOLS_EXPORT Q_DECL_EXPORT +# else +# define Q_GSTTOOLS_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_GSTTOOLS_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QGSTTOOLS_GLOBAL_H diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index 8b7de3661..24d3e889d 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <QtCore/qmap.h> #include <QtCore/qset.h> #include <QtCore/qvector.h> @@ -85,7 +86,7 @@ class QImage; class QVideoSurfaceFormat; namespace QGstUtils { - struct CameraInfo + struct Q_GSTTOOLS_EXPORT CameraInfo { QString name; QString description; @@ -94,74 +95,74 @@ namespace QGstUtils { QByteArray driver; }; - QMap<QByteArray, QVariant> gstTagListToMap(const GstTagList *list); + Q_GSTTOOLS_EXPORT QMap<QByteArray, QVariant> gstTagListToMap(const GstTagList *list); - QSize capsResolution(const GstCaps *caps); - QSize capsCorrectedResolution(const GstCaps *caps); - QAudioFormat audioFormatForCaps(const GstCaps *caps); + Q_GSTTOOLS_EXPORT QSize capsResolution(const GstCaps *caps); + Q_GSTTOOLS_EXPORT QSize capsCorrectedResolution(const GstCaps *caps); + Q_GSTTOOLS_EXPORT QAudioFormat audioFormatForCaps(const GstCaps *caps); #if GST_CHECK_VERSION(1,0,0) - QAudioFormat audioFormatForSample(GstSample *sample); + Q_GSTTOOLS_EXPORT QAudioFormat audioFormatForSample(GstSample *sample); #else - QAudioFormat audioFormatForBuffer(GstBuffer *buffer); + Q_GSTTOOLS_EXPORT QAudioFormat audioFormatForBuffer(GstBuffer *buffer); #endif - GstCaps *capsForAudioFormat(const QAudioFormat &format); - void initializeGst(); - QMultimedia::SupportEstimate hasSupport(const QString &mimeType, + Q_GSTTOOLS_EXPORT GstCaps *capsForAudioFormat(const QAudioFormat &format); + Q_GSTTOOLS_EXPORT void initializeGst(); + Q_GSTTOOLS_EXPORT QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList &codecs, const QSet<QString> &supportedMimeTypeSet); - QVector<CameraInfo> enumerateCameras(GstElementFactory *factory = 0); - QList<QByteArray> cameraDevices(GstElementFactory * factory = 0); - QString cameraDescription(const QString &device, GstElementFactory * factory = 0); - QCamera::Position cameraPosition(const QString &device, GstElementFactory * factory = 0); - int cameraOrientation(const QString &device, GstElementFactory * factory = 0); - QByteArray cameraDriver(const QString &device, GstElementFactory * factory = 0); + Q_GSTTOOLS_EXPORT QVector<CameraInfo> enumerateCameras(GstElementFactory *factory = 0); + Q_GSTTOOLS_EXPORT QList<QByteArray> cameraDevices(GstElementFactory * factory = 0); + Q_GSTTOOLS_EXPORT QString cameraDescription(const QString &device, GstElementFactory * factory = 0); + Q_GSTTOOLS_EXPORT QCamera::Position cameraPosition(const QString &device, GstElementFactory * factory = 0); + Q_GSTTOOLS_EXPORT int cameraOrientation(const QString &device, GstElementFactory * factory = 0); + Q_GSTTOOLS_EXPORT QByteArray cameraDriver(const QString &device, GstElementFactory * factory = 0); - QSet<QString> supportedMimeTypes(bool (*isValidFactory)(GstElementFactory *factory)); + Q_GSTTOOLS_EXPORT QSet<QString> supportedMimeTypes(bool (*isValidFactory)(GstElementFactory *factory)); #if GST_CHECK_VERSION(1,0,0) - QImage bufferToImage(GstBuffer *buffer, const GstVideoInfo &info); - QVideoSurfaceFormat formatForCaps( + Q_GSTTOOLS_EXPORT QImage bufferToImage(GstBuffer *buffer, const GstVideoInfo &info); + Q_GSTTOOLS_EXPORT QVideoSurfaceFormat formatForCaps( GstCaps *caps, GstVideoInfo *info = 0, QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle); #else - QImage bufferToImage(GstBuffer *buffer); - QVideoSurfaceFormat formatForCaps( + Q_GSTTOOLS_EXPORT QImage bufferToImage(GstBuffer *buffer); + Q_GSTTOOLS_EXPORT QVideoSurfaceFormat formatForCaps( GstCaps *caps, int *bytesPerLine = 0, QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle); #endif - GstCaps *capsForFormats(const QList<QVideoFrame::PixelFormat> &formats); + Q_GSTTOOLS_EXPORT GstCaps *capsForFormats(const QList<QVideoFrame::PixelFormat> &formats); void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer); - void setMetaData(GstElement *element, const QMap<QByteArray, QVariant> &data); - void setMetaData(GstBin *bin, const QMap<QByteArray, QVariant> &data); + Q_GSTTOOLS_EXPORT void setMetaData(GstElement *element, const QMap<QByteArray, QVariant> &data); + Q_GSTTOOLS_EXPORT void setMetaData(GstBin *bin, const QMap<QByteArray, QVariant> &data); - GstCaps *videoFilterCaps(); + Q_GSTTOOLS_EXPORT GstCaps *videoFilterCaps(); - QSize structureResolution(const GstStructure *s); - QVideoFrame::PixelFormat structurePixelFormat(const GstStructure *s, int *bpp = 0); - QSize structurePixelAspectRatio(const GstStructure *s); - QPair<qreal, qreal> structureFrameRateRange(const GstStructure *s); + Q_GSTTOOLS_EXPORT QSize structureResolution(const GstStructure *s); + Q_GSTTOOLS_EXPORT QVideoFrame::PixelFormat structurePixelFormat(const GstStructure *s, int *bpp = 0); + Q_GSTTOOLS_EXPORT QSize structurePixelAspectRatio(const GstStructure *s); + Q_GSTTOOLS_EXPORT QPair<qreal, qreal> structureFrameRateRange(const GstStructure *s); - QString fileExtensionForMimeType(const QString &mimeType); + Q_GSTTOOLS_EXPORT QString fileExtensionForMimeType(const QString &mimeType); } -void qt_gst_object_ref_sink(gpointer object); -GstCaps *qt_gst_pad_get_current_caps(GstPad *pad); -GstCaps *qt_gst_pad_get_caps(GstPad *pad); -GstStructure *qt_gst_structure_new_empty(const char *name); -gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur); -gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur); -GstCaps *qt_gst_caps_normalize(GstCaps *caps); -const gchar *qt_gst_element_get_factory_name(GstElement *element); -gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2); -GList *qt_gst_video_sinks(); -void qt_gst_util_double_to_fraction(gdouble src, gint *dest_n, gint *dest_d); - -QDebug operator <<(QDebug debug, GstCaps *caps); +Q_GSTTOOLS_EXPORT void qt_gst_object_ref_sink(gpointer object); +Q_GSTTOOLS_EXPORT GstCaps *qt_gst_pad_get_current_caps(GstPad *pad); +Q_GSTTOOLS_EXPORT GstCaps *qt_gst_pad_get_caps(GstPad *pad); +Q_GSTTOOLS_EXPORT GstStructure *qt_gst_structure_new_empty(const char *name); +Q_GSTTOOLS_EXPORT gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur); +Q_GSTTOOLS_EXPORT gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur); +Q_GSTTOOLS_EXPORT GstCaps *qt_gst_caps_normalize(GstCaps *caps); +Q_GSTTOOLS_EXPORT const gchar *qt_gst_element_get_factory_name(GstElement *element); +Q_GSTTOOLS_EXPORT gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2); +Q_GSTTOOLS_EXPORT GList *qt_gst_video_sinks(); +Q_GSTTOOLS_EXPORT void qt_gst_util_double_to_fraction(gdouble src, gint *dest_n, gint *dest_d); + +Q_GSTTOOLS_EXPORT QDebug operator <<(QDebug debug, GstCaps *caps); QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h index d2802d9a2..c67c57021 100644 --- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h +++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qabstractvideobuffer.h> #include <QtCore/qvariant.h> @@ -60,14 +61,14 @@ QT_BEGIN_NAMESPACE #if GST_CHECK_VERSION(1,0,0) -class QGstVideoBuffer : public QAbstractPlanarVideoBuffer +class Q_GSTTOOLS_EXPORT QGstVideoBuffer : public QAbstractPlanarVideoBuffer { public: QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info); QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, HandleType handleType, const QVariant &handle); #else -class QGstVideoBuffer : public QAbstractVideoBuffer +class Q_GSTTOOLS_EXPORT QGstVideoBuffer : public QAbstractVideoBuffer { public: QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine); diff --git a/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h index 6a0c4c6bd..df36dbe09 100644 --- a/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h +++ b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qgsttools_global_p.h> #include <qabstractvideobuffer.h> #include <qvideosurfaceformat.h> #include <QtCore/qobject.h> @@ -64,7 +65,7 @@ class QAbstractVideoSurface; const QLatin1String QGstVideoRendererPluginKey("gstvideorenderer"); -class QGstVideoRenderer +class Q_GSTTOOLS_EXPORT QGstVideoRenderer { public: virtual ~QGstVideoRenderer() {} @@ -81,7 +82,7 @@ public: /* Abstract interface for video buffers allocation. */ -class QGstVideoRendererInterface +class Q_GSTTOOLS_EXPORT QGstVideoRendererInterface { public: virtual ~QGstVideoRendererInterface() {} @@ -92,7 +93,7 @@ public: #define QGstVideoRendererInterface_iid "org.qt-project.qt.gstvideorenderer/5.4" Q_DECLARE_INTERFACE(QGstVideoRendererInterface, QGstVideoRendererInterface_iid) -class QGstVideoRendererPlugin : public QObject, public QGstVideoRendererInterface +class Q_GSTTOOLS_EXPORT QGstVideoRendererPlugin : public QObject, public QGstVideoRendererInterface { Q_OBJECT Q_INTERFACES(QGstVideoRendererInterface) diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index 0f3f3ff6b..d5d8b40d3 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -72,9 +72,9 @@ ANDROID_JAR_DEPENDENCIES = \ jar/QtMultimedia.jar:org.qtproject.qt5.android.multimedia.QtMultimediaUtils ANDROID_LIB_DEPENDENCIES = \ plugins/mediaservice/libqtmedia_android.so \ - lib/libQt5MultimediaQuick_p.so:Qt5Quick + lib/libQt5MultimediaQuick.so:Qt5Quick ANDROID_BUNDLED_FILES += \ - lib/libQt5MultimediaQuick_p.so + lib/libQt5MultimediaQuick.so ANDROID_PERMISSIONS += \ android.permission.CAMERA \ android.permission.RECORD_AUDIO diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp index a4ad97251..3f24d0f55 100644 --- a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp +++ b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp @@ -42,6 +42,7 @@ #include "qmediacontent.h" #include "qmediaobject_p.h" #include "qplaylistfileparser_p.h" +#include "qrandom.h" QT_BEGIN_NAMESPACE @@ -266,7 +267,7 @@ void QMediaNetworkPlaylistProvider::shuffle() QList<QMediaContent> resources; while (!d->resources.isEmpty()) { - resources.append(d->resources.takeAt(qrand() % d->resources.size())); + resources.append(d->resources.takeAt(QRandomGenerator::global()->bounded(d->resources.size()))); } d->resources = resources; diff --git a/src/multimedia/playback/qmediaplaylistnavigator.cpp b/src/multimedia/playback/qmediaplaylistnavigator.cpp index 192fd463c..0966c9396 100644 --- a/src/multimedia/playback/qmediaplaylistnavigator.cpp +++ b/src/multimedia/playback/qmediaplaylistnavigator.cpp @@ -43,6 +43,7 @@ #include "qmediaobject_p.h" #include <QtCore/qdebug.h> +#include <QtCore/qrandom.h> QT_BEGIN_NAMESPACE @@ -124,7 +125,7 @@ int QMediaPlaylistNavigatorPrivate::nextItemPos(int steps) const randomModePositions.append(-1); int res = randomModePositions[randomPositionsOffset+steps]; if (res<0 || res >= playlist->mediaCount()) { - res = qrand() % playlist->mediaCount(); + res = QRandomGenerator::global()->bounded(playlist->mediaCount()); randomModePositions[randomPositionsOffset+steps] = res; } @@ -177,7 +178,7 @@ int QMediaPlaylistNavigatorPrivate::previousItemPos(int steps) const int res = randomModePositions[randomPositionsOffset-steps]; if (res<0 || res >= playlist->mediaCount()) { - res = qrand() % playlist->mediaCount(); + res = QRandomGenerator::global()->bounded(playlist->mediaCount()); randomModePositions[randomPositionsOffset-steps] = res; } diff --git a/src/multimedia/qmediaobject.cpp b/src/multimedia/qmediaobject.cpp index a2f0d58aa..71b2d148c 100644 --- a/src/multimedia/qmediaobject.cpp +++ b/src/multimedia/qmediaobject.cpp @@ -55,7 +55,13 @@ void QMediaObjectPrivate::_q_notify() const QMetaObject* m = q->metaObject(); - for (int pi : qAsConst(notifyProperties)) { + // QTBUG-57045 + // we create a copy of notifyProperties container to ensure that if a property is removed + // from the original container as a result of invoking propertyChanged signal, the iterator + // won't become invalidated + QSet<int> properties = notifyProperties; + + for (int pi : qAsConst(properties)) { QMetaProperty p = m->property(pi); p.notifySignal().invoke( q, QGenericArgument(QMetaType::typeName(p.userType()), p.read(q).data())); diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro index 8e4a78278..57d4194ec 100644 --- a/src/multimediawidgets/multimediawidgets.pro +++ b/src/multimediawidgets/multimediawidgets.pro @@ -28,4 +28,6 @@ qtConfig(graphicsview) { HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS +msvc:lessThan(QMAKE_MSC_VER, 1900): QMAKE_CXXFLAGS += -Zm200 + load(qt_module) diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp index 214e5ec7e..6e93e150d 100644 --- a/src/multimediawidgets/qpaintervideosurface.cpp +++ b/src/multimediawidgets/qpaintervideosurface.cpp @@ -191,6 +191,10 @@ QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::paint( m_imageSize.height(), m_frame.bytesPerLine(), m_imageFormat); + // Do not render into ARGB32 images using QPainter. + // Using QImage::Format_ARGB32_Premultiplied is significantly faster. + if (m_imageFormat == QImage::Format_ARGB32) + image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); const QTransform oldTransform = painter->transform(); QTransform transform = oldTransform; diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm index 7fd04250e..71ea31e5b 100644 --- a/src/plugins/avfoundation/camera/avfcameraservice.mm +++ b/src/plugins/avfoundation/camera/avfcameraservice.mm @@ -37,7 +37,6 @@ ** ****************************************************************************/ -#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qvariant.h> #include <QtCore/qdebug.h> @@ -95,9 +94,8 @@ AVFCameraService::AVFCameraService(QObject *parent): m_imageCaptureControl = new AVFImageCaptureControl(this); m_cameraFocusControl = new AVFCameraFocusControl(this); m_cameraExposureControl = 0; -#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) - m_cameraExposureControl = new AVFCameraExposureControl(this); +#ifdef Q_OS_IOS + m_cameraExposureControl = new AVFCameraExposureControl(this); #endif m_cameraZoomControl = 0; diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm index 872075e0f..22713d613 100644 --- a/src/plugins/avfoundation/camera/avfcamerautility.mm +++ b/src/plugins/avfoundation/camera/avfcamerautility.mm @@ -40,7 +40,6 @@ #include "avfcamerautility.h" #include "avfcameradebug.h" -#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qvector.h> #include <QtCore/qpair.h> #include <private/qmultimediautils_p.h> @@ -180,12 +179,10 @@ QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format) { Q_ASSERT(format); QSize res; -#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - const CMVideoDimensions hrDim(format.highResolutionStillImageDimensions); - res.setWidth(hrDim.width); - res.setHeight(hrDim.height); - } +#if defined(Q_OS_IOS) + const CMVideoDimensions hrDim(format.highResolutionStillImageDimensions); + res.setWidth(hrDim.width); + res.setHeight(hrDim.height); #endif return res; } diff --git a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm index 8384ce6ae..e858d93c4 100644 --- a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm +++ b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm @@ -48,7 +48,6 @@ #include <QtMultimedia/qmediaencodersettings.h> -#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qdebug.h> #include <AVFoundation/AVFoundation.h> @@ -94,17 +93,15 @@ QList<QSize> AVFImageEncoderControl::supportedResolutions(const QImageEncoderSet const QSize res(qt_device_format_resolution(format)); if (!res.isNull() && res.isValid()) resolutions << res; -#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - // From Apple's docs (iOS): - // By default, AVCaptureStillImageOutput emits images with the same dimensions as - // its source AVCaptureDevice instance’s activeFormat.formatDescription. However, - // if you set this property to YES, the receiver emits still images at the capture - // device’s highResolutionStillImageDimensions value. - const QSize hrRes(qt_device_format_high_resolution(format)); - if (!hrRes.isNull() && hrRes.isValid()) - resolutions << res; - } +#ifdef Q_OS_IOS + // From Apple's docs (iOS): + // By default, AVCaptureStillImageOutput emits images with the same dimensions as + // its source AVCaptureDevice instance’s activeFormat.formatDescription. However, + // if you set this property to YES, the receiver emits still images at the capture + // device’s highResolutionStillImageDimensions value. + const QSize hrRes(qt_device_format_high_resolution(format)); + if (!hrRes.isNull() && hrRes.isValid()) + resolutions << res; #endif } @@ -133,17 +130,15 @@ QImageEncoderSettings AVFImageEncoderControl::imageSettings() const } QSize res(qt_device_format_resolution(captureDevice.activeFormat)); -#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - if (!m_service->imageCaptureControl() || !m_service->imageCaptureControl()->stillImageOutput()) { - qDebugCamera() << Q_FUNC_INFO << "no still image output"; - return settings; - } - - AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput(); - if (stillImageOutput.highResolutionStillImageOutputEnabled) - res = qt_device_format_high_resolution(captureDevice.activeFormat); +#ifdef Q_OS_IOS + if (!m_service->imageCaptureControl() || !m_service->imageCaptureControl()->stillImageOutput()) { + qDebugCamera() << Q_FUNC_INFO << "no still image output"; + return settings; } + + AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput(); + if (stillImageOutput.highResolutionStillImageOutputEnabled) + res = qt_device_format_high_resolution(captureDevice.activeFormat); #endif if (res.isNull() || !res.isValid()) { qDebugCamera() << Q_FUNC_INFO << "failed to exctract the image resolution"; @@ -217,14 +212,12 @@ bool AVFImageEncoderControl::applySettings() activeFormatChanged = qt_set_active_format(captureDevice, match, true); -#if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput(); - if (res == qt_device_format_high_resolution(captureDevice.activeFormat)) - imageOutput.highResolutionStillImageOutputEnabled = YES; - else - imageOutput.highResolutionStillImageOutputEnabled = NO; - } +#ifdef Q_OS_IOS + AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput(); + if (res == qt_device_format_high_resolution(captureDevice.activeFormat)) + imageOutput.highResolutionStillImageOutputEnabled = YES; + else + imageOutput.highResolutionStillImageOutputEnabled = NO; #endif return activeFormatChanged; diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm index d657dc17d..0b31bd0bc 100644 --- a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm +++ b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm @@ -49,6 +49,7 @@ #include "avfmediacontainercontrol.h" #include "avfcamerautility.h" +#include <QtCore/qmath.h> #include <QtCore/qdebug.h> QT_USE_NAMESPACE @@ -273,14 +274,11 @@ void AVFMediaRecorderControlIOS::setState(QMediaRecorder::State state) else rotation = (screenOrientation + (360 - cameraInfo.orientation)) % 360; - // convert to radians - rotation *= M_PI / 180.f; - if ([m_writer setupWithFileURL:nsFileURL cameraService:m_service audioSettings:m_audioSettings videoSettings:m_videoSettings - transform:CGAffineTransformMakeRotation(rotation)]) { + transform:CGAffineTransformMakeRotation(qDegreesToRadians(rotation))]) { m_state = QMediaRecorder::RecordingState; m_lastStatus = QMediaRecorder::StartingStatus; diff --git a/src/plugins/common/evr/evrcustompresenter.cpp b/src/plugins/common/evr/evrcustompresenter.cpp index 38e8c3a8f..958204079 100644 --- a/src/plugins/common/evr/evrcustompresenter.cpp +++ b/src/plugins/common/evr/evrcustompresenter.cpp @@ -560,7 +560,6 @@ EVRCustomPresenter::EVRCustomPresenter(QAbstractVideoSurface *surface) , m_mediaType(0) , m_surface(0) , m_canRenderToSurface(false) - , m_sampleToPresent(0) { // Initial source rectangle = (0,0,1,1) m_sourceRect.top = 0; diff --git a/src/plugins/common/evr/evrcustompresenter.h b/src/plugins/common/evr/evrcustompresenter.h index 5c240ea95..199dee774 100644 --- a/src/plugins/common/evr/evrcustompresenter.h +++ b/src/plugins/common/evr/evrcustompresenter.h @@ -367,8 +367,6 @@ private: QAbstractVideoSurface *m_surface; bool m_canRenderToSurface; - - IMFSample *m_sampleToPresent; }; bool qt_evr_setCustomPresenter(IUnknown *evr, EVRCustomPresenter *presenter); diff --git a/src/plugins/common/evr/evrd3dpresentengine.cpp b/src/plugins/common/evr/evrd3dpresentengine.cpp index 043d0ad73..fd9ccdef1 100644 --- a/src/plugins/common/evr/evrd3dpresentengine.cpp +++ b/src/plugins/common/evr/evrd3dpresentengine.cpp @@ -49,7 +49,7 @@ #include <private/qmediaopenglhelper_p.h> #ifdef MAYBE_ANGLE -# include <qtgui/qguiapplication.h> +# include <qguiapplication.h> # include <qpa/qplatformnativeinterface.h> # include <qopenglfunctions.h> # include <EGL/eglext.h> diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro index 2857f87d9..54d617166 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -8,7 +8,13 @@ win32:!qtHaveModule(opengl)|qtConfig(dynamicgl) { HEADERS += dsserviceplugin.h SOURCES += dsserviceplugin.cpp -mingw: DEFINES += NO_DSHOW_STRSAFE +# Remove WINVER/_WIN32_WINNT definitions added to qt_build_config.prf +# by qtbase/d57a7c41712f8627a462d893329dc3f0dbb52d32 since the multimedia +# headers of MinGW 5.3/7.1 are too broken to compile with 0x0601. +mingw { + DEFINES -= WINVER=0x0601 _WIN32_WINNT=0x0601 + DEFINES += NO_DSHOW_STRSAFE +} include(common/common.pri) qtConfig(directshow-player): include(player/player.pri) diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri index cbe87be4f..d0c5c7bdd 100644 --- a/src/plugins/gstreamer/common.pri +++ b/src/plugins/gstreamer/common.pri @@ -1,12 +1,10 @@ -QT += core-private multimedia-private network +QT += core-private multimedia-private multimediagsttools-private network qtHaveModule(widgets) { QT += widgets multimediawidgets-private DEFINES += HAVE_WIDGETS } -LIBS += -lqgsttools_p - QMAKE_USE += gstreamer qtConfig(resourcepolicy): \ diff --git a/src/plugins/pulseaudio/qpulsehelpers.cpp b/src/plugins/pulseaudio/qpulsehelpers.cpp index 17579bdd9..0604c97f5 100644 --- a/src/plugins/pulseaudio/qpulsehelpers.cpp +++ b/src/plugins/pulseaudio/qpulsehelpers.cpp @@ -49,30 +49,23 @@ pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format) spec.rate = format.sampleRate(); spec.channels = format.channelCount(); - - if (format.sampleSize() == 8) { - spec.format = PA_SAMPLE_U8; - } else if (format.sampleSize() == 16) { - switch (format.byteOrder()) { - case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S16BE; break; - case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S16LE; break; - } - } else if (format.sampleSize() == 24) { - switch (format.byteOrder()) { - case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S24BE; break; - case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S24LE; break; - } - } else if (format.sampleSize() == 32) { - switch (format.byteOrder()) { - case QAudioFormat::BigEndian: - format.sampleType() == QAudioFormat::Float ? spec.format = PA_SAMPLE_FLOAT32BE : spec.format = PA_SAMPLE_S32BE; - break; - case QAudioFormat::LittleEndian: - format.sampleType() == QAudioFormat::Float ? spec.format = PA_SAMPLE_FLOAT32LE : spec.format = PA_SAMPLE_S32LE; - break; + spec.format = PA_SAMPLE_INVALID; + const bool isBigEndian = (format.byteOrder() == QAudioFormat::BigEndian); + + if (format.sampleType() == QAudioFormat::UnSignedInt) { + if (format.sampleSize() == 8) + spec.format = PA_SAMPLE_U8; + } else if (format.sampleType() == QAudioFormat::SignedInt) { + if (format.sampleSize() == 16) { + spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; + } else if (format.sampleSize() == 24) { + spec.format = isBigEndian ? PA_SAMPLE_S24BE : PA_SAMPLE_S24LE; + } else if (format.sampleSize() == 32) { + spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; } - } else { - spec.format = PA_SAMPLE_INVALID; + } else if (format.sampleType() == QAudioFormat::Float) { + if (format.sampleSize() == 32) + spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; } return spec; diff --git a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp index d08d01e6d..c4c09f543 100644 --- a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp +++ b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp @@ -43,19 +43,24 @@ #include <private/qaudiohelpers_p.h> +#pragma GCC diagnostic ignored "-Wvla" + QT_BEGIN_NAMESPACE QnxAudioOutput::QnxAudioOutput() - : m_source(0), - m_pushSource(false), - m_notifyInterval(1000), - m_error(QAudio::NoError), - m_state(QAudio::StoppedState), - m_volume(1.0), - m_periodSize(0), - m_pcmHandle(0), - m_bytesWritten(0), - m_intervalOffset(0) + : m_source(0) + , m_pushSource(false) + , m_notifyInterval(1000) + , m_error(QAudio::NoError) + , m_state(QAudio::StoppedState) + , m_volume(1.0) + , m_periodSize(0) + , m_pcmHandle(0) + , m_bytesWritten(0) + , m_intervalOffset(0) +#if _NTO_VERSION >= 700 + , m_pcmNotifier(0) +#endif { m_timer.setSingleShot(false); m_timer.setInterval(20); @@ -124,20 +129,16 @@ void QnxAudioOutput::reset() void QnxAudioOutput::suspend() { - m_timer.stop(); snd_pcm_playback_pause(m_pcmHandle); - setState(QAudio::SuspendedState); + if (state() != QAudio::InterruptedState) + suspendInternal(QAudio::SuspendedState); } void QnxAudioOutput::resume() { snd_pcm_playback_resume(m_pcmHandle); - if (m_pushSource) - setState(QAudio::IdleState); - else { - setState(QAudio::ActiveState); - m_timer.start(); - } + if (state() != QAudio::InterruptedState) + resumeInternal(); } int QnxAudioOutput::bytesFree() const @@ -146,6 +147,7 @@ int QnxAudioOutput::bytesFree() const return 0; snd_pcm_channel_status_t status; + memset(&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; const int errorCode = snd_pcm_plugin_status(m_pcmHandle, &status); @@ -214,9 +216,21 @@ qreal QnxAudioOutput::volume() const return m_volume; } +void QnxAudioOutput::setCategory(const QString &category) +{ + m_category = category; +} + +QString QnxAudioOutput::category() const +{ + return m_category; +} + void QnxAudioOutput::pullData() { - if (m_state == QAudio::StoppedState || m_state == QAudio::SuspendedState) + if (m_state == QAudio::StoppedState + || m_state == QAudio::SuspendedState + || m_state == QAudio::InterruptedState) return; const int bytesAvailable = bytesFree(); @@ -290,6 +304,8 @@ bool QnxAudioOutput::open() return false; } + addPcmEventFilter(); + // Necessary so that bytesFree() which uses the "free" member of the status struct works snd_pcm_plugin_set_disable(m_pcmHandle, PLUGIN_MMAP); @@ -303,6 +319,7 @@ bool QnxAudioOutput::open() } snd_pcm_channel_params_t params = QnxAudioUtils::formatToChannelParams(m_format, QAudio::AudioOutput, info.max_fragment_size); + setTypeName(¶ms); if ((errorCode = snd_pcm_plugin_params(m_pcmHandle, ¶ms)) < 0) { qWarning("QnxAudioOutput: open error, couldn't set channel params (0x%x)", -errorCode); @@ -331,6 +348,8 @@ bool QnxAudioOutput::open() m_intervalOffset = 0; m_bytesWritten = 0; + createPcmNotifiers(); + return true; } @@ -338,6 +357,8 @@ void QnxAudioOutput::close() { m_timer.stop(); + destroyPcmNotifiers(); + if (m_pcmHandle) { snd_pcm_plugin_flush(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK); snd_pcm_close(m_pcmHandle); @@ -400,6 +421,109 @@ qint64 QnxAudioOutput::write(const char *data, qint64 len) } } +void QnxAudioOutput::suspendInternal(QAudio::State suspendState) +{ + m_timer.stop(); + setState(suspendState); +} + +void QnxAudioOutput::resumeInternal() +{ + if (m_pushSource) { + setState(QAudio::IdleState); + } else { + setState(QAudio::ActiveState); + m_timer.start(); + } +} + +#if _NTO_VERSION >= 700 + +QAudio::State suspendState(const snd_pcm_event_t &event) +{ + Q_ASSERT(event.type == SND_PCM_EVENT_AUDIOMGMT_STATUS); + Q_ASSERT(event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED); + return event.data.audiomgmt_status.flags & SND_PCM_STATUS_EVENT_HARD_SUSPEND + ? QAudio::InterruptedState : QAudio::SuspendedState; +} + +void QnxAudioOutput::addPcmEventFilter() +{ + /* Enable PCM events */ + snd_pcm_filter_t filter; + memset(&filter, 0, sizeof(filter)); + filter.enable = (1<<SND_PCM_EVENT_AUDIOMGMT_STATUS) | + (1<<SND_PCM_EVENT_AUDIOMGMT_MUTE) | + (1<<SND_PCM_EVENT_OUTPUTCLASS); + snd_pcm_set_filter(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK, &filter); +} + +void QnxAudioOutput::createPcmNotifiers() +{ + // QSocketNotifier::Read for poll based event dispatcher. Exception for + // select based event dispatcher. + m_pcmNotifier = new QSocketNotifier(snd_pcm_file_descriptor(m_pcmHandle, + SND_PCM_CHANNEL_PLAYBACK), + QSocketNotifier::Read, this); + connect(m_pcmNotifier, &QSocketNotifier::activated, + this, &QnxAudioOutput::pcmNotifierActivated); +} + +void QnxAudioOutput::destroyPcmNotifiers() +{ + if (m_pcmNotifier) { + delete m_pcmNotifier; + m_pcmNotifier = 0; + } +} + +void QnxAudioOutput::setTypeName(snd_pcm_channel_params_t *params) +{ + if (m_category.isEmpty()) + return; + + QByteArray latin1Category = m_category.toLatin1(); + + if (QString::fromLatin1(latin1Category) != m_category) { + qWarning("QnxAudioOutput: audio category name isn't a Latin1 string."); + return; + } + + if (latin1Category.size() >= static_cast<int>(sizeof(params->audio_type_name))) { + qWarning("QnxAudioOutput: audio category name too long."); + return; + } + + strcpy(params->audio_type_name, latin1Category.constData()); +} + +void QnxAudioOutput::pcmNotifierActivated(int socket) +{ + Q_UNUSED(socket); + + snd_pcm_event_t pcm_event; + memset(&pcm_event, 0, sizeof(pcm_event)); + while (snd_pcm_channel_read_event(m_pcmHandle, SND_PCM_CHANNEL_PLAYBACK, &pcm_event) == 0) { + if (pcm_event.type == SND_PCM_EVENT_AUDIOMGMT_STATUS) { + if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_SUSPENDED) + suspendInternal(suspendState(pcm_event)); + else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_RUNNING) + resumeInternal(); + else if (pcm_event.data.audiomgmt_status.new_status == SND_PCM_STATUS_PAUSED) + suspendInternal(QAudio::SuspendedState); + } + } +} + +#else + +void QnxAudioOutput::addPcmEventFilter() {} +void QnxAudioOutput::createPcmNotifiers() {} +void QnxAudioOutput::destroyPcmNotifiers() {} +void QnxAudioOutput::setTypeName(snd_pcm_channel_params_t *) {} + +#endif + QnxPushIODevice::QnxPushIODevice(QnxAudioOutput *output) : QIODevice(output), m_output(output) diff --git a/src/plugins/qnx-audio/audio/qnxaudiooutput.h b/src/plugins/qnx-audio/audio/qnxaudiooutput.h index 5ee69b542..85aadf4b9 100644 --- a/src/plugins/qnx-audio/audio/qnxaudiooutput.h +++ b/src/plugins/qnx-audio/audio/qnxaudiooutput.h @@ -45,8 +45,10 @@ #include <QTime> #include <QTimer> #include <QIODevice> +#include <QSocketNotifier> #include <sys/asoundlib.h> +#include <sys/neutrino.h> QT_BEGIN_NAMESPACE @@ -80,6 +82,8 @@ public: QAudioFormat format() const Q_DECL_OVERRIDE; void setVolume(qreal volume) Q_DECL_OVERRIDE; qreal volume() const Q_DECL_OVERRIDE; + void setCategory(const QString &category) Q_DECL_OVERRIDE; + QString category() const Q_DECL_OVERRIDE; private slots: void pullData(); @@ -90,6 +94,14 @@ private: void setError(QAudio::Error error); void setState(QAudio::State state); + void addPcmEventFilter(); + void createPcmNotifiers(); + void destroyPcmNotifiers(); + void setTypeName(snd_pcm_channel_params_t *params); + + void suspendInternal(QAudio::State suspendState); + void resumeInternal(); + friend class QnxPushIODevice; qint64 write(const char *data, qint64 len); @@ -102,6 +114,7 @@ private: QAudio::State m_state; QAudioFormat m_format; qreal m_volume; + QString m_category; int m_periodSize; snd_pcm_t *m_pcmHandle; @@ -109,6 +122,13 @@ private: QTime m_startTimeStamp; QTime m_intervalTimeStamp; qint64 m_intervalOffset; + +#if _NTO_VERSION >= 700 + QSocketNotifier *m_pcmNotifier; + +private slots: + void pcmNotifierActivated(int socket); +#endif }; class QnxPushIODevice : public QIODevice diff --git a/src/plugins/qnx/mediaplayer/mediaplayer.pri b/src/plugins/qnx/mediaplayer/mediaplayer.pri index 4c4363a91..71bb98827 100644 --- a/src/plugins/qnx/mediaplayer/mediaplayer.pri +++ b/src/plugins/qnx/mediaplayer/mediaplayer.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD HEADERS += \ + $$PWD/mmrendereraudiorolecontrol.h \ $$PWD/mmrenderermediaplayercontrol.h \ $$PWD/mmrenderermediaplayerservice.h \ $$PWD/mmrenderermetadata.h \ @@ -11,6 +12,7 @@ HEADERS += \ $$PWD/mmreventmediaplayercontrol.h \ $$PWD/mmreventthread.h SOURCES += \ + $$PWD/mmrendereraudiorolecontrol.cpp \ $$PWD/mmrenderermediaplayercontrol.cpp \ $$PWD/mmrenderermediaplayerservice.cpp \ $$PWD/mmrenderermetadata.cpp \ diff --git a/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.cpp new file mode 100644 index 000000000..e470ed4c5 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "mmrendereraudiorolecontrol.h" +#include "mmrendererutil.h" + +QT_BEGIN_NAMESPACE + +MmRendererAudioRoleControl::MmRendererAudioRoleControl(QObject *parent) + : QAudioRoleControl(parent) + , m_role(QAudio::UnknownRole) +{ +} + +QAudio::Role MmRendererAudioRoleControl::audioRole() const +{ + return m_role; +} + +void MmRendererAudioRoleControl::setAudioRole(QAudio::Role role) +{ + if (m_role != role) { + m_role = role; + emit audioRoleChanged(m_role); + } +} + +QList<QAudio::Role> MmRendererAudioRoleControl::supportedAudioRoles() const +{ + return qnxSupportedAudioRoles(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.h b/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.h new file mode 100644 index 000000000..7458d3512 --- /dev/null +++ b/src/plugins/qnx/mediaplayer/mmrendereraudiorolecontrol.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MMRENDERERAUDIOROLECONTROL_H +#define MMRENDERERAUDIOROLECONTROL_H + +#include <qaudiorolecontrol.h> + +QT_BEGIN_NAMESPACE + +class MmRendererAudioRoleControl : public QAudioRoleControl +{ + Q_OBJECT +public: + explicit MmRendererAudioRoleControl(QObject *parent = 0); + + QAudio::Role audioRole() const Q_DECL_OVERRIDE; + void setAudioRole(QAudio::Role role) Q_DECL_OVERRIDE; + + QList<QAudio::Role> supportedAudioRoles() const Q_DECL_OVERRIDE; + +private: + QAudio::Role m_role; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index d8b0a3934..55116f642 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -36,6 +36,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "mmrendereraudiorolecontrol.h" #include "mmrenderermediaplayercontrol.h" #include "mmrenderermetadatareadercontrol.h" #include "mmrendererplayervideorenderercontrol.h" @@ -70,7 +71,6 @@ MmRendererMediaPlayerControl::MmRendererMediaPlayerControl(QObject *parent) m_mediaStatus(QMediaPlayer::NoMedia), m_playAfterMediaLoaded(false), m_inputAttached(false), - m_stopEventsToIgnore(0), m_bufferLevel(0) { m_loadingTimer.setSingleShot(true); @@ -109,30 +109,12 @@ void MmRendererMediaPlayerControl::openConnection() startMonitoring(); } -void MmRendererMediaPlayerControl::handleMmStatusUpdate(qint64 newPosition) -{ - // Prevent spurious position change events from overriding our own position, for example - // when setting the position to 0 in stop(). - // Also, don't change the position while we're loading the media, as then play() would - // set a wrong initial position. - if (m_state != QMediaPlayer::PlayingState || - m_mediaStatus == QMediaPlayer::LoadingMedia || - m_mediaStatus == QMediaPlayer::NoMedia || - m_mediaStatus == QMediaPlayer::InvalidMedia) - return; - - setMmPosition(newPosition); -} - void MmRendererMediaPlayerControl::handleMmStopped() { // Only react to stop events that happen when the end of the stream is reached and // playback is stopped because of this. - // Ignore other stop event sources, souch as calling mmr_stop() ourselves and - // mmr_input_attach(). - if (m_stopEventsToIgnore > 0) { - --m_stopEventsToIgnore; - } else { + // Ignore other stop event sources, such as calling mmr_stop() ourselves. + if (m_state != QMediaPlayer::StoppedState) { setMediaStatus(QMediaPlayer::EndOfMedia); stopInternal(IgnoreMmRenderer); } @@ -197,6 +179,17 @@ void MmRendererMediaPlayerControl::attach() return; } + if (m_audioId != -1 && m_audioRoleControl) { + QString audioType = qnxAudioType(m_audioRoleControl->audioRole()); + QByteArray latin1AudioType = audioType.toLatin1(); + if (!audioType.isEmpty() && latin1AudioType == audioType) { + strm_dict_t *dict = strm_dict_new(); + dict = strm_dict_set(dict, "audio_type", latin1AudioType.constData()); + if (mmr_output_parameters(m_context, m_audioId, dict) != 0) + emitMmError("mmr_output_parameters: Setting audio_type failed"); + } + } + const QByteArray resourcePath = resourcePathForUrl(m_media.canonicalUrl()); if (resourcePath.isEmpty()) { detach(); @@ -210,11 +203,6 @@ void MmRendererMediaPlayerControl::attach() return; } - // For whatever reason, the mmrenderer sends out a MMR_STOPPED event when calling - // mmr_input_attach() above. Ignore it, as otherwise we'll trigger stopping right after we - // started. - m_stopEventsToIgnore++; - m_inputAttached = true; setMediaStatus(QMediaPlayer::LoadedMedia); @@ -351,7 +339,6 @@ void MmRendererMediaPlayerControl::stopInternal(StopCommand stopCommand) if (m_state != QMediaPlayer::StoppedState) { if (stopCommand == StopMmRenderer) { - ++m_stopEventsToIgnore; mmr_stop(m_context); } @@ -519,7 +506,6 @@ void MmRendererMediaPlayerControl::play() return; } - m_stopEventsToIgnore = 0; // once playing, stop events must be proccessed setState( QMediaPlayer::PlayingState); } @@ -556,6 +542,11 @@ void MmRendererMediaPlayerControl::setMetaDataReaderControl(MmRendererMetaDataRe m_metaDataReaderControl = metaDataReaderControl; } +void MmRendererMediaPlayerControl::setAudioRoleControl(MmRendererAudioRoleControl *audioRoleControl) +{ + m_audioRoleControl = audioRoleControl; +} + void MmRendererMediaPlayerControl::setMmPosition(qint64 newPosition) { if (newPosition != 0 && newPosition != m_position) { diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h index 2edbd50e0..ffa80bd27 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h @@ -52,6 +52,7 @@ typedef struct strm_dict strm_dict_t; QT_BEGIN_NAMESPACE +class MmRendererAudioRoleControl; class MmRendererMetaDataReaderControl; class MmRendererPlayerVideoRendererControl; class MmRendererVideoWindowControl; @@ -103,6 +104,7 @@ public: MmRendererVideoWindowControl *videoWindowControl() const; void setVideoWindowControl(MmRendererVideoWindowControl *videoControl); void setMetaDataReaderControl(MmRendererMetaDataReaderControl *metaDataReaderControl); + void setAudioRoleControl(MmRendererAudioRoleControl *audioRoleControl); protected: virtual void startMonitoring() = 0; @@ -115,7 +117,6 @@ protected: void setMmBufferStatus(const QString &bufferStatus); void setMmBufferLevel(const QString &bufferLevel); void handleMmStopped(); - void handleMmStatusUpdate(qint64 position); void updateMetaData(const strm_dict_t *dict); // must be called from subclass dtors (calls virtual function stopMonitoring()) @@ -156,12 +157,12 @@ private: QPointer<MmRendererPlayerVideoRendererControl> m_videoRendererControl; QPointer<MmRendererVideoWindowControl> m_videoWindowControl; QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl; + QPointer<MmRendererAudioRoleControl> m_audioRoleControl; MmRendererMetaData m_metaData; qint64 m_position; QMediaPlayer::MediaStatus m_mediaStatus; bool m_playAfterMediaLoaded; bool m_inputAttached; - int m_stopEventsToIgnore; int m_bufferLevel; QTimer m_loadingTimer; }; diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp index 1258d199c..257c437ce 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "mmrenderermediaplayerservice.h" +#include "mmrendereraudiorolecontrol.h" #include "mmrenderermediaplayercontrol.h" #include "mmrenderermetadatareadercontrol.h" #include "mmrendererplayervideorenderercontrol.h" @@ -66,6 +67,7 @@ MmRendererMediaPlayerService::~MmRendererMediaPlayerService() delete m_videoWindowControl; delete m_mediaPlayerControl; delete m_metaDataReaderControl; + delete m_audioRoleControl; } QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name) @@ -76,15 +78,19 @@ QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name) updateControls(); } return m_mediaPlayerControl; - } - else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { + } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { if (!m_metaDataReaderControl) { m_metaDataReaderControl = new MmRendererMetaDataReaderControl(); updateControls(); } return m_metaDataReaderControl; - } - else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { + } else if (qstrcmp(name, QAudioRoleControl_iid) == 0) { + if (!m_audioRoleControl) { + m_audioRoleControl = new MmRendererAudioRoleControl(); + updateControls(); + } + return m_audioRoleControl; + } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { if (!m_appHasDrmPermissionChecked) { m_appHasDrmPermission = checkForDrmPermission(); m_appHasDrmPermissionChecked = true; @@ -102,8 +108,7 @@ QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name) updateControls(); } return m_videoRendererControl; - } - else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { + } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { if (!m_videoWindowControl) { m_videoWindowControl = new MmRendererVideoWindowControl(); updateControls(); @@ -123,6 +128,8 @@ void MmRendererMediaPlayerService::releaseControl(QMediaControl *control) m_mediaPlayerControl = 0; if (control == m_metaDataReaderControl) m_metaDataReaderControl = 0; + if (control == m_audioRoleControl) + m_audioRoleControl = 0; delete control; } @@ -136,6 +143,9 @@ void MmRendererMediaPlayerService::updateControls() if (m_metaDataReaderControl && m_mediaPlayerControl) m_mediaPlayerControl->setMetaDataReaderControl(m_metaDataReaderControl); + + if (m_audioRoleControl && m_mediaPlayerControl) + m_mediaPlayerControl->setAudioRoleControl(m_audioRoleControl); } QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h index de85293cb..9434b85b2 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h @@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE +class MmRendererAudioRoleControl; class MmRendererMediaPlayerControl; class MmRendererMetaDataReaderControl; class MmRendererPlayerVideoRendererControl; @@ -66,6 +67,7 @@ private: QPointer<MmRendererVideoWindowControl> m_videoWindowControl; QPointer<MmRendererMediaPlayerControl> m_mediaPlayerControl; QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl; + QPointer<MmRendererAudioRoleControl> m_audioRoleControl; bool m_appHasDrmPermission : 1; bool m_appHasDrmPermissionChecked : 1; diff --git a/src/plugins/qnx/mediaplayer/mmrendererutil.cpp b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp index 239d9d52e..7a9f6393b 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererutil.cpp +++ b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp @@ -41,6 +41,11 @@ #include <QDebug> #include <QDir> #include <QFile> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonValue> +#include <QMutex> +#include <QMutex> #include <QString> #include <QXmlStreamReader> @@ -85,6 +90,91 @@ static const MmError mmErrors[] = { }; static const unsigned int numMmErrors = sizeof(mmErrors) / sizeof(MmError); +static QBasicMutex roleMapMutex; +static bool roleMapInitialized = false; +static QString roleMap[QAudio::GameRole + 1]; + +template <typename T, size_t N> +constexpr size_t countof(T (&)[N]) +{ + return N; +} + +constexpr bool inBounds(QAudio::Role r) +{ + return r >= 0 && r < countof(roleMap); +} + +QString keyValueMapsLocation() +{ + QByteArray qtKeyValueMaps = qgetenv("QT_KEY_VALUE_MAPS"); + if (qtKeyValueMaps.isNull()) + return QStringLiteral("/etc/qt/keyvaluemaps"); + else + return qtKeyValueMaps; +} + +QJsonObject loadMapObject(const QString &keyValueMapPath) +{ + QFile mapFile(keyValueMapsLocation() + keyValueMapPath); + if (mapFile.open(QIODevice::ReadOnly)) { + QByteArray mapFileContents = mapFile.readAll(); + QJsonDocument mapDocument = QJsonDocument::fromJson(mapFileContents); + if (mapDocument.isObject()) { + QJsonObject mapObject = mapDocument.object(); + return mapObject; + } + } + return QJsonObject(); +} + +static void loadRoleMap() +{ + QMutexLocker locker(&roleMapMutex); + + if (!roleMapInitialized) { + QJsonObject mapObject = loadMapObject("/QAudio/Role.json"); + if (!mapObject.isEmpty()) { + // Wrapping the loads in a switch like this ensures that anyone adding + // a new enumerator will be notified that this code must be updated. A + // compile error will occur because the enumerator is missing from the + // switch. A compile error will also occur if the enumerator used to + // size the mapping table isn't updated when a new enumerator is added. + // One or more enumerators will be outside the bounds of the array when + // the wrong enumerator is used to size the array. + // + // The code loads a mapping for each enumerator because role is set + // to UnknownRole and all the cases drop through to the next case. +#pragma GCC diagnostic push +#pragma GCC diagnostic error "-Wswitch" +#define loadRoleMapping(r) \ + case QAudio::r: \ + static_assert(inBounds(QAudio::r), #r " out-of-bounds." \ + " Do you need to change the enumerator used to size the mapping table" \ + " because you added new QAudio::Role enumerators?"); \ + roleMap[QAudio::r] = mapObject.value(QLatin1String(#r)).toString(); + + QAudio::Role role = QAudio::UnknownRole; + switch (role) { + loadRoleMapping(UnknownRole); + loadRoleMapping(MusicRole); + loadRoleMapping(VideoRole); + loadRoleMapping(VoiceCommunicationRole); + loadRoleMapping(AlarmRole); + loadRoleMapping(NotificationRole); + loadRoleMapping(RingtoneRole); + loadRoleMapping(AccessibilityRole); + loadRoleMapping(SonificationRole); + loadRoleMapping(GameRole); + } +#undef loadRoleMapping +#pragma GCC diagnostic pop + } + + roleMapInitialized = true; + } +} + QString mmErrorMessage(const QString &msg, mmr_context_t *context, int *errorCode) { const mmr_error_info_t * const mmError = mmr_error_info(context); @@ -124,4 +214,27 @@ bool checkForDrmPermission() return false; } +QString qnxAudioType(QAudio::Role role) +{ + loadRoleMap(); + + if (role >= 0 && role < countof(roleMap)) + return roleMap[role]; + else + return QString(); +} + +QList<QAudio::Role> qnxSupportedAudioRoles() +{ + loadRoleMap(); + + QList<QAudio::Role> result; + for (size_t i = 0; i < countof(roleMap); ++i) { + if (!roleMap[i].isEmpty() || (i == QAudio::UnknownRole)) + result.append(static_cast<QAudio::Role>(i)); + } + + return result; +} + QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendererutil.h b/src/plugins/qnx/mediaplayer/mmrendererutil.h index 8017b2690..ac6f73a7d 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererutil.h +++ b/src/plugins/qnx/mediaplayer/mmrendererutil.h @@ -40,6 +40,7 @@ #define MMRENDERERUTIL_H #include <QtCore/qglobal.h> +#include <QtMultimedia/qaudio.h> typedef struct mmr_context mmr_context_t; @@ -51,6 +52,9 @@ QString mmErrorMessage(const QString &msg, mmr_context_t *context, int * errorCo bool checkForDrmPermission(); +QString qnxAudioType(QAudio::Role role); +QList<QAudio::Role> qnxSupportedAudioRoles(); + QT_END_NAMESPACE #endif diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.h b/src/plugins/windowsaudio/qwindowsaudiooutput.h index 19b4b92af..f25475b02 100644 --- a/src/plugins/windowsaudio/qwindowsaudiooutput.h +++ b/src/plugins/windowsaudio/qwindowsaudiooutput.h @@ -116,7 +116,6 @@ private slots: private: QByteArray m_device; - bool resuming; int bytesAvailable; QTime timeStamp; qint64 elapsedTimeOffset; @@ -139,8 +138,6 @@ private: WAVEFORMATEXTENSIBLE wfx; HWAVEOUT hWaveOut; - MMRESULT result; - WAVEHDR header; WAVEHDR* waveBlocks; volatile bool finished; volatile int waveFreeBlockCount; diff --git a/src/plugins/wmf/mfstream.cpp b/src/plugins/wmf/mfstream.cpp index fd95bf20b..a98b5a704 100644 --- a/src/plugins/wmf/mfstream.cpp +++ b/src/plugins/wmf/mfstream.cpp @@ -231,6 +231,8 @@ STDMETHODIMP MFStream::Seek( qint64 pos = qint64(llSeekOffset); switch (SeekOrigin) { + case msoBegin: + break; case msoCurrent: pos += m_stream->pos(); break; diff --git a/src/plugins/wmf/player/mfmetadatacontrol.cpp b/src/plugins/wmf/player/mfmetadatacontrol.cpp index 01be95e84..ac57ccfb5 100644 --- a/src/plugins/wmf/player/mfmetadatacontrol.cpp +++ b/src/plugins/wmf/player/mfmetadatacontrol.cpp @@ -193,6 +193,11 @@ QVariant MFMetaDataControl::metaData(const QString &key) const if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_FrameWidth, &var))) res.setWidth(convertValue(var).toUInt()); value = res; + } else if (key == QMediaMetaData::Orientation) { + uint orientation = 0; + if (m_content && SUCCEEDED(m_content->GetValue(PKEY_Video_Orientation, &var))) + orientation = convertValue(var).toUInt(); + value = orientation; } else if (key == QMediaMetaData::PixelAspectRatio) { QSize aspectRatio; aspectRatio.setWidth(value.toUInt()); @@ -352,6 +357,8 @@ void MFMetaDataControl::updateSource(IMFPresentationDescriptor* sourcePD, IMFMed m_availableMetaDatas.push_back(QMediaMetaData::ThumbnailImage); } else if (key == PKEY_Video_FrameHeight) { m_availableMetaDatas.push_back(QMediaMetaData::Resolution); + } else if (key == PKEY_Video_Orientation) { + m_availableMetaDatas.push_back(QMediaMetaData::Orientation); } else if (key == PKEY_Video_HorizontalAspectRatio) { m_availableMetaDatas.push_back(QMediaMetaData::PixelAspectRatio); } else if (key == PKEY_Video_FrameRate) { diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro index e4e157a54..bffdc6ec2 100644 --- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro +++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro @@ -1,4 +1,4 @@ -TARGET = QtMultimediaQuick_p +TARGET = QtMultimediaQuick QT = core quick multimedia-private CONFIG += internal_module diff --git a/sync.profile b/sync.profile index 4623849da..2ac22b5bd 100644 --- a/sync.profile +++ b/sync.profile @@ -1,7 +1,8 @@ %modules = ( # path to module name map "QtMultimedia" => "$basedir/src/multimedia", "QtMultimediaWidgets" => "$basedir/src/multimediawidgets", - "QtMultimediaQuick_p" => "$basedir/src/qtmultimediaquicktools", + "QtMultimediaQuick" => "$basedir/src/qtmultimediaquicktools", + "QtMultimediaGstTools" => "$basedir/src/gsttools", ); %moduleheaders = ( # restrict the module headers to those found in relative path diff --git a/tests/auto/integration/multimedia.pro b/tests/auto/integration/multimedia.pro index de152d942..88960ec03 100644 --- a/tests/auto/integration/multimedia.pro +++ b/tests/auto/integration/multimedia.pro @@ -17,6 +17,3 @@ qtHaveModule(quick) { } !qtHaveModule(widgets): SUBDIRS -= qcamerabackend - -# QTBUG-60268 -boot2qt: SUBDIRS -= qdeclarativevideooutput_window diff --git a/tests/auto/integration/qaudiodecoderbackend/BLACKLIST b/tests/auto/integration/qaudiodecoderbackend/BLACKLIST index 8b6712728..316c5a083 100644 --- a/tests/auto/integration/qaudiodecoderbackend/BLACKLIST +++ b/tests/auto/integration/qaudiodecoderbackend/BLACKLIST @@ -1,10 +1,2 @@ # QTBUG-56796 windows - -[fileTest] -# QTBUG-60268 -b2qt - -[deviceTest] -# QTBUG-60268 -b2qt diff --git a/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro b/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro index 7464a8aa2..672bcfa6a 100644 --- a/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro +++ b/tests/auto/integration/qaudiodecoderbackend/qaudiodecoderbackend.pro @@ -9,5 +9,13 @@ TESTDATA += testdata/* INCLUDEPATH += \ ../../../../src/multimedia/audio +HEADERS += \ + ../shared/mediafileselector.h + SOURCES += \ tst_qaudiodecoderbackend.cpp + +boot2qt: { + # Yocto sysroot does not have gstreamer/wav + QMAKE_CXXFLAGS += -DWAV_SUPPORT_NOT_FORCED +} diff --git a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp index 2af06b46c..1e582d14b 100644 --- a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp +++ b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp @@ -30,6 +30,8 @@ #include <QDebug> #include "qaudiodecoder.h" +#include "../shared/mediafileselector.h" + #define TEST_FILE_NAME "testdata/test.wav" #define TEST_UNSUPPORTED_FILE_NAME "testdata/test-unsupported.avi" #define TEST_CORRUPTED_FILE_NAME "testdata/test-corrupted.wav" @@ -56,6 +58,9 @@ private slots: void unsupportedFileTest(); void corruptedFileTest(); void deviceTest(); + +private: + bool isWavSupported(); }; void tst_QAudioDecoderBackend::init() @@ -67,14 +72,28 @@ void tst_QAudioDecoderBackend::initTestCase() QAudioDecoder d; if (!d.isAvailable()) QSKIP("Audio decoder service is not available"); + + qRegisterMetaType<QMediaContent>(); } void tst_QAudioDecoderBackend::cleanup() { } +bool tst_QAudioDecoderBackend::isWavSupported() +{ +#ifdef WAV_SUPPORT_NOT_FORCED + return !MediaFileSelector::selectMediaFile(QStringList() << QFINDTESTDATA(TEST_FILE_NAME)).isNull(); +#else + return true; +#endif +} + void tst_QAudioDecoderBackend::fileTest() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QAudioDecoder d; if (d.error() == QAudioDecoder::ServiceMissingError) QSKIP("There is no audio decoding support on this platform."); @@ -411,6 +430,9 @@ void tst_QAudioDecoderBackend::corruptedFileTest() void tst_QAudioDecoderBackend::deviceTest() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QAudioDecoder d; if (d.error() == QAudioDecoder::ServiceMissingError) QSKIP("There is no audio decoding support on this platform."); diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST index 4f8656e0a..8aa622881 100644 --- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST +++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST @@ -9,13 +9,9 @@ opensuse-13.1 64bit [loadMedia] windows 64bit developer-build -# QTBUG-60268 -b2qt [unloadMedia] windows 64bit developer-build -# QTBUG-60268 -b2qt [playPauseStop] linux @@ -23,18 +19,12 @@ windows 64bit developer-build [processEOS] windows 64bit developer-build -# QTBUG-60268 -b2qt [deleteLaterAtEOS] windows 64bit developer-build -# QTBUG-60268 -b2qt [initialVolume] windows 64bit developer-build -# QTBUG-60268 -b2qt [playlist] redhatenterpriselinuxworkstation-6.6 @@ -53,7 +43,3 @@ redhatenterpriselinuxworkstation-6.6 [surfaceTest] redhatenterpriselinuxworkstation-6.6 - -[playlistObject] -# QTBUG-60268 -b2qt diff --git a/tests/auto/integration/qmediaplayerbackend/qmediaplayerbackend.pro b/tests/auto/integration/qmediaplayerbackend/qmediaplayerbackend.pro index 919fae91d..b9417f7c2 100644 --- a/tests/auto/integration/qmediaplayerbackend/qmediaplayerbackend.pro +++ b/tests/auto/integration/qmediaplayerbackend/qmediaplayerbackend.pro @@ -9,9 +9,14 @@ CONFIG += testcase SOURCES += \ tst_qmediaplayerbackend.cpp +HEADERS += \ + ../shared/mediafileselector.h + TESTDATA += testdata/* boot2qt: { + # Yocto sysroot does not have gstreamer/wav + QMAKE_CXXFLAGS += -DWAV_SUPPORT_NOT_FORCED # OGV testing is unstable with qemu QMAKE_CXXFLAGS += -DSKIP_OGV_TEST } diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp index 9fe0a39ec..082e81b34 100644 --- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp +++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -36,6 +36,7 @@ #include <qmediaplaylist.h> #include <qmediametadata.h> +#include "../shared/mediafileselector.h" //TESTED_COMPONENT=src/multimedia QT_USE_NAMESPACE @@ -79,7 +80,7 @@ private slots: private: QMediaContent selectVideoFile(const QStringList& mediaCandidates); - QMediaContent selectMediaFile(const QStringList& mediaCandidates); + bool isWavSupported(); //one second local wav file QMediaContent localWavFile; @@ -171,31 +172,13 @@ QMediaContent tst_QMediaPlayerBackend::selectVideoFile(const QStringList& mediaC return QMediaContent(); } -QMediaContent tst_QMediaPlayerBackend::selectMediaFile(const QStringList& mediaCandidates) +bool tst_QMediaPlayerBackend::isWavSupported() { - QMediaPlayer player; - - QSignalSpy errorSpy(&player, SIGNAL(error(QMediaPlayer::Error))); - - foreach (QString s, mediaCandidates) { - QFileInfo mediaFile(s); - if (!mediaFile.exists()) - continue; - QMediaContent media = QMediaContent(QUrl::fromLocalFile(mediaFile.absoluteFilePath())); - player.setMedia(media); - player.play(); - - for (int i = 0; i < 2000 && player.mediaStatus() != QMediaPlayer::BufferedMedia && errorSpy.isEmpty(); i+=50) { - QTest::qWait(50); - } - - if (player.mediaStatus() == QMediaPlayer::BufferedMedia && errorSpy.isEmpty()) { - return media; - } - errorSpy.clear(); - } - - return QMediaContent(); +#ifdef WAV_SUPPORT_NOT_FORCED + return !localWavFile.isNull(); +#else + return true; +#endif } void tst_QMediaPlayerBackend::initTestCase() @@ -204,35 +187,24 @@ void tst_QMediaPlayerBackend::initTestCase() if (!player.isAvailable()) QSKIP("Media player service is not available"); - const QString testFileName = QFINDTESTDATA("testdata/test.wav"); - QFileInfo wavFile(testFileName); - - QVERIFY(wavFile.exists()); - - localWavFile = QMediaContent(QUrl::fromLocalFile(wavFile.absoluteFilePath())); - - const QString testFileName2 = QFINDTESTDATA("testdata/_test.wav"); - QFileInfo wavFile2(testFileName2); - - QVERIFY(wavFile2.exists()); - - localWavFile2 = QMediaContent(QUrl::fromLocalFile(wavFile2.absoluteFilePath())); - qRegisterMetaType<QMediaContent>(); + localWavFile = MediaFileSelector::selectMediaFile(QStringList() << QFINDTESTDATA("testdata/test.wav")); + localWavFile2 = MediaFileSelector::selectMediaFile(QStringList() << QFINDTESTDATA("testdata/_test.wav"));; + QStringList mediaCandidates; mediaCandidates << QFINDTESTDATA("testdata/colors.mp4"); #ifndef SKIP_OGV_TEST mediaCandidates << QFINDTESTDATA("testdata/colors.ogv"); #endif - localVideoFile = selectMediaFile(mediaCandidates); + localVideoFile = MediaFileSelector::selectMediaFile(mediaCandidates); mediaCandidates.clear(); mediaCandidates << QFINDTESTDATA("testdata/nokia-tune.mp3"); mediaCandidates << QFINDTESTDATA("testdata/nokia-tune.mkv"); - localCompressedSoundFile = selectMediaFile(mediaCandidates); + localCompressedSoundFile = MediaFileSelector::selectMediaFile(mediaCandidates); - localFileWithMetadata = selectMediaFile(QStringList() << QFINDTESTDATA("testdata/nokia-tune.mp3")); + localFileWithMetadata = MediaFileSelector::selectMediaFile(QStringList() << QFINDTESTDATA("testdata/nokia-tune.mp3")); qgetenv("QT_TEST_CI").toInt(&m_inCISystem,10); } @@ -249,7 +221,11 @@ void tst_QMediaPlayerBackend::construction() void tst_QMediaPlayerBackend::loadMedia() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QMediaPlayer player; + QCOMPARE(player.state(), QMediaPlayer::StoppedState); QCOMPARE(player.mediaStatus(), QMediaPlayer::NoMedia); @@ -281,6 +257,9 @@ void tst_QMediaPlayerBackend::loadMedia() void tst_QMediaPlayerBackend::unloadMedia() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QMediaPlayer player; player.setNotifyInterval(50); @@ -339,6 +318,9 @@ void tst_QMediaPlayerBackend::loadMediaInLoadingState() void tst_QMediaPlayerBackend::playPauseStop() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QMediaPlayer player; player.setNotifyInterval(50); @@ -491,6 +473,9 @@ void tst_QMediaPlayerBackend::playPauseStop() void tst_QMediaPlayerBackend::processEOS() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QMediaPlayer player; player.setNotifyInterval(50); @@ -623,6 +608,9 @@ private: // QTBUG-24927 - deleteLater() called to QMediaPlayer from its signal handler does not work as expected void tst_QMediaPlayerBackend::deleteLaterAtEOS() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QPointer<QMediaPlayer> player(new QMediaPlayer); DeleteLaterAtEos deleter(player); player->setMedia(localWavFile); @@ -747,6 +735,9 @@ void tst_QMediaPlayerBackend::volumeAcrossFiles() void tst_QMediaPlayerBackend::initialVolume() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + { QMediaPlayer player; player.setVolume(1); @@ -1206,6 +1197,9 @@ void tst_QMediaPlayerBackend::playlist() void tst_QMediaPlayerBackend::playlistObject() { + if (!isWavSupported()) + QSKIP("Sound format is not supported"); + QMediaPlayer player; QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent))); diff --git a/tests/auto/integration/shared/mediafileselector.h b/tests/auto/integration/shared/mediafileselector.h new file mode 100644 index 000000000..8b88d14a4 --- /dev/null +++ b/tests/auto/integration/shared/mediafileselector.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MEDIAFILESELECTOR_H +#define MEDIAFILESELECTOR_H + +#include <QMediaContent> +#include <QMediaPlayer> + +QT_BEGIN_NAMESPACE + +namespace MediaFileSelector { + +static QMediaContent selectMediaFile(const QStringList& mediaCandidates) +{ + QMediaPlayer player; + + QSignalSpy errorSpy(&player, SIGNAL(error(QMediaPlayer::Error))); + + foreach (QString s, mediaCandidates) { + QFileInfo mediaFile(s); + if (!mediaFile.exists()) + continue; + QMediaContent media = QMediaContent(QUrl::fromLocalFile(mediaFile.absoluteFilePath())); + player.setMedia(media); + player.play(); + + for (int i = 0; i < 2000 && player.mediaStatus() != QMediaPlayer::BufferedMedia && errorSpy.isEmpty(); i+=50) { + QTest::qWait(50); + } + + if (player.mediaStatus() == QMediaPlayer::BufferedMedia && errorSpy.isEmpty()) { + return media; + } + errorSpy.clear(); + } + + return QMediaContent(); +} + +} // MediaFileSelector namespace + +QT_END_NAMESPACE + +#endif + diff --git a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp index 4b2136a5c..c2f18d2a4 100644 --- a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp +++ b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp @@ -557,6 +557,11 @@ void tst_QPainterVideoSurface::shaderType() { QPainterVideoSurface surface; QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); @@ -649,6 +654,11 @@ void tst_QPainterVideoSurface::shaderTypeStarted() QFETCH(QPainterVideoSurface::ShaderType, shaderType); QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); @@ -894,6 +904,11 @@ void tst_QPainterVideoSurface::shaderSupportedFormat() QFETCH(bool, supportedFormat); QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); @@ -1011,6 +1026,11 @@ void tst_QPainterVideoSurface::shaderPresent() QFETCH(int, bytesPerLineB); QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); @@ -1142,6 +1162,11 @@ void tst_QPainterVideoSurface::shaderPresentOpaqueFrame() QFETCH(QPainterVideoSurface::ShaderType, shaderType); QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); @@ -1191,6 +1216,11 @@ void tst_QPainterVideoSurface::shaderPresentGLFrame() QFETCH(QPainterVideoSurface::ShaderType, shaderType); QGLWidget widget; + if (!widget.context() + || !widget.context()->isValid()) { + QSKIP("Platform does not support GLContext"); + } + widget.show(); QTest::qWaitForWindowExposed(&widget); widget.makeCurrent(); |