diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2023-01-30 17:18:50 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2023-02-08 10:17:39 +0100 |
commit | e3c0c190136a55634451024cfa3ac8024c74caa3 (patch) | |
tree | 59880c5e4b9901fa9bbf302191b549024d5226f0 | |
parent | ed04adaf7cffa247fd2b5fee9b5b53b0269997ab (diff) | |
download | qtmultimedia-e3c0c190136a55634451024cfa3ac8024c74caa3.tar.gz |
Adjust multimedia examples to use new QPermission API
Now when the library itself does not request permissions, that needs
to be done on the user application level.
This patch updates all examples to query the required permissions.
As there is no QML API yet, the QML examples do it directly from
main.
Note: the WRITE_EXTERNAL_STORAGE Android permission is not handled
by this patch, because it's currently not supported by the QPermission
API.
Task-number: QTBUG-109965
Change-Id: Iaeb09f9e32fced0ecb0f5ffc63d40c64ec386cfb
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r-- | examples/multimedia/audiodevices/audiodevices.cpp | 35 | ||||
-rw-r--r-- | examples/multimedia/audiodevices/audiodevices.h | 1 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.cpp | 58 | ||||
-rw-r--r-- | examples/multimedia/audiorecorder/audiorecorder.h | 1 | ||||
-rw-r--r-- | examples/multimedia/audiosource/audiosource.cpp | 38 | ||||
-rw-r--r-- | examples/multimedia/audiosource/audiosource.h | 2 | ||||
-rw-r--r-- | examples/multimedia/camera/camera.cpp | 44 | ||||
-rw-r--r-- | examples/multimedia/camera/camera.h | 2 | ||||
-rw-r--r-- | examples/multimedia/declarative-camera/qmlcamera.cpp | 33 | ||||
-rw-r--r-- | examples/multimedia/spectrum/engine.cpp | 31 | ||||
-rw-r--r-- | examples/multimedia/spectrum/engine.h | 5 | ||||
-rw-r--r-- | examples/multimedia/video/qmlvideo/main.cpp | 23 | ||||
-rw-r--r-- | examples/multimedia/video/recorder/CMakeLists.txt | 1 | ||||
-rw-r--r-- | examples/multimedia/video/recorder/main.cpp | 28 | ||||
-rw-r--r-- | examples/multimedia/video/recorder/main_no_permissions.qml | 26 |
15 files changed, 295 insertions, 33 deletions
diff --git a/examples/multimedia/audiodevices/audiodevices.cpp b/examples/multimedia/audiodevices/audiodevices.cpp index 018983e92..453f055f7 100644 --- a/examples/multimedia/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audiodevices/audiodevices.cpp @@ -7,6 +7,10 @@ #include <QMediaDevices> #include <QMediaFormat> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + // Utility functions for converting QAudioFormat fields into text static QString toString(QAudioFormat::SampleFormat sampleFormat) @@ -34,6 +38,37 @@ AudioDevicesBase::~AudioDevicesBase() = default; AudioTest::AudioTest(QWidget *parent) : AudioDevicesBase(parent), m_devices(new QMediaDevices(this)) { + init(); +} + +void AudioTest::init() +{ +#if QT_CONFIG(permissions) + // camera + QCameraPermission cameraPermission; + switch (qApp->checkPermission(cameraPermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(cameraPermission, this, &AudioTest::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Camera permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } + // microphone + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &AudioTest::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif m_devices->videoInputs(); qDebug() << "<<<<<<<<<<<<<<<<<<"; QMediaFormat().supportedFileFormats(QMediaFormat::Encode); diff --git a/examples/multimedia/audiodevices/audiodevices.h b/examples/multimedia/audiodevices/audiodevices.h index ad1de73e1..efe4e373c 100644 --- a/examples/multimedia/audiodevices/audiodevices.h +++ b/examples/multimedia/audiodevices/audiodevices.h @@ -32,6 +32,7 @@ private: QMediaDevices *m_devices = nullptr; private slots: + void init(); void updateAudioDevices(); void modeChanged(int idx); void deviceChanged(int idx); diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp index f96a925b8..8d97ce705 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.cpp +++ b/examples/multimedia/audiorecorder/audiorecorder.cpp @@ -17,12 +17,53 @@ #include <QMimeType> #include <QStandardPaths> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + static QList<qreal> getBufferLevels(const QAudioBuffer &buffer); AudioRecorder::AudioRecorder() : ui(new Ui::AudioRecorder) { ui->setupUi(this); + // channels + ui->channelsBox->addItem(tr("Default"), QVariant(-1)); + ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1)); + ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2)); + ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4)); + + // quality + ui->qualitySlider->setRange(0, int(QImageCapture::VeryHighQuality)); + ui->qualitySlider->setValue(int(QImageCapture::NormalQuality)); + + // bit rates: + ui->bitrateBox->addItem(tr("Default"), QVariant(0)); + ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000)); + ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000)); + ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000)); + ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000)); + + // audio input initialization + init(); +} + +void AudioRecorder::init() +{ +#if QT_CONFIG(permissions) + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &AudioRecorder::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif + m_audioRecorder = new QMediaRecorder(this); m_captureSession.setRecorder(m_audioRecorder); m_captureSession.setAudioInput(new QAudioInput(this)); @@ -52,23 +93,6 @@ AudioRecorder::AudioRecorder() : ui(new Ui::AudioRecorder) qBound(m_captureSession.audioInput()->device().minimumSampleRate(), 44100, m_captureSession.audioInput()->device().maximumSampleRate())); - // channels - ui->channelsBox->addItem(tr("Default"), QVariant(-1)); - ui->channelsBox->addItem(QStringLiteral("1"), QVariant(1)); - ui->channelsBox->addItem(QStringLiteral("2"), QVariant(2)); - ui->channelsBox->addItem(QStringLiteral("4"), QVariant(4)); - - // quality - ui->qualitySlider->setRange(0, int(QImageCapture::VeryHighQuality)); - ui->qualitySlider->setValue(int(QImageCapture::NormalQuality)); - - // bit rates: - ui->bitrateBox->addItem(tr("Default"), QVariant(0)); - ui->bitrateBox->addItem(QStringLiteral("32000"), QVariant(32000)); - ui->bitrateBox->addItem(QStringLiteral("64000"), QVariant(64000)); - ui->bitrateBox->addItem(QStringLiteral("96000"), QVariant(96000)); - ui->bitrateBox->addItem(QStringLiteral("128000"), QVariant(128000)); - connect(m_audioRecorder, &QMediaRecorder::durationChanged, this, &AudioRecorder::updateProgress); connect(m_audioRecorder, &QMediaRecorder::recorderStateChanged, this, diff --git a/examples/multimedia/audiorecorder/audiorecorder.h b/examples/multimedia/audiorecorder/audiorecorder.h index 830e4b001..47d7ed1e2 100644 --- a/examples/multimedia/audiorecorder/audiorecorder.h +++ b/examples/multimedia/audiorecorder/audiorecorder.h @@ -29,6 +29,7 @@ public slots: void processBuffer(const QAudioBuffer &); private slots: + void init(); void setOutputLocation(); void togglePause(); void toggleRecord(); diff --git a/examples/multimedia/audiosource/audiosource.cpp b/examples/multimedia/audiosource/audiosource.cpp index 39a7f3b32..8a06191c5 100644 --- a/examples/multimedia/audiosource/audiosource.cpp +++ b/examples/multimedia/audiosource/audiosource.cpp @@ -7,10 +7,16 @@ #include <QAudioSource> #include <QDateTime> #include <QDebug> +#include <QLabel> #include <QPainter> #include <QVBoxLayout> #include <QtEndian> +#if QT_CONFIG(permissions) + #include <QCoreApplication> + #include <QPermission> +#endif + #include <math.h> #include <stdlib.h> @@ -92,8 +98,7 @@ void RenderArea::setLevel(qreal value) InputTest::InputTest() : m_devices(new QMediaDevices(this)) { - initializeWindow(); - initializeAudio(QMediaDevices::defaultAudioInput()); + init(); } void InputTest::initializeWindow() @@ -147,6 +152,35 @@ void InputTest::initializeAudio(const QAudioDevice &deviceInfo) toggleMode(); } +void InputTest::initializeErrorWindow() +{ + QVBoxLayout *layout = new QVBoxLayout(this); + QLabel *errorLabel = new QLabel(tr("Microphone permission is not granted!")); + errorLabel->setWordWrap(true); + errorLabel->setAlignment(Qt::AlignCenter); + layout->addWidget(errorLabel); +} + +void InputTest::init() +{ +#if QT_CONFIG(permissions) + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &InputTest::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + initializeErrorWindow(); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif + initializeWindow(); + initializeAudio(QMediaDevices::defaultAudioInput()); +} + void InputTest::toggleMode() { m_audioInput->stop(); diff --git a/examples/multimedia/audiosource/audiosource.h b/examples/multimedia/audiosource/audiosource.h index 05b891fe7..dd9a7bc4a 100644 --- a/examples/multimedia/audiosource/audiosource.h +++ b/examples/multimedia/audiosource/audiosource.h @@ -68,8 +68,10 @@ public: private: void initializeWindow(); void initializeAudio(const QAudioDevice &deviceInfo); + void initializeErrorWindow(); private slots: + void init(); void toggleMode(); void toggleSuspend(); void deviceChanged(int index); diff --git a/examples/multimedia/camera/camera.cpp b/examples/multimedia/camera/camera.cpp index 221dd58e0..5fd8837f6 100644 --- a/examples/multimedia/camera/camera.cpp +++ b/examples/multimedia/camera/camera.cpp @@ -30,9 +30,53 @@ #include <QTimer> #include <QVideoWidget> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + Camera::Camera() : ui(new Ui::Camera) { ui->setupUi(this); + // disable all buttons by default + updateCameraActive(false); + readyForCapture(false); + ui->recordButton->setEnabled(false); + ui->pauseButton->setEnabled(false); + ui->stopButton->setEnabled(false); + ui->metaDataButton->setEnabled(false); + + // try to actually initialize camera & mic + init(); +} + +void Camera::init() +{ +#if QT_CONFIG(permissions) + // camera + QCameraPermission cameraPermission; + switch (qApp->checkPermission(cameraPermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(cameraPermission, this, &Camera::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Camera permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } + // microphone + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &Camera::init); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif m_audioInput.reset(new QAudioInput); m_captureSession.setAudioInput(m_audioInput.get()); diff --git a/examples/multimedia/camera/camera.h b/examples/multimedia/camera/camera.h index 4ba58a770..c92aa2d6a 100644 --- a/examples/multimedia/camera/camera.h +++ b/examples/multimedia/camera/camera.h @@ -35,6 +35,8 @@ public slots: void saveMetaData(); private slots: + void init(); + void setCamera(const QCameraDevice &cameraDevice); void startCamera(); diff --git a/examples/multimedia/declarative-camera/qmlcamera.cpp b/examples/multimedia/declarative-camera/qmlcamera.cpp index 347b7684f..d399ecd1b 100644 --- a/examples/multimedia/declarative-camera/qmlcamera.cpp +++ b/examples/multimedia/declarative-camera/qmlcamera.cpp @@ -5,16 +5,37 @@ #include <QQmlEngine> #include <QQuickView> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); - // Qt.quit() called in embedded .qml by default only emits - // quit() signal, so do this (optionally use Qt.exit()). - QObject::connect(view.engine(), &QQmlEngine::quit, qApp, &QGuiApplication::quit); - view.setSource(QUrl("qrc:///declarative-camera.qml")); - view.resize(800, 480); - view.show(); + + auto setupView = [&view]() { + // Qt.quit() called in embedded .qml by default only emits + // quit() signal, so do this (optionally use Qt.exit()). + QObject::connect(view.engine(), &QQmlEngine::quit, qApp, &QGuiApplication::quit); + view.setSource(QUrl("qrc:///declarative-camera.qml")); + view.resize(800, 480); + view.show(); + }; + +#if QT_CONFIG(permissions) + QCameraPermission cameraPermission; + qApp->requestPermission(cameraPermission, [&setupView](const QPermission &permission) { + // Show UI in any case. If there is no permission, the UI will just + // be disabled. + if (permission.status() != Qt::PermissionStatus::Granted) + qWarning("Camera permission is not granted!"); + setupView(); + }); +#else + setupView(); +#endif + return app.exec(); } diff --git a/examples/multimedia/spectrum/engine.cpp b/examples/multimedia/spectrum/engine.cpp index 296d4e4dd..cb7aeadcb 100644 --- a/examples/multimedia/spectrum/engine.cpp +++ b/examples/multimedia/spectrum/engine.cpp @@ -14,6 +14,10 @@ #include <QSet> #include <QThread> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + #include <math.h> //----------------------------------------------------------------------------- @@ -37,13 +41,9 @@ Engine::Engine(QObject *parent) m_generateTone(false), m_file(nullptr), m_analysisFile(nullptr), - m_availableAudioInputDevices(m_devices->audioInputs()), - m_audioInputDevice(m_devices->defaultAudioInput()), m_audioInput(nullptr), m_audioInputIODevice(nullptr), m_recordPosition(0), - m_availableAudioOutputDevices(m_devices->audioOutputs()), - m_audioOutputDevice(m_devices->defaultAudioOutput()), m_audioOutput(nullptr), m_playPosition(0), m_bufferPosition(0), @@ -68,6 +68,8 @@ Engine::Engine(QObject *parent) break; } + initAudioDevices(); + initialize(); #ifdef DUMP_DATA @@ -272,6 +274,27 @@ void Engine::setAudioOutputDevice(const QAudioDevice &device) // Private slots //----------------------------------------------------------------------------- +void Engine::initAudioDevices() +{ +#if QT_CONFIG(permissions) + QMicrophonePermission microphonePermission; + switch (qApp->checkPermission(microphonePermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(microphonePermission, this, &Engine::initAudioDevices); + return; + case Qt::PermissionStatus::Denied: + qWarning("Microphone permission is not granted!"); + return; + case Qt::PermissionStatus::Granted: + break; + } +#endif + m_availableAudioInputDevices = m_devices->audioInputs(); + m_audioInputDevice = m_devices->defaultAudioInput(); + m_availableAudioOutputDevices = m_devices->audioOutputs(); + m_audioOutputDevice = m_devices->defaultAudioOutput(); +} + void Engine::audioNotify() { switch (m_mode) { diff --git a/examples/multimedia/spectrum/engine.h b/examples/multimedia/spectrum/engine.h index 0ac454484..9e8ba51d0 100644 --- a/examples/multimedia/spectrum/engine.h +++ b/examples/multimedia/spectrum/engine.h @@ -203,6 +203,7 @@ signals: void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer); private slots: + void initAudioDevices(); void audioNotify(); void audioStateChanged(QAudio::State state); void audioDataReady(); @@ -251,13 +252,13 @@ private: QAudioFormat m_format; - const QList<QAudioDevice> m_availableAudioInputDevices; + QList<QAudioDevice> m_availableAudioInputDevices; QAudioDevice m_audioInputDevice; QAudioSource *m_audioInput; QIODevice *m_audioInputIODevice; qint64 m_recordPosition; - const QList<QAudioDevice> m_availableAudioOutputDevices; + QList<QAudioDevice> m_availableAudioOutputDevices; QAudioDevice m_audioOutputDevice; QAudioSink *m_audioOutput; qint64 m_playPosition; diff --git a/examples/multimedia/video/qmlvideo/main.cpp b/examples/multimedia/video/qmlvideo/main.cpp index a63146df0..c8d5fa048 100644 --- a/examples/multimedia/video/qmlvideo/main.cpp +++ b/examples/multimedia/video/qmlvideo/main.cpp @@ -16,6 +16,10 @@ #include <QString> #include <QStringList> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + static const QString DefaultFileName1 = ""; static const QString DefaultFileName2 = ""; @@ -99,8 +103,23 @@ int main(int argc, char *argv[]) QMetaObject::invokeMethod(rootObject, "init"); - viewer.setMinimumSize(QSize(640, 360)); - viewer.show(); + auto setupView = [&viewer]() { + viewer.setMinimumSize(QSize(640, 360)); + viewer.show(); + }; + +#if QT_CONFIG(permissions) + QCameraPermission cameraPermission; + qApp->requestPermission(cameraPermission, [&setupView](const QPermission &permission) { + // Show UI in any case. If there is no permission, the UI will just + // be disabled. + if (permission.status() != Qt::PermissionStatus::Granted) + qWarning("Camera permission is not granted! Camera will not be available."); + setupView(); + }); +#else + setupView(); +#endif return app.exec(); } diff --git a/examples/multimedia/video/recorder/CMakeLists.txt b/examples/multimedia/video/recorder/CMakeLists.txt index 96077b732..ec84533e4 100644 --- a/examples/multimedia/video/recorder/CMakeLists.txt +++ b/examples/multimedia/video/recorder/CMakeLists.txt @@ -21,6 +21,7 @@ qt_add_executable(recorder set(resource_files "main.qml" + "main_no_permissions.qml" "qmldir" "MediaList.qml" "AudioInputSelect.qml" diff --git a/examples/multimedia/video/recorder/main.cpp b/examples/multimedia/video/recorder/main.cpp index 195290319..92e54cb1b 100644 --- a/examples/multimedia/video/recorder/main.cpp +++ b/examples/multimedia/video/recorder/main.cpp @@ -4,6 +4,10 @@ #include <QGuiApplication> #include <QQmlApplicationEngine> +#if QT_CONFIG(permissions) + #include <QPermission> +#endif + int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); @@ -17,7 +21,31 @@ int main(int argc, char *argv[]) QCoreApplication::exit(-1); }, Qt::QueuedConnection); + +#if QT_CONFIG(permissions) + // If the permissions are not granted, display another main window, which + // simply contains the error message. + const QUrl noPermissionsUrl(QStringLiteral("qrc:/main_no_permissions.qml")); + QCameraPermission cameraPermission; + qApp->requestPermission(cameraPermission, [&](const QPermission &permission) { + if (permission.status() != Qt::PermissionStatus::Granted) { + qWarning("Camera permission is not granted!"); + engine.load(noPermissionsUrl); + return; + } + QMicrophonePermission micPermission; + qApp->requestPermission(micPermission, [&](const QPermission &permission) { + if (permission.status() != Qt::PermissionStatus::Granted) { + qWarning("Microphone permission is not granted!"); + engine.load(noPermissionsUrl); + } else { + engine.load(url); + } + }); + }); +#else engine.load(url); +#endif return app.exec(); } diff --git a/examples/multimedia/video/recorder/main_no_permissions.qml b/examples/multimedia/video/recorder/main_no_permissions.qml new file mode 100644 index 000000000..8c76533b0 --- /dev/null +++ b/examples/multimedia/video/recorder/main_no_permissions.qml @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window + +Window { + id: root + visible: true + title: "Media recorder" + width: Style.screenWidth + height: Style.screenHeigth + + StyleRectangle { + anchors.fill: parent + Text { + anchors.fill: parent + anchors.margins: 20 + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: qsTr("The example is not usable without the permissions.\n" + + "Please grant all requested permissions and restart the application.") + } + } +} |