diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-08 23:43:04 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-08 23:43:04 +0200 |
commit | c3ea9be0d49ec1eecda9d07e933d5426ed52670a (patch) | |
tree | 2522225f27fdf1a139b167ea612a5bb016e4eb22 | |
parent | 11eb454e7f53a5ddc81458b57afe2605c8fa5d4d (diff) | |
parent | d32aff3e0453475c1a22d5e8c7a106df18c0ad10 (diff) | |
download | qtmultimedia-c3ea9be0d49ec1eecda9d07e933d5426ed52670a.tar.gz |
Merge remote-tracking branch 'origin/5.7' into dev
Change-Id: Ie1331c18854bea488c773807597f8ad209437657
189 files changed, 3051 insertions, 838 deletions
diff --git a/config.tests/alsa/alsatest.cpp b/config.tests/alsa/alsatest.cpp index 5ee77f2ac..ea511cd21 100644 --- a/config.tests/alsa/alsatest.cpp +++ b/config.tests/alsa/alsatest.cpp @@ -27,7 +27,7 @@ ****************************************************************************/ #include <alsa/asoundlib.h> -#if (!(SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 10))) +#if SND_LIB_VERSION < 0x1000a // 1.0.10 #error "Alsa version found too old, require >= 1.0.10" #endif diff --git a/config.tests/directshow/directshow.pro b/config.tests/directshow/directshow.pro index 6493e54ab..6dfc54a01 100644 --- a/config.tests/directshow/directshow.pro +++ b/config.tests/directshow/directshow.pro @@ -3,4 +3,4 @@ CONFIG += console SOURCES += main.cpp -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 +!wince: LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 diff --git a/config.tests/directshow/main.cpp b/config.tests/directshow/main.cpp index 25e36f966..bb9a304ec 100644 --- a/config.tests/directshow/main.cpp +++ b/config.tests/directshow/main.cpp @@ -27,8 +27,10 @@ ****************************************************************************/ #include <dshow.h> +#ifndef _WIN32_WCE #include <d3d9.h> #include <vmr9.h> +#endif int main(int, char**) { diff --git a/dist/changes-5.6.0 b/dist/changes-5.6.0 new file mode 100644 index 000000000..5051431f8 --- /dev/null +++ b/dist/changes-5.6.0 @@ -0,0 +1,138 @@ +Qt 5.6 introduces many new features and improvements as well as bugfixes +over the 5.5.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.6 + +The Qt version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + + - QAudioOutput now transitions to IdleState instead of ActiveState when + calling resume() in push mode. This was already the documented behavior + but in practice, it was not respected on any platform. See QTBUG-50390. + + - DirectShow is now the default backend on all desktop versions of Windows, + regardless of the compiler used. The Windows Media Foundation backend + (WMF) can be re-enabled by configuring Qt with the -wmf-backend option. + See QTBUG-45597. + +**************************************************************************** +* Library * +**************************************************************************** + +QtMultimedia +------------ + + - Added new Playlist QML type. + + - Audio Engine QML types + * All types can now be created dynamically and added to the engine + using new 'add' functions. + + - MediaPlayer, Audio and Video (QML): + * Added new audio role API. + * Added playlist support. + + - QMediaPlayer: + * Added new audio role API. + + - [QTBUG-49838] Fixed crash when playing very short WAV files with + QSoundEffect. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - QAudioOutput: improved detection of the default buffer size and sample + rate. + - [QTBUG-35416] Camera QVideoFrames can now me mapped when retrieved using + QAbstractVideoSurface or QVideoProbe. + - [QTBUG-37837] Fixed crash when recording the camera on specific devices. + - [QTBUG-46491] Fixed media player blocking the UI when loading a media. + - [QTBUG-49134] Fixed crash when starting the camera on specific devices. + - [QTBUG-50282] Fixed QAudioRecorder crashing when trying to start it + with invalid settings. + +iOS / OS X +---------- + + - Greatly improved performance of displaying camera frames using the QML + VideoOutput type on iOS. + - Camera capture previews from the imageCaptured() signal are now in higher + resolutions. + - QMediaPlayer::isSeekable() (and QML counterpart) now correctly reports + the seekable status. + - QAudioRecorder::setVolume() is now functional. + - [QTBUG-45570] Fixed media player playback rate not working when set + before calling play(). + - [QTBUG-48057] Media player now correctly seeks as soon as playback starts + when the position is changed before calling play(). + - [QTBUG-48154] Fixed media player volume not working when set before + loading a media. + - [QTBUG-49170] It is not necessary anymore to set a viewfinder on a + QCamera to be able to query the supported viewfinder settings. + - [QTBUG-49170] Fixed QCamera ignoring the resolution set in + QCameraViewfinderSettings. + +Linux +----- + + - QCameraImageProcessing is now functional. + - [QTBUG-49531] Fixed QMediaPlayer not being able to play the same resource + file more than once. + +QNX +--- + + - QAudioRecorder::setVolume() is now functional. + - [QTBUG-49668] Fixed 'loops' property not working for Audio, Video and + MediaPlayer QML types. + +Windows +------- + + - [QTBUG-45593] The DirectShow backend now supports HW-accelerated video + decoding. + - The QML MediaPlayer and Video types previously supported HW-accelerated + video decoding only when using the ANGLE OpenGL implementation. It now + works with desktop OpenGL as well. + - QAudioRecorder::setVolume() is now functional. + - QCameraImageProcessing is now functional. + - Fixed media player volume not working when set before a media is loaded. + - Fixed QVideoFrame::startTime() not returning any value. + - Fixed seek requests never being processed when QMediaPlayer::setPosition() + is called while the media is not playing. + +WinRT +----- + + - Improved camera support: focus, focus lock and video probe APIs are now + functional. + - [QTBUG-47465] Fixed camera viewfinder aspect ratio. + - [QTBUG-47809] Fixed camera frames being upside down after switching + between front and back cameras. + - [QTBUG-48331][QTBUG-49660] Fixed camera viewfinder frames not being + displayed on the Lumia 930 and 1520. + - [QTBUG-48534] Fixed QCamera::searchAndLock() blocking the UI. + - [QTBUG-48569] Fixed crash when resuming an application that uses the + camera. + - [QTBUG-48672] Fixed crash when mapping camera frames after the camera + has stopped. + - [QTBUG-49236] Fixed playback of local files. + - [QTBUG-49347] Fixed crash when the application is suspended while + a camera focus lock is in progress. diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp index f3bf9f805..fd73d4f16 100644 --- a/examples/multimedia/audioinput/audioinput.cpp +++ b/examples/multimedia/audioinput/audioinput.cpp @@ -237,7 +237,7 @@ InputTest::InputTest() , m_audioInfo(0) , m_audioInput(0) , m_input(0) - , m_pullMode(false) + , m_pullMode(true) , m_buffer(BufferSize, 0) { initializeWindow(); @@ -291,8 +291,6 @@ void InputTest::initializeWindow() void InputTest::initializeAudio() { - m_pullMode = true; - m_format.setSampleRate(8000); m_format.setChannelCount(1); m_format.setSampleSize(16); @@ -300,12 +298,14 @@ void InputTest::initializeAudio() m_format.setByteOrder(QAudioFormat::LittleEndian); m_format.setCodec("audio/pcm"); - QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice()); + QAudioDeviceInfo info(m_device); if (!info.isFormatSupported(m_format)) { qWarning() << "Default format not supported - trying to use nearest"; m_format = info.nearestFormat(m_format); } + if (m_audioInfo) + delete m_audioInfo; m_audioInfo = new AudioInfo(m_format, this); connect(m_audioInfo, SIGNAL(update()), SLOT(refreshDisplay())); @@ -381,7 +381,7 @@ void InputTest::deviceChanged(int index) delete m_audioInput; m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>(); - createAudioInput(); + initializeAudio(); } void InputTest::sliderChanged(int value) diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp index 9368a611e..a00ffbb00 100644 --- a/examples/multimedia/audiooutput/audiooutput.cpp +++ b/examples/multimedia/audiooutput/audiooutput.cpp @@ -167,6 +167,7 @@ AudioTest::AudioTest() , m_generator(0) , m_audioOutput(0) , m_output(0) + , m_pullMode(true) , m_buffer(BufferSize, 0) { initializeWindow(); @@ -222,8 +223,6 @@ void AudioTest::initializeAudio() { connect(m_pushTimer, SIGNAL(timeout()), SLOT(pushTimerExpired())); - m_pullMode = true; - m_format.setSampleRate(DataSampleRateHz); m_format.setChannelCount(1); m_format.setSampleSize(16); @@ -231,12 +230,14 @@ void AudioTest::initializeAudio() m_format.setByteOrder(QAudioFormat::LittleEndian); m_format.setSampleType(QAudioFormat::SignedInt); - QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); + QAudioDeviceInfo info(m_device); if (!info.isFormatSupported(m_format)) { qWarning() << "Default format not supported - trying to use nearest"; m_format = info.nearestFormat(m_format); } + if (m_generator) + delete m_generator; m_generator = new Generator(m_format, DurationSeconds*1000000, ToneSampleRateHz, this); createAudioOutput(); @@ -264,7 +265,7 @@ void AudioTest::deviceChanged(int index) m_audioOutput->stop(); m_audioOutput->disconnect(this); m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>(); - createAudioOutput(); + initializeAudio(); } void AudioTest::volumeChanged(int value) diff --git a/examples/multimedia/audiooutput/doc/images/audiooutput-example.png b/examples/multimedia/audiooutput/doc/images/audiooutput-example.png Binary files differindex 5588fbb57..1abf5571f 100644 --- a/examples/multimedia/audiooutput/doc/images/audiooutput-example.png +++ b/examples/multimedia/audiooutput/doc/images/audiooutput-example.png diff --git a/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png b/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png Binary files differindex 5b29174c5..882180b21 100644 --- a/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png +++ b/examples/multimedia/declarative-radio/doc/images/declarative-radio-example.png diff --git a/examples/multimedia/spectrum/app/images/record.png b/examples/multimedia/spectrum/app/images/record.png Binary files differindex e7493aad9..184fce809 100644 --- a/examples/multimedia/spectrum/app/images/record.png +++ b/examples/multimedia/spectrum/app/images/record.png diff --git a/examples/multimedia/spectrum/doc/images/spectrum-demo.png b/examples/multimedia/spectrum/doc/images/spectrum-demo.png Binary files differindex 9ccb489a9..077cbb68d 100644 --- a/examples/multimedia/spectrum/doc/images/spectrum-demo.png +++ b/examples/multimedia/spectrum/doc/images/spectrum-demo.png diff --git a/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml b/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml deleted file mode 100644 index 0612d484c..000000000 --- a/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0"?> -<manifest package="org.qtproject.example.qmlvideofx" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> - <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name"> - <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:launchMode="singleTop"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.LAUNCHER"/> - </intent-filter> - <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> - <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> - <meta-data android:name="android.app.repository" android:value="default"/> - <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> - <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> - <!-- Deploy Qt libs as part of package --> - <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> - <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> - <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/> - <!-- Run with local libs --> - <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> - <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> - <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/> - <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> - <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> - <!-- Messages maps --> - <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/> - <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/> - <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/> - <!-- Messages maps --> - - <!-- Splash screen --> - <!-- - <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/> - --> - <!-- Splash screen --> - </activity> - </application> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="14"/> - <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> - - <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. - Remove the comment if you do not require these default permissions. --> - <!-- %%INSERT_PERMISSIONS --> - - <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application. - Remove the comment if you do not require these default features. --> - <!-- %%INSERT_FEATURES --> - -</manifest> diff --git a/examples/multimedia/video/qmlvideofx/images/qt-logo.png b/examples/multimedia/video/qmlvideofx/images/qt-logo.png Binary files differindex 7d3e97eb3..ecbff0ca3 100644 --- a/examples/multimedia/video/qmlvideofx/images/qt-logo.png +++ b/examples/multimedia/video/qmlvideofx/images/qt-logo.png diff --git a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro index e9633954c..678ba4c97 100644 --- a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro +++ b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro @@ -13,9 +13,4 @@ include($$PWD/../snippets/performancemonitor/performancemonitordeclarative.pri) target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/video/qmlvideofx INSTALLS += target -ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android - -OTHER_FILES += \ - android/AndroidManifest.xml - QMAKE_INFO_PLIST = Info.plist diff --git a/examples/multimediawidgets/player/main.cpp b/examples/multimediawidgets/player/main.cpp index c32cbc83e..a3dabe15d 100644 --- a/examples/multimediawidgets/player/main.cpp +++ b/examples/multimediawidgets/player/main.cpp @@ -41,13 +41,33 @@ #include "player.h" #include <QApplication> +#include <QCommandLineParser> +#include <QCommandLineOption> +#include <QDir> int main(int argc, char *argv[]) { QApplication app(argc, argv); + QCoreApplication::setApplicationName("Player Example"); + QCoreApplication::setOrganizationName("QtProject"); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCommandLineParser parser; + parser.setApplicationDescription("Qt MultiMedia Player Example"); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("url", "The URL to open."); + parser.process(app); + Player player; + if (!parser.positionalArguments().isEmpty() && player.isPlayerAvailable()) { + QList<QUrl> urls; + foreach (const QString &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(); diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp index b450bc361..e787aa269 100644 --- a/examples/multimediawidgets/player/player.cpp +++ b/examples/multimediawidgets/player/player.cpp @@ -167,7 +167,7 @@ Player::Player(QWidget *parent) setLayout(layout); - if (!player->isAvailable()) { + if (!isPlayerAvailable()) { QMessageBox::warning(this, tr("Service not available"), tr("The QMediaPlayer object does not have a valid service.\n"\ "Please check the media service plugins are installed.")); @@ -182,38 +182,47 @@ Player::Player(QWidget *parent) } metaDataChanged(); - - QStringList arguments = qApp->arguments(); - arguments.removeAt(0); - addToPlaylist(arguments); } Player::~Player() { } +bool Player::isPlayerAvailable() const +{ + return player->isAvailable(); +} + void Player::open() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files")); - addToPlaylist(fileNames); + QFileDialog fileDialog(this); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setWindowTitle(tr("Open Files")); + QStringList supportedMimeTypes = player->supportedMimeTypes(); + if (!supportedMimeTypes.isEmpty()) { + supportedMimeTypes.append("audio/x-m3u"); // MP3 playlists + fileDialog.setMimeTypeFilters(supportedMimeTypes); + } + fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath())); + if (fileDialog.exec() == QDialog::Accepted) + addToPlaylist(fileDialog.selectedUrls()); } -void Player::addToPlaylist(const QStringList& fileNames) +static bool isPlaylist(const QUrl &url) // Check for ".m3u" playlists. { - foreach (QString const &argument, fileNames) { - QFileInfo fileInfo(argument); - if (fileInfo.exists()) { - QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath()); - if (fileInfo.suffix().toLower() == QLatin1String("m3u")) { - playlist->load(url); - } else - playlist->addMedia(url); - } else { - QUrl url(argument); - if (url.isValid()) { - playlist->addMedia(url); - } - } + if (!url.isLocalFile()) + return false; + const QFileInfo fileInfo(url.toLocalFile()); + return fileInfo.exists() && !fileInfo.suffix().compare(QLatin1String("m3u"), Qt::CaseInsensitive); +} + +void Player::addToPlaylist(const QList<QUrl> urls) +{ + foreach (const QUrl &url, urls) { + if (isPlaylist(url)) + playlist->load(url); + else + playlist->addMedia(url); } } diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h index 61f3cff27..7f5d0881b 100644 --- a/examples/multimediawidgets/player/player.h +++ b/examples/multimediawidgets/player/player.h @@ -69,6 +69,10 @@ public: Player(QWidget *parent = 0); ~Player(); + bool isPlayerAvailable() const; + + void addToPlaylist(const QList<QUrl> urls); + signals: void fullScreenChanged(bool fullScreen); @@ -93,7 +97,6 @@ private slots: #ifndef PLAYER_NO_COLOROPTIONS void showColorDialog(); #endif - void addToPlaylist(const QStringList &fileNames); private: void setTrackInfo(const QString &info); diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp index 95ba0c4eb..bd35d4b0a 100644 --- a/src/gsttools/qgstreamerbushelper.cpp +++ b/src/gsttools/qgstreamerbushelper.cpp @@ -41,6 +41,8 @@ #include <QtCore/qtimer.h> #include <QtCore/qmutex.h> #include <QtCore/qlist.h> +#include <QtCore/qabstracteventdispatcher.h> +#include <QtCore/qcoreapplication.h> #include "qgstreamerbushelper_p.h" @@ -53,31 +55,31 @@ class QGstreamerBusHelperPrivate : public QObject public: QGstreamerBusHelperPrivate(QGstreamerBusHelper *parent, GstBus* bus) : QObject(parent), + m_tag(0), m_bus(bus), - m_helper(parent) + m_helper(parent), + m_intervalTimer(nullptr) { -#ifdef QT_NO_GLIB - Q_UNUSED(bus); - - m_intervalTimer = new QTimer(this); - m_intervalTimer->setInterval(250); - - connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval())); - m_intervalTimer->start(); -#else - m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL); -#endif - + // glib event loop can be disabled either by env variable or QT_NO_GLIB define, so check the dispacher + QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher(); + const bool hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib"); + if (!hasGlib) { + m_intervalTimer = new QTimer(this); + m_intervalTimer->setInterval(250); + connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval())); + m_intervalTimer->start(); + } else { + m_tag = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT, busCallback, this, NULL); + } } ~QGstreamerBusHelperPrivate() { m_helper = 0; -#ifdef QT_NO_GLIB - m_intervalTimer->stop(); -#else - g_source_remove(m_tag); -#endif + delete m_intervalTimer; + + if (m_tag) + g_source_remove(m_tag); } GstBus* bus() const { return m_bus; } @@ -116,9 +118,7 @@ private: guint m_tag; GstBus* m_bus; QGstreamerBusHelper* m_helper; -#ifdef QT_NO_GLIB QTimer* m_intervalTimer; -#endif private slots: void doProcessMessage(const QGstreamerMessage& msg) diff --git a/src/imports/audioengine/audioengine.pro b/src/imports/audioengine/audioengine.pro index 6c4b17c1d..c00a6ec6b 100644 --- a/src/imports/audioengine/audioengine.pro +++ b/src/imports/audioengine/audioengine.pro @@ -1,7 +1,7 @@ CXX_MODULE = multimedia TARGET = declarative_audioengine TARGETPATH = QtAudioEngine -IMPORT_VERSION = 1.0 +IMPORT_VERSION = 1.1 QT += quick qml multimedia-private diff --git a/src/imports/audioengine/plugins.qmltypes b/src/imports/audioengine/plugins.qmltypes index 22fad073a..0468d839a 100644 --- a/src/imports/audioengine/plugins.qmltypes +++ b/src/imports/audioengine/plugins.qmltypes @@ -4,10 +4,10 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtAudioEngine 1.0' +// 'qmlplugindump -nonrelocatable QtAudioEngine 1.1' Module { - dependencies: [] + dependencies: ["QtQuick 2.0"] Component { name: "QDeclarativeAttenuationModel" prototype: "QObject" diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp b/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp index d88bb87e8..729558cd2 100644 --- a/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp +++ b/src/imports/audioengine/qdeclarative_attenuationmodel_p.cpp @@ -85,17 +85,11 @@ void QDeclarativeAttenuationModel::setName(const QString& name) \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - AttenuationModelLinear must be defined inside \l AudioEngine or be added to it using \l{QtAudioEngine::AudioEngine::addAttenuationModel()}{AudioEngine.addAttenuationModel()} if AttenuationModelLinear is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - - Rectangle { color:"white" width: 300 @@ -220,17 +214,11 @@ qreal QDeclarativeAttenuationModelLinear::calculateGain(const QVector3D &listene \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - AttenuationModelInverse must be defined inside \l AudioEngine or be added to it using \l{QtAudioEngine::AudioEngine::addAttenuationModel()}{AudioEngine.addAttenuationModel()} if AttenuationModelInverse is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_audiocategory_p.cpp b/src/imports/audioengine/qdeclarative_audiocategory_p.cpp index f766ae515..84ba6b190 100644 --- a/src/imports/audioengine/qdeclarative_audiocategory_p.cpp +++ b/src/imports/audioengine/qdeclarative_audiocategory_p.cpp @@ -54,17 +54,12 @@ QT_USE_NAMESPACE \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - An instance of AudioCategory can be accessed through \l {QtAudioEngine::AudioEngine::categories} {AudioEngine.categories} with its unique name and must be defined inside AudioEngine or be added to it using \l{QtAudioEngine::AudioEngine::addAudioCategory()}{AudioEngine.addAudioCategory()} if AudioCategory is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.cpp b/src/imports/audioengine/qdeclarative_audioengine_p.cpp index c4b4bd41b..bd309457e 100644 --- a/src/imports/audioengine/qdeclarative_audioengine_p.cpp +++ b/src/imports/audioengine/qdeclarative_audioengine_p.cpp @@ -63,12 +63,7 @@ QT_BEGIN_NAMESPACE \inherits Item \preliminary - \c AudioEngine is part of the \b{QtAudioEngine 1.0} module. - \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_audiolistener_p.cpp b/src/imports/audioengine/qdeclarative_audiolistener_p.cpp index f45010930..39a30171b 100644 --- a/src/imports/audioengine/qdeclarative_audiolistener_p.cpp +++ b/src/imports/audioengine/qdeclarative_audiolistener_p.cpp @@ -55,15 +55,10 @@ QT_USE_NAMESPACE \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - AudioListener will have only one global instance and you can either access it through the listener property of AudioEngine: \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 @@ -98,9 +93,6 @@ QT_USE_NAMESPACE or alternatively, by defining an AudioListener outside AudioEngine: \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_audiosample_p.cpp b/src/imports/audioengine/qdeclarative_audiosample_p.cpp index a8dc76279..4eccf5052 100644 --- a/src/imports/audioengine/qdeclarative_audiosample_p.cpp +++ b/src/imports/audioengine/qdeclarative_audiosample_p.cpp @@ -57,17 +57,12 @@ QT_USE_NAMESPACE \inherits Item \preliminary - \c AudioSample is part of the \b{QtAudioEngine 1.0} module. - It can be accessed through QtAudioEngine::AudioEngine::samples with its unique name and must be defined inside AudioEngine or be added to it using \l{QtAudioEngine::AudioEngine::addAudioSample()}{AudioEngine.addAudioSample()} if AudioSample is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_playvariation_p.cpp b/src/imports/audioengine/qdeclarative_playvariation_p.cpp index 9cb36c50e..36ffca668 100644 --- a/src/imports/audioengine/qdeclarative_playvariation_p.cpp +++ b/src/imports/audioengine/qdeclarative_playvariation_p.cpp @@ -59,16 +59,11 @@ QT_USE_NAMESPACE \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - PlayVariation must be defined inside a \l Sound or be added to it using \l{QtAudioEngine::Sound::addPlayVariation()}{Sound.addPlayVariation()} if PlayVariation is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { color:"white" width: 300 diff --git a/src/imports/audioengine/qdeclarative_sound_p.cpp b/src/imports/audioengine/qdeclarative_sound_p.cpp index 1c746f534..0849215be 100644 --- a/src/imports/audioengine/qdeclarative_sound_p.cpp +++ b/src/imports/audioengine/qdeclarative_sound_p.cpp @@ -165,16 +165,12 @@ void QDeclarativeSoundCone::setEngine(QDeclarativeAudioEngine *engine) \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - Sound can be accessed through QtAudioEngine::AudioEngine::sounds with its unique name and must be defined inside AudioEngine or be added to it using \l{QtAudioEngine::AudioEngine::addSound()}{AudioEngine.addSound()} if \l Sound is created dynamically. \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 Rectangle { color:"white" diff --git a/src/imports/audioengine/qdeclarative_soundinstance_p.cpp b/src/imports/audioengine/qdeclarative_soundinstance_p.cpp index 830f8ee7b..7f8c33233 100644 --- a/src/imports/audioengine/qdeclarative_soundinstance_p.cpp +++ b/src/imports/audioengine/qdeclarative_soundinstance_p.cpp @@ -58,15 +58,10 @@ QT_USE_NAMESPACE \inherits Item \preliminary - This type is part of the \b{QtAudioEngine 1.0} module. - There are two ways to create SoundInstance objects. You can obtain it by calling newInstance method of a \l Sound: \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { id:root color:"white" @@ -104,9 +99,6 @@ QT_USE_NAMESPACE easier qml bindings: \qml - import QtQuick 2.0 - import QtAudioEngine 1.0 - Rectangle { id:root color:"white" diff --git a/src/multimedia/audio/qaudiodecoder.h b/src/multimedia/audio/qaudiodecoder.h index 6817d35d5..a63a6836f 100644 --- a/src/multimedia/audio/qaudiodecoder.h +++ b/src/multimedia/audio/qaudiodecoder.h @@ -75,7 +75,7 @@ public: ServiceMissingError }; - QAudioDecoder(QObject *parent = 0); + explicit QAudioDecoder(QObject *parent = Q_NULLPTR); ~QAudioDecoder(); static QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs = QStringList()); diff --git a/src/multimedia/audio/qaudioinput.h b/src/multimedia/audio/qaudioinput.h index ce20db4fd..d1a58424e 100644 --- a/src/multimedia/audio/qaudioinput.h +++ b/src/multimedia/audio/qaudioinput.h @@ -62,8 +62,8 @@ class Q_MULTIMEDIA_EXPORT QAudioInput : public QObject Q_OBJECT public: - explicit QAudioInput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0); - explicit QAudioInput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0); + explicit QAudioInput(const QAudioFormat &format = QAudioFormat(), QObject *parent = Q_NULLPTR); + explicit QAudioInput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = Q_NULLPTR); ~QAudioInput(); QAudioFormat format() const; diff --git a/src/multimedia/audio/qaudiooutput.h b/src/multimedia/audio/qaudiooutput.h index 3b6c7db0f..fab562ae1 100644 --- a/src/multimedia/audio/qaudiooutput.h +++ b/src/multimedia/audio/qaudiooutput.h @@ -62,8 +62,8 @@ class Q_MULTIMEDIA_EXPORT QAudioOutput : public QObject Q_OBJECT public: - explicit QAudioOutput(const QAudioFormat &format = QAudioFormat(), QObject *parent = 0); - explicit QAudioOutput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = 0); + explicit QAudioOutput(const QAudioFormat &format = QAudioFormat(), QObject *parent = Q_NULLPTR); + explicit QAudioOutput(const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format = QAudioFormat(), QObject *parent = Q_NULLPTR); ~QAudioOutput(); QAudioFormat format() const; diff --git a/src/multimedia/audio/qaudioprobe.h b/src/multimedia/audio/qaudioprobe.h index 499ff041b..376a54e34 100644 --- a/src/multimedia/audio/qaudioprobe.h +++ b/src/multimedia/audio/qaudioprobe.h @@ -53,7 +53,7 @@ class Q_MULTIMEDIA_EXPORT QAudioProbe : public QObject { Q_OBJECT public: - explicit QAudioProbe(QObject *parent = 0); + explicit QAudioProbe(QObject *parent = Q_NULLPTR); ~QAudioProbe(); bool setSource(QMediaObject *source); diff --git a/src/multimedia/audio/qaudiosystemplugin.h b/src/multimedia/audio/qaudiosystemplugin.h index 4fa9faf0e..b26b2a3b9 100644 --- a/src/multimedia/audio/qaudiosystemplugin.h +++ b/src/multimedia/audio/qaudiosystemplugin.h @@ -78,7 +78,7 @@ class Q_MULTIMEDIA_EXPORT QAudioSystemPlugin : public QObject, public QAudioSyst Q_INTERFACES(QAudioSystemFactoryInterface) public: - QAudioSystemPlugin(QObject *parent = 0); + explicit QAudioSystemPlugin(QObject *parent = Q_NULLPTR); ~QAudioSystemPlugin(); virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0; diff --git a/src/multimedia/audio/qsound.h b/src/multimedia/audio/qsound.h index 5e8e792db..f8d47676f 100644 --- a/src/multimedia/audio/qsound.h +++ b/src/multimedia/audio/qsound.h @@ -58,7 +58,7 @@ public: static void play(const QString& filename); - explicit QSound(const QString& filename, QObject* parent = 0); + explicit QSound(const QString &filename, QObject *parent = Q_NULLPTR); ~QSound(); int loops() const; diff --git a/src/multimedia/audio/qsoundeffect.h b/src/multimedia/audio/qsoundeffect.h index c24600b26..f59c4d91d 100644 --- a/src/multimedia/audio/qsoundeffect.h +++ b/src/multimedia/audio/qsoundeffect.h @@ -80,7 +80,7 @@ public: Error }; - explicit QSoundEffect(QObject *parent = 0); + explicit QSoundEffect(QObject *parent = Q_NULLPTR); ~QSoundEffect(); static QStringList supportedMimeTypes(); diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index 472c01489..79d1d96ab 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -55,10 +55,7 @@ #include "qsoundeffect_pulse_p.h" -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) -#include <pulse/ext-stream-restore.h> -#endif - +#include <private/qaudiohelpers_p.h> #include <private/qmediaresourcepolicy_p.h> #include <private/qmediaresourceset_p.h> @@ -130,26 +127,9 @@ public: return m_context; } - inline pa_cvolume * calcVolume(pa_cvolume *dest, int soundEffectVolume) - { - pa_volume_t v = m_vol * soundEffectVolume / 100; - for (int i = 0; i < dest->channels; ++i) - dest->values[i] = v; - return dest; - } - - void updateStatus(const pa_cvolume& volume) - { - if (m_vol != pa_cvolume_max(&volume)) { - m_vol = pa_cvolume_max(&volume); - emit volumeChanged(); - } - } - Q_SIGNALS: void contextReady(); void contextFailed(); - void volumeChanged(); private Q_SLOTS: void onContextFailed() @@ -164,8 +144,6 @@ private Q_SLOTS: void prepare() { - m_vol = PA_VOLUME_NORM; - m_context = 0; m_mainLoop = pa_threaded_mainloop_new(); if (m_mainLoop == 0) { @@ -238,11 +216,6 @@ private: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: - #if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - pa_ext_stream_restore_read(c, &stream_restore_info_callback, self); - pa_ext_stream_restore_set_subscribe_cb(c, &stream_restore_monitor_callback, self); - pa_ext_stream_restore_subscribe(c, 1, 0, self); - #endif QMetaObject::invokeMethod(self, "contextReady", Qt::QueuedConnection); break; case PA_CONTEXT_FAILED: @@ -253,37 +226,6 @@ private: } } -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - - static void stream_restore_monitor_callback(pa_context *c, void *userdata) - { - PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata); - pa_ext_stream_restore_read(c, &stream_restore_info_callback, self); - } - - static void stream_restore_info_callback(pa_context *c, - const pa_ext_stream_restore_info *info, - int eol, void *userdata) - { - Q_UNUSED(c) - - PulseDaemon *self = reinterpret_cast<PulseDaemon*>(userdata); - - if (!eol) { - if (QString(info->name).startsWith(QLatin1String("sink-input-by-media-role:x-maemo"))) { -#ifdef QT_PA_DEBUG - qDebug() << "x-maemo volume =(" << info->volume.values[0] * 100 / PA_VOLUME_NORM << "," - << info->volume.values[1] * 100 / PA_VOLUME_NORM << "), " - << "mute = " << info->mute; -#endif - self->updateStatus(info->volume); - } - } - } -#endif - - pa_volume_t m_vol; - bool m_prepared; pa_context *m_context; pa_threaded_mainloop *m_mainLoop; @@ -391,9 +333,6 @@ QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): m_sample(0), m_position(0), m_resourcesAvailable(false) -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - , m_customVolume(false) -#endif { m_ref = new QSoundEffectRef(this); pa_sample_spec_init(&m_pulseSpec); @@ -544,60 +483,32 @@ void QSoundEffectPrivate::setLoopCount(int loopCount) qreal QSoundEffectPrivate::volume() const { + QReadLocker locker(&m_volumeLock); return m_volume; } void QSoundEffectPrivate::setVolume(qreal volume) { -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - m_customVolume = true; -#endif - m_volume = volume; - emit volumeChanged(); - updateVolume(); -} + QWriteLocker locker(&m_volumeLock); -void QSoundEffectPrivate::updateVolume() -{ - if (m_sinkInputId < 0) + if (qFuzzyCompare(m_volume, volume)) return; -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - if (!m_customVolume) - return; -#endif - PulseDaemonLocker locker; - pa_cvolume volume; - volume.channels = m_pulseSpec.channels; - if (pulseDaemon()->context()) - pa_operation_unref(pa_context_set_sink_input_volume(pulseDaemon()->context(), m_sinkInputId, pulseDaemon()->calcVolume(&volume, qRound(m_volume * 100)), setvolume_callback, m_ref->getRef())); - Q_ASSERT(pa_cvolume_valid(&volume)); -#ifdef QT_PA_DEBUG - qDebug() << this << "updateVolume =" << pa_cvolume_max(&volume); -#endif + + m_volume = qBound(qreal(0), volume, qreal(1)); + emit volumeChanged(); } bool QSoundEffectPrivate::isMuted() const { + QReadLocker locker(&m_volumeLock); return m_muted; } void QSoundEffectPrivate::setMuted(bool muted) { + QWriteLocker locker(&m_volumeLock); m_muted = muted; emit mutedChanged(); - updateMuted(); -} - -void QSoundEffectPrivate::updateMuted() -{ - if (m_sinkInputId < 0) - return; - PulseDaemonLocker locker; - if (pulseDaemon()->context()) - pa_operation_unref(pa_context_set_sink_input_mute(pulseDaemon()->context(), m_sinkInputId, m_muted, setmuted_callback, m_ref->getRef())); -#ifdef QT_PA_DEBUG - qDebug() << this << "updateMuted = " << m_muted; -#endif } bool QSoundEffectPrivate::isLoaded() const @@ -807,7 +718,6 @@ void QSoundEffectPrivate::unloadPulseStream() pa_stream_set_underflow_callback(m_pulseStream, 0, 0); pa_stream_disconnect(m_pulseStream); pa_stream_unref(m_pulseStream); - disconnect(pulseDaemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume())); disconnect(pulseDaemon(), SIGNAL(contextFailed()), this, SLOT(contextFailed())); m_pulseStream = 0; m_reloadCategory = false; // category will be reloaded when we connect anyway @@ -828,11 +738,8 @@ void QSoundEffectPrivate::prepare() << "actual writeBytes =" << writeBytes << "m_playQueued =" << m_playQueued; #endif - m_position = int(writeBytes); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())), writeBytes, - stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } + m_position = writeToStream(m_sample->data().data(), writeBytes); + if (m_playQueued) { m_playQueued = false; setLoopsRemaining(m_loopCount); @@ -860,15 +767,13 @@ void QSoundEffectPrivate::uploadSample() } } - int writtenBytes = 0; int writableSize = int(pa_stream_writable_size(m_pulseStream)); int firstPartLength = qMin(m_sample->data().size() - m_position, writableSize); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data()) + m_position), - firstPartLength, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } - writtenBytes = firstPartLength; - m_position += firstPartLength; + + int writtenBytes = writeToStream(m_sample->data().data() + m_position, + firstPartLength); + + m_position += writtenBytes; if (m_position == m_sample->data().size()) { m_position = 0; if (m_runningCount > 0) @@ -877,11 +782,8 @@ void QSoundEffectPrivate::uploadSample() { while (writtenBytes < writableSize) { int writeSize = qMin(writableSize - writtenBytes, m_sample->data().size()); - if (pa_stream_write(m_pulseStream, reinterpret_cast<void *>(const_cast<char*>(m_sample->data().data())), - writeSize, stream_write_done_callback, 0, PA_SEEK_RELATIVE) != 0) { - qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); - } - writtenBytes += writeSize; + writtenBytes += writeToStream(m_sample->data().data(), writeSize); + if (writeSize < m_sample->data().size()) { m_position = writeSize; break; @@ -899,6 +801,39 @@ void QSoundEffectPrivate::uploadSample() #endif } +int QSoundEffectPrivate::writeToStream(const void *data, int size) +{ + m_volumeLock.lockForRead(); + qreal volume = m_muted ? 0 : m_volume; + m_volumeLock.unlock(); + pa_free_cb_t writeDoneCb = stream_write_done_callback; + + if (volume < 1.0f) { + // Don't use PulseAudio volume, as it might affect all other streams of the same category + // or even affect the system volume if flat volumes are enabled + void *dest = NULL; + size_t nbytes = size; + if (pa_stream_begin_write(m_pulseStream, &dest, &nbytes) < 0) { + qWarning("QSoundEffect(pulseaudio): pa_stream_begin_write, error = %s", + pa_strerror(pa_context_errno(pulseDaemon()->context()))); + return 0; + } + + size = int(nbytes); + QAudioHelperInternal::qMultiplySamples(volume, m_sample->format(), data, dest, size); + data = dest; + writeDoneCb = NULL; + } + + if (pa_stream_write(m_pulseStream, data, size, writeDoneCb, 0, PA_SEEK_RELATIVE) < 0) { + qWarning("QSoundEffect(pulseaudio): pa_stream_write, error = %s", + pa_strerror(pa_context_errno(pulseDaemon()->context()))); + return 0; + } + + return size; +} + void QSoundEffectPrivate::playSample() { #ifdef QT_PA_DEBUG @@ -945,8 +880,6 @@ void QSoundEffectPrivate::streamReady() #endif PulseDaemonLocker locker; m_sinkInputId = pa_stream_get_index(m_pulseStream); - updateMuted(); - updateVolume(); #ifdef QT_PA_DEBUG const pa_buffer_attr *realBufAttr = pa_stream_get_buffer_attr(m_pulseStream); qDebug() << this << "m_sinkInputId =" << m_sinkInputId @@ -972,7 +905,6 @@ void QSoundEffectPrivate::createPulseStream() pa_stream *stream = pa_stream_new_with_proplist(pulseDaemon()->context(), m_name.constData(), &m_pulseSpec, 0, propList); pa_proplist_free(propList); - connect(pulseDaemon(), SIGNAL(volumeChanged()), this, SLOT(updateVolume())); connect(pulseDaemon(), SIGNAL(contextFailed()), this, SLOT(contextFailed())); if (stream == 0) { @@ -1000,9 +932,7 @@ void QSoundEffectPrivate::createPulseStream() #else if (pa_stream_connect_playback(m_pulseStream, 0, 0, #endif - m_muted ? pa_stream_flags_t(PA_STREAM_START_MUTED | PA_STREAM_START_CORKED) - : pa_stream_flags_t(PA_STREAM_START_UNMUTED | PA_STREAM_START_CORKED), - 0, 0) < 0) { + PA_STREAM_START_CORKED, 0, 0) < 0) { qWarning("QSoundEffect(pulseaudio): Failed to connect stream, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); } @@ -1121,46 +1051,6 @@ void QSoundEffectPrivate::stream_adjust_prebuffer_callback(pa_stream *s, int suc QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection); } -void QSoundEffectPrivate::setvolume_callback(pa_context *c, int success, void *userdata) -{ -#ifdef QT_PA_DEBUG - qDebug() << "setvolume_callback"; -#endif - Q_UNUSED(c); - Q_UNUSED(userdata); - QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata); - QSoundEffectPrivate *self = ref->soundEffect(); - ref->release(); - if (!self) - return; -#ifdef QT_PA_DEBUG - qDebug() << self << "setvolume_callback"; -#endif - if (!success) { - qWarning("QSoundEffect(pulseaudio): faild to set volume"); - } -} - -void QSoundEffectPrivate::setmuted_callback(pa_context *c, int success, void *userdata) -{ -#ifdef QT_PA_DEBUG - qDebug() << "setmuted_callback"; -#endif - Q_UNUSED(c); - Q_UNUSED(userdata); - QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata); - QSoundEffectPrivate *self = ref->soundEffect(); - ref->release(); - if (!self) - return; -#ifdef QT_PA_DEBUG - qDebug() << self << "setmuted_callback"; -#endif - if (!success) { - qWarning("QSoundEffect(pulseaudio): faild to set muted"); - } -} - void QSoundEffectPrivate::stream_underrun_callback(pa_stream *s, void *userdata) { Q_UNUSED(s); diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h index 259d2e046..6bf2416cf 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.h +++ b/src/multimedia/audio/qsoundeffect_pulse_p.h @@ -56,6 +56,7 @@ #include <QtCore/qobject.h> #include <QtCore/qdatetime.h> +#include <QtCore/qreadwritelock.h> #include <qmediaplayer.h> #include <pulse/pulseaudio.h> #include "qsamplecache_p.h" @@ -117,8 +118,6 @@ private Q_SLOTS: void prepare(); void streamReady(); void emptyComplete(void *stream); - void updateVolume(); - void updateMuted(); void handleAvailabilityChanged(bool available); @@ -130,6 +129,8 @@ private: void createPulseStream(); void unloadPulseStream(); + int writeToStream(const void *data, int size); + void setPlaying(bool playing); void setStatus(QSoundEffect::Status status); void setLoopsRemaining(int loopsRemaining); @@ -142,8 +143,6 @@ private: static void stream_write_done_callback(void *p); static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata); static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata); - static void setvolume_callback(pa_context *c, int success, void *userdata); - static void setmuted_callback(pa_context *c, int success, void *userdata); pa_stream *m_pulseStream; int m_sinkInputId; @@ -171,11 +170,9 @@ private: bool m_resourcesAvailable; - QMediaPlayerResourceSetInterface *m_resources; + mutable QReadWriteLock m_volumeLock; -#if defined(Q_WS_MAEMO_6) || defined(NEMO_AUDIO) - bool m_customVolume; -#endif + QMediaPlayerResourceSetInterface *m_resources; }; QT_END_NAMESPACE diff --git a/src/multimedia/camera/qcamera.h b/src/multimedia/camera/qcamera.h index 1c626748e..7d7063650 100644 --- a/src/multimedia/camera/qcamera.h +++ b/src/multimedia/camera/qcamera.h @@ -165,10 +165,10 @@ public: FrontFace }; - QCamera(QObject *parent = 0); - QCamera(const QByteArray& deviceName, QObject *parent = 0); - QCamera(const QCameraInfo& cameraInfo, QObject *parent = 0); - QCamera(QCamera::Position position, QObject *parent = 0); + explicit QCamera(QObject *parent = Q_NULLPTR); + explicit QCamera(const QByteArray& deviceName, QObject *parent = Q_NULLPTR); + explicit QCamera(const QCameraInfo& cameraInfo, QObject *parent = Q_NULLPTR); + explicit QCamera(QCamera::Position position, QObject *parent = Q_NULLPTR); ~QCamera(); #if QT_DEPRECATED_SINCE(5, 3) diff --git a/src/multimedia/camera/qcameraexposure.h b/src/multimedia/camera/qcameraexposure.h index c71bb8575..e0924ca60 100644 --- a/src/multimedia/camera/qcameraexposure.h +++ b/src/multimedia/camera/qcameraexposure.h @@ -135,9 +135,9 @@ public: qreal requestedAperture() const; qreal requestedShutterSpeed() const; - QList<int> supportedIsoSensitivities(bool *continuous = 0) const; - QList<qreal> supportedApertures(bool * continuous = 0) const; - QList<qreal> supportedShutterSpeeds(bool *continuous = 0) const; + QList<int> supportedIsoSensitivities(bool *continuous = Q_NULLPTR) const; + QList<qreal> supportedApertures(bool *continuous = Q_NULLPTR) const; + QList<qreal> supportedShutterSpeeds(bool *continuous = Q_NULLPTR) const; public Q_SLOTS: void setFlashMode(FlashModes mode); @@ -168,7 +168,7 @@ Q_SIGNALS: private: friend class QCamera; friend class QCameraPrivate; - explicit QCameraExposure(QCamera *parent = 0); + explicit QCameraExposure(QCamera *parent = Q_NULLPTR); virtual ~QCameraExposure(); Q_DISABLE_COPY(QCameraExposure) diff --git a/src/multimedia/camera/qcameraimagecapture.h b/src/multimedia/camera/qcameraimagecapture.h index 190dabb15..3f3c6bd26 100644 --- a/src/multimedia/camera/qcameraimagecapture.h +++ b/src/multimedia/camera/qcameraimagecapture.h @@ -87,7 +87,7 @@ public: }; Q_DECLARE_FLAGS(CaptureDestinations, CaptureDestination) - QCameraImageCapture(QMediaObject *mediaObject, QObject *parent = 0); + explicit QCameraImageCapture(QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); ~QCameraImageCapture(); bool isAvailable() const; @@ -104,7 +104,7 @@ public: QString imageCodecDescription(const QString &codecName) const; QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = Q_NULLPTR) const; QImageEncoderSettings encodingSettings() const; void setEncodingSettings(const QImageEncoderSettings& settings); diff --git a/src/multimedia/controls/qaudiodecodercontrol.h b/src/multimedia/controls/qaudiodecodercontrol.h index d864da4f0..f02da4963 100644 --- a/src/multimedia/controls/qaudiodecodercontrol.h +++ b/src/multimedia/controls/qaudiodecodercontrol.h @@ -92,7 +92,7 @@ Q_SIGNALS: void durationChanged(qint64 duration); protected: - QAudioDecoderControl(QObject* parent = 0); + explicit QAudioDecoderControl(QObject *parent = Q_NULLPTR); }; #define QAudioDecoderControl_iid "org.qt-project.qt.audiodecodercontrol/5.0" diff --git a/src/multimedia/controls/qaudioencodersettingscontrol.h b/src/multimedia/controls/qaudioencodersettingscontrol.h index 77a72ed83..1906904d8 100644 --- a/src/multimedia/controls/qaudioencodersettingscontrol.h +++ b/src/multimedia/controls/qaudioencodersettingscontrol.h @@ -67,13 +67,13 @@ public: virtual QString codecDescription(const QString &codecName) const = 0; virtual QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, - bool *continuous = 0) const = 0; + bool *continuous = Q_NULLPTR) const = 0; virtual QAudioEncoderSettings audioSettings() const = 0; virtual void setAudioSettings(const QAudioEncoderSettings&) = 0; protected: - QAudioEncoderSettingsControl(QObject *parent = 0); + explicit QAudioEncoderSettingsControl(QObject *parent = Q_NULLPTR); }; #define QAudioEncoderSettingsControl_iid "org.qt-project.qt.audioencodersettingscontrol/5.0" diff --git a/src/multimedia/controls/qaudioinputselectorcontrol.h b/src/multimedia/controls/qaudioinputselectorcontrol.h index 98c9c7b89..eceaa76dd 100644 --- a/src/multimedia/controls/qaudioinputselectorcontrol.h +++ b/src/multimedia/controls/qaudioinputselectorcontrol.h @@ -68,7 +68,7 @@ Q_SIGNALS: void availableInputsChanged(); protected: - QAudioInputSelectorControl(QObject *parent = 0); + explicit QAudioInputSelectorControl(QObject *parent = Q_NULLPTR); }; #define QAudioInputSelectorControl_iid "org.qt-project.qt.audioinputselectorcontrol/5.0" diff --git a/src/multimedia/controls/qaudiooutputselectorcontrol.h b/src/multimedia/controls/qaudiooutputselectorcontrol.h index 4c7be6d73..b2d27a349 100644 --- a/src/multimedia/controls/qaudiooutputselectorcontrol.h +++ b/src/multimedia/controls/qaudiooutputselectorcontrol.h @@ -68,7 +68,7 @@ Q_SIGNALS: void availableOutputsChanged(); protected: - QAudioOutputSelectorControl(QObject *parent = 0); + explicit QAudioOutputSelectorControl(QObject *parent = Q_NULLPTR); }; #define QAudioOutputSelectorControl_iid "org.qt-project.qt.audiooutputselectorcontrol/5.0" diff --git a/src/multimedia/controls/qaudiorolecontrol.h b/src/multimedia/controls/qaudiorolecontrol.h index 1dd9271ec..5d9db177b 100644 --- a/src/multimedia/controls/qaudiorolecontrol.h +++ b/src/multimedia/controls/qaudiorolecontrol.h @@ -64,7 +64,7 @@ Q_SIGNALS: void audioRoleChanged(QAudio::Role role); protected: - explicit QAudioRoleControl(QObject *parent = 0); + explicit QAudioRoleControl(QObject *parent = Q_NULLPTR); }; #define QAudioRoleControl_iid "org.qt-project.qt.audiorolecontrol/5.6" diff --git a/src/multimedia/controls/qcameracapturebufferformatcontrol.h b/src/multimedia/controls/qcameracapturebufferformatcontrol.h index ecac16f81..cb8c3d6d9 100644 --- a/src/multimedia/controls/qcameracapturebufferformatcontrol.h +++ b/src/multimedia/controls/qcameracapturebufferformatcontrol.h @@ -62,7 +62,7 @@ Q_SIGNALS: void bufferFormatChanged(QVideoFrame::PixelFormat); protected: - QCameraCaptureBufferFormatControl(QObject* parent = 0); + explicit QCameraCaptureBufferFormatControl(QObject *parent = Q_NULLPTR); }; #define QCameraCaptureBufferFormatControl_iid "org.qt-project.qt.cameracapturebufferformatcontrol/5.0" diff --git a/src/multimedia/controls/qcameracapturedestinationcontrol.h b/src/multimedia/controls/qcameracapturedestinationcontrol.h index ee0246ecd..90142d6b5 100644 --- a/src/multimedia/controls/qcameracapturedestinationcontrol.h +++ b/src/multimedia/controls/qcameracapturedestinationcontrol.h @@ -62,7 +62,7 @@ Q_SIGNALS: void captureDestinationChanged(QCameraImageCapture::CaptureDestinations); protected: - QCameraCaptureDestinationControl(QObject* parent = 0); + explicit QCameraCaptureDestinationControl(QObject *parent = Q_NULLPTR); }; #define QCameraCaptureDestinationControl_iid "org.qt-project.qt.cameracapturedestinationcontrol/5.0" diff --git a/src/multimedia/controls/qcameracontrol.h b/src/multimedia/controls/qcameracontrol.h index b7b0b6cb0..f17af0ce9 100644 --- a/src/multimedia/controls/qcameracontrol.h +++ b/src/multimedia/controls/qcameracontrol.h @@ -83,7 +83,7 @@ Q_SIGNALS: void captureModeChanged(QCamera::CaptureModes); protected: - QCameraControl(QObject* parent = 0); + explicit QCameraControl(QObject *parent = Q_NULLPTR); }; #define QCameraControl_iid "org.qt-project.qt.cameracontrol/5.0" diff --git a/src/multimedia/controls/qcameraexposurecontrol.h b/src/multimedia/controls/qcameraexposurecontrol.h index 891683ea5..88dda12ed 100644 --- a/src/multimedia/controls/qcameraexposurecontrol.h +++ b/src/multimedia/controls/qcameraexposurecontrol.h @@ -87,7 +87,7 @@ Q_SIGNALS: void parameterRangeChanged(int parameter); protected: - QCameraExposureControl(QObject* parent = 0); + explicit QCameraExposureControl(QObject *parent = Q_NULLPTR); }; #define QCameraExposureControl_iid "org.qt-project.qt.cameraexposurecontrol/5.0" diff --git a/src/multimedia/controls/qcamerafeedbackcontrol.h b/src/multimedia/controls/qcamerafeedbackcontrol.h index b99c7120c..cee97210f 100644 --- a/src/multimedia/controls/qcamerafeedbackcontrol.h +++ b/src/multimedia/controls/qcamerafeedbackcontrol.h @@ -84,7 +84,7 @@ public: virtual bool setEventFeedbackSound(EventType, const QString &filePath) = 0; protected: - QCameraFeedbackControl(QObject* parent = 0); + explicit QCameraFeedbackControl(QObject *parent = Q_NULLPTR); }; #define QCameraFeedbackControl_iid "org.qt-project.qt.camerafeedbackcontrol/5.0" diff --git a/src/multimedia/controls/qcameraflashcontrol.h b/src/multimedia/controls/qcameraflashcontrol.h index 6ceccd67a..08e991f5a 100644 --- a/src/multimedia/controls/qcameraflashcontrol.h +++ b/src/multimedia/controls/qcameraflashcontrol.h @@ -68,7 +68,7 @@ Q_SIGNALS: void flashReady(bool); protected: - QCameraFlashControl(QObject* parent = 0); + explicit QCameraFlashControl(QObject *parent = Q_NULLPTR); }; #define QCameraFlashControl_iid "org.qt-project.qt.cameraflashcontrol/5.0" diff --git a/src/multimedia/controls/qcamerafocuscontrol.h b/src/multimedia/controls/qcamerafocuscontrol.h index accbd3a4c..32da7cc31 100644 --- a/src/multimedia/controls/qcamerafocuscontrol.h +++ b/src/multimedia/controls/qcamerafocuscontrol.h @@ -77,7 +77,7 @@ Q_SIGNALS: void focusZonesChanged(); protected: - QCameraFocusControl(QObject* parent = 0); + explicit QCameraFocusControl(QObject *parent = Q_NULLPTR); }; #define QCameraFocusControl_iid "org.qt-project.qt.camerafocuscontrol/5.0" diff --git a/src/multimedia/controls/qcameraimagecapturecontrol.h b/src/multimedia/controls/qcameraimagecapturecontrol.h index 94d4e2a7b..4fe7b9387 100644 --- a/src/multimedia/controls/qcameraimagecapturecontrol.h +++ b/src/multimedia/controls/qcameraimagecapturecontrol.h @@ -80,7 +80,7 @@ Q_SIGNALS: void error(int id, int error, const QString &errorString); protected: - QCameraImageCaptureControl(QObject* parent = 0); + explicit QCameraImageCaptureControl(QObject *parent = Q_NULLPTR); }; #define QCameraImageCaptureControl_iid "org.qt-project.qt.cameraimagecapturecontrol/5.0" diff --git a/src/multimedia/controls/qcameraimageprocessingcontrol.h b/src/multimedia/controls/qcameraimageprocessingcontrol.h index eee45aa62..ee46143e4 100644 --- a/src/multimedia/controls/qcameraimageprocessingcontrol.h +++ b/src/multimedia/controls/qcameraimageprocessingcontrol.h @@ -82,7 +82,7 @@ public: virtual void setParameter(ProcessingParameter parameter, const QVariant &value) = 0; protected: - QCameraImageProcessingControl(QObject* parent = 0); + explicit QCameraImageProcessingControl(QObject *parent = Q_NULLPTR); }; #define QCameraImageProcessingControl_iid "org.qt-project.qt.cameraimageprocessingcontrol/5.0" diff --git a/src/multimedia/controls/qcamerainfocontrol.h b/src/multimedia/controls/qcamerainfocontrol.h index 3156761ab..32f85fc3a 100644 --- a/src/multimedia/controls/qcamerainfocontrol.h +++ b/src/multimedia/controls/qcamerainfocontrol.h @@ -58,7 +58,7 @@ public: virtual int cameraOrientation(const QString &deviceName) const = 0; protected: - QCameraInfoControl(QObject *parent = 0); + explicit QCameraInfoControl(QObject *parent = Q_NULLPTR); }; #define QCameraInfoControl_iid "org.qt-project.qt.camerainfocontrol/5.3" diff --git a/src/multimedia/controls/qcameralockscontrol.h b/src/multimedia/controls/qcameralockscontrol.h index b830f01fa..01178642f 100644 --- a/src/multimedia/controls/qcameralockscontrol.h +++ b/src/multimedia/controls/qcameralockscontrol.h @@ -67,7 +67,7 @@ Q_SIGNALS: void lockStatusChanged(QCamera::LockType type, QCamera::LockStatus status, QCamera::LockChangeReason reason); protected: - QCameraLocksControl(QObject* parent = 0); + explicit QCameraLocksControl(QObject *parent = Q_NULLPTR); }; #define QCameraLocksControl_iid "org.qt-project.qt.cameralockscontrol/5.0" diff --git a/src/multimedia/controls/qcameraviewfindersettingscontrol.h b/src/multimedia/controls/qcameraviewfindersettingscontrol.h index aa3dd913e..c67fdaabb 100644 --- a/src/multimedia/controls/qcameraviewfindersettingscontrol.h +++ b/src/multimedia/controls/qcameraviewfindersettingscontrol.h @@ -70,7 +70,7 @@ public: virtual void setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value) = 0; protected: - QCameraViewfinderSettingsControl(QObject *parent = 0); + explicit QCameraViewfinderSettingsControl(QObject *parent = Q_NULLPTR); }; #define QCameraViewfinderSettingsControl_iid "org.qt-project.qt.cameraviewfindersettingscontrol/5.0" @@ -92,7 +92,7 @@ public: virtual void setViewfinderSettings(const QCameraViewfinderSettings &settings) = 0; protected: - QCameraViewfinderSettingsControl2(QObject *parent = 0); + explicit QCameraViewfinderSettingsControl2(QObject *parent = Q_NULLPTR); }; #define QCameraViewfinderSettingsControl2_iid "org.qt-project.qt.cameraviewfindersettingscontrol2/5.5" diff --git a/src/multimedia/controls/qcamerazoomcontrol.h b/src/multimedia/controls/qcamerazoomcontrol.h index 67763d301..776d6ddab 100644 --- a/src/multimedia/controls/qcamerazoomcontrol.h +++ b/src/multimedia/controls/qcamerazoomcontrol.h @@ -75,7 +75,7 @@ Q_SIGNALS: void currentDigitalZoomChanged(qreal digitalZoom); protected: - QCameraZoomControl(QObject* parent = 0); + explicit QCameraZoomControl(QObject *parent = Q_NULLPTR); }; #define QCameraZoomControl_iid "org.qt-project.qt.camerazoomcontrol/5.0" diff --git a/src/multimedia/controls/qimageencodercontrol.h b/src/multimedia/controls/qimageencodercontrol.h index 023e9beb5..292e16b1f 100644 --- a/src/multimedia/controls/qimageencodercontrol.h +++ b/src/multimedia/controls/qimageencodercontrol.h @@ -68,13 +68,13 @@ public: virtual QString imageCodecDescription(const QString &codecName) const = 0; virtual QList<QSize> supportedResolutions(const QImageEncoderSettings &settings, - bool *continuous = 0) const = 0; + bool *continuous = Q_NULLPTR) const = 0; virtual QImageEncoderSettings imageSettings() const = 0; virtual void setImageSettings(const QImageEncoderSettings &settings) = 0; protected: - QImageEncoderControl(QObject *parent = 0); + explicit QImageEncoderControl(QObject *parent = Q_NULLPTR); }; #define QImageEncoderControl_iid "org.qt-project.qt.imageencodercontrol/5.0" diff --git a/src/multimedia/controls/qmediaaudioprobecontrol.h b/src/multimedia/controls/qmediaaudioprobecontrol.h index c5e384927..9d679c768 100644 --- a/src/multimedia/controls/qmediaaudioprobecontrol.h +++ b/src/multimedia/controls/qmediaaudioprobecontrol.h @@ -56,7 +56,7 @@ Q_SIGNALS: void flush(); protected: - explicit QMediaAudioProbeControl(QObject *parent = 0); + explicit QMediaAudioProbeControl(QObject *parent = Q_NULLPTR); }; #define QMediaAudioProbeControl_iid "org.qt-project.qt.mediaaudioprobecontrol/5.0" diff --git a/src/multimedia/controls/qmediaavailabilitycontrol.h b/src/multimedia/controls/qmediaavailabilitycontrol.h index 7bab5c0fb..55149ccb0 100644 --- a/src/multimedia/controls/qmediaavailabilitycontrol.h +++ b/src/multimedia/controls/qmediaavailabilitycontrol.h @@ -62,7 +62,7 @@ Q_SIGNALS: void availabilityChanged(QMultimedia::AvailabilityStatus availability); protected: - QMediaAvailabilityControl(QObject* parent = 0); + explicit QMediaAvailabilityControl(QObject *parent = Q_NULLPTR); }; #define QMediaAvailabilityControl_iid "org.qt-project.qt.mediaavailabilitycontrol/5.0" diff --git a/src/multimedia/controls/qmediacontainercontrol.h b/src/multimedia/controls/qmediacontainercontrol.h index 8e17b98fe..8c315590e 100644 --- a/src/multimedia/controls/qmediacontainercontrol.h +++ b/src/multimedia/controls/qmediacontainercontrol.h @@ -62,7 +62,7 @@ public: virtual QString containerDescription(const QString &formatMimeType) const = 0; protected: - QMediaContainerControl(QObject *parent = 0); + explicit QMediaContainerControl(QObject *parent = Q_NULLPTR); }; #define QMediaContainerControl_iid "org.qt-project.qt.mediacontainercontrol/5.0" diff --git a/src/multimedia/controls/qmediagaplessplaybackcontrol.h b/src/multimedia/controls/qmediagaplessplaybackcontrol.h index e9a1472e1..8ab31ef62 100644 --- a/src/multimedia/controls/qmediagaplessplaybackcontrol.h +++ b/src/multimedia/controls/qmediagaplessplaybackcontrol.h @@ -66,7 +66,7 @@ Q_SIGNALS: void advancedToNextMedia(); protected: - QMediaGaplessPlaybackControl(QObject* parent = 0); + explicit QMediaGaplessPlaybackControl(QObject *parent = Q_NULLPTR); }; #define QMediaGaplessPlaybackControl_iid "org.qt-project.qt.mediagaplessplaybackcontrol/5.0" diff --git a/src/multimedia/controls/qmedianetworkaccesscontrol.h b/src/multimedia/controls/qmedianetworkaccesscontrol.h index 118e315a7..1c258a0bb 100644 --- a/src/multimedia/controls/qmedianetworkaccesscontrol.h +++ b/src/multimedia/controls/qmedianetworkaccesscontrol.h @@ -65,7 +65,7 @@ Q_SIGNALS: void configurationChanged(const QNetworkConfiguration& configuration); protected: - QMediaNetworkAccessControl(QObject *parent = 0); + explicit QMediaNetworkAccessControl(QObject *parent = Q_NULLPTR); }; #define QMediaNetworkAccessControl_iid "org.qt-project.qt.medianetworkaccesscontrol/5.0" diff --git a/src/multimedia/controls/qmediaplayercontrol.h b/src/multimedia/controls/qmediaplayercontrol.h index 416cfa5f1..a3fb1d4e1 100644 --- a/src/multimedia/controls/qmediaplayercontrol.h +++ b/src/multimedia/controls/qmediaplayercontrol.h @@ -110,7 +110,7 @@ Q_SIGNALS: void error(int error, const QString &errorString); protected: - QMediaPlayerControl(QObject* parent = 0); + explicit QMediaPlayerControl(QObject *parent = Q_NULLPTR); }; #define QMediaPlayerControl_iid "org.qt-project.qt.mediaplayercontrol/5.0" diff --git a/src/multimedia/controls/qmediarecordercontrol.h b/src/multimedia/controls/qmediarecordercontrol.h index 297640f23..85f5c78d5 100644 --- a/src/multimedia/controls/qmediarecordercontrol.h +++ b/src/multimedia/controls/qmediarecordercontrol.h @@ -88,7 +88,7 @@ public Q_SLOTS: virtual void setVolume(qreal volume) = 0; protected: - QMediaRecorderControl(QObject* parent = 0); + explicit QMediaRecorderControl(QObject *parent = Q_NULLPTR); }; #define QMediaRecorderControl_iid "org.qt-project.qt.mediarecordercontrol/5.0" diff --git a/src/multimedia/controls/qmediastreamscontrol.h b/src/multimedia/controls/qmediastreamscontrol.h index db738c922..ea12dd188 100644 --- a/src/multimedia/controls/qmediastreamscontrol.h +++ b/src/multimedia/controls/qmediastreamscontrol.h @@ -73,7 +73,7 @@ Q_SIGNALS: void activeStreamsChanged(); protected: - QMediaStreamsControl(QObject *parent = 0); + explicit QMediaStreamsControl(QObject *parent = Q_NULLPTR); }; #define QMediaStreamsControl_iid "org.qt-project.qt.mediastreamscontrol/5.0" diff --git a/src/multimedia/controls/qmediavideoprobecontrol.h b/src/multimedia/controls/qmediavideoprobecontrol.h index 3adea5846..25caefee6 100644 --- a/src/multimedia/controls/qmediavideoprobecontrol.h +++ b/src/multimedia/controls/qmediavideoprobecontrol.h @@ -58,7 +58,7 @@ Q_SIGNALS: void flush(); protected: - explicit QMediaVideoProbeControl(QObject *parent = 0); + explicit QMediaVideoProbeControl(QObject *parent = Q_NULLPTR); }; #define QMediaVideoProbeControl_iid "org.qt-project.qt.mediavideoprobecontrol/5.0" diff --git a/src/multimedia/controls/qmetadatareadercontrol.h b/src/multimedia/controls/qmetadatareadercontrol.h index 4923be102..9162d6454 100644 --- a/src/multimedia/controls/qmetadatareadercontrol.h +++ b/src/multimedia/controls/qmetadatareadercontrol.h @@ -71,7 +71,7 @@ Q_SIGNALS: void metaDataAvailableChanged(bool available); protected: - QMetaDataReaderControl(QObject *parent = 0); + explicit QMetaDataReaderControl(QObject *parent = Q_NULLPTR); }; #define QMetaDataReaderControl_iid "org.qt-project.qt.metadatareadercontrol/5.0" diff --git a/src/multimedia/controls/qmetadatawritercontrol.h b/src/multimedia/controls/qmetadatawritercontrol.h index adef3af8d..1c2f4cf69 100644 --- a/src/multimedia/controls/qmetadatawritercontrol.h +++ b/src/multimedia/controls/qmetadatawritercontrol.h @@ -74,7 +74,7 @@ Q_SIGNALS: void metaDataAvailableChanged(bool available); protected: - QMetaDataWriterControl(QObject *parent = 0); + explicit QMetaDataWriterControl(QObject *parent = Q_NULLPTR); }; #define QMetaDataWriterControl_iid "org.qt-project.qt.metadatawritercontrol/5.0" diff --git a/src/multimedia/controls/qradiodatacontrol.h b/src/multimedia/controls/qradiodatacontrol.h index e61978d8b..28b3a57b2 100644 --- a/src/multimedia/controls/qradiodatacontrol.h +++ b/src/multimedia/controls/qradiodatacontrol.h @@ -76,7 +76,7 @@ Q_SIGNALS: void error(QRadioData::Error err); protected: - QRadioDataControl(QObject *parent = 0); + explicit QRadioDataControl(QObject *parent = Q_NULLPTR); }; #define QRadioDataControl_iid "org.qt-project.qt.radiodatacontrol/5.0" diff --git a/src/multimedia/controls/qradiotunercontrol.h b/src/multimedia/controls/qradiotunercontrol.h index 106e3e272..9a9e12059 100644 --- a/src/multimedia/controls/qradiotunercontrol.h +++ b/src/multimedia/controls/qradiotunercontrol.h @@ -107,7 +107,7 @@ Q_SIGNALS: void antennaConnectedChanged(bool connectionStatus); protected: - QRadioTunerControl(QObject *parent = 0); + explicit QRadioTunerControl(QObject *parent = Q_NULLPTR); }; #define QRadioTunerControl_iid "org.qt-project.qt.radiotunercontrol/5.0" diff --git a/src/multimedia/controls/qvideodeviceselectorcontrol.h b/src/multimedia/controls/qvideodeviceselectorcontrol.h index de154aafe..10a703bb2 100644 --- a/src/multimedia/controls/qvideodeviceselectorcontrol.h +++ b/src/multimedia/controls/qvideodeviceselectorcontrol.h @@ -71,7 +71,7 @@ Q_SIGNALS: void devicesChanged(); protected: - QVideoDeviceSelectorControl(QObject *parent = 0); + explicit QVideoDeviceSelectorControl(QObject *parent = Q_NULLPTR); }; #define QVideoDeviceSelectorControl_iid "org.qt-project.qt.videodeviceselectorcontrol/5.0" diff --git a/src/multimedia/controls/qvideoencodersettingscontrol.h b/src/multimedia/controls/qvideoencodersettingscontrol.h index 4bf8c4d45..ea1401aeb 100644 --- a/src/multimedia/controls/qvideoencodersettingscontrol.h +++ b/src/multimedia/controls/qvideoencodersettingscontrol.h @@ -65,10 +65,10 @@ public: virtual ~QVideoEncoderSettingsControl(); virtual QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, - bool *continuous = 0) const = 0; + bool *continuous = Q_NULLPTR) const = 0; virtual QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, - bool *continuous = 0) const = 0; + bool *continuous = Q_NULLPTR) const = 0; virtual QStringList supportedVideoCodecs() const = 0; virtual QString videoCodecDescription(const QString &codecName) const = 0; @@ -77,7 +77,7 @@ public: virtual void setVideoSettings(const QVideoEncoderSettings &settings) = 0; protected: - QVideoEncoderSettingsControl(QObject *parent = 0); + explicit QVideoEncoderSettingsControl(QObject *parent = Q_NULLPTR); }; #define QVideoEncoderSettingsControl_iid "org.qt-project.qt.videoencodersettingscontrol/5.0" diff --git a/src/multimedia/controls/qvideorenderercontrol.h b/src/multimedia/controls/qvideorenderercontrol.h index 6c4606318..2ddab28e1 100644 --- a/src/multimedia/controls/qvideorenderercontrol.h +++ b/src/multimedia/controls/qvideorenderercontrol.h @@ -56,7 +56,7 @@ public: virtual void setSurface(QAbstractVideoSurface *surface) = 0; protected: - QVideoRendererControl(QObject *parent = 0); + explicit QVideoRendererControl(QObject *parent = Q_NULLPTR); }; #define QVideoRendererControl_iid "org.qt-project.qt.videorenderercontrol/5.0" diff --git a/src/multimedia/controls/qvideowindowcontrol.h b/src/multimedia/controls/qvideowindowcontrol.h index 6b9478b1f..d26579ddc 100644 --- a/src/multimedia/controls/qvideowindowcontrol.h +++ b/src/multimedia/controls/qvideowindowcontrol.h @@ -94,7 +94,7 @@ Q_SIGNALS: void nativeSizeChanged(); protected: - QVideoWindowControl(QObject *parent = 0); + explicit QVideoWindowControl(QObject *parent = Q_NULLPTR); }; #define QVideoWindowControl_iid "org.qt-project.qt.videowindowcontrol/5.0" diff --git a/src/multimedia/doc/src/images/annotatedurl.png b/src/multimedia/doc/src/images/annotatedurl.png Binary files differindex 38d86fb49..b6cf8637c 100644 --- a/src/multimedia/doc/src/images/annotatedurl.png +++ b/src/multimedia/doc/src/images/annotatedurl.png diff --git a/src/multimedia/doc/src/images/video-graphics-memory.png b/src/multimedia/doc/src/images/video-graphics-memory.png Binary files differindex 9479cce4c..4bea33322 100644 --- a/src/multimedia/doc/src/images/video-graphics-memory.png +++ b/src/multimedia/doc/src/images/video-graphics-memory.png diff --git a/src/multimedia/doc/src/images/video-qml-paint-rate.png b/src/multimedia/doc/src/images/video-qml-paint-rate.png Binary files differindex 1519ff64e..cb7d822d9 100644 --- a/src/multimedia/doc/src/images/video-qml-paint-rate.png +++ b/src/multimedia/doc/src/images/video-qml-paint-rate.png diff --git a/src/multimedia/doc/src/multimedia.qdoc b/src/multimedia/doc/src/multimedia.qdoc index 5849af59d..813847d88 100644 --- a/src/multimedia/doc/src/multimedia.qdoc +++ b/src/multimedia/doc/src/multimedia.qdoc @@ -177,12 +177,12 @@ what changed, and what you might need to change when porting code. \section2 QML Types The QML types are accessed by using: \code -import QtMultimedia 5.5 +import QtMultimedia 5.6 \endcode \annotatedlist multimedia_qml The following types are accessed by using \l{Qt Audio Engine QML Types}{Qt Audio Engine}: \code -import QtAudioEngine 1.0 +import QtAudioEngine 1.1 \endcode \annotatedlist multimedia_audioengine diff --git a/src/multimedia/doc/src/qtaudioengine.qdoc b/src/multimedia/doc/src/qtaudioengine.qdoc index 3b65379d3..2de2bb250 100644 --- a/src/multimedia/doc/src/qtaudioengine.qdoc +++ b/src/multimedia/doc/src/qtaudioengine.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! -\qmlmodule QtAudioEngine 1.0 +\qmlmodule QtAudioEngine 1.1 \title Qt Audio Engine QML Types \ingroup qmlmodules \brief Provides QML types for 3D positional audio playback and content management. @@ -37,7 +37,7 @@ Engine provides types for 3D positional audio playback and content management. The QML types can be imported into your application using the following import statement in your .qml file: \code -import QtAudioEngine 1.0 +import QtAudioEngine 1.1 \endcode \section1 Qt Audio Engine Features diff --git a/src/multimedia/doc/src/qtmultimedia-index.qdoc b/src/multimedia/doc/src/qtmultimedia-index.qdoc index e51ec97e0..989b8886e 100644 --- a/src/multimedia/doc/src/qtmultimedia-index.qdoc +++ b/src/multimedia/doc/src/qtmultimedia-index.qdoc @@ -54,7 +54,7 @@ import statement in your \c {.qml} file. \code - import QtMultimedia 5.5 + import QtMultimedia 5.6 \endcode If you intend to use the C++ classes in your application, include the C++ diff --git a/src/multimedia/doc/src/qtmultimedia5.qdoc b/src/multimedia/doc/src/qtmultimedia5.qdoc index 0d3e087a0..21854ae7c 100644 --- a/src/multimedia/doc/src/qtmultimedia5.qdoc +++ b/src/multimedia/doc/src/qtmultimedia5.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! -\qmlmodule QtMultimedia 5.5 +\qmlmodule QtMultimedia 5.6 \title Qt Multimedia QML Types \ingroup qmlmodules \brief Provides QML types for multimedia support. @@ -42,7 +42,7 @@ The QML types for \l{Qt Multimedia} support the basic use cases such as: The QML types can be imported into your application using the following import statement in your .qml file: \code -import QtMultimedia 5.5 +import QtMultimedia 5.6 \endcode \section1 QML types diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index b16a792fb..761e488ba 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -12,8 +12,6 @@ MODULE_PLUGIN_TYPES = \ QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf -load(qt_module) - INCLUDEPATH *= . PRIVATE_HEADERS += \ @@ -84,6 +82,12 @@ ANDROID_FEATURES += \ android.hardware.camera.autofocus \ android.hardware.microphone +MODULE_WINRT_CAPABILITIES_DEVICE += \ + microphone \ + webcam + win32: LIBS_PRIVATE += -luuid HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS + +load(qt_module) diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index 6babc281e..f8d91b999 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -119,13 +119,13 @@ public: MediaIsPlaylist }; - QMediaPlayer(QObject *parent = 0, Flags flags = 0); + explicit QMediaPlayer(QObject *parent = Q_NULLPTR, Flags flags = Flags()); ~QMediaPlayer(); static QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs = QStringList(), - Flags flags = 0); - static QStringList supportedMimeTypes(Flags flags = 0); + Flags flags = Flags()); + static QStringList supportedMimeTypes(Flags flags = Flags()); void setVideoOutput(QVideoWidget *); void setVideoOutput(QGraphicsVideoItem *); @@ -174,7 +174,7 @@ public Q_SLOTS: void setPlaybackRate(qreal rate); - void setMedia(const QMediaContent &media, QIODevice *stream = 0); + void setMedia(const QMediaContent &media, QIODevice *stream = Q_NULLPTR); void setPlaylist(QMediaPlaylist *playlist); void setNetworkConfigurations(const QList<QNetworkConfiguration> &configurations); diff --git a/src/multimedia/playback/qmediaplaylist.h b/src/multimedia/playback/qmediaplaylist.h index 1fa75a24d..05ab8f42e 100644 --- a/src/multimedia/playback/qmediaplaylist.h +++ b/src/multimedia/playback/qmediaplaylist.h @@ -67,7 +67,7 @@ public: enum PlaybackMode { CurrentItemOnce, CurrentItemInLoop, Sequential, Loop, Random }; enum Error { NoError, FormatError, FormatNotSupportedError, NetworkError, AccessDeniedError }; - QMediaPlaylist(QObject *parent = 0); + explicit QMediaPlaylist(QObject *parent = Q_NULLPTR); virtual ~QMediaPlaylist(); QMediaObject *mediaObject() const; @@ -96,11 +96,11 @@ public: bool removeMedia(int start, int end); bool clear(); - void load(const QNetworkRequest &request, const char *format = 0); - void load(const QUrl &location, const char *format = 0); - void load(QIODevice * device, const char *format = 0); + void load(const QNetworkRequest &request, const char *format = Q_NULLPTR); + void load(const QUrl &location, const char *format = Q_NULLPTR); + void load(QIODevice *device, const char *format = Q_NULLPTR); - bool save(const QUrl &location, const char *format = 0); + bool save(const QUrl &location, const char *format = Q_NULLPTR); bool save(QIODevice * device, const char *format); Error error() const; diff --git a/src/multimedia/qmediacontrol.h b/src/multimedia/qmediacontrol.h index 0f4c5d295..3c95444d0 100644 --- a/src/multimedia/qmediacontrol.h +++ b/src/multimedia/qmediacontrol.h @@ -59,8 +59,8 @@ public: ~QMediaControl(); protected: - QMediaControl(QObject *parent = 0); - QMediaControl(QMediaControlPrivate &dd, QObject *parent = 0); + explicit QMediaControl(QObject *parent = Q_NULLPTR); + explicit QMediaControl(QMediaControlPrivate &dd, QObject *parent = Q_NULLPTR); QMediaControlPrivate *d_ptr; diff --git a/src/multimedia/qtmultimediaquicktools_headers/qtmultimediaquickdefs_p.h b/src/multimedia/qtmultimediaquicktools_headers/qtmultimediaquickdefs_p.h index 2b2dcb6f6..20188739c 100644 --- a/src/multimedia/qtmultimediaquicktools_headers/qtmultimediaquickdefs_p.h +++ b/src/multimedia/qtmultimediaquicktools_headers/qtmultimediaquickdefs_p.h @@ -54,7 +54,7 @@ #include <QtCore/qglobal.h> #ifndef QT_STATIC -# if defined(QT_BUILD_QTMM_QUICK_LIB) +# if defined(QT_BUILD_QTMULTIMEDIAQUICKTOOLS_LIB) # define Q_MULTIMEDIAQUICK_EXPORT Q_DECL_EXPORT # else # define Q_MULTIMEDIAQUICK_EXPORT Q_DECL_IMPORT diff --git a/src/multimedia/radio/qradiodata.h b/src/multimedia/radio/qradiodata.h index 40b03a72b..a5cc09900 100644 --- a/src/multimedia/radio/qradiodata.h +++ b/src/multimedia/radio/qradiodata.h @@ -82,7 +82,7 @@ public: College }; - QRadioData(QMediaObject *mediaObject, QObject *parent = 0); + explicit QRadioData(QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); ~QRadioData(); QMultimedia::AvailabilityStatus availability() const; diff --git a/src/multimedia/radio/qradiotuner.h b/src/multimedia/radio/qradiotuner.h index 8f9175933..a9de6416d 100644 --- a/src/multimedia/radio/qradiotuner.h +++ b/src/multimedia/radio/qradiotuner.h @@ -78,7 +78,7 @@ public: enum StereoMode { ForceStereo, ForceMono, Auto }; enum SearchMode { SearchFast, SearchGetStationId }; - QRadioTuner(QObject *parent = 0); + explicit QRadioTuner(QObject *parent = Q_NULLPTR); ~QRadioTuner(); QMultimedia::AvailabilityStatus availability() const; diff --git a/src/multimedia/recording/qaudiorecorder.h b/src/multimedia/recording/qaudiorecorder.h index 34e58bbe9..75f95d354 100644 --- a/src/multimedia/recording/qaudiorecorder.h +++ b/src/multimedia/recording/qaudiorecorder.h @@ -62,7 +62,7 @@ class Q_MULTIMEDIA_EXPORT QAudioRecorder : public QMediaRecorder Q_OBJECT Q_PROPERTY(QString audioInput READ audioInput WRITE setAudioInput NOTIFY audioInputChanged) public: - QAudioRecorder(QObject *parent = 0); + explicit QAudioRecorder(QObject *parent = Q_NULLPTR); ~QAudioRecorder(); QStringList audioInputs() const; diff --git a/src/multimedia/recording/qmediarecorder.h b/src/multimedia/recording/qmediarecorder.h index a06c1ce70..3ac25129b 100644 --- a/src/multimedia/recording/qmediarecorder.h +++ b/src/multimedia/recording/qmediarecorder.h @@ -106,7 +106,7 @@ public: OutOfSpaceError }; - QMediaRecorder(QMediaObject *mediaObject, QObject *parent = 0); + explicit QMediaRecorder(QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); ~QMediaRecorder(); QMediaObject *mediaObject() const; @@ -137,16 +137,16 @@ public: QString audioCodecDescription(const QString &codecName) const; QList<int> supportedAudioSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = Q_NULLPTR) const; QStringList supportedVideoCodecs() const; QString videoCodecDescription(const QString &codecName) const; QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = Q_NULLPTR) const; QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = Q_NULLPTR) const; QAudioEncoderSettings audioSettings() const; QVideoEncoderSettings videoSettings() const; @@ -193,7 +193,7 @@ Q_SIGNALS: void availabilityChanged(QMultimedia::AvailabilityStatus availability); protected: - QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent = 0); + QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); bool setMediaObject(QMediaObject *object); QMediaRecorderPrivate *d_ptr; diff --git a/src/multimedia/video/qabstractvideofilter.h b/src/multimedia/video/qabstractvideofilter.h index 266c1ea02..7e125fac4 100644 --- a/src/multimedia/video/qabstractvideofilter.h +++ b/src/multimedia/video/qabstractvideofilter.h @@ -68,7 +68,7 @@ class Q_MULTIMEDIA_EXPORT QAbstractVideoFilter : public QObject Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) public: - explicit QAbstractVideoFilter(QObject *parent = 0); + explicit QAbstractVideoFilter(QObject *parent = Q_NULLPTR); ~QAbstractVideoFilter(); bool isActive() const; diff --git a/src/multimedia/video/qabstractvideosurface.h b/src/multimedia/video/qabstractvideosurface.h index cb367b197..f3d3e0799 100644 --- a/src/multimedia/video/qabstractvideosurface.h +++ b/src/multimedia/video/qabstractvideosurface.h @@ -64,7 +64,7 @@ public: ResourceError }; - explicit QAbstractVideoSurface(QObject *parent = 0); + explicit QAbstractVideoSurface(QObject *parent = Q_NULLPTR); ~QAbstractVideoSurface(); virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats( diff --git a/src/multimedia/video/qvideoprobe.h b/src/multimedia/video/qvideoprobe.h index 1bcc954dc..854e71272 100644 --- a/src/multimedia/video/qvideoprobe.h +++ b/src/multimedia/video/qvideoprobe.h @@ -53,7 +53,7 @@ class Q_MULTIMEDIA_EXPORT QVideoProbe : public QObject { Q_OBJECT public: - explicit QVideoProbe(QObject *parent = 0); + explicit QVideoProbe(QObject *parent = Q_NULLPTR); ~QVideoProbe(); bool setSource(QMediaObject *source); diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro index ec96be57c..60321fba8 100644 --- a/src/multimediawidgets/multimediawidgets.pro +++ b/src/multimediawidgets/multimediawidgets.pro @@ -7,8 +7,6 @@ qtHaveModule(opengl):!contains(QT_CONFIG, opengles1) { DEFINES += QT_NO_OPENGL } -load(qt_module) - PRIVATE_HEADERS += \ qvideowidget_p.h \ qpaintervideosurface_p.h \ @@ -44,3 +42,5 @@ maemo6 { } HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS + +load(qt_module) diff --git a/src/multimediawidgets/qcameraviewfinder.h b/src/multimediawidgets/qcameraviewfinder.h index 5be820179..2bd49fe83 100644 --- a/src/multimediawidgets/qcameraviewfinder.h +++ b/src/multimediawidgets/qcameraviewfinder.h @@ -61,7 +61,7 @@ class Q_MULTIMEDIAWIDGETS_EXPORT QCameraViewfinder : public QVideoWidget { Q_OBJECT public: - QCameraViewfinder(QWidget *parent = 0); + explicit QCameraViewfinder(QWidget *parent = Q_NULLPTR); ~QCameraViewfinder(); QMediaObject *mediaObject() const; diff --git a/src/multimediawidgets/qgraphicsvideoitem.h b/src/multimediawidgets/qgraphicsvideoitem.h index b6a76b9be..89de3397a 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.h +++ b/src/multimediawidgets/qgraphicsvideoitem.h @@ -63,7 +63,7 @@ class Q_MULTIMEDIAWIDGETS_EXPORT QGraphicsVideoItem : public QGraphicsObject, pu Q_PROPERTY(QSizeF size READ size WRITE setSize) Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged) public: - QGraphicsVideoItem(QGraphicsItem *parent = 0); + explicit QGraphicsVideoItem(QGraphicsItem *parent = Q_NULLPTR); ~QGraphicsVideoItem(); QMediaObject *mediaObject() const; @@ -81,7 +81,7 @@ public: QRectF boundingRect() const; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); Q_SIGNALS: void nativeSizeChanged(const QSizeF &size); diff --git a/src/multimediawidgets/qvideowidget.h b/src/multimediawidgets/qvideowidget.h index c52ffe577..9aca9d3a4 100644 --- a/src/multimediawidgets/qvideowidget.h +++ b/src/multimediawidgets/qvideowidget.h @@ -64,7 +64,7 @@ class Q_MULTIMEDIAWIDGETS_EXPORT QVideoWidget : public QWidget, public QMediaBin Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged) public: - QVideoWidget(QWidget *parent = 0); + explicit QVideoWidget(QWidget *parent = Q_NULLPTR); ~QVideoWidget(); QMediaObject *mediaObject() const; diff --git a/src/multimediawidgets/qvideowidgetcontrol.h b/src/multimediawidgets/qvideowidgetcontrol.h index a3eedb25e..7d9423882 100644 --- a/src/multimediawidgets/qvideowidgetcontrol.h +++ b/src/multimediawidgets/qvideowidgetcontrol.h @@ -85,7 +85,7 @@ Q_SIGNALS: void saturationChanged(int saturation); protected: - QVideoWidgetControl(QObject *parent = 0); + explicit QVideoWidgetControl(QObject *parent = Q_NULLPTR); }; #define QVideoWidgetControl_iid "org.qt-project.qt.videowidgetcontrol/5.0" diff --git a/src/plugins/alsa/alsa.pro b/src/plugins/alsa/alsa.pro index 481c57eaf..56657f100 100644 --- a/src/plugins/alsa/alsa.pro +++ b/src/plugins/alsa/alsa.pro @@ -1,10 +1,6 @@ TARGET = qtaudio_alsa QT += multimedia-private -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = QAlsaPlugin -load(qt_plugin) - LIBS += -lasound HEADERS += \ @@ -21,3 +17,7 @@ SOURCES += \ OTHER_FILES += \ alsa.json + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = QAlsaPlugin +load(qt_plugin) diff --git a/src/plugins/alsa/qalsaaudiodeviceinfo.cpp b/src/plugins/alsa/qalsaaudiodeviceinfo.cpp index 5e7aaa3d0..0342ca546 100644 --- a/src/plugins/alsa/qalsaaudiodeviceinfo.cpp +++ b/src/plugins/alsa/qalsaaudiodeviceinfo.cpp @@ -147,7 +147,7 @@ bool QAlsaAudioDeviceInfo::open() QList<QByteArray> devices = availableDevices(mode); if(dev.compare(QLatin1String("default")) == 0) { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 if (devices.size() > 0) dev = QLatin1String(devices.first().constData()); else @@ -156,7 +156,7 @@ bool QAlsaAudioDeviceInfo::open() dev = QLatin1String("hw:0,0"); #endif } else { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 dev = device; #else int idx = 0; @@ -200,7 +200,7 @@ bool QAlsaAudioDeviceInfo::testSettings(const QAudioFormat& format) const snd_pcm_hw_params_t *params; QString dev; -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 dev = device; if (dev.compare(QLatin1String("default")) == 0) { QList<QByteArray> devices = availableDevices(QAudio::AudioOutput); @@ -341,7 +341,7 @@ QList<QByteArray> QAlsaAudioDeviceInfo::availableDevices(QAudio::Mode mode) QList<QByteArray> devices; QByteArray filter; -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 // Create a list of all current audio devices that support mode void **hints, **n; char *name, *descr, *io; diff --git a/src/plugins/alsa/qalsaaudioinput.cpp b/src/plugins/alsa/qalsaaudioinput.cpp index bdf190cd3..5f83631ab 100644 --- a/src/plugins/alsa/qalsaaudioinput.cpp +++ b/src/plugins/alsa/qalsaaudioinput.cpp @@ -309,7 +309,7 @@ bool QAlsaAudioInput::open() QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAlsaAudioDeviceInfo::availableDevices(QAudio::AudioInput); if(dev.compare(QLatin1String("default")) == 0) { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 if (devices.size() > 0) dev = QLatin1String(devices.first()); else @@ -318,7 +318,7 @@ bool QAlsaAudioInput::open() dev = QLatin1String("hw:0,0"); #endif } else { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 dev = QLatin1String(m_device); #else int idx = 0; diff --git a/src/plugins/alsa/qalsaaudiooutput.cpp b/src/plugins/alsa/qalsaaudiooutput.cpp index 9fee690b5..df050ecd7 100644 --- a/src/plugins/alsa/qalsaaudiooutput.cpp +++ b/src/plugins/alsa/qalsaaudiooutput.cpp @@ -312,7 +312,7 @@ bool QAlsaAudioOutput::open() QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAlsaAudioDeviceInfo::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 if (devices.size() > 0) dev = QLatin1String(devices.first()); else @@ -321,7 +321,7 @@ bool QAlsaAudioOutput::open() dev = QLatin1String("hw:0,0"); #endif } else { -#if (SND_LIB_MAJOR == 1 && (SND_LIB_MINOR > 0 || SND_LIB_SUBMINOR >= 14)) +#if SND_LIB_VERSION >= 0x1000e // 1.0.14 dev = QLatin1String(m_device); #else int idx = 0; diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index 713123baf..5408fb109 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -1,7 +1,6 @@ load(qt_build_paths) CONFIG += java DESTDIR = $$MODULE_BASE_OUTDIR/jar -API_VERSION = android-11 JAVACLASSPATH += $$PWD/src diff --git a/src/plugins/android/src/src.pro b/src/plugins/android/src/src.pro index 6a472a0a8..166bcc42b 100644 --- a/src/plugins/android/src/src.pro +++ b/src/plugins/android/src/src.pro @@ -1,9 +1,6 @@ TARGET = qtmedia_android -QT += multimedia-private core-private network -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = QAndroidMediaServicePlugin -load(qt_plugin) +QT += multimedia-private core-private network HEADERS += \ qandroidmediaserviceplugin.h @@ -17,3 +14,7 @@ include (mediaplayer/mediaplayer.pri) include (mediacapture/mediacapture.pri) OTHER_FILES += android_mediaservice.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = QAndroidMediaServicePlugin +load(qt_plugin) diff --git a/src/plugins/android/src/wrappers/jni/androidsurfaceview.cpp b/src/plugins/android/src/wrappers/jni/androidsurfaceview.cpp index d2c150d00..6eec85171 100644 --- a/src/plugins/android/src/wrappers/jni/androidsurfaceview.cpp +++ b/src/plugins/android/src/wrappers/jni/androidsurfaceview.cpp @@ -137,8 +137,32 @@ AndroidSurfaceView::AndroidSurfaceView() , m_surfaceHolder(0) , m_pendingVisible(-1) { - setAutoDelete(false); - QtAndroidPrivate::runOnUiThread(this, QJNIEnvironmentPrivate()); + QtAndroidPrivate::runOnAndroidThreadSync([this] { + m_surfaceView = QJNIObjectPrivate("android/view/SurfaceView", + "(Landroid/content/Context;)V", + QtAndroidPrivate::activity()); + }, QJNIEnvironmentPrivate()); + + Q_ASSERT(m_surfaceView.isValid()); + + QJNIObjectPrivate holder = m_surfaceView.callObjectMethod("getHolder", + "()Landroid/view/SurfaceHolder;"); + if (!holder.isValid()) { + m_surfaceView = QJNIObjectPrivate(); + } else { + m_surfaceHolder = new AndroidSurfaceHolder(holder); + connect(m_surfaceHolder, &AndroidSurfaceHolder::surfaceCreated, + this, &AndroidSurfaceView::surfaceCreated); + { // Lock now to avoid a race with handleSurfaceCreated() + QMutexLocker locker(shLock); + m_window = QWindow::fromWinId(WId(m_surfaceView.object())); + + if (m_pendingVisible != -1) + m_window->setVisible(m_pendingVisible); + if (m_pendingGeometry.isValid()) + m_window->setGeometry(m_pendingGeometry); + } + } } AndroidSurfaceView::~AndroidSurfaceView() @@ -168,43 +192,4 @@ void AndroidSurfaceView::setGeometry(int x, int y, int width, int height) m_pendingGeometry = QRect(x, y, width, height); } -bool AndroidSurfaceView::event(QEvent *e) -{ - if (e->type() == QEvent::User) { - Q_ASSERT(m_surfaceView.isValid()); - - QJNIObjectPrivate holder = m_surfaceView.callObjectMethod("getHolder", - "()Landroid/view/SurfaceHolder;"); - if (!holder.isValid()) { - m_surfaceView = QJNIObjectPrivate(); - } else { - m_surfaceHolder = new AndroidSurfaceHolder(holder); - connect(m_surfaceHolder, &AndroidSurfaceHolder::surfaceCreated, - this, &AndroidSurfaceView::surfaceCreated); - { // Lock now to avoid a race with handleSurfaceCreated() - QMutexLocker locker(shLock); - m_window = QWindow::fromWinId(WId(m_surfaceView.object())); - - if (m_pendingVisible != -1) - m_window->setVisible(m_pendingVisible); - if (m_pendingGeometry.isValid()) - m_window->setGeometry(m_pendingGeometry); - } - } - - return true; - } - - return QObject::event(e); -} - -// Called on the Android UI thread. -void AndroidSurfaceView::run() -{ - m_surfaceView = QJNIObjectPrivate("android/view/SurfaceView", - "(Landroid/content/Context;)V", - QtAndroidPrivate::activity()); - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); -} - QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jni/androidsurfaceview.h b/src/plugins/android/src/wrappers/jni/androidsurfaceview.h index 3d28f5325..ef603061d 100644 --- a/src/plugins/android/src/wrappers/jni/androidsurfaceview.h +++ b/src/plugins/android/src/wrappers/jni/androidsurfaceview.h @@ -74,7 +74,7 @@ private: friend class AndroidSurfaceView; }; -class AndroidSurfaceView : public QObject, public QRunnable +class AndroidSurfaceView : public QObject { Q_OBJECT public: @@ -86,14 +86,9 @@ public: void setVisible(bool v); void setGeometry(int x, int y, int width, int height); - bool event(QEvent *); - Q_SIGNALS: void surfaceCreated(); -protected: - void run() override; - private: QJNIObjectPrivate m_surfaceView; QWindow *m_window; diff --git a/src/plugins/android/videonode/videonode.pro b/src/plugins/android/videonode/videonode.pro index 661e36436..daf07c9ec 100644 --- a/src/plugins/android/videonode/videonode.pro +++ b/src/plugins/android/videonode/videonode.pro @@ -1,10 +1,6 @@ TARGET = qtsgvideonode_android -QT += quick multimedia-private qtmultimediaquicktools-private -PLUGIN_TYPE = video/videonode -PLUGIN_EXTENDS = quick -PLUGIN_CLASS_NAME = QAndroidSGVideoNodeFactoryPlugin -load(qt_plugin) +QT += quick multimedia-private qtmultimediaquicktools-private HEADERS += \ qandroidsgvideonodeplugin.h \ @@ -15,3 +11,8 @@ SOURCES += \ qandroidsgvideonode.cpp OTHER_FILES += android_videonode.json + +PLUGIN_TYPE = video/videonode +PLUGIN_EXTENDS = quick +PLUGIN_CLASS_NAME = QAndroidSGVideoNodeFactoryPlugin +load(qt_plugin) diff --git a/src/plugins/audiocapture/audiocapture.pro b/src/plugins/audiocapture/audiocapture.pro index 833e4b5fc..ba2e5c802 100644 --- a/src/plugins/audiocapture/audiocapture.pro +++ b/src/plugins/audiocapture/audiocapture.pro @@ -1,10 +1,6 @@ TARGET = qtmedia_audioengine QT += multimedia-private -PLUGIN_TYPE=mediaservice -PLUGIN_CLASS_NAME = AudioCaptureServicePlugin -load(qt_plugin) - HEADERS += audioencodercontrol.h \ audiocontainercontrol.h \ audiomediarecordercontrol.h \ @@ -25,3 +21,7 @@ SOURCES += audioencodercontrol.cpp \ OTHER_FILES += \ audiocapture.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = AudioCaptureServicePlugin +load(qt_plugin) diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro index a82d88ded..8563eb655 100644 --- a/src/plugins/avfoundation/camera/camera.pro +++ b/src/plugins/avfoundation/camera/camera.pro @@ -1,13 +1,10 @@ +TARGET = qavfcamera + # Avoid clash with a variable named `slots' in a Quartz header CONFIG += no_keywords -TARGET = qavfcamera QT += multimedia-private network -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = AVFServicePlugin -load(qt_plugin) - LIBS += -framework AudioToolbox \ -framework CoreAudio \ -framework QuartzCore \ @@ -79,3 +76,7 @@ OBJECTIVE_SOURCES += avfcamerazoomcontrol.mm \ avfmediarecordercontrol_ios.mm } + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = AVFServicePlugin +load(qt_plugin) diff --git a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro index 8b5f14b4e..779d5ff2d 100644 --- a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro +++ b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro @@ -1,16 +1,11 @@ -load(qt_build_config) +TARGET = qavfmediaplayer #DEFINES += QT_DEBUG_AVF # Avoid clash with a variable named `slots' in a Quartz header CONFIG += no_keywords -TARGET = qavfmediaplayer QT += multimedia-private network -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = AVFMediaPlayerServicePlugin -load(qt_plugin) - LIBS += -framework AVFoundation -framework CoreMedia -framework CoreVideo -framework QuartzCore DEFINES += QMEDIA_AVF_MEDIAPLAYER @@ -75,3 +70,7 @@ ios|tvos { OTHER_FILES += \ avfmediaplayer.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = AVFMediaPlayerServicePlugin +load(qt_plugin) diff --git a/src/plugins/common/evr/evrcustompresenter.cpp b/src/plugins/common/evr/evrcustompresenter.cpp index 9df08012a..7a26afd10 100644 --- a/src/plugins/common/evr/evrcustompresenter.cpp +++ b/src/plugins/common/evr/evrcustompresenter.cpp @@ -848,8 +848,6 @@ HRESULT EVRCustomPresenter::OnClockStart(MFTIME, LONGLONG clockStartOffset) return hr; } - startSurface(); - // Now try to get new output samples from the mixer. processOutputLoop(); @@ -897,8 +895,6 @@ HRESULT EVRCustomPresenter::OnClockStop(MFTIME) cancelFrameStep(); } - stopSurface(); - return S_OK; } @@ -1406,6 +1402,7 @@ HRESULT EVRCustomPresenter::setMediaType(IMFMediaType *mediaType) // Clearing the media type is allowed in any state (including shutdown). if (!mediaType) { + stopSurface(); qt_evr_safe_release(&m_mediaType); releaseResources(); return S_OK; @@ -1466,6 +1463,8 @@ HRESULT EVRCustomPresenter::setMediaType(IMFMediaType *mediaType) m_mediaType = mediaType; m_mediaType->AddRef(); + startSurface(); + done: if (FAILED(hr)) releaseResources(); @@ -1879,18 +1878,19 @@ float EVRCustomPresenter::getMaxRate(bool thin) bool EVRCustomPresenter::event(QEvent *e) { - if (e->type() == StartSurface) { + switch (int(e->type())) { + case StartSurface: startSurface(); return true; - } else if (e->type() == StopSurface) { + case StopSurface: stopSurface(); return true; - } else if (e->type() == PresentSample) { - PresentSampleEvent *ev = static_cast<PresentSampleEvent *>(e); - presentSample(ev->sample()); + case PresentSample: + presentSample(static_cast<PresentSampleEvent *>(e)->sample()); return true; + default: + break; } - return QObject::event(e); } diff --git a/src/plugins/common/evr/evrdefs.h b/src/plugins/common/evr/evrdefs.h index f939d01a0..f898209b8 100644 --- a/src/plugins/common/evr/evrdefs.h +++ b/src/plugins/common/evr/evrdefs.h @@ -41,12 +41,12 @@ #define EVRDEFS_H #include <d3d9.h> -#include <Evr9.h> +#include <evr9.h> #include <evr.h> #include <dxva2api.h> #include <mfapi.h> #include <mfidl.h> -#include <Mferror.h> +#include <mferror.h> extern const CLSID clsid_EnhancedVideoRenderer; extern const GUID mr_VIDEO_RENDER_SERVICE; diff --git a/src/plugins/coreaudio/coreaudio.pro b/src/plugins/coreaudio/coreaudio.pro index e01932c6a..50159311a 100644 --- a/src/plugins/coreaudio/coreaudio.pro +++ b/src/plugins/coreaudio/coreaudio.pro @@ -1,10 +1,6 @@ TARGET = qtaudio_coreaudio QT += multimedia-private -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = CoreAudioPlugin - -load(qt_plugin) OTHER_FILES += \ coreaudio.json @@ -37,3 +33,7 @@ ios|tvos { LIBS += \ -framework CoreAudio \ -framework AudioToolbox + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = CoreAudioPlugin +load(qt_plugin) diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index a266e2226..9e1be9606 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -1098,9 +1098,19 @@ void DSCameraSession::disconnectGraph() pPin = NULL; } - m_filterGraph->RemoveFilter(m_nullRendererFilter); - m_filterGraph->RemoveFilter(m_previewFilter); - m_filterGraph->RemoveFilter(m_sourceFilter); + // To avoid increasing the memory usage every time the graph is re-connected it's + // important that all filters are released; also the ones added by the "Intelligent Connect". + IEnumFilters *enumFilters = NULL; + hr = m_filterGraph->EnumFilters(&enumFilters); + if (SUCCEEDED(hr)) { + IBaseFilter *filter = NULL; + while (enumFilters->Next(1, &filter, NULL) == S_OK) { + m_filterGraph->RemoveFilter(filter); + enumFilters->Reset(); + filter->Release(); + } + enumFilters->Release(); + } } static bool qt_frameRateRangeGreaterThan(const QCamera::FrameRateRange &r1, const QCamera::FrameRateRange &r2) diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro index 4d7183923..117b02ade 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -2,9 +2,6 @@ TARGET = dsengine win32:!qtHaveModule(opengl)|contains(QT_CONFIG,dynamicgl) { LIBS_PRIVATE += -lgdi32 -luser32 } -PLUGIN_TYPE=mediaservice -PLUGIN_CLASS_NAME = DSServicePlugin -load(qt_plugin) QT += multimedia-private @@ -16,8 +13,12 @@ SOURCES += dsserviceplugin.cpp mingw: DEFINES += NO_DSHOW_STRSAFE !config_wmf: include(player/player.pri) -include(camera/camera.pri) +!wince: include(camera/camera.pri) OTHER_FILES += \ directshow.json \ directshow_camera.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = DSServicePlugin +load(qt_plugin) diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index 73d9f4eb1..6f31ce7e2 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -37,14 +37,16 @@ ** ****************************************************************************/ +#include <dshow.h> + #include <QtCore/qstring.h> #include <QtCore/qdebug.h> #include <QtCore/QFile> #include "dsserviceplugin.h" -#include "dsvideodevicecontrol.h" #ifdef QMEDIA_DIRECTSHOW_CAMERA +#include "dsvideodevicecontrol.h" #include <dshow.h> #include "dscameraservice.h" #endif diff --git a/src/plugins/directshow/player/directshowglobal.h b/src/plugins/directshow/player/directshowglobal.h index 1f9466269..f7890c52b 100644 --- a/src/plugins/directshow/player/directshowglobal.h +++ b/src/plugins/directshow/player/directshowglobal.h @@ -40,10 +40,10 @@ #ifndef DIRECTSHOWGLOBAL_H #define DIRECTSHOWGLOBAL_H -#include <QtCore/qglobal.h> - #include <dshow.h> +#include <QtCore/qglobal.h> + template <typename T> T *com_cast(IUnknown *unknown, const IID &iid) { T *iface = 0; @@ -118,6 +118,7 @@ DECLARE_INTERFACE_(IFileSourceFilter ,IUnknown) #ifndef __IAMOpenProgress_INTERFACE_DEFINED__ #define __IAMOpenProgress_INTERFACE_DEFINED__ +#undef INTERFACE #define INTERFACE IAMOpenProgress DECLARE_INTERFACE_(IAMOpenProgress ,IUnknown) { diff --git a/src/plugins/directshow/player/directshowioreader.h b/src/plugins/directshow/player/directshowioreader.h index 2e8656059..deb5d5327 100644 --- a/src/plugins/directshow/player/directshowioreader.h +++ b/src/plugins/directshow/player/directshowioreader.h @@ -40,12 +40,12 @@ #ifndef DIRECTSHOWIOREADER_H #define DIRECTSHOWIOREADER_H +#include <dshow.h> + #include <QtCore/qmutex.h> #include <QtCore/qobject.h> #include <QtCore/qwaitcondition.h> -#include <dshow.h> - QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE diff --git a/src/plugins/directshow/player/directshowmediatype.h b/src/plugins/directshow/player/directshowmediatype.h index 136fefaea..cf5ac73aa 100644 --- a/src/plugins/directshow/player/directshowmediatype.h +++ b/src/plugins/directshow/player/directshowmediatype.h @@ -40,9 +40,10 @@ #ifndef DIRECTSHOWMEDIATYPE_H #define DIRECTSHOWMEDIATYPE_H +#include <dshow.h> + #include <qvideosurfaceformat.h> -#include <dshow.h> #include <dvdmedia.h> class DirectShowMediaType : public AM_MEDIA_TYPE diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/plugins/directshow/player/directshowmediatypelist.h index 0579dada7..c6dac0e9b 100644 --- a/src/plugins/directshow/player/directshowmediatypelist.h +++ b/src/plugins/directshow/player/directshowmediatypelist.h @@ -40,10 +40,10 @@ #ifndef DIRECTSHOWMEDIATYPELIST_H #define DIRECTSHOWMEDIATYPELIST_H -#include <QtCore/qvector.h> - #include <dshow.h> +#include <QtCore/qvector.h> + class DirectShowMediaTypeList : public IUnknown { public: diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 8e4f5a766..6a88d76a9 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp @@ -37,13 +37,20 @@ ** ****************************************************************************/ +#include <dshow.h> +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif + #include <QtMultimedia/qmediametadata.h> #include <QtCore/qcoreapplication.h> #include <QSize> #include <qdatetime.h> #include <qimage.h> -#include <dshow.h> #include <initguid.h> #include <qnetwork.h> diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h index e871bdb14..b42b48c67 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.h +++ b/src/plugins/directshow/player/directshowmetadatacontrol.h @@ -40,6 +40,8 @@ #ifndef DIRECTSHOWMETADATACONTROL_H #define DIRECTSHOWMETADATACONTROL_H +#include <dshow.h> + #include <qmetadatareadercontrol.h> #include "directshowglobal.h" diff --git a/src/plugins/directshow/player/directshowpinenum.h b/src/plugins/directshow/player/directshowpinenum.h index c95f23d68..8859f49a5 100644 --- a/src/plugins/directshow/player/directshowpinenum.h +++ b/src/plugins/directshow/player/directshowpinenum.h @@ -40,9 +40,10 @@ #ifndef DIRECTSHOWPINENUM_H #define DIRECTSHOWPINENUM_H +#include <dshow.h> + #include <QtCore/qlist.h> -#include <dshow.h> class DirectShowPinEnum : public IEnumPins { diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp index 490add322..d4fd0c8be 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.cpp +++ b/src/plugins/directshow/player/directshowplayercontrol.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include <dshow.h> + #include "directshowplayercontrol.h" #include "directshowplayerservice.h" diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h index 295f6527b..184951544 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.h +++ b/src/plugins/directshow/player/directshowplayercontrol.h @@ -40,6 +40,8 @@ #ifndef DIRECTSHOWPLAYERCONTROL_H #define DIRECTSHOWPLAYERCONTROL_H +#include <dshow.h> + #include "qmediacontent.h" #include "qmediaplayercontrol.h" diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp index 74b37a2a2..7c2cd8a9a 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -37,14 +37,25 @@ ** ****************************************************************************/ +#include <dshow.h> +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif + #include "directshowplayerservice.h" +#ifndef Q_OS_WINCE #include "directshowaudioendpointcontrol.h" -#include "directshowiosource.h" #include "directshowmetadatacontrol.h" +#include "vmr9videowindowcontrol.h" +#endif +#include "directshowiosource.h" #include "directshowplayercontrol.h" #include "directshowvideorenderercontrol.h" -#include "vmr9videowindowcontrol.h" + #ifdef HAVE_EVR #include "directshowevrvideowindowcontrol.h" @@ -85,10 +96,14 @@ private: DirectShowPlayerService::DirectShowPlayerService(QObject *parent) : QMediaService(parent) , m_playerControl(0) +#ifndef Q_OS_WINCE , m_metaDataControl(0) +#endif , m_videoRendererControl(0) +#ifndef Q_OS_WINCE , m_videoWindowControl(0) , m_audioEndpointControl(0) +#endif , m_taskThread(0) , m_loop(qt_directShowEventLoop()) , m_pendingTasks(0) @@ -112,8 +127,10 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_dontCacheNextSeekResult(false) { m_playerControl = new DirectShowPlayerControl(this); +#ifndef Q_OS_WINCE m_metaDataControl = new DirectShowMetaDataControl(this); m_audioEndpointControl = new DirectShowAudioEndpointControl(this); +#endif m_taskThread = new DirectShowPlayerServiceThread(this); m_taskThread->start(); @@ -144,10 +161,14 @@ DirectShowPlayerService::~DirectShowPlayerService() } delete m_playerControl; +#ifndef Q_OS_WINCE delete m_audioEndpointControl; delete m_metaDataControl; +#endif delete m_videoRendererControl; +#ifndef Q_OS_WINCE delete m_videoWindowControl; +#endif ::CloseHandle(m_taskHandle); } @@ -156,12 +177,18 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name) { if (qstrcmp(name, QMediaPlayerControl_iid) == 0) { return m_playerControl; +#ifndef Q_OS_WINCE } else if (qstrcmp(name, QAudioOutputSelectorControl_iid) == 0) { return m_audioEndpointControl; } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { return m_metaDataControl; +#endif } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { - if (!m_videoRendererControl && !m_videoWindowControl) { + if (!m_videoRendererControl +#ifndef Q_OS_WINCE + && !m_videoWindowControl +#endif + ){ m_videoRendererControl = new DirectShowVideoRendererControl(m_loop); connect(m_videoRendererControl, SIGNAL(filterChanged()), @@ -169,6 +196,7 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name) return m_videoRendererControl; } +#ifndef Q_OS_WINCE } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) { if (!m_videoRendererControl && !m_videoWindowControl) { IBaseFilter *filter; @@ -191,6 +219,7 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name) return m_videoWindowControl; } +#endif } return 0; } @@ -206,12 +235,14 @@ void DirectShowPlayerService::releaseControl(QMediaControl *control) delete m_videoRendererControl; m_videoRendererControl = 0; +#ifndef Q_OS_WINCE } else if (control == m_videoWindowControl) { setVideoOutput(0); delete m_videoWindowControl; m_videoWindowControl = 0; +#endif } } @@ -237,7 +268,9 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_seekable = false; m_atEnd = false; m_dontCacheNextSeekResult = false; +#ifndef Q_OS_WINCE m_metaDataControl->reset(); +#endif if (m_resources.isEmpty() && !stream) { m_pendingTasks = 0; @@ -1141,7 +1174,9 @@ void DirectShowPlayerService::customEvent(QEvent *event) QMutexLocker locker(&m_mutex); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); +#ifndef Q_OS_WINCE m_metaDataControl->updateMetadata(m_graph, m_source, m_url.toString()); +#endif updateStatus(); } else if (event->type() == QEvent::Type(Error)) { diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h index 8eaa2db8d..9419a8a99 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -40,6 +40,8 @@ #ifndef DIRECTSHOWPLAYERSERVICE_H #define DIRECTSHOWPLAYERSERVICE_H +#include <dshow.h> + #include "qmediaplayer.h" #include "qmediaresource.h" #include "qmediaservice.h" @@ -174,10 +176,14 @@ private: }; DirectShowPlayerControl *m_playerControl; +#ifndef Q_OS_WINCE DirectShowMetaDataControl *m_metaDataControl; +#endif DirectShowVideoRendererControl *m_videoRendererControl; +#ifndef Q_OS_WINCE QVideoWindowControl *m_videoWindowControl; DirectShowAudioEndpointControl *m_audioEndpointControl; +#endif QThread *m_taskThread; DirectShowEventLoop *m_loop; diff --git a/src/plugins/directshow/player/directshowsamplescheduler.h b/src/plugins/directshow/player/directshowsamplescheduler.h index cce418ab7..1670d23ed 100644 --- a/src/plugins/directshow/player/directshowsamplescheduler.h +++ b/src/plugins/directshow/player/directshowsamplescheduler.h @@ -40,12 +40,12 @@ #ifndef DIRECTSHOWSAMPLESCHEDULER_H #define DIRECTSHOWSAMPLESCHEDULER_H +#include <dshow.h> + #include <QtCore/qmutex.h> #include <QtCore/qobject.h> #include <QtCore/qsemaphore.h> -#include <dshow.h> - class DirectShowTimedSample; class DirectShowSampleScheduler : public QObject, public IMemInputPin diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.h b/src/plugins/directshow/player/directshowvideorenderercontrol.h index 5082e6bd7..17dd4705b 100644 --- a/src/plugins/directshow/player/directshowvideorenderercontrol.h +++ b/src/plugins/directshow/player/directshowvideorenderercontrol.h @@ -40,10 +40,10 @@ #ifndef DIRECTSHOWVIDEORENDERERCONTROL_H #define DIRECTSHOWVIDEORENDERERCONTROL_H -#include "qvideorenderercontrol.h" - #include <dshow.h> +#include "qvideorenderercontrol.h" + class DirectShowEventLoop; QT_USE_NAMESPACE diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.h b/src/plugins/directshow/player/mediasamplevideobuffer.h index cf4142972..6ec1470c5 100644 --- a/src/plugins/directshow/player/mediasamplevideobuffer.h +++ b/src/plugins/directshow/player/mediasamplevideobuffer.h @@ -40,10 +40,10 @@ #ifndef MEDIASAMPLEVIDEOBUFFER_H #define MEDIASAMPLEVIDEOBUFFER_H -#include <qabstractvideobuffer.h> - #include <dshow.h> +#include <qabstractvideobuffer.h> + class MediaSampleVideoBuffer : public QAbstractVideoBuffer { public: diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri index 5ecb912b2..c5fb8442a 100644 --- a/src/plugins/directshow/player/player.pri +++ b/src/plugins/directshow/player/player.pri @@ -1,45 +1,53 @@ INCLUDEPATH += $$PWD -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32 +LIBS += -lstrmiids -ldmoguids -luuid -lole32 -loleaut32 +!wince: LIBS += -lmsdmo -lgdi32 + qtHaveModule(widgets): QT += widgets DEFINES += QMEDIA_DIRECTSHOW_PLAYER HEADERS += \ - $$PWD/directshowaudioendpointcontrol.h \ $$PWD/directshoweventloop.h \ $$PWD/directshowglobal.h \ $$PWD/directshowioreader.h \ $$PWD/directshowiosource.h \ $$PWD/directshowmediatype.h \ $$PWD/directshowmediatypelist.h \ - $$PWD/directshowmetadatacontrol.h \ $$PWD/directshowpinenum.h \ $$PWD/directshowplayercontrol.h \ $$PWD/directshowplayerservice.h \ $$PWD/directshowsamplescheduler.h \ $$PWD/directshowvideorenderercontrol.h \ $$PWD/mediasamplevideobuffer.h \ - $$PWD/videosurfacefilter.h \ - $$PWD/vmr9videowindowcontrol.h + $$PWD/videosurfacefilter.h SOURCES += \ - $$PWD/directshowaudioendpointcontrol.cpp \ $$PWD/directshoweventloop.cpp \ $$PWD/directshowioreader.cpp \ $$PWD/directshowiosource.cpp \ $$PWD/directshowmediatype.cpp \ $$PWD/directshowmediatypelist.cpp \ - $$PWD/directshowmetadatacontrol.cpp \ $$PWD/directshowpinenum.cpp \ $$PWD/directshowplayercontrol.cpp \ $$PWD/directshowplayerservice.cpp \ $$PWD/directshowsamplescheduler.cpp \ $$PWD/directshowvideorenderercontrol.cpp \ $$PWD/mediasamplevideobuffer.cpp \ - $$PWD/videosurfacefilter.cpp \ + $$PWD/videosurfacefilter.cpp + +!wince { +HEADERS += \ + $$PWD/directshowaudioendpointcontrol.h \ + $$PWD/directshowmetadatacontrol.h \ + $$PWD/vmr9videowindowcontrol.h + +SOURCES += \ + $$PWD/directshowaudioendpointcontrol.cpp \ + $$PWD/directshowmetadatacontrol.cpp \ $$PWD/vmr9videowindowcontrol.cpp +} config_evr { DEFINES += HAVE_EVR diff --git a/src/plugins/gstreamer/audiodecoder/audiodecoder.pro b/src/plugins/gstreamer/audiodecoder/audiodecoder.pro index 8cd1d587e..4e816e920 100644 --- a/src/plugins/gstreamer/audiodecoder/audiodecoder.pro +++ b/src/plugins/gstreamer/audiodecoder/audiodecoder.pro @@ -1,9 +1,5 @@ TARGET = gstaudiodecoder -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = QGstreamerAudioDecoderServicePlugin -load(qt_plugin) - include(../common.pri) INCLUDEPATH += $$PWD @@ -23,3 +19,6 @@ SOURCES += \ OTHER_FILES += \ audiodecoder.json +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = QGstreamerAudioDecoderServicePlugin +load(qt_plugin) diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro index b807071f2..214489f3e 100644 --- a/src/plugins/gstreamer/camerabin/camerabin.pro +++ b/src/plugins/gstreamer/camerabin/camerabin.pro @@ -2,10 +2,6 @@ TARGET = gstcamerabin QT += multimedia-private -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = CameraBinServicePlugin -load(qt_plugin) - include(../common.pri) INCLUDEPATH += $$PWD \ @@ -101,3 +97,7 @@ config_linux_v4l: { OTHER_FILES += \ camerabin.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = CameraBinServicePlugin +load(qt_plugin) diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri index eb6a29987..babdb7cfb 100644 --- a/src/plugins/gstreamer/common.pri +++ b/src/plugins/gstreamer/common.pri @@ -1,6 +1,5 @@ QT += core-private multimedia-private network -CONFIG += no_private_qt_headers_warning qtHaveModule(widgets) { QT += widgets multimediawidgets-private diff --git a/src/plugins/gstreamer/mediacapture/mediacapture.pro b/src/plugins/gstreamer/mediacapture/mediacapture.pro index 5baa0fd8f..db5210d4d 100644 --- a/src/plugins/gstreamer/mediacapture/mediacapture.pro +++ b/src/plugins/gstreamer/mediacapture/mediacapture.pro @@ -1,9 +1,5 @@ TARGET = gstmediacapture -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = QGstreamerCaptureServicePlugin -load(qt_plugin) - include(../common.pri) INCLUDEPATH += $$PWD @@ -50,3 +46,7 @@ use_gstreamer_camera:config_linux_v4l { OTHER_FILES += \ mediacapture.json } + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = QGstreamerCaptureServicePlugin +load(qt_plugin) diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro index b986fc787..5ccf89bfd 100644 --- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro +++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro @@ -1,9 +1,5 @@ TARGET = gstmediaplayer -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = QGstreamerPlayerServicePlugin -load(qt_plugin) - include(../common.pri) INCLUDEPATH += $$PWD @@ -28,3 +24,7 @@ SOURCES += \ OTHER_FILES += \ mediaplayer.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = QGstreamerPlayerServicePlugin +load(qt_plugin) diff --git a/src/plugins/m3u/m3u.pro b/src/plugins/m3u/m3u.pro index 3897e2de8..d46911e0d 100644 --- a/src/plugins/m3u/m3u.pro +++ b/src/plugins/m3u/m3u.pro @@ -1,12 +1,12 @@ TARGET = qtmultimedia_m3u QT += multimedia-private -PLUGIN_TYPE=playlistformats -PLUGIN_CLASS_NAME = QM3uPlaylistPlugin -load(qt_plugin) - HEADERS += qm3uhandler.h SOURCES += qm3uhandler.cpp OTHER_FILES += \ m3u.json + +PLUGIN_TYPE = playlistformats +PLUGIN_CLASS_NAME = QM3uPlaylistPlugin +load(qt_plugin) diff --git a/src/plugins/opensles/opensles.pro b/src/plugins/opensles/opensles.pro index aa8e05444..2bb0f3cf5 100644 --- a/src/plugins/opensles/opensles.pro +++ b/src/plugins/opensles/opensles.pro @@ -1,10 +1,6 @@ TARGET = qtaudio_opensles QT += multimedia-private core-private -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = QOpenSLESPlugin -load(qt_plugin) - LIBS += -lOpenSLES HEADERS += \ @@ -23,3 +19,7 @@ SOURCES += \ OTHER_FILES += \ opensles.json + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = QOpenSLESPlugin +load(qt_plugin) diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 8b3322024..67b06a61b 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -34,7 +34,8 @@ win32:!winrt:!wince { } winrt { - SUBDIRS += winrt + SUBDIRS += wasapi \ + winrt } unix:!mac:!android { diff --git a/src/plugins/pulseaudio/pulseaudio.pro b/src/plugins/pulseaudio/pulseaudio.pro index e8ab9317c..7f4d3de22 100644 --- a/src/plugins/pulseaudio/pulseaudio.pro +++ b/src/plugins/pulseaudio/pulseaudio.pro @@ -1,10 +1,6 @@ TARGET = qtmedia_pulse QT += multimedia-private -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = QPulseAudioPlugin -load(qt_plugin) - CONFIG += link_pkgconfig PKGCONFIG += libpulse @@ -24,3 +20,7 @@ SOURCES += qpulseaudioplugin.cpp \ OTHER_FILES += \ pulseaudio.json + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = QPulseAudioPlugin +load(qt_plugin) diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.cpp b/src/plugins/pulseaudio/qaudioinput_pulse.cpp index ebf6f0a4b..050731071 100644 --- a/src/plugins/pulseaudio/qaudioinput_pulse.cpp +++ b/src/plugins/pulseaudio/qaudioinput_pulse.cpp @@ -40,6 +40,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qmath.h> +#include <private/qaudiohelpers_p.h> #include "qaudioinput_pulse.h" #include "qaudiodeviceinfo_pulse.h" @@ -124,39 +125,12 @@ static void inputStreamSuccessCallback(pa_stream *stream, int success, void *use pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0); } -void QPulseAudioInput::sourceInfoCallback(pa_context *context, const pa_source_info *i, int eol, void *userdata) -{ - Q_UNUSED(context); - Q_UNUSED(eol); - - Q_ASSERT(userdata); - if (i) { - QPulseAudioInput *that = reinterpret_cast<QPulseAudioInput*>(userdata); - that->m_volume = pa_sw_volume_to_linear(pa_cvolume_avg(&i->volume)); - } -} - -void QPulseAudioInput::inputVolumeCallback(pa_context *context, int success, void *userdata) -{ - Q_UNUSED(success); - - if (!success) - qWarning() << "QAudioInput: failed to set input volume"; - - QPulseAudioInput *that = reinterpret_cast<QPulseAudioInput*>(userdata); - - // Regardless of success or failure, we update the volume property - if (that->m_stream) - pa_context_get_source_info_by_index(context, pa_stream_get_device_index(that->m_stream), sourceInfoCallback, userdata); -} - QPulseAudioInput::QPulseAudioInput(const QByteArray &device) : m_totalTimeValue(0) , m_audioSource(0) , m_errorState(QAudio::NoError) , m_deviceState(QAudio::StoppedState) , m_volume(qreal(1.0f)) - , m_customVolumeRequired(false) , m_pullMode(true) , m_opened(false) , m_bytesAvailable(0) @@ -362,9 +336,6 @@ bool QPulseAudioInput::open() if (actualBufferAttr->tlength != (uint32_t)-1) m_bufferSize = actualBufferAttr->tlength; - if (m_customVolumeRequired) - setPulseVolume(); - pulseEngine->unlock(); connect(pulseEngine, &QPulseAudioEngine::contextFailed, this, &QPulseAudioInput::onPulseContextFailed); @@ -413,32 +384,6 @@ void QPulseAudioInput::close() m_opened = false; } -/* Call this with the stream opened and the mainloop locked */ -void QPulseAudioInput::setPulseVolume() -{ - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - Q_ASSERT(pulseEngine->context() != 0); - - pa_cvolume cvolume; - - if (qFuzzyCompare(m_volume, 0.0)) { - pa_cvolume_mute(&cvolume, m_spec.channels); - } else { - pa_cvolume_set(&cvolume, m_spec.channels, pa_sw_volume_from_linear(m_volume)); - } - - pa_operation *op = pa_context_set_source_volume_by_index(pulseEngine->context(), - pa_stream_get_device_index(m_stream), - &cvolume, - inputVolumeCallback, - this); - - if (op == NULL) - qWarning() << "QAudioInput: Failed to set volume"; - else - pa_operation_unref(op); -} - int QPulseAudioInput::checkBytesReady() { if (m_deviceState != QAudio::ActiveState && m_deviceState != QAudio::IdleState) { @@ -500,7 +445,9 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) qint64 actualLength = 0; if (m_pullMode) { - actualLength = m_audioSource->write(static_cast<const char *>(audioBuffer), readLength); + QByteArray adjusted(readLength, Qt::Uninitialized); + applyVolume(audioBuffer, adjusted.data(), readLength); + actualLength = m_audioSource->write(adjusted); if (actualLength < qint64(readLength)) { pulseEngine->unlock(); @@ -512,7 +459,7 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) } } else { actualLength = qMin(static_cast<int>(len - readBytes), static_cast<int>(readLength)); - memcpy(data + readBytes, audioBuffer, actualLength); + applyVolume(audioBuffer, data + readBytes, actualLength); } #ifdef DEBUG_PULSE @@ -523,7 +470,10 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- appending " << readLength - actualLength << " bytes of data to temp buffer"; #endif - m_tempBuffer.append(static_cast<const char *>(audioBuffer) + actualLength, readLength - actualLength); + int diff = readLength - actualLength; + int oldSize = m_tempBuffer.size(); + m_tempBuffer.resize(m_tempBuffer.size() + diff); + applyVolume(static_cast<const char *>(audioBuffer) + actualLength, m_tempBuffer.data() + oldSize, diff); QMetaObject::invokeMethod(this, "userFeed", Qt::QueuedConnection); } @@ -550,6 +500,14 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) return readBytes; } +void QPulseAudioInput::applyVolume(const void *src, void *dest, int len) +{ + if (m_volume < 1.f) + QAudioHelperInternal::qMultiplySamples(m_volume, m_format, src, dest, len); + else + memcpy(dest, src, len); +} + void QPulseAudioInput::resume() { if (m_deviceState == QAudio::SuspendedState || m_deviceState == QAudio::IdleState) { @@ -573,30 +531,17 @@ void QPulseAudioInput::resume() void QPulseAudioInput::setVolume(qreal vol) { - if (vol >= 0.0 && vol <= 1.0) { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - m_customVolumeRequired = true; - if (!qFuzzyCompare(m_volume, vol)) { - m_volume = vol; - if (m_opened) { - setPulseVolume(); - } - } - pulseEngine->unlock(); - } + if (qFuzzyCompare(m_volume, vol)) + return; + + m_volume = qBound(qreal(0), vol, qreal(1)); } qreal QPulseAudioInput::volume() const { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - qreal vol = m_volume; - pulseEngine->unlock(); - return vol; + return m_volume; } - void QPulseAudioInput::setBufferSize(int value) { m_bufferSize = value; diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.h b/src/plugins/pulseaudio/qaudioinput_pulse.h index c04cd1299..32a2c031c 100644 --- a/src/plugins/pulseaudio/qaudioinput_pulse.h +++ b/src/plugins/pulseaudio/qaudioinput_pulse.h @@ -106,8 +106,6 @@ public: QAudio::Error m_errorState; QAudio::State m_deviceState; qreal m_volume; - bool m_customVolumeRequired; - pa_cvolume m_chVolume; private slots: void userFeed(); @@ -118,13 +116,11 @@ private: void setState(QAudio::State state); void setError(QAudio::Error error); + void applyVolume(const void *src, void *dest, int len); + int checkBytesReady(); bool open(); void close(); - void setPulseVolume(); - - static void sourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata); - static void inputVolumeCallback(pa_context *context, int success, void *userdata); bool m_pullMode; bool m_opened; diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.cpp b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp index 6cc9329dd..0c7dc270a 100644 --- a/src/plugins/pulseaudio/qaudiooutput_pulse.cpp +++ b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp @@ -40,6 +40,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qmath.h> +#include <private/qaudiohelpers_p.h> #include "qaudiooutput_pulse.h" #include "qaudiodeviceinfo_pulse.h" @@ -91,7 +92,6 @@ static void outputStreamUnderflowCallback(pa_stream *stream, void *userdata) { Q_UNUSED(stream) ((QPulseAudioOutput*)userdata)->streamUnderflowCallback(); - qWarning() << "Got a buffer underflow!"; } static void outputStreamOverflowCallback(pa_stream *stream, void *userdata) @@ -139,6 +139,18 @@ static void outputStreamDrainComplete(pa_stream *stream, int success, void *user #endif } +static void streamAdjustPrebufferCallback(pa_stream *stream, int success, void *userdata) +{ + Q_UNUSED(stream); + Q_UNUSED(success); + Q_UNUSED(userdata); + +#ifdef DEBUG_PULSE + qDebug() << "Adjust prebuffer completed successfully: " << (bool)success; +#endif +} + + QPulseAudioOutput::QPulseAudioOutput(const QByteArray &device) : m_device(device) , m_errorState(QAudio::NoError) @@ -157,7 +169,6 @@ QPulseAudioOutput::QPulseAudioOutput(const QByteArray &device) , m_audioBuffer(0) , m_resuming(false) , m_volume(1.0) - , m_customVolumeRequired(false) { connect(m_tickTimer, SIGNAL(timeout()), SLOT(userFeed())); } @@ -213,17 +224,19 @@ void QPulseAudioOutput::start(QIODevice *device) // Handle change of mode if (m_audioSource && !m_pullMode) { delete m_audioSource; - m_audioSource = 0; } + m_audioSource = 0; close(); - if (!open()) - return; - m_pullMode = true; m_audioSource = device; + if (!open()) { + m_audioSource = 0; + return; + } + setState(QAudio::ActiveState); } @@ -235,17 +248,18 @@ QIODevice *QPulseAudioOutput::start() // Handle change of mode if (m_audioSource && !m_pullMode) { delete m_audioSource; - m_audioSource = 0; } + m_audioSource = 0; close(); + m_pullMode = false; + if (!open()) return Q_NULLPTR; m_audioSource = new PulseOutputPrivate(this); m_audioSource->open(QIODevice::WriteOnly|QIODevice::Unbuffered); - m_pullMode = false; setState(QAudio::IdleState); @@ -304,27 +318,6 @@ bool QPulseAudioOutput::open() pa_stream_set_overflow_callback(m_stream, outputStreamOverflowCallback, this); pa_stream_set_latency_update_callback(m_stream, outputStreamLatencyCallback, this); - pa_volume_t paVolume; - - /* streams without a custom volume set are expected to already have a - * sensible volume set by Pulse, so we don't set it explicitly. - * - * explicit setting also breaks volume handling on sailfish, where each - * stream's volume is set separately inside pulseaudio, with the - * exception of streams that already have a volume set (i.e. if we set - * it here, we'd ignore system volume). - */ - if (m_customVolumeRequired) { - if (qFuzzyCompare(m_volume, 0.0)) { - paVolume = PA_VOLUME_MUTED; - m_volume = 0.0; - } else { - paVolume = qFloor(m_volume * PA_VOLUME_NORM + 0.5); - } - - pa_cvolume_set(&m_chVolume, m_spec.channels, paVolume); - } - if (m_bufferSize <= 0 && m_category == LOW_LATENCY_CATEGORY_NAME) { m_bufferSize = bytesPerSecond * LowLatencyBufferSizeMs / qint64(1000); } @@ -336,7 +329,7 @@ bool QPulseAudioOutput::open() requestedBuffer.prebuf = (uint32_t)-1; requestedBuffer.tlength = m_bufferSize; - if (pa_stream_connect_playback(m_stream, m_device.data(), (m_bufferSize > 0) ? &requestedBuffer : NULL, (pa_stream_flags_t)0, m_customVolumeRequired ? &m_chVolume : NULL, NULL) < 0) { + if (pa_stream_connect_playback(m_stream, m_device.data(), (m_bufferSize > 0) ? &requestedBuffer : NULL, (pa_stream_flags_t)0, NULL, NULL) < 0) { qWarning() << "pa_stream_connect_playback() failed!"; pa_stream_unref(m_stream); m_stream = 0; @@ -355,6 +348,17 @@ bool QPulseAudioOutput::open() m_bufferSize = buffer->tlength; m_maxBufferSize = buffer->maxlength; m_audioBuffer = new char[m_maxBufferSize]; + + const qint64 streamSize = m_audioSource ? m_audioSource->size() : 0; + if (m_pullMode && streamSize > 0 && static_cast<qint64>(buffer->prebuf) > streamSize) { + pa_buffer_attr newBufferAttr; + newBufferAttr = *buffer; + newBufferAttr.prebuf = streamSize; + pa_operation *o = pa_stream_set_buffer_attr(m_stream, &newBufferAttr, streamAdjustPrebufferCallback, NULL); + if (o) + pa_operation_unref(o); + } + #ifdef DEBUG_PULSE qDebug() << "Buffering info:"; qDebug() << "\tMax length: " << buffer->maxlength; @@ -472,8 +476,33 @@ qint64 QPulseAudioOutput::write(const char *data, qint64 len) QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); pulseEngine->lock(); + len = qMin(len, static_cast<qint64>(pa_stream_writable_size(m_stream))); - pa_stream_write(m_stream, data, len, 0, 0, PA_SEEK_RELATIVE); + + if (m_volume < 1.0f) { + // Don't use PulseAudio volume, as it might affect all other streams of the same category + // or even affect the system volume if flat volumes are enabled + void *dest = NULL; + size_t nbytes = len; + if (pa_stream_begin_write(m_stream, &dest, &nbytes) < 0) { + qWarning("QAudioOutput(pulseaudio): pa_stream_begin_write, error = %s", + pa_strerror(pa_context_errno(pulseEngine->context()))); + setError(QAudio::IOError); + return 0; + } + + len = int(nbytes); + QAudioHelperInternal::qMultiplySamples(m_volume, m_format, data, dest, len); + data = reinterpret_cast<char *>(dest); + } + + if (pa_stream_write(m_stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) { + qWarning("QAudioOutput(pulseaudio): pa_stream_write, error = %s", + pa_strerror(pa_context_errno(pulseEngine->context()))); + setError(QAudio::IOError); + return 0; + } + pulseEngine->unlock(); m_totalTimeValue += len; @@ -645,34 +674,10 @@ qint64 PulseOutputPrivate::writeData(const char *data, qint64 len) void QPulseAudioOutput::setVolume(qreal vol) { - if (vol >= 0.0 && vol <= 1.0) { - if (!qFuzzyCompare(m_volume, vol)) { - m_customVolumeRequired = true; - m_volume = vol; - if (m_opened) { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - pa_volume_t paVolume; - if (qFuzzyCompare(vol, 0.0)) { - pa_cvolume_mute(&m_chVolume, m_spec.channels); - m_volume = 0.0; - } else { - paVolume = qFloor(m_volume * PA_VOLUME_NORM + 0.5); - pa_cvolume_set(&m_chVolume, m_spec.channels, paVolume); - } - pa_operation *op = pa_context_set_sink_input_volume(pulseEngine->context(), - pa_stream_get_index(m_stream), - &m_chVolume, - NULL, - NULL); - if (op == NULL) - qWarning()<<"QAudioOutput: Failed to set volume"; - else - pa_operation_unref(op); - pulseEngine->unlock(); - } - } - } + if (qFuzzyCompare(m_volume, vol)) + return; + + m_volume = qBound(qreal(0), vol, qreal(1)); } qreal QPulseAudioOutput::volume() const diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.h b/src/plugins/pulseaudio/qaudiooutput_pulse.h index a628c6bae..58f175e18 100644 --- a/src/plugins/pulseaudio/qaudiooutput_pulse.h +++ b/src/plugins/pulseaudio/qaudiooutput_pulse.h @@ -141,8 +141,6 @@ private: QString m_category; qreal m_volume; - bool m_customVolumeRequired; - pa_cvolume m_chVolume; pa_sample_spec m_spec; }; diff --git a/src/plugins/qnx-audio/audio/audio.pro b/src/plugins/qnx-audio/audio/audio.pro index 35ddf73de..bd69dfe1e 100644 --- a/src/plugins/qnx-audio/audio/audio.pro +++ b/src/plugins/qnx-audio/audio/audio.pro @@ -1,9 +1,6 @@ TARGET = qtmedia_qnx_audio -QT += multimedia-private -CONFIG += no_private_qt_headers_warning -PLUGIN_TYPE = audio -load(qt_plugin) +QT += multimedia-private LIBS += -lasound @@ -20,3 +17,6 @@ SOURCES += qnxaudioplugin.cpp \ qnxaudioutils.cpp OTHER_FILES += qnx_audio.json + +PLUGIN_TYPE = audio +load(qt_plugin) diff --git a/src/plugins/qnx/common/windowgrabber.cpp b/src/plugins/qnx/common/windowgrabber.cpp index 19cd73f03..ce5b45298 100644 --- a/src/plugins/qnx/common/windowgrabber.cpp +++ b/src/plugins/qnx/common/windowgrabber.cpp @@ -46,6 +46,7 @@ #include <qpa/qplatformnativeinterface.h> #include <QOpenGLContext> +#include <QOpenGLFunctions> #ifdef Q_OS_BLACKBERRY #include <bps/event.h> @@ -282,7 +283,8 @@ bool WindowGrabber::handleScreenEvent(screen_event_t screen_event) return false; } - if (m_windowId == idString) { + // Grab windows that have a non-empty ID string and a matching window id to grab + if (idString[0] != '\0' && m_windowId == idString) { m_window = window; start(); } @@ -348,6 +350,9 @@ void WindowGrabber::checkForEglImageExtension() m_eglImageSupported = m_context->hasExtension(QByteArrayLiteral("GL_OES_EGL_image")) && eglExtensions.contains(QByteArrayLiteral("EGL_KHR_image")); + if (strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)), "VMware")) + m_eglImageSupported = false; + m_eglImageCheck = true; } diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index f01562116..4d76fa5f7 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -1,10 +1,6 @@ TARGET = qtmedia_qnx QT += multimedia-private gui-private -PLUGIN_TYPE=mediaservice -PLUGIN_CLASS_NAME = BbServicePlugin -load(qt_plugin) - LIBS += -lscreen include(common/common.pri) @@ -20,3 +16,7 @@ blackberry { SOURCES += neutrinoserviceplugin.cpp OTHER_FILES += neutrino_mediaservice.json } + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = BbServicePlugin +load(qt_plugin) diff --git a/src/plugins/resourcepolicy/resourcepolicy.pro b/src/plugins/resourcepolicy/resourcepolicy.pro index 4805c5250..91a946665 100644 --- a/src/plugins/resourcepolicy/resourcepolicy.pro +++ b/src/plugins/resourcepolicy/resourcepolicy.pro @@ -1,13 +1,9 @@ TARGET = resourceqt QT += multimedia-private -CONFIG += no_private_qt_headers_warning link_pkgconfig +CONFIG += link_pkgconfig PKGCONFIG += libresourceqt5 -PLUGIN_TYPE = resourcepolicy -PLUGIN_CLASS_NAME = ResourceQtPolicyPlugin -load(qt_plugin) - INCLUDEPATH += $$PWD \ $${SOURCE_DIR}/src/multimedia @@ -21,3 +17,6 @@ SOURCES += \ $$PWD/resourcepolicyimpl.cpp \ $$PWD/resourcepolicyint.cpp +PLUGIN_TYPE = resourcepolicy +PLUGIN_CLASS_NAME = ResourceQtPolicyPlugin +load(qt_plugin) diff --git a/src/plugins/v4l/v4l.pro b/src/plugins/v4l/v4l.pro index c5e953538..28d89e3e9 100644 --- a/src/plugins/v4l/v4l.pro +++ b/src/plugins/v4l/v4l.pro @@ -1,11 +1,11 @@ TARGET = qtmedia_v4lengine QT += multimedia-private -PLUGIN_TYPE = mediaservice -PLUGIN_CLASS_NAME = V4LServicePlugin -load(qt_plugin) - HEADERS += v4lserviceplugin.h SOURCES += v4lserviceplugin.cpp include(radio/radio.pri) + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = V4LServicePlugin +load(qt_plugin) diff --git a/src/plugins/videonode/egl/egl.pro b/src/plugins/videonode/egl/egl.pro index a6256cea1..7151123ea 100644 --- a/src/plugins/videonode/egl/egl.pro +++ b/src/plugins/videonode/egl/egl.pro @@ -1,12 +1,8 @@ TARGET = eglvideonode + QT += multimedia-private qtmultimediaquicktools-private CONFIG += egl -PLUGIN_TYPE=video/videonode -PLUGIN_EXTENDS = quick -PLUGIN_CLASS_NAME = QSGVideoNodeFactory_EGL -load(qt_plugin) - HEADERS += \ qsgvideonode_egl.h @@ -15,3 +11,8 @@ SOURCES += \ OTHER_FILES += \ egl.json + +PLUGIN_TYPE = video/videonode +PLUGIN_EXTENDS = quick +PLUGIN_CLASS_NAME = QSGVideoNodeFactory_EGL +load(qt_plugin) diff --git a/src/plugins/videonode/imx6/imx6.pro b/src/plugins/videonode/imx6/imx6.pro index 36e25e86b..c8085a31e 100644 --- a/src/plugins/videonode/imx6/imx6.pro +++ b/src/plugins/videonode/imx6/imx6.pro @@ -1,10 +1,6 @@ TARGET = imx6vivantevideonode -QT += multimedia-private qtmultimediaquicktools-private -PLUGIN_TYPE=video/videonode -PLUGIN_EXTENDS = quick -PLUGIN_CLASS_NAME = QSGVivanteVideoNodeFactory -load(qt_plugin) +QT += multimedia-private qtmultimediaquicktools-private HEADERS += \ qsgvivantevideonode.h \ @@ -20,3 +16,8 @@ SOURCES += \ OTHER_FILES += \ imx6.json + +PLUGIN_TYPE = video/videonode +PLUGIN_EXTENDS = quick +PLUGIN_CLASS_NAME = QSGVivanteVideoNodeFactory +load(qt_plugin) diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp new file mode 100644 index 000000000..283e8b740 --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasapiaudiodeviceinfo.h" +#include "qwasapiutils.h" + +#include <Audioclient.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMmDeviceInfo, "qt.multimedia.deviceinfo") + +QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode) + : m_deviceName(dev) +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__ << dev << mode; + m_interface = QWasapiUtils::createOrGetInterface(dev, mode); + + QAudioFormat referenceFormat = m_interface->m_mixFormat; + + const int rates[] = {8000, 11025, 160000, 22050, 32000, 44100, 48000, 88200, 96000, 192000}; + for (int rate : rates) { + QAudioFormat f = referenceFormat; + f.setSampleRate(rate); + if (isFormatSupported(f)) + m_sampleRates.append(rate); + } + + for (int i = 1; i <= 18; ++i) { + QAudioFormat f = referenceFormat; + f.setChannelCount(i); + if (isFormatSupported(f)) + m_channelCounts.append(i); + } + + const int sizes[] = {8, 12, 16, 20, 24, 32, 64}; + for (int s : sizes) { + QAudioFormat f = referenceFormat; + f.setSampleSize(s); + if (isFormatSupported(f)) + m_sampleSizes.append(s); + } + + referenceFormat.setSampleType(QAudioFormat::SignedInt); + if (isFormatSupported(referenceFormat)) + m_sampleTypes.append(QAudioFormat::SignedInt); + + referenceFormat.setSampleType(QAudioFormat::Float); + if (isFormatSupported(referenceFormat)) + m_sampleTypes.append(QAudioFormat::Float); +} + +QWasapiAudioDeviceInfo::~QWasapiAudioDeviceInfo() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; +} + +bool QWasapiAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__ << format; + + WAVEFORMATEX nfmt; + if (!QWasapiUtils::convertToNativeFormat(format, &nfmt)) + return false; + + WAVEFORMATEX closest; + WAVEFORMATEX *pClosest = &closest; + HRESULT hr; + hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nfmt, &pClosest); + + if (hr == S_OK) // S_FALSE is inside SUCCEEDED() + return true; + + if (lcMmDeviceInfo().isDebugEnabled()) { + QAudioFormat f; + QWasapiUtils::convertFromNativeFormat(pClosest, &f); + qCDebug(lcMmDeviceInfo) << __FUNCTION__ << hr << "Closest match is:" << f; + } + + return false; +} + +QAudioFormat QWasapiAudioDeviceInfo::preferredFormat() const +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_interface->m_mixFormat; +} + +QString QWasapiAudioDeviceInfo::deviceName() const +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_deviceName; +} + +QStringList QWasapiAudioDeviceInfo::supportedCodecs() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return QStringList() << QStringLiteral("audio/pcm"); +} + +QList<int> QWasapiAudioDeviceInfo::supportedSampleRates() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_sampleRates; +} + +QList<int> QWasapiAudioDeviceInfo::supportedChannelCounts() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_channelCounts; +} + +QList<int> QWasapiAudioDeviceInfo::supportedSampleSizes() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_sampleSizes; +} + +QList<QAudioFormat::Endian> QWasapiAudioDeviceInfo::supportedByteOrders() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return QList<QAudioFormat::Endian>() << m_interface->m_mixFormat.byteOrder(); +} + +QList<QAudioFormat::SampleType> QWasapiAudioDeviceInfo::supportedSampleTypes() +{ + qCDebug(lcMmDeviceInfo) << __FUNCTION__; + return m_sampleTypes; +} + +QT_END_NAMESPACE diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.h b/src/plugins/wasapi/qwasapiaudiodeviceinfo.h new file mode 100644 index 000000000..1bf4d846d --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudiodeviceinfo.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASAPIAUDIODEVICEINFO_H +#define QWASAPIAUDIODEVICEINFO_H + +#include <QtCore/QList> +#include <QtCore/QLoggingCategory> +#include <QtCore/QStringList> +#include <QtMultimedia/QAbstractAudioDeviceInfo> +#include <QtMultimedia/QAudio> +#include <QtMultimedia/QAudioFormat> + +#include <wrl.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcMmDeviceInfo) + +class AudioInterface; +class QWasapiAudioDeviceInfo : public QAbstractAudioDeviceInfo +{ + Q_OBJECT +public: + explicit QWasapiAudioDeviceInfo(QByteArray dev,QAudio::Mode mode); + ~QWasapiAudioDeviceInfo(); + + QAudioFormat preferredFormat() const Q_DECL_OVERRIDE; + bool isFormatSupported(const QAudioFormat& format) const Q_DECL_OVERRIDE; + QString deviceName() const Q_DECL_OVERRIDE; + QStringList supportedCodecs() Q_DECL_OVERRIDE; + QList<int> supportedSampleRates() Q_DECL_OVERRIDE; + QList<int> supportedChannelCounts() Q_DECL_OVERRIDE; + QList<int> supportedSampleSizes() Q_DECL_OVERRIDE; + QList<QAudioFormat::Endian> supportedByteOrders() Q_DECL_OVERRIDE; + QList<QAudioFormat::SampleType> supportedSampleTypes() Q_DECL_OVERRIDE; + +private: + Microsoft::WRL::ComPtr<AudioInterface> m_interface; + QString m_deviceName; + QList<int> m_sampleRates; + QList<int> m_channelCounts; + QList<int> m_sampleSizes; + QList<QAudioFormat::SampleType> m_sampleTypes; +}; + +QT_END_NAMESPACE + +#endif // QWASAPIAUDIODEVICEINFO_H diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp new file mode 100644 index 000000000..1cc1c38f7 --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudioinput.cpp @@ -0,0 +1,560 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasapiaudioinput.h" +#include "qwasapiutils.h" + +#include <QtCore/QMutexLocker> +#include <QtCore/QThread> +#include <QtCore/qfunctions_winrt.h> + +#include <Audioclient.h> + +using namespace Microsoft::WRL; + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMmAudioInput, "qt.multimedia.audioinput") + +class WasapiInputDevicePrivate : public QIODevice +{ + Q_OBJECT +public: + WasapiInputDevicePrivate(QWasapiAudioInput* input); + ~WasapiInputDevicePrivate(); + + qint64 readData(char* data, qint64 len); + qint64 writeData(const char* data, qint64 len); + +private: + QWasapiAudioInput *m_input; +}; + +WasapiInputDevicePrivate::WasapiInputDevicePrivate(QWasapiAudioInput* input) + : m_input(input) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; +} + +WasapiInputDevicePrivate::~WasapiInputDevicePrivate() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; +} + +qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + + const quint32 channelCount = m_input->m_currentFormat.channelCount(); + const quint32 sampleBytes = m_input->m_currentFormat.sampleSize() / 8; + + const quint32 requestedFrames = len / channelCount / sampleBytes; + quint32 availableFrames = 0; + HRESULT hr = m_input->m_capture->GetNextPacketSize(&availableFrames); + + quint32 readFrames = qMin(requestedFrames, availableFrames); + const qint64 readBytes = readFrames * channelCount * sampleBytes; + + BYTE* buffer; + DWORD flags; + + QMutexLocker locker(&m_input->m_mutex); + + quint64 devicePosition; + hr = m_input->m_capture->GetBuffer(&buffer, &readFrames, &flags, &devicePosition, NULL); + if (hr != S_OK) { + m_input->m_currentError = QAudio::FatalError; + emit m_input->errorChanged(m_input->m_currentError); + hr = m_input->m_capture->ReleaseBuffer(readFrames); + qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer."; + return 0; + } + if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) { + // In case this flag is set, user is supposed to ignore the content + // of the buffer and manually write silence + qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: " + << "Ignoring buffer and writing silence."; + memset(data, 0, readBytes); + } else { + memcpy(data, buffer, readBytes); + } + + hr = m_input->m_capture->ReleaseBuffer(readFrames); + if (hr != S_OK) + qFatal("Could not release buffer"); + + if (m_input->m_interval && m_input->m_openTime.elapsed() - m_input->m_openTimeOffset > m_input->m_interval) { + QMetaObject::invokeMethod(m_input, "notify", Qt::QueuedConnection); + m_input->m_openTimeOffset = m_input->m_openTime.elapsed(); + } + + m_input->m_bytesProcessed += readBytes; + + if (m_input->m_currentState != QAudio::ActiveState) { + m_input->m_currentState = QAudio::ActiveState; + QMetaObject::invokeMethod(m_input, "stateChanged", Qt::QueuedConnection, + Q_ARG(QAudio::State, QAudio::ActiveState)); + } + return readBytes; +} + +qint64 WasapiInputDevicePrivate::writeData(const char* data, qint64 len) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + Q_UNUSED(data) + Q_UNUSED(len) + return 0; +} + +QWasapiAudioInput::QWasapiAudioInput(const QByteArray &device) + : m_deviceName(device) +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + , m_volumeCache(qreal(1.)) +#endif + , m_currentState(QAudio::StoppedState) + , m_currentError(QAudio::NoError) + , m_bufferFrames(0) + , m_bufferBytes(4096) + , m_eventThread(0) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << device; + Q_UNUSED(device) +} + +QWasapiAudioInput::~QWasapiAudioInput() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + stop(); +} + +void QWasapiAudioInput::setVolume(qreal vol) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << vol; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond + m_volumeCache = vol; + if (m_volumeControl) { + quint32 channelCount; + HRESULT hr = m_volumeControl->GetChannelCount(&channelCount); + for (quint32 i = 0; i < channelCount; ++i) { + // ### TODO: Use QAudioHelperInternal::qScaleVolumeFromLinear when integrated + hr = m_volumeControl->SetChannelVolume(i, vol); + RETURN_VOID_IF_FAILED("Could not set audio volume."); + } + } +#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 +} + +qreal QWasapiAudioInput::volume() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond + return m_volumeCache; +#else + return qreal(1.0); +#endif +} + +void QWasapiAudioInput::process() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + const quint32 channelCount = m_currentFormat.channelCount(); + const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; + BYTE* buffer; + HRESULT hr; + DWORD waitRet; + + bool processing = true; + do { + waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE); + if (waitRet != WAIT_OBJECT_0) { + qFatal("Returned while waiting for event."); + return; + } + + QMutexLocker locker(&m_mutex); + + if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) + break; + + if (!m_pullMode) { + QMetaObject::invokeMethod(m_eventDevice, "readyRead", Qt::QueuedConnection); + ResetEvent(m_event); + continue; + } + + quint32 packetFrames; + hr = m_capture->GetNextPacketSize(&packetFrames); + + while (packetFrames != 0 && m_currentState == QAudio::ActiveState) { + DWORD flags; + quint64 devicePosition; + hr = m_capture->GetBuffer(&buffer, &packetFrames, &flags, &devicePosition, NULL); + if (hr != S_OK) { + m_currentError = QAudio::FatalError; + QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, + Q_ARG(QAudio::Error, QAudio::UnderrunError)); + // Also Error Buffers need to be released + hr = m_capture->ReleaseBuffer(packetFrames); + qCDebug(lcMmAudioInput) << __FUNCTION__ << "Could not acquire input buffer."; + return; + } + const quint32 writeBytes = packetFrames * channelCount * sampleBytes; + if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) { + // In case this flag is set, user is supposed to ignore the content + // of the buffer and manually write silence + qCDebug(lcMmAudioInput) << __FUNCTION__ << "AUDCLNT_BUFFERFLAGS_SILENT: " + << "Ignoring buffer and writing silence."; + buffer = new BYTE[writeBytes]; + memset(buffer, 0, writeBytes); + } + + qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes); + + if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT)) + delete [] buffer; + + if (written < static_cast<qint64>(writeBytes)) { + if (m_currentError != QAudio::UnderrunError) { + m_currentError = QAudio::UnderrunError; + QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, + Q_ARG(QAudio::Error, QAudio::UnderrunError)); + } + } + hr = m_capture->ReleaseBuffer(packetFrames); + if (hr != S_OK) + qFatal("Could not release buffer"); + + m_bytesProcessed += writeBytes; + + hr = m_capture->GetNextPacketSize(&packetFrames); + } + ResetEvent(m_event); + + if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { + QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection); + m_openTimeOffset = m_openTime.elapsed(); + } + processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; + } while (processing); +} + +bool QWasapiAudioInput::initStart(bool pull) +{ + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + stop(); + + QMutexLocker locker(&m_mutex); + + m_interface = QWasapiUtils::createOrGetInterface(m_deviceName, QAudio::AudioInput); + Q_ASSERT(m_interface); + + m_pullMode = pull; + WAVEFORMATEX nFmt; + WAVEFORMATEX closest; + WAVEFORMATEX *pClose = &closest; + + if (!m_currentFormat.isValid() || !QWasapiUtils::convertToNativeFormat(m_currentFormat, &nFmt)) { + m_currentError = QAudio::OpenError; + emit errorChanged(m_currentError); + return false; + } + + HRESULT hr; + + hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nFmt, &pClose); + if (hr != S_OK) { + m_currentError = QAudio::OpenError; + emit errorChanged(m_currentError); + return false; + } + + REFERENCE_TIME t = ((10000.0 * 10000 / nFmt.nSamplesPerSec * 1024) + 0.5); + if (m_bufferBytes) + t = m_currentFormat.durationForBytes(m_bufferBytes) * 10; + + const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK; + hr = m_interface->m_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, t, 0, &nFmt, NULL); + EMIT_RETURN_FALSE_IF_FAILED("Could not initialize audio client.", QAudio::OpenError) + + hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_capture)); + EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError) + +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT + hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl)); + if (FAILED(hr)) + qCDebug(lcMmAudioInput) << "Could not acquire volume control."; +#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + + hr = m_interface->m_client->GetBufferSize(&m_bufferFrames); + EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError) + + m_event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); + m_eventThread = new QWasapiProcessThread(this, false); + m_eventThread->m_event = m_event; + hr = m_interface->m_client->SetEventHandle(m_event); + EMIT_RETURN_FALSE_IF_FAILED("Could not set event handle.", QAudio::OpenError) + + if (!m_pullMode) { + m_eventDevice = new WasapiInputDevicePrivate(this); + m_eventDevice->open(QIODevice::ReadOnly|QIODevice::Unbuffered); + } + + hr = m_interface->m_client->Start(); + EMIT_RETURN_FALSE_IF_FAILED("Could not start audio render client.", QAudio::OpenError) + + m_openTime.restart(); + m_openTimeOffset = 0; + m_bytesProcessed = 0; + + return true; +} + +QAudio::Error QWasapiAudioInput::error() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << m_currentError; + return m_currentError; +} + +QAudio::State QWasapiAudioInput::state() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + return m_currentState; +} + +void QWasapiAudioInput::start(QIODevice* device) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << device; + if (!initStart(true)) { + qCDebug(lcMmAudioInput) << __FUNCTION__ << "failed"; + return; + } + m_eventDevice = device; + + m_mutex.lock(); + m_currentState = QAudio::ActiveState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + m_eventThread->start(); +} + +QIODevice *QWasapiAudioInput::start() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (!initStart(false)) { + qCDebug(lcMmAudioInput) << __FUNCTION__ << "failed"; + return nullptr; + } + + m_mutex.lock(); + m_currentState = QAudio::IdleState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + m_eventThread->start(); + return m_eventDevice; +} + +void QWasapiAudioInput::stop() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return; + + m_mutex.lock(); + m_currentState = QAudio::StoppedState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + + if (m_currentError != QAudio::NoError) { + m_mutex.lock(); + m_currentError = QAudio::NoError; + m_mutex.unlock(); + emit errorChanged(m_currentError); + } + + HRESULT hr = m_interface->m_client->Stop(); + hr = m_interface->m_client->Reset(); + + if (m_eventThread) { + SetEvent(m_eventThread->m_event); + while (m_eventThread->isRunning()) + QThread::yieldCurrentThread(); + m_eventThread->deleteLater(); + m_eventThread = 0; + } +} + +void QWasapiAudioInput::setFormat(const QAudioFormat& fmt) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << fmt; + if (m_currentState != QAudio::StoppedState) + return; + m_currentFormat = fmt; +} + +QAudioFormat QWasapiAudioInput::format() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + return m_currentFormat; +} + +int QWasapiAudioInput::bytesReady() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState != QAudio::IdleState && m_currentState != QAudio::ActiveState) + return 0; + + const quint32 channelCount = m_currentFormat.channelCount(); + const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; + + quint32 packetFrames; + HRESULT hr = m_capture->GetNextPacketSize(&packetFrames); + + if (FAILED(hr)) + return 0; + const quint32 writeBytes = packetFrames * channelCount * sampleBytes; + + return writeBytes; +} + +void QWasapiAudioInput::resume() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState != QAudio::SuspendedState) + return; + + HRESULT hr = m_interface->m_client->Start(); + EMIT_RETURN_VOID_IF_FAILED("Could not start audio render client.", QAudio::FatalError) + + m_mutex.lock(); + m_currentError = QAudio::NoError; + m_currentState = QAudio::ActiveState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + m_eventThread->start(); +} + +void QWasapiAudioInput::setBufferSize(int value) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << value; + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + return; + m_bufferBytes = value; +} + +int QWasapiAudioInput::bufferSize() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + return m_bufferFrames * m_currentFormat.channelCount()* m_currentFormat.sampleSize() / 8; + + return m_bufferBytes; +} + +int QWasapiAudioInput::periodSize() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + REFERENCE_TIME defaultDevicePeriod; + REFERENCE_TIME minimumPeriod; + HRESULT hr = m_interface->m_client->GetDevicePeriod(&defaultDevicePeriod, &minimumPeriod); + if (FAILED(hr)) + return 0; + const int res = m_currentFormat.bytesForDuration(minimumPeriod / 10); + return res; +} + +void QWasapiAudioInput::setNotifyInterval(int ms) +{ + qCDebug(lcMmAudioInput) << __FUNCTION__ << ms; + m_interval = qMax(0, ms); +} + +int QWasapiAudioInput::notifyInterval() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + return m_interval; +} + +qint64 QWasapiAudioInput::processedUSecs() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return 0; + qint64 res = qint64(1000000) * m_bytesProcessed / + (m_currentFormat.channelCount() * (m_currentFormat.sampleSize() / 8)) / + m_currentFormat.sampleRate(); + + return res; +} + +void QWasapiAudioInput::suspend() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState != QAudio::ActiveState) + return; + + m_mutex.lock(); + m_currentState = QAudio::SuspendedState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + + HRESULT hr = m_interface->m_client->Stop(); + EMIT_RETURN_VOID_IF_FAILED("Could not suspend audio render client.", QAudio::FatalError); + + if (m_eventThread) { + SetEvent(m_eventThread->m_event); + while (m_eventThread->isRunning()) + QThread::yieldCurrentThread(); + } + qCDebug(lcMmAudioInput) << __FUNCTION__ << "Thread has stopped"; +} + +qint64 QWasapiAudioInput::elapsedUSecs() const +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return 0; + return m_openTime.elapsed() * qint64(1000); +} + +void QWasapiAudioInput::reset() +{ + qCDebug(lcMmAudioInput) << __FUNCTION__; + stop(); +} + +QT_END_NAMESPACE + +#include "qwasapiaudioinput.moc" diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h new file mode 100644 index 000000000..829cad153 --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudioinput.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QAUDIOINPUTWASAPI_H +#define QAUDIOINPUTWASAPI_H + +#include <QtCore/QLoggingCategory> +#include <QtCore/QMutex> +#include <QtCore/QTime> +#include <QtMultimedia/QAbstractAudioInput> +#include <QtMultimedia/QAudio> + +#include <wrl.h> + +struct IAudioCaptureClient; +struct IAudioStreamVolume; + +QT_BEGIN_NAMESPACE + +class AudioInterface; +class WasapiInputDevicePrivate; +class QWasapiProcessThread; + +Q_DECLARE_LOGGING_CATEGORY(lcMmAudioInput) + +class QWasapiAudioInput : public QAbstractAudioInput +{ + Q_OBJECT +public: + explicit QWasapiAudioInput(const QByteArray &device); + ~QWasapiAudioInput(); + + void start(QIODevice* device) Q_DECL_OVERRIDE; + QIODevice* start() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void reset() Q_DECL_OVERRIDE; + void suspend() Q_DECL_OVERRIDE; + void resume() Q_DECL_OVERRIDE; + int bytesReady() const Q_DECL_OVERRIDE; + int periodSize() const Q_DECL_OVERRIDE; + void setBufferSize(int value) Q_DECL_OVERRIDE; + int bufferSize() const Q_DECL_OVERRIDE; + void setNotifyInterval(int milliSeconds) Q_DECL_OVERRIDE; + int notifyInterval() const Q_DECL_OVERRIDE; + qint64 processedUSecs() const Q_DECL_OVERRIDE; + qint64 elapsedUSecs() const Q_DECL_OVERRIDE; + QAudio::Error error() const Q_DECL_OVERRIDE; + QAudio::State state() const Q_DECL_OVERRIDE; + void setFormat(const QAudioFormat& fmt) Q_DECL_OVERRIDE; + QAudioFormat format() const Q_DECL_OVERRIDE; + void setVolume(qreal) Q_DECL_OVERRIDE; + qreal volume() const Q_DECL_OVERRIDE; + + void process(); +private: + bool initStart(bool pull); + friend class WasapiInputDevicePrivate; + friend class WasapiInputPrivate; + QByteArray m_deviceName; + Microsoft::WRL::ComPtr<AudioInterface> m_interface; + Microsoft::WRL::ComPtr<IAudioCaptureClient> m_capture; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl; + qreal m_volumeCache; +#endif + QMutex m_mutex; + QAudio::State m_currentState; + QAudio::Error m_currentError; + QAudioFormat m_currentFormat; + qint64 m_bytesProcessed; + QTime m_openTime; + int m_openTimeOffset; + int m_interval; + bool m_pullMode; + quint32 m_bufferFrames; + quint32 m_bufferBytes; + HANDLE m_event; + QWasapiProcessThread *m_eventThread; + QIODevice *m_eventDevice; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp new file mode 100644 index 000000000..a45bc1f07 --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudiooutput.cpp @@ -0,0 +1,572 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasapiaudiooutput.h" +#include "qwasapiutils.h" +#include <QtCore/qfunctions_winrt.h> +#include <QtCore/QMutexLocker> +#include <QtCore/QThread> +#include <QtCore/QTimer> + +#include <Audioclient.h> +#include <functional> + +using namespace Microsoft::WRL; + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMmAudioOutput, "qt.multimedia.audiooutput") + +class WasapiOutputDevicePrivate : public QIODevice +{ + Q_OBJECT +public: + WasapiOutputDevicePrivate(QWasapiAudioOutput* output); + ~WasapiOutputDevicePrivate(); + + qint64 readData(char* data, qint64 len); + qint64 writeData(const char* data, qint64 len); + +private: + QWasapiAudioOutput *m_output; + QTimer m_timer; +}; + +WasapiOutputDevicePrivate::WasapiOutputDevicePrivate(QWasapiAudioOutput* output) + : m_output(output) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + + m_timer.setSingleShot(true); + connect(&m_timer, &QTimer::timeout, [=](){ + if (m_output->m_currentState == QAudio::ActiveState) { + m_output->m_currentState = QAudio::IdleState; + emit m_output->stateChanged(m_output->m_currentState); + m_output->m_currentError = QAudio::UnderrunError; + emit m_output->errorChanged(m_output->m_currentError); + } + }); +} + +WasapiOutputDevicePrivate::~WasapiOutputDevicePrivate() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; +} + +qint64 WasapiOutputDevicePrivate::readData(char* data, qint64 len) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + Q_UNUSED(data) + Q_UNUSED(len) + + return 0; +} + +qint64 WasapiOutputDevicePrivate::writeData(const char* data, qint64 len) +{ + if (m_output->state() != QAudio::ActiveState && m_output->state() != QAudio::IdleState) + return 0; + + QMutexLocker locker(&m_output->m_mutex); + m_timer.stop(); + + const quint32 channelCount = m_output->m_currentFormat.channelCount(); + const quint32 sampleBytes = m_output->m_currentFormat.sampleSize() / 8; + const quint32 freeBytes = static_cast<quint32>(m_output->bytesFree()); + const quint32 bytesToWrite = qMin(freeBytes, static_cast<quint32>(len)); + const quint32 framesToWrite = bytesToWrite / (channelCount * sampleBytes); + + BYTE *buffer; + HRESULT hr; + hr = m_output->m_renderer->GetBuffer(framesToWrite, &buffer); + if (hr != S_OK) { + m_output->m_currentError = QAudio::UnderrunError; + QMetaObject::invokeMethod(m_output, "errorChanged", Qt::QueuedConnection, + Q_ARG(QAudio::Error, QAudio::UnderrunError)); + // Also Error Buffers need to be released + hr = m_output->m_renderer->ReleaseBuffer(framesToWrite, 0); + return 0; + } + + memcpy_s(buffer, bytesToWrite, data, bytesToWrite); + + hr = m_output->m_renderer->ReleaseBuffer(framesToWrite, 0); + if (hr != S_OK) + qFatal("Could not release buffer"); + + if (m_output->m_interval && m_output->m_openTime.elapsed() - m_output->m_openTimeOffset > m_output->m_interval) { + QMetaObject::invokeMethod(m_output, "notify", Qt::QueuedConnection); + m_output->m_openTimeOffset = m_output->m_openTime.elapsed(); + } + + m_output->m_bytesProcessed += bytesToWrite; + + if (m_output->m_currentState != QAudio::ActiveState) { + m_output->m_currentState = QAudio::ActiveState; + emit m_output->stateChanged(m_output->m_currentState); + } + if (m_output->m_currentError != QAudio::NoError) { + m_output->m_currentError = QAudio::NoError; + emit m_output->errorChanged(m_output->m_currentError); + } + + quint32 paddingFrames; + hr = m_output->m_interface->m_client->GetCurrentPadding(&paddingFrames); + const quint32 paddingBytes = paddingFrames * m_output->m_currentFormat.channelCount() * m_output->m_currentFormat.sampleSize() / 8; + + m_timer.setInterval(m_output->m_currentFormat.durationForBytes(paddingBytes) / 1000); + m_timer.start(); + return bytesToWrite; +} + +QWasapiAudioOutput::QWasapiAudioOutput(const QByteArray &device) + : m_deviceName(device) +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + , m_volumeCache(qreal(1.)) +#endif + , m_currentState(QAudio::StoppedState) + , m_currentError(QAudio::NoError) + , m_interval(1000) + , m_pullMode(true) + , m_bufferFrames(0) + , m_bufferBytes(4096) + , m_eventThread(0) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << device; +} + +QWasapiAudioOutput::~QWasapiAudioOutput() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + stop(); +} + +void QWasapiAudioOutput::setVolume(qreal vol) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << vol; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT + m_volumeCache = vol; + if (m_volumeControl) { + quint32 channelCount; + HRESULT hr = m_volumeControl->GetChannelCount(&channelCount); + for (quint32 i = 0; i < channelCount; ++i) { + // ### TODO: Use QAudioHelperInternal::qScaleVolumeFromLinear when integrated + hr = m_volumeControl->SetChannelVolume(i, vol); + RETURN_VOID_IF_FAILED("Could not set audio volume."); + } + } +#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 +} + +qreal QWasapiAudioOutput::volume() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT + return m_volumeCache; +#else + return qreal(1.0); +#endif +} + +void QWasapiAudioOutput::process() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + const quint32 channelCount = m_currentFormat.channelCount(); + const quint32 sampleBytes = m_currentFormat.sampleSize() / 8; + BYTE* buffer; + HRESULT hr; + DWORD waitRet; + + bool processing = true; + do { + waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE); + if (waitRet != WAIT_OBJECT_0) { + qFatal("Returned while waiting for event."); + return; + } + + QMutexLocker locker(&m_mutex); + + if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) + break; + + quint32 paddingFrames; + hr = m_interface->m_client->GetCurrentPadding(&paddingFrames); + + quint32 availableFrames = m_bufferFrames - paddingFrames; + hr = m_renderer->GetBuffer(availableFrames, &buffer); + if (hr != S_OK) { + m_currentError = QAudio::UnderrunError; + QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, + Q_ARG(QAudio::Error, QAudio::UnderrunError)); + // Also Error Buffers need to be released + hr = m_renderer->ReleaseBuffer(availableFrames, 0); + ResetEvent(m_event); + continue; // We will continue trying + } + + const quint32 readBytes = availableFrames * channelCount * sampleBytes; + qint64 read = m_eventDevice->read((char*)buffer, readBytes); + if (read < static_cast<qint64>(readBytes)) { + // Fill the rest of the buffer with zero to avoid audio glitches + if (m_currentError != QAudio::UnderrunError) { + m_currentError = QAudio::UnderrunError; + QMetaObject::invokeMethod(this, "errorChanged", Qt::QueuedConnection, + Q_ARG(QAudio::Error, QAudio::UnderrunError)); + } + if (m_currentState != QAudio::IdleState) { + m_currentState = QAudio::IdleState; + QMetaObject::invokeMethod(this, "stateChanged", Qt::QueuedConnection, + Q_ARG(QAudio::State, QAudio::IdleState)); + } + } + + hr = m_renderer->ReleaseBuffer(availableFrames, 0); + if (hr != S_OK) + qFatal("Could not release buffer"); + ResetEvent(m_event); + + if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) { + QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection); + m_openTimeOffset = m_openTime.elapsed(); + } + + m_bytesProcessed += read; + processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState; + } while (processing); +} + +bool QWasapiAudioOutput::initStart(bool pull) +{ + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + stop(); + + QMutexLocker locker(&m_mutex); + + m_interface = QWasapiUtils::createOrGetInterface(m_deviceName, QAudio::AudioOutput); + Q_ASSERT(m_interface); + + m_pullMode = pull; + WAVEFORMATEX nFmt; + WAVEFORMATEX closest; + WAVEFORMATEX *pClose = &closest; + + if (!m_currentFormat.isValid() || !QWasapiUtils::convertToNativeFormat(m_currentFormat, &nFmt)) { + m_currentError = QAudio::OpenError; + emit errorChanged(m_currentError); + return false; + } + + HRESULT hr; + + hr = m_interface->m_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &nFmt, &pClose); + if (hr != S_OK) { + m_currentError = QAudio::OpenError; + emit errorChanged(m_currentError); + return false; + } + + REFERENCE_TIME t = ((10000.0 * 10000 / nFmt.nSamplesPerSec * 1024) + 0.5); + if (m_bufferBytes) + t = m_currentFormat.durationForBytes(m_bufferBytes) * 100; + + DWORD flags = pull ? AUDCLNT_STREAMFLAGS_EVENTCALLBACK : 0; + hr = m_interface->m_client->Initialize(AUDCLNT_SHAREMODE_SHARED, flags, t, 0, &nFmt, NULL); + EMIT_RETURN_FALSE_IF_FAILED("Could not initialize audio client.", QAudio::OpenError) + + hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_renderer)); + EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError) + +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond + hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl)); + if (FAILED(hr)) + qCDebug(lcMmAudioOutput) << "Could not acquire volume control."; +#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + + hr = m_interface->m_client->GetBufferSize(&m_bufferFrames); + EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError) + + if (m_pullMode) { + m_eventThread = new QWasapiProcessThread(this); + m_event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); + m_eventThread->m_event = m_event; + + hr = m_interface->m_client->SetEventHandle(m_event); + EMIT_RETURN_FALSE_IF_FAILED("Could not set event handle.", QAudio::OpenError) + } else { + m_eventDevice = new WasapiOutputDevicePrivate(this); + m_eventDevice->open(QIODevice::WriteOnly|QIODevice::Unbuffered); + } + // Send some initial data, do not exit on failure, latest in process + // those an error will be caught + BYTE *pdata = nullptr; + hr = m_renderer->GetBuffer(m_bufferFrames, &pdata); + hr = m_renderer->ReleaseBuffer(m_bufferFrames, AUDCLNT_BUFFERFLAGS_SILENT); + + hr = m_interface->m_client->Start(); + EMIT_RETURN_FALSE_IF_FAILED("Could not start audio render client.", QAudio::OpenError) + + m_openTime.restart(); + m_openTimeOffset = 0; + m_bytesProcessed = 0; + return true; +} + +QAudio::Error QWasapiAudioOutput::error() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << m_currentError; + return m_currentError; +} + +QAudio::State QWasapiAudioOutput::state() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + return m_currentState; +} + +void QWasapiAudioOutput::start(QIODevice *device) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << device; + if (!initStart(true)) { + qCDebug(lcMmAudioOutput) << __FUNCTION__ << "failed"; + return; + } + m_eventDevice = device; + + m_mutex.lock(); + m_currentState = QAudio::ActiveState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + m_eventThread->start(); +} + +QIODevice *QWasapiAudioOutput::start() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + + if (!initStart(false)) { + qCDebug(lcMmAudioOutput) << __FUNCTION__ << "failed"; + return nullptr; + } + + m_mutex.lock(); + m_currentState = QAudio::IdleState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + + return m_eventDevice; +} + +void QWasapiAudioOutput::stop() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return; + + if (!m_pullMode) { + HRESULT hr; + hr = m_interface->m_client->Stop(); + hr = m_interface->m_client->Reset(); + } + + m_mutex.lock(); + m_currentState = QAudio::StoppedState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + if (m_currentError != QAudio::NoError) { + m_mutex.lock(); + m_currentError = QAudio::NoError; + m_mutex.unlock(); + emit errorChanged(m_currentError); + } + + HRESULT hr = m_interface->m_client->Stop(); + if (m_currentState == QAudio::StoppedState) { + hr = m_interface->m_client->Reset(); + } + + if (m_eventThread) { + SetEvent(m_eventThread->m_event); + while (m_eventThread->isRunning()) + QThread::yieldCurrentThread(); + m_eventThread->deleteLater(); + m_eventThread = 0; + } +} + +int QWasapiAudioOutput::bytesFree() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) + return 0; + + quint32 paddingFrames; + HRESULT hr = m_interface->m_client->GetCurrentPadding(&paddingFrames); + if (FAILED(hr)) { + qCDebug(lcMmAudioOutput) << __FUNCTION__ << "Could not query padding frames."; + return bufferSize(); + } + + const quint32 availableFrames = m_bufferFrames - paddingFrames; + const quint32 res = availableFrames * m_currentFormat.channelCount() * m_currentFormat.sampleSize() / 8; + return res; +} + +int QWasapiAudioOutput::periodSize() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + REFERENCE_TIME defaultDevicePeriod; + HRESULT hr = m_interface->m_client->GetDevicePeriod(&defaultDevicePeriod, NULL); + if (FAILED(hr)) + return 0; + const QAudioFormat f = m_currentFormat.isValid() ? m_currentFormat : m_interface->m_mixFormat; + const int res = m_currentFormat.bytesForDuration(defaultDevicePeriod / 10); + return res; +} + +void QWasapiAudioOutput::setBufferSize(int value) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << value; + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + return; + m_bufferBytes = value; +} + +int QWasapiAudioOutput::bufferSize() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + if (m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState) + return m_bufferFrames * m_currentFormat.channelCount()* m_currentFormat.sampleSize() / 8; + + return m_bufferBytes; +} + +void QWasapiAudioOutput::setNotifyInterval(int ms) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << ms; + m_interval = qMax(0, ms); +} + +int QWasapiAudioOutput::notifyInterval() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + return m_interval; +} + +qint64 QWasapiAudioOutput::processedUSecs() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return 0; + qint64 res = qint64(1000000) * m_bytesProcessed / + (m_currentFormat.channelCount() * (m_currentFormat.sampleSize() / 8)) / + m_currentFormat.sampleRate(); + + return res; +} + +void QWasapiAudioOutput::resume() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + + if (m_currentState != QAudio::SuspendedState) + return; + + HRESULT hr = m_interface->m_client->Start(); + EMIT_RETURN_VOID_IF_FAILED("Could not start audio render client.", QAudio::FatalError) + + m_mutex.lock(); + m_currentError = QAudio::NoError; + m_currentState = m_pullMode ? QAudio::ActiveState : QAudio::IdleState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + if (m_eventThread) + m_eventThread->start(); +} + +void QWasapiAudioOutput::setFormat(const QAudioFormat& fmt) +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__ << fmt; + if (m_currentState != QAudio::StoppedState) + return; + m_currentFormat = fmt; +} + +QAudioFormat QWasapiAudioOutput::format() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + return m_currentFormat; +} + +void QWasapiAudioOutput::suspend() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + + if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState) + return; + + m_mutex.lock(); + m_currentState = QAudio::SuspendedState; + m_mutex.unlock(); + emit stateChanged(m_currentState); + + HRESULT hr = m_interface->m_client->Stop(); + EMIT_RETURN_VOID_IF_FAILED("Could not suspend audio render client.", QAudio::FatalError); + if (m_eventThread) { + SetEvent(m_eventThread->m_event); + while (m_eventThread->isRunning()) + QThread::yieldCurrentThread(); + qCDebug(lcMmAudioOutput) << __FUNCTION__ << "Thread has stopped"; + } +} + +qint64 QWasapiAudioOutput::elapsedUSecs() const +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + if (m_currentState == QAudio::StoppedState) + return 0; + return m_openTime.elapsed() * qint64(1000); +} + +void QWasapiAudioOutput::reset() +{ + qCDebug(lcMmAudioOutput) << __FUNCTION__; + stop(); +} + +QT_END_NAMESPACE + +#include "qwasapiaudiooutput.moc" diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h new file mode 100644 index 000000000..4575c8672 --- /dev/null +++ b/src/plugins/wasapi/qwasapiaudiooutput.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QAUDIOOUTPUTWASAPI_H +#define QAUDIOOUTPUTWASAPI_H + +#include <QtCore/QLoggingCategory> +#include <QtCore/QMutex> +#include <QtCore/QTime> +#include <QtMultimedia/QAbstractAudioOutput> +#include <QtMultimedia/QAudio> + +#include <QReadWriteLock> +#include <wrl.h> + +struct IAudioRenderClient; +struct IAudioStreamVolume; + +QT_BEGIN_NAMESPACE + +class AudioInterface; +class WasapiOutputDevicePrivate; +class QWasapiProcessThread; + +Q_DECLARE_LOGGING_CATEGORY(lcMmAudioOutput) + +class QWasapiAudioOutput : public QAbstractAudioOutput +{ + Q_OBJECT +public: + explicit QWasapiAudioOutput(const QByteArray &device); + ~QWasapiAudioOutput(); + + void start(QIODevice* device) Q_DECL_OVERRIDE; + QIODevice* start() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void reset() Q_DECL_OVERRIDE; + void suspend() Q_DECL_OVERRIDE; + void resume() Q_DECL_OVERRIDE; + int bytesFree() const Q_DECL_OVERRIDE; + int periodSize() const Q_DECL_OVERRIDE; + void setBufferSize(int value) Q_DECL_OVERRIDE; + int bufferSize() const Q_DECL_OVERRIDE; + void setNotifyInterval(int milliSeconds) Q_DECL_OVERRIDE; + int notifyInterval() const Q_DECL_OVERRIDE; + qint64 processedUSecs() const Q_DECL_OVERRIDE; + qint64 elapsedUSecs() const Q_DECL_OVERRIDE; + QAudio::Error error() const Q_DECL_OVERRIDE; + QAudio::State state() const Q_DECL_OVERRIDE; + void setFormat(const QAudioFormat& fmt) Q_DECL_OVERRIDE; + QAudioFormat format() const Q_DECL_OVERRIDE; + void setVolume(qreal) Q_DECL_OVERRIDE; + qreal volume() const Q_DECL_OVERRIDE; + + void process(); +private: + bool initStart(bool pull); + friend class WasapiOutputDevicePrivate; + friend class WasapiOutputPrivate; + QByteArray m_deviceName; + Microsoft::WRL::ComPtr<AudioInterface> m_interface; + Microsoft::WRL::ComPtr<IAudioRenderClient> m_renderer; +#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 + Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl; + qreal m_volumeCache; +#endif + QMutex m_mutex; + QAudio::State m_currentState; + QAudio::Error m_currentError; + QAudioFormat m_currentFormat; + qint64 m_bytesProcessed; + QTime m_openTime; + int m_openTimeOffset; + int m_interval; + bool m_pullMode; + quint32 m_bufferFrames; + quint32 m_bufferBytes; + HANDLE m_event; + QWasapiProcessThread *m_eventThread; + QIODevice *m_eventDevice; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/wasapi/qwasapiplugin.cpp b/src/plugins/wasapi/qwasapiplugin.cpp new file mode 100644 index 000000000..7b64a101d --- /dev/null +++ b/src/plugins/wasapi/qwasapiplugin.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasapiplugin.h" +#include "qwasapiaudiodeviceinfo.h" +#include "qwasapiaudioinput.h" +#include "qwasapiaudiooutput.h" +#include "qwasapiutils.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMmPlugin, "qt.multimedia.plugin") + +QWasapiPlugin::QWasapiPlugin(QObject *parent) + : QAudioSystemPlugin(parent) +{ + qCDebug(lcMmPlugin) << __FUNCTION__; +} + +QList<QByteArray> QWasapiPlugin::availableDevices(QAudio::Mode mode) const +{ + qCDebug(lcMmPlugin) << __FUNCTION__ << mode; + return QWasapiUtils::availableDevices(mode); +} + +QAbstractAudioInput *QWasapiPlugin::createInput(const QByteArray &device) +{ + qCDebug(lcMmPlugin) << __FUNCTION__ << device; + return new QWasapiAudioInput(device); +} + +QAbstractAudioOutput *QWasapiPlugin::createOutput(const QByteArray &device) +{ + qCDebug(lcMmPlugin) << __FUNCTION__ << device; + return new QWasapiAudioOutput(device); +} + +QAbstractAudioDeviceInfo *QWasapiPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode) +{ + qCDebug(lcMmPlugin) << __FUNCTION__ << device << mode; + return new QWasapiAudioDeviceInfo(device, mode); +} + +QT_END_NAMESPACE diff --git a/src/plugins/wasapi/qwasapiplugin.h b/src/plugins/wasapi/qwasapiplugin.h new file mode 100644 index 000000000..18c2e9575 --- /dev/null +++ b/src/plugins/wasapi/qwasapiplugin.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASAPIPLUGIN_H +#define QWASAPIPLUGIN_H + +#include <QtCore/QLoggingCategory> +#include <QtCore/QList> +#include <QtMultimedia/QAudioSystemPlugin> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcMmPlugin) + +class QWasapiPlugin : public QAudioSystemPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "wasapi.json") + +public: + explicit QWasapiPlugin(QObject *parent = 0); + ~QWasapiPlugin() {} + + QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE; + QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE; + QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE; + QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode) Q_DECL_OVERRIDE; + +private: + QList<QByteArray> m_deviceNames; + QList<QByteArray> m_deviceIds; +}; + +QT_END_NAMESPACE + +#endif // QWASAPIPLUGIN_H diff --git a/src/plugins/wasapi/qwasapiutils.cpp b/src/plugins/wasapi/qwasapiutils.cpp new file mode 100644 index 000000000..87daa4e45 --- /dev/null +++ b/src/plugins/wasapi/qwasapiutils.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasapiutils.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/private/qeventdispatcher_winrt_p.h> + +// For Desktop Win32 support +#ifdef CLASSIC_APP_BUILD +#define Q_OS_WINRT +#endif +#include <QtCore/qfunctions_winrt.h> + +#include <QtMultimedia/QAudioDeviceInfo> +#include <Audioclient.h> +#include <windows.devices.enumeration.h> +#include <windows.foundation.collections.h> +#include <windows.media.devices.h> + +#include <functional> + +using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Media::Devices; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +#define RETURN_EMPTY_LIST_IF_FAILED(msg) RETURN_IF_FAILED(msg, return QList<QByteArray>()) + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMmAudioInterface, "qt.multimedia.audiointerface") +Q_LOGGING_CATEGORY(lcMmUtils, "qt.multimedia.utils") + +#ifdef CLASSIC_APP_BUILD +// Opening bracket has to be in the same line as MSVC2013 and 2015 complain on +// different lines otherwise +#pragma warning (suppress: 4273) +HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT()> &delegate, bool waitForRun) { + Q_UNUSED(waitForRun) + return delegate(); +} +#endif + +namespace QWasapiUtils { +struct DeviceMapping { + QList<QByteArray> outputDeviceNames; + QList<QString> outputDeviceIds; + QList<QByteArray> inputDeviceNames; + QList<QString> inputDeviceIds; +}; +Q_GLOBAL_STATIC(DeviceMapping, gMapping) +} + +AudioInterface::AudioInterface() +{ + qCDebug(lcMmAudioInterface) << __FUNCTION__; + m_currentState = Initialized; +} + +AudioInterface::~AudioInterface() +{ + qCDebug(lcMmAudioInterface) << __FUNCTION__; +} + +HRESULT AudioInterface::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *op) +{ + qCDebug(lcMmAudioInterface) << __FUNCTION__; + + IUnknown *aInterface; + HRESULT hr; + HRESULT hrActivate; + hr = op->GetActivateResult(&hrActivate, &aInterface); + if (FAILED(hr) || FAILED(hrActivate)) { + qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not query activate results."; + m_currentState = Error; + return hr; + } + + hr = aInterface->QueryInterface(IID_PPV_ARGS(&m_client)); + if (FAILED(hr)) { + qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not access AudioClient interface."; + m_currentState = Error; + return hr; + } + + WAVEFORMATEX *format; + hr = m_client->GetMixFormat(&format); + if (FAILED(hr)) { + qCDebug(lcMmAudioInterface) << __FUNCTION__ << "Could not get mix format."; + m_currentState = Error; + return hr; + } + + QWasapiUtils::convertFromNativeFormat(format, &m_mixFormat); + + m_currentState = Activated; + return S_OK; +} + +bool QWasapiUtils::convertToNativeFormat(const QAudioFormat &qt, WAVEFORMATEX *native) +{ + if (!native + || !qt.isValid() + || qt.codec() != QStringLiteral("audio/pcm") + || qt.sampleRate() <= 0 + || qt.channelCount() <= 0 + || qt.sampleSize() <= 0 + || qt.byteOrder() != QAudioFormat::LittleEndian) { + return false; + } + + native->nSamplesPerSec = qt.sampleRate(); + native->wBitsPerSample = qt.sampleSize(); + native->nChannels = qt.channelCount(); + native->nBlockAlign = (native->wBitsPerSample * native->nChannels) / 8; + native->nAvgBytesPerSec = native->nBlockAlign * native->nSamplesPerSec; + native->cbSize = 0; + + if (qt.sampleType() == QAudioFormat::Float) + native->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + else + native->wFormatTag = WAVE_FORMAT_PCM; + + return true; +} + +bool QWasapiUtils::convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFormat *qt) +{ + if (!native || !qt) + return false; + + qt->setByteOrder(QAudioFormat::LittleEndian); + qt->setChannelCount(native->nChannels); + qt->setCodec(QStringLiteral("audio/pcm")); + qt->setSampleRate(native->nSamplesPerSec); + qt->setSampleSize(native->wBitsPerSample); + qt->setSampleType(native->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ? QAudioFormat::Float : QAudioFormat::SignedInt); + + return true; +} + +QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode) +{ + qCDebug(lcMmUtils) << __FUNCTION__ << mode; + + ComPtr<IDeviceInformationStatics> statics; + HRESULT hr; + + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), + &statics); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr<IMediaDeviceStatics> mediaDeviceStatics; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mediaDeviceStatics); + Q_ASSERT_SUCCEEDED(hr); + + HString defaultAudioRender; + quint32 dARSize = 0; + hr = mediaDeviceStatics->GetDefaultAudioRenderId(AudioDeviceRole_Default, defaultAudioRender.GetAddressOf()); + const wchar_t *darWStr = defaultAudioRender.GetRawBuffer(&dARSize); + const QString defaultAudioDeviceId = QString::fromWCharArray(darWStr, dARSize); + + DeviceClass dc = mode == QAudio::AudioInput ? DeviceClass_AudioCapture : DeviceClass_AudioRender; + + QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames; + QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds; + + // We need to refresh due to plugable devices (ie USB) + deviceNames.clear(); + deviceIds.clear(); + + ComPtr<IAsyncOperation<ABI::Windows::Devices::Enumeration::DeviceInformationCollection *>> op; + hr = statics->FindAllAsyncDeviceClass(dc, &op ); + RETURN_EMPTY_LIST_IF_FAILED("Could not query audio devices."); + + ComPtr<IVectorView<DeviceInformation *>> resultVector; + hr = QWinRTFunctions::await(op, resultVector.GetAddressOf()); + RETURN_EMPTY_LIST_IF_FAILED("Could not receive audio device list."); + + quint32 deviceCount; + hr = resultVector->get_Size(&deviceCount); + RETURN_EMPTY_LIST_IF_FAILED("Could not access audio device count."); + qCDebug(lcMmUtils) << "Found " << deviceCount << " audio devices for" << mode; + + for (quint32 i = 0; i < deviceCount; ++i) { + ComPtr<IDeviceInformation> item; + hr = resultVector->GetAt(i, &item); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not access audio device item."); + continue; + } + + HString hString; + quint32 size; + + hr = item->get_Name(hString.GetAddressOf()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not access audio device name."); + continue; + } + const wchar_t *nameWStr = hString.GetRawBuffer(&size); + const QString deviceName = QString::fromWCharArray(nameWStr, size); + + hr = item->get_Id(hString.GetAddressOf()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not access audio device id."); + continue; + } + const wchar_t *idWStr = hString.GetRawBuffer(&size); + const QString deviceId = QString::fromWCharArray(idWStr, size); + + boolean def; + hr = item->get_IsDefault(&def); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not access audio device default."); + continue; + } + + // At least on desktop no device is marked as default + // Hence use the default audio device string from above + if (!def && !defaultAudioDeviceId.isEmpty()) + def = defaultAudioDeviceId == deviceId; + + boolean enabled; + hr = item->get_IsEnabled(&enabled); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not access audio device enabled."); + continue; + } + + qCDebug(lcMmUtils) << "Audio Device:" << deviceName << " ID:" << deviceId + << " Enabled:" << enabled << " Default:" << def; + if (def) { + deviceNames.prepend(deviceName.toLocal8Bit()); + deviceIds.prepend(deviceId); + } else { + deviceNames.append(deviceName.toLocal8Bit()); + deviceIds.append(deviceId); + } + } + return deviceNames; +} + +Microsoft::WRL::ComPtr<AudioInterface> QWasapiUtils::createOrGetInterface(const QByteArray &dev, QAudio::Mode mode) +{ + qCDebug(lcMmUtils) << __FUNCTION__ << dev << mode; + Q_ASSERT((mode == QAudio::AudioInput ? gMapping->inputDeviceNames.indexOf(dev) : gMapping->outputDeviceNames.indexOf(dev)) != -1); + + Microsoft::WRL::ComPtr<AudioInterface> result; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([dev, mode, &result]() { + HRESULT hr; + QString id = mode == QAudio::AudioInput ? gMapping->inputDeviceIds.at(gMapping->inputDeviceNames.indexOf(dev)) : + gMapping->outputDeviceIds.at(gMapping->outputDeviceNames.indexOf(dev)); + + result = Make<AudioInterface>(); + + ComPtr<IActivateAudioInterfaceAsyncOperation> op; + + // We cannot use QWinRTFunctions::await here as that will return + // E_NO_INTERFACE. Instead we leave the lambda and wait for the + // status to get out of Activating + result->setState(AudioInterface::Activating); + hr = ActivateAudioInterfaceAsync(reinterpret_cast<LPCWSTR>(id.utf16()), __uuidof(IAudioClient), NULL, result.Get(), op.GetAddressOf()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not invoke audio interface activation."); + result->setState(AudioInterface::Error); + } + return hr; + }); + qCDebug(lcMmUtils) << "Activation stated:" << hr; + while (result->state() == AudioInterface::Activating) { + QThread::yieldCurrentThread(); + } + qCDebug(lcMmUtils) << "Activation done:" << hr; + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/wasapi/qwasapiutils.h b/src/plugins/wasapi/qwasapiutils.h new file mode 100644 index 000000000..21eff3583 --- /dev/null +++ b/src/plugins/wasapi/qwasapiutils.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASAPIUTILS_H +#define QWASAPIUTILS_H +#include "qwasapiaudiodeviceinfo.h" +#include "qwasapiaudioinput.h" +#include "qwasapiaudiooutput.h" +#include <QtCore/QLoggingCategory> +#include <QtCore/QThread> +#include <QtMultimedia/QAudio> +#include <QtMultimedia/QAudioFormat> + +#include <wrl.h> +#include <Audioclient.h> +#include <mmdeviceapi.h> + +struct IAudioClient; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcMmAudioInterface) +Q_DECLARE_LOGGING_CATEGORY(lcMmUtils) + +#define EMIT_RETURN_FALSE_IF_FAILED(msg, err) \ + if (FAILED(hr)) { \ + m_currentError = err; \ + emit errorChanged(m_currentError); \ + } \ + RETURN_FALSE_IF_FAILED(msg) + +#define EMIT_RETURN_VOID_IF_FAILED(msg, err) \ + if (FAILED(hr)) { \ + m_currentError = err; \ + emit errorChanged(m_currentError); \ + } \ + RETURN_VOID_IF_FAILED(msg) + +class AudioInterface : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags + <Microsoft::WRL::Delegate>, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler> +{ +public: + enum State { + Initialized = 0, + Activating, + Activated, + Error + } ; + + explicit AudioInterface(); + + ~AudioInterface(); + + virtual HRESULT STDMETHODCALLTYPE ActivateCompleted(IActivateAudioInterfaceAsyncOperation *op); + + inline State state() const { return m_currentState; } + void setState(State s) { m_currentState = s; } + + Microsoft::WRL::ComPtr<IAudioClient> m_client; + QWasapiAudioDeviceInfo *m_parent; + State m_currentState; + QAudioFormat m_mixFormat; +}; + +class QWasapiProcessThread : public QThread +{ +public: + explicit QWasapiProcessThread(QObject *item, bool output = true) : QThread(), + m_endpoint(item), + m_output(output) + { + qCDebug(lcMmUtils) << __FUNCTION__ << item; + } + + ~QWasapiProcessThread() + { + qCDebug(lcMmUtils) << __FUNCTION__; + CloseHandle(m_event); + } + + void run() + { + qCDebug(lcMmUtils) << __FUNCTION__ << m_endpoint; + if (m_output) { + QWasapiAudioOutput *output = static_cast<QWasapiAudioOutput *>(m_endpoint); + output->process(); + } else { + QWasapiAudioInput *input = static_cast<QWasapiAudioInput *>(m_endpoint); + input->process(); + } + } + + HANDLE m_event; +private: + QObject *m_endpoint; + bool m_output; +}; + +namespace QWasapiUtils +{ + bool convertToNativeFormat(const QAudioFormat &qt, WAVEFORMATEX *native); + bool convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFormat *qt); + + QList<QByteArray> availableDevices(QAudio::Mode mode); + Microsoft::WRL::ComPtr<AudioInterface> createOrGetInterface(const QByteArray &dev, QAudio::Mode mode); +} + +QT_END_NAMESPACE + +#endif // QWASAPIUTILS_H diff --git a/src/plugins/wasapi/wasapi.json b/src/plugins/wasapi/wasapi.json new file mode 100644 index 000000000..8d6876490 --- /dev/null +++ b/src/plugins/wasapi/wasapi.json @@ -0,0 +1,3 @@ +{ + "Keys": ["wasapi"] +} diff --git a/src/plugins/wasapi/wasapi.pro b/src/plugins/wasapi/wasapi.pro new file mode 100644 index 000000000..11dfd8abe --- /dev/null +++ b/src/plugins/wasapi/wasapi.pro @@ -0,0 +1,30 @@ +TARGET = qtaudio_wasapi +QT += core-private multimedia-private + +HEADERS += \ + qwasapiplugin.h \ + qwasapiaudiodeviceinfo.h \ + qwasapiaudioinput.h \ + qwasapiaudiooutput.h \ + qwasapiutils.h + +SOURCES += \ + qwasapiplugin.cpp \ + qwasapiaudiodeviceinfo.cpp \ + qwasapiaudioinput.cpp \ + qwasapiaudiooutput.cpp \ + qwasapiutils.cpp + +OTHER_FILES += \ + wasapi.json + +LIBS += Mmdevapi.lib + +win32-* { + DEFINES += CLASSIC_APP_BUILD + LIBS += runtimeobject.lib +} + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = QWasapiPlugin +load(qt_plugin) diff --git a/src/plugins/windowsaudio/windowsaudio.pro b/src/plugins/windowsaudio/windowsaudio.pro index 7e8e4320b..ce64847dc 100644 --- a/src/plugins/windowsaudio/windowsaudio.pro +++ b/src/plugins/windowsaudio/windowsaudio.pro @@ -1,10 +1,6 @@ TARGET = qtaudio_windows QT += multimedia-private -PLUGIN_TYPE = audio -PLUGIN_CLASS_NAME = QWindowsAudioPlugin -load(qt_plugin) - LIBS += -lstrmiids -lole32 -loleaut32 !wince*:LIBS += -lwinmm @@ -24,3 +20,7 @@ SOURCES += \ OTHER_FILES += \ windowsaudio.json + +PLUGIN_TYPE = audio +PLUGIN_CLASS_NAME = QWindowsAudioPlugin +load(qt_plugin) diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro index 2f87ea8ff..87e44cce2 100644 --- a/src/plugins/winrt/winrt.pro +++ b/src/plugins/winrt/winrt.pro @@ -1,10 +1,6 @@ TARGET = winrtengine QT += multimedia-private -PLUGIN_TYPE=mediaservice -PLUGIN_CLASS_NAME = WinRTServicePlugin -load(qt_plugin) - LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11 -lruntimeobject HEADERS += \ @@ -43,3 +39,7 @@ SOURCES += \ OTHER_FILES += \ winrt.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = WinRTServicePlugin +load(qt_plugin) diff --git a/src/plugins/wmf/player/mfaudioendpointcontrol.cpp b/src/plugins/wmf/player/mfaudioendpointcontrol.cpp index 054f5c12b..3b86c52b7 100644 --- a/src/plugins/wmf/player/mfaudioendpointcontrol.cpp +++ b/src/plugins/wmf/player/mfaudioendpointcontrol.cpp @@ -40,6 +40,8 @@ #include "QtCore/qdebug.h" #include "mfaudioendpointcontrol.h" +#include <mmdeviceapi.h> + MFAudioEndpointControl::MFAudioEndpointControl(QObject *parent) : QAudioOutputSelectorControl(parent) , m_currentActivate(0) diff --git a/src/plugins/wmf/player/mfaudioendpointcontrol.h b/src/plugins/wmf/player/mfaudioendpointcontrol.h index 770ed1386..a439c31a5 100644 --- a/src/plugins/wmf/player/mfaudioendpointcontrol.h +++ b/src/plugins/wmf/player/mfaudioendpointcontrol.h @@ -42,7 +42,6 @@ #include <mfapi.h> #include <mfidl.h> -#include <mmdeviceapi.h> #include "qaudiooutputselectorcontrol.h" diff --git a/src/plugins/wmf/wmf.pro b/src/plugins/wmf/wmf.pro index 1f43bb128..e83c51595 100644 --- a/src/plugins/wmf/wmf.pro +++ b/src/plugins/wmf/wmf.pro @@ -5,10 +5,6 @@ win32:!qtHaveModule(opengl) { LIBS_PRIVATE += -lgdi32 -luser32 } -PLUGIN_TYPE=mediaservice -PLUGIN_CLASS_NAME = WMFServicePlugin -load(qt_plugin) - INCLUDEPATH += . HEADERS += \ @@ -32,3 +28,7 @@ include (decoder/decoder.pri) OTHER_FILES += \ wmf.json + +PLUGIN_TYPE = mediaservice +PLUGIN_CLASS_NAME = WMFServicePlugin +load(qt_plugin) diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro index b38f209e3..e1425c3ec 100644 --- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro +++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro @@ -1,11 +1,8 @@ TARGET = QtMultimediaQuick_p + QT = core quick multimedia-private CONFIG += internal_module -load(qt_module) - -DEFINES += QT_BUILD_QTMM_QUICK_LIB - # Header files must go inside source directory of a module # to be installed by syncqt. INCLUDEPATH += ../multimedia/qtmultimediaquicktools_headers/ @@ -47,3 +44,5 @@ OTHER_FILES += \ shaders/biplanaryuvvideo_swizzle.frag \ shaders/triplanaryuvvideo.vert \ shaders/triplanaryuvvideo.frag + +load(qt_module) diff --git a/tests/auto/unit/qaudiodecoder/qaudiodecoder.pro b/tests/auto/unit/qaudiodecoder/qaudiodecoder.pro index 21204847c..4534fb4fe 100644 --- a/tests/auto/unit/qaudiodecoder/qaudiodecoder.pro +++ b/tests/auto/unit/qaudiodecoder/qaudiodecoder.pro @@ -1,14 +1,8 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-02-07T15:27:07 -# -#------------------------------------------------- - QT += multimedia multimedia-private testlib gui TARGET = tst_qaudiodecoder -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TEMPLATE = app diff --git a/tests/auto/unit/qaudioprobe/qaudioprobe.pro b/tests/auto/unit/qaudioprobe/qaudioprobe.pro index 3d275b402..a83769cc7 100644 --- a/tests/auto/unit/qaudioprobe/qaudioprobe.pro +++ b/tests/auto/unit/qaudioprobe/qaudioprobe.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qaudioprobe QT += multimedia-private testlib diff --git a/tests/auto/unit/qaudiorecorder/qaudiorecorder.pro b/tests/auto/unit/qaudiorecorder/qaudiorecorder.pro index ccb5531e7..a40fba233 100644 --- a/tests/auto/unit/qaudiorecorder/qaudiorecorder.pro +++ b/tests/auto/unit/qaudiorecorder/qaudiorecorder.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qaudiorecorder QT += multimedia-private testlib diff --git a/tests/auto/unit/qdeclarativeaudio/qdeclarativeaudio.pro b/tests/auto/unit/qdeclarativeaudio/qdeclarativeaudio.pro index 2bed926b9..f59027bc2 100644 --- a/tests/auto/unit/qdeclarativeaudio/qdeclarativeaudio.pro +++ b/tests/auto/unit/qdeclarativeaudio/qdeclarativeaudio.pro @@ -5,10 +5,12 @@ QT += multimedia-private qml testlib HEADERS += \ ../../../../src/imports/multimedia/qdeclarativeaudio_p.h \ + ../../../../src/imports/multimedia/qdeclarativeplaylist_p.h \ ../../../../src/imports/multimedia/qdeclarativemediametadata_p.h SOURCES += \ tst_qdeclarativeaudio.cpp \ + ../../../../src/imports/multimedia/qdeclarativeplaylist.cpp \ ../../../../src/imports/multimedia/qdeclarativeaudio.cpp INCLUDEPATH += ../../../../src/imports/multimedia diff --git a/tests/auto/unit/qmediaobject/qmediaobject.pro b/tests/auto/unit/qmediaobject/qmediaobject.pro index 71a22ee62..26c9f1223 100644 --- a/tests/auto/unit/qmediaobject/qmediaobject.pro +++ b/tests/auto/unit/qmediaobject/qmediaobject.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qmediaobject QT += multimedia-private testlib diff --git a/tests/auto/unit/qmediaplayer/qmediaplayer.pro b/tests/auto/unit/qmediaplayer/qmediaplayer.pro index da52f081d..7279239e0 100644 --- a/tests/auto/unit/qmediaplayer/qmediaplayer.pro +++ b/tests/auto/unit/qmediaplayer/qmediaplayer.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qmediaplayer QT += network multimedia-private testlib SOURCES += tst_qmediaplayer.cpp diff --git a/tests/auto/unit/qmediaplayerwidgets/qmediaplayerwidgets.pro b/tests/auto/unit/qmediaplayerwidgets/qmediaplayerwidgets.pro index 97232f934..60c4f25f4 100644 --- a/tests/auto/unit/qmediaplayerwidgets/qmediaplayerwidgets.pro +++ b/tests/auto/unit/qmediaplayerwidgets/qmediaplayerwidgets.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qmediaplayerwidgets QT += network multimedia-private multimediawidgets-private testlib widgets SOURCES += tst_qmediaplayerwidgets.cpp diff --git a/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp index c43f69886..3a59823ca 100644 --- a/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp +++ b/tests/auto/unit/qmediaplaylist/tst_qmediaplaylist.cpp @@ -1218,7 +1218,7 @@ void tst_QMediaPlaylist::mediaPlayListControl() { // To check changes in abstract classe's pure virtual functions QObject parent; - MockMediaPlaylistControl plylistctrl(&parent); + MockMediaPlaylistControl plylistctrl(false, &parent); } // MaemoAPI-1850:test QMediaPlayListSourceControl constructor diff --git a/tests/auto/unit/qmediarecorder/qmediarecorder.pro b/tests/auto/unit/qmediarecorder/qmediarecorder.pro index 417ba17d2..7103ea157 100644 --- a/tests/auto/unit/qmediarecorder/qmediarecorder.pro +++ b/tests/auto/unit/qmediarecorder/qmediarecorder.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qmediarecorder QT += multimedia-private testlib SOURCES += tst_qmediarecorder.cpp diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin1/mockserviceplugin1.pro b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin1/mockserviceplugin1.pro index c17f5c3d6..7fcaadbc2 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin1/mockserviceplugin1.pro +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin1/mockserviceplugin1.pro @@ -1,7 +1,12 @@ -TARGET = mockserviceplugin1 QT += multimedia-private -PLUGIN_TYPE=mediaservice +HEADERS += ../mockservice.h +SOURCES += mockserviceplugin1.cpp +OTHER_FILES += mockserviceplugin1.json + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = MockServicePlugin1 load(qt_plugin) @@ -14,9 +19,4 @@ win32 { } } -HEADERS += ../mockservice.h -SOURCES += mockserviceplugin1.cpp -OTHER_FILES += mockserviceplugin1.json - target.path = $$[QT_INSTALL_TESTS]/tst_qmediaserviceprovider/$${PLUGIN_TYPE} - diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.pro b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.pro index 21c78790e..4ac001ec9 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.pro +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.pro @@ -1,7 +1,12 @@ -TARGET = mockserviceplugin2 QT += multimedia-private -PLUGIN_TYPE=mediaservice +HEADERS += ../mockservice.h +SOURCES += mockserviceplugin2.cpp +OTHER_FILES += mockserviceplugin2.json + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = MockServicePlugin2 load(qt_plugin) @@ -14,9 +19,4 @@ win32 { } } -HEADERS += ../mockservice.h -SOURCES += mockserviceplugin2.cpp -OTHER_FILES += mockserviceplugin2.json - target.path = $$[QT_INSTALL_TESTS]/tst_qmediaserviceprovider/$${PLUGIN_TYPE} - diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin3/mockserviceplugin3.pro b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin3/mockserviceplugin3.pro index 4e516a095..34cd2fed1 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin3/mockserviceplugin3.pro +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin3/mockserviceplugin3.pro @@ -1,7 +1,12 @@ -TARGET = mockserviceplugin3 QT += multimedia-private -PLUGIN_TYPE=mediaservice +HEADERS += ../mockservice.h +SOURCES += mockserviceplugin3.cpp +OTHER_FILES += mockserviceplugin3.json + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = MockServicePlugin3 load(qt_plugin) @@ -14,9 +19,4 @@ win32 { } } -HEADERS += ../mockservice.h -SOURCES += mockserviceplugin3.cpp -OTHER_FILES += mockserviceplugin3.json - target.path = $$[QT_INSTALL_TESTS]/tst_qmediaserviceprovider/$${PLUGIN_TYPE} - diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.pro b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.pro index 3446e2456..0900bfc40 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.pro +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.pro @@ -1,7 +1,12 @@ -TARGET = mockserviceplugin4 QT += multimedia-private -PLUGIN_TYPE=mediaservice +HEADERS += ../mockservice.h +SOURCES += mockserviceplugin4.cpp +OTHER_FILES += mockserviceplugin4.json + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = MockServicePlugin4 load(qt_plugin) @@ -14,9 +19,4 @@ win32 { } } -HEADERS += ../mockservice.h -SOURCES += mockserviceplugin4.cpp -OTHER_FILES += mockserviceplugin4.json - target.path = $$[QT_INSTALL_TESTS]/tst_qmediaserviceprovider/$${PLUGIN_TYPE} - diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin5/mockserviceplugin5.pro b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin5/mockserviceplugin5.pro index 2358fa503..37f287f9d 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin5/mockserviceplugin5.pro +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin5/mockserviceplugin5.pro @@ -1,7 +1,12 @@ -TARGET = mockserviceplugin5 QT += multimedia-private -PLUGIN_TYPE=mediaservice +HEADERS += ../mockservice.h +SOURCES += mockserviceplugin5.cpp +OTHER_FILES += mockserviceplugin5.json + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = MockServicePlugin5 load(qt_plugin) @@ -14,9 +19,4 @@ win32 { } } -HEADERS += ../mockservice.h -SOURCES += mockserviceplugin5.cpp -OTHER_FILES += mockserviceplugin5.json - target.path = $$[QT_INSTALL_TESTS]/tst_qmediaserviceprovider/$${PLUGIN_TYPE} - diff --git a/tests/auto/unit/qradiodata/qradiodata.pro b/tests/auto/unit/qradiodata/qradiodata.pro index b8914c222..b08262d70 100644 --- a/tests/auto/unit/qradiodata/qradiodata.pro +++ b/tests/auto/unit/qradiodata/qradiodata.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qradiodata QT += multimedia-private testlib SOURCES += tst_qradiodata.cpp diff --git a/tests/auto/unit/qradiotuner/qradiotuner.pro b/tests/auto/unit/qradiotuner/qradiotuner.pro index 4298110d7..d15c4c6a2 100644 --- a/tests/auto/unit/qradiotuner/qradiotuner.pro +++ b/tests/auto/unit/qradiotuner/qradiotuner.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qradiotuner QT += multimedia-private testlib SOURCES += tst_qradiotuner.cpp diff --git a/tests/auto/unit/qsamplecache/qsamplecache.pro b/tests/auto/unit/qsamplecache/qsamplecache.pro index c17c15919..02ca7cb18 100644 --- a/tests/auto/unit/qsamplecache/qsamplecache.pro +++ b/tests/auto/unit/qsamplecache/qsamplecache.pro @@ -1,4 +1,4 @@ -CONFIG += no_private_qt_headers_warning testcase +CONFIG += testcase TARGET = tst_qsamplecache QT += multimedia-private testlib diff --git a/tests/auto/unit/qvideoprobe/qvideoprobe.pro b/tests/auto/unit/qvideoprobe/qvideoprobe.pro index 03c7d56f7..52fb9cde5 100644 --- a/tests/auto/unit/qvideoprobe/qvideoprobe.pro +++ b/tests/auto/unit/qvideoprobe/qvideoprobe.pro @@ -1,4 +1,4 @@ -CONFIG += testcase no_private_qt_headers_warning +CONFIG += testcase TARGET = tst_qvideoprobe QT += multimedia-private testlib diff --git a/tests/auto/unit/qwavedecoder/qwavedecoder.pro b/tests/auto/unit/qwavedecoder/qwavedecoder.pro index 39ebaf63e..1409df98b 100644 --- a/tests/auto/unit/qwavedecoder/qwavedecoder.pro +++ b/tests/auto/unit/qwavedecoder/qwavedecoder.pro @@ -4,6 +4,6 @@ SOURCES += tst_qwavedecoder.cpp \ ../../../../src/multimedia/audio/qwavedecoder_p.cpp QT += multimedia-private testlib network -CONFIG += no_private_qt_headers_warning testcase +CONFIG += testcase TESTDATA += data/* |