summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-09-21 09:28:06 +0200
committerLiang Qi <liang.qi@qt.io>2016-09-21 09:28:06 +0200
commite1ae1235f259393e72e4a2e0d77278e9054405fb (patch)
tree04f57d7b2a9429844306c55e9604f10562ba9783 /src
parent2e556aef9375377439b9b6da8d455fe891abfd7c (diff)
parent01c9322bfe918b886468eb520d77b21b6d8c0c11 (diff)
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts: src/imports/multimedia/multimedia.cpp Change-Id: I38899391ec8d2fcec6f2d46514286759f7a27629
Diffstat (limited to 'src')
-rw-r--r--src/imports/audioengine/audioengine.cpp2
-rw-r--r--src/imports/multimedia/Video.qml12
-rw-r--r--src/imports/multimedia/multimedia.cpp5
-rw-r--r--src/imports/multimedia/plugins.qmltypes23
-rw-r--r--src/imports/multimedia/qdeclarativeaudio.cpp24
-rw-r--r--src/imports/multimedia/qdeclarativeplaylist.cpp14
-rw-r--r--src/multimedia/audio/qaudioinput.cpp7
-rw-r--r--src/multimedia/audio/qaudiooutput.cpp13
-rw-r--r--src/multimedia/audio/qaudiosystemplugin.cpp2
-rw-r--r--src/multimedia/audio/qsoundeffect.cpp25
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.cpp49
-rw-r--r--src/multimedia/audio/qsoundeffect_pulse_p.h10
-rw-r--r--src/multimedia/controls/qmediaplayercontrol.cpp2
-rw-r--r--src/multimedia/controls/qmediarecordercontrol.cpp6
-rw-r--r--src/multimedia/doc/src/qtmultimedia-examples.qdoc2
-rw-r--r--src/multimedia/playback/qmediaplayer.cpp10
-rw-r--r--src/multimedia/playback/qmediaplaylist.cpp6
-rw-r--r--src/multimedia/recording/qmediarecorder.cpp11
-rw-r--r--src/multimedia/video/qabstractvideobuffer.cpp2
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm16
-rw-r--r--src/plugins/avfoundation/mediaplayer/avfvideowidget.mm6
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp2
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp77
-rw-r--r--src/plugins/directshow/player/directshowiosource.h2
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp31
-rw-r--r--src/plugins/videonode/videonode.pro1
-rw-r--r--src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp2
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.cpp121
-rw-r--r--src/plugins/wasapi/qwasapiaudioinput.h3
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.cpp86
-rw-r--r--src/plugins/wasapi/qwasapiaudiooutput.h3
-rw-r--r--src/plugins/wasapi/qwasapiutils.cpp11
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp11
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h2
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.cpp191
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.h76
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.cpp164
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.h3
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp4
-rw-r--r--src/plugins/winrt/winrt.pro2
40 files changed, 786 insertions, 253 deletions
diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp
index 8eb2dea33..a132af49a 100644
--- a/src/imports/audioengine/audioengine.cpp
+++ b/src/imports/audioengine/audioengine.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QAudioEngineDeclarativeModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QAudioEngineDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/multimedia/Video.qml b/src/imports/multimedia/Video.qml
index 26dd12ca4..66b86c74b 100644
--- a/src/imports/multimedia/Video.qml
+++ b/src/imports/multimedia/Video.qml
@@ -360,7 +360,17 @@ Item {
/*!
\qmlproperty real Video::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside
+ this range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic
+ scale will produce linear changes in perceived loudness, which is what a user would normally
+ expect from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
property alias volume: player.volume
diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp
index 19e932fb9..1b8c87cc0 100644
--- a/src/imports/multimedia/multimedia.cpp
+++ b/src/imports/multimedia/multimedia.cpp
@@ -81,7 +81,7 @@ static QObject *multimedia_global_object(QQmlEngine *qmlEngine, QJSEngine *jsEng
class QMultimediaDeclarativeModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QMultimediaDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
@@ -140,6 +140,9 @@ public:
qmlRegisterUncreatableType<QDeclarativeCameraImageProcessing, 2>(uri, 5, 7, "CameraImageProcessing",
trUtf8("CameraImageProcessing is provided by Camera"));
+ // 5.8 types (nothing new, re-register one of the types)
+ qmlRegisterType<QSoundEffect>(uri, 5, 8, "SoundEffect");
+
// 5.9 types
qmlRegisterType<QDeclarativeAudio, 2>(uri, 5, 9, "Audio");
qmlRegisterType<QDeclarativeAudio, 2>(uri, 5, 9, "MediaPlayer");
diff --git a/src/imports/multimedia/plugins.qmltypes b/src/imports/multimedia/plugins.qmltypes
index 91fff02eb..20bbf7d3e 100644
--- a/src/imports/multimedia/plugins.qmltypes
+++ b/src/imports/multimedia/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtMultimedia 5.7'
+// 'qmlplugindump -nonrelocatable QtMultimedia 5.8'
Module {
dependencies: ["QtQuick 2.0"]
@@ -1248,8 +1248,24 @@ Module {
isCreatable: false
isSingleton: true
exportMetaObjectRevisions: [0]
+ Enum {
+ name: "VolumeScale"
+ values: {
+ "LinearVolumeScale": 0,
+ "CubicVolumeScale": 1,
+ "LogarithmicVolumeScale": 2,
+ "DecibelVolumeScale": 3
+ }
+ }
Property { name: "defaultCamera"; type: "QJSValue"; isReadonly: true }
Property { name: "availableCameras"; type: "QJSValue"; isReadonly: true }
+ Method {
+ name: "convertVolume"
+ type: "double"
+ Parameter { name: "volume"; type: "double" }
+ Parameter { name: "from"; type: "VolumeScale" }
+ Parameter { name: "to"; type: "VolumeScale" }
+ }
}
Component {
name: "QDeclarativePlaylist"
@@ -1794,9 +1810,10 @@ Module {
prototype: "QObject"
exports: [
"QtMultimedia/SoundEffect 5.0",
- "QtMultimedia/SoundEffect 5.3"
+ "QtMultimedia/SoundEffect 5.3",
+ "QtMultimedia/SoundEffect 5.8"
]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 0, 0]
Enum {
name: "Loop"
values: {
diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp
index 608337d54..75bb21ee5 100644
--- a/src/imports/multimedia/qdeclarativeaudio.cpp
+++ b/src/imports/multimedia/qdeclarativeaudio.cpp
@@ -718,9 +718,17 @@ QDeclarativeAudio::PlaybackState QDeclarativeAudio::playbackState() const
/*!
\qmlproperty real QtMultimedia::Audio::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume.
- Defaults to 1.0.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
@@ -1355,9 +1363,17 @@ void QDeclarativeAudio::_q_mediaChanged(const QMediaContent &media)
/*!
\qmlproperty real QtMultimedia::MediaPlayer::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume of the media player.
- Defaults to 1.0.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
diff --git a/src/imports/multimedia/qdeclarativeplaylist.cpp b/src/imports/multimedia/qdeclarativeplaylist.cpp
index 0620942bd..b338c33e5 100644
--- a/src/imports/multimedia/qdeclarativeplaylist.cpp
+++ b/src/imports/multimedia/qdeclarativeplaylist.cpp
@@ -597,7 +597,7 @@ void QDeclarativePlaylist::componentComplete()
}
/*!
- \qmlsignal QtMultimedia::Audio::itemAboutToBeInserted(start, end)
+ \qmlsignal QtMultimedia::Playlist::itemAboutToBeInserted(start, end)
This signal is emitted when items are to be inserted into the playlist at \a start and ending at
\a end.
@@ -606,7 +606,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::itemInserted(start, end)
+ \qmlsignal QtMultimedia::Playlist::itemInserted(start, end)
This signal is emitted after items have been inserted into the playlist. The new items are those
between \a start and \a end inclusive.
@@ -615,7 +615,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::itemAboutToBeRemoved(start, end)
+ \qmlsignal QtMultimedia::Playlist::itemAboutToBeRemoved(start, end)
This signal emitted when items are to be deleted from the playlist at \a start and ending at
\a end.
@@ -624,7 +624,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::itemRemoved(start, end)
+ \qmlsignal QtMultimedia::Playlist::itemRemoved(start, end)
This signal is emitted after items have been removed from the playlist. The removed items are
those between \a start and \a end inclusive.
@@ -633,7 +633,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::itemChanged(start, end)
+ \qmlsignal QtMultimedia::Playlist::itemChanged(start, end)
This signal is emitted after items have been changed in the playlist between \a start and
\a end positions inclusive.
@@ -642,7 +642,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::loaded()
+ \qmlsignal QtMultimedia::Playlist::loaded()
This signal is emitted when the playlist loading succeeded.
@@ -650,7 +650,7 @@ void QDeclarativePlaylist::componentComplete()
*/
/*!
- \qmlsignal QtMultimedia::Audio::loadFailed()
+ \qmlsignal QtMultimedia::Playlist::loadFailed()
This signal is emitted when the playlist loading failed. \l error and \l errorString can be
checked for more information on the failure.
diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp
index bc6b6215b..ad54521fa 100644
--- a/src/multimedia/audio/qaudioinput.cpp
+++ b/src/multimedia/audio/qaudioinput.cpp
@@ -330,10 +330,15 @@ int QAudioInput::notifyInterval() const
/*!
Sets the input volume to \a volume.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
If the device does not support adjusting the input
volume then \a volume will be ignored and the input
volume will remain at 1.0.
+ The default volume is \c 1.0.
+
Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
*/
void QAudioInput::setVolume(qreal volume)
@@ -342,7 +347,7 @@ void QAudioInput::setVolume(qreal volume)
}
/*!
- Returns the input volume (gain).
+ Returns the input volume.
If the device does not support adjusting the input volume
the returned value will be 1.0.
diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp
index 585855ace..670dca7bc 100644
--- a/src/multimedia/audio/qaudiooutput.cpp
+++ b/src/multimedia/audio/qaudiooutput.cpp
@@ -349,9 +349,18 @@ QAudio::State QAudioOutput::state() const
}
/*!
- Sets the volume.
- Where \a volume is between 0.0 and 1.0 inclusive.
+ Sets the output volume to \a volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
void QAudioOutput::setVolume(qreal volume)
{
diff --git a/src/multimedia/audio/qaudiosystemplugin.cpp b/src/multimedia/audio/qaudiosystemplugin.cpp
index 438b8b7bb..636b614d4 100644
--- a/src/multimedia/audio/qaudiosystemplugin.cpp
+++ b/src/multimedia/audio/qaudiosystemplugin.cpp
@@ -77,7 +77,7 @@ QAudioSystemPluginExtension::~QAudioSystemPluginExtension()
\sa QAbstractAudioDeviceInfo, QAbstractAudioOutput, QAbstractAudioInput
- Qt comes with plugins for Windows (WinMM and WASAPI), Linux (ALSA and PulseAudio), OS X / iOS
+ Qt comes with plugins for Windows (WinMM and WASAPI), Linux (ALSA and PulseAudio), \macos / iOS
(CoreAudio), Android (OpenSL ES) and QNX.
If no audio plugins are available, a fallback dummy backend will be used.
diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp
index f653de86e..d3b818073 100644
--- a/src/multimedia/audio/qsoundeffect.cpp
+++ b/src/multimedia/audio/qsoundeffect.cpp
@@ -258,12 +258,22 @@ int QSoundEffect::loopsRemaining() const
/*!
\qmlproperty qreal QtMultimedia::SoundEffect::volume
- This property holds the volume of the sound effect playback, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the volume of the sound effect playback.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
\property QSoundEffect::volume
- This property holds the volume of the sound effect playback, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the volume of the sound effect playback, from 0.0 (silence) to 1.0 (full volume).
*/
/*!
@@ -275,7 +285,16 @@ qreal QSoundEffect::volume() const
}
/*!
- Sets the volume to play the sound effect at to \a volume, from 0.0 (silent) to 1.0 (maximum volume).
+ Sets the sound effect volume to \a volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
void QSoundEffect::setVolume(qreal volume)
{
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
index 79d1d96ab..6e4aadd0b 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp
@@ -419,7 +419,13 @@ void QSoundEffectPrivate::setSource(const QUrl &url)
#ifdef QT_PA_DEBUG
qDebug() << this << "setSource =" << url;
#endif
+
+ // Make sure the stream is empty before loading a new source (otherwise whatever is there will
+ // be played before the new source)
+ emptyStream();
+
stop();
+
if (m_sample) {
if (!m_sampleReady) {
disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
@@ -594,7 +600,7 @@ void QSoundEffectPrivate::playAvailable()
setLoopsRemaining(0);
m_playQueued = true;
Q_ASSERT(m_pulseStream);
- emptyStream();
+ emptyStream(ReloadSampleWhenDone);
return;
}
setLoopsRemaining(m_loopCount);
@@ -604,18 +610,25 @@ void QSoundEffectPrivate::playAvailable()
setPlaying(true);
}
-void QSoundEffectPrivate::emptyStream()
+void QSoundEffectPrivate::emptyStream(EmptyStreamOptions options)
{
#ifdef QT_PA_DEBUG
qDebug() << this << "emptyStream";
#endif
+ if (!m_pulseStream || m_emptying)
+ return;
+
+ const bool reloadSample = options.testFlag(ReloadSampleWhenDone);
+ pa_stream_success_cb_t flushCompleteCb = reloadSample ? stream_flush_reload_callback
+ : stream_flush_callback;
+
m_emptying = true;
pa_stream_set_write_callback(m_pulseStream, 0, 0);
pa_stream_set_underflow_callback(m_pulseStream, 0, 0);
- pa_operation_unref(pa_stream_flush(m_pulseStream, stream_flush_callback, m_ref->getRef()));
+ pa_operation_unref(pa_stream_flush(m_pulseStream, flushCompleteCb, m_ref->getRef()));
}
-void QSoundEffectPrivate::emptyComplete(void *stream)
+void QSoundEffectPrivate::emptyComplete(void *stream, bool reload)
{
PulseDaemonLocker locker;
#ifdef QT_PA_DEBUG
@@ -625,7 +638,7 @@ void QSoundEffectPrivate::emptyComplete(void *stream)
m_emptying = false;
if ((pa_stream *)stream == m_pulseStream)
- pa_operation_unref(pa_stream_cork(m_pulseStream, 1, stream_cork_callback, m_ref->getRef()));
+ pa_operation_unref(pa_stream_cork(m_pulseStream, 1, reload ? stream_cork_callback : 0, m_ref->getRef()));
}
void QSoundEffectPrivate::sampleReady()
@@ -729,6 +742,10 @@ void QSoundEffectPrivate::prepare()
if (!m_pulseStream || !m_sampleReady)
return;
PulseDaemonLocker locker;
+
+ if (pa_stream_get_state(m_pulseStream) != PA_STREAM_READY)
+ return;
+
pa_stream_set_write_callback(m_pulseStream, stream_write_callback, this);
pa_stream_set_underflow_callback(m_pulseStream, stream_underrun_callback, this);
m_stopping = false;
@@ -857,7 +874,7 @@ void QSoundEffectPrivate::stop()
PulseDaemonLocker locker;
m_stopping = true;
if (m_pulseStream) {
- emptyStream();
+ emptyStream(ReloadSampleWhenDone);
if (m_reloadCategory) {
unloadPulseStream(); // upon play we reconnect anyway
}
@@ -1100,10 +1117,26 @@ void QSoundEffectPrivate::stream_flush_callback(pa_stream *s, int success, void
if (!success)
qWarning("QSoundEffect(pulseaudio): faild to drain");
+
+ QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, false));
+}
+
+void QSoundEffectPrivate::stream_flush_reload_callback(pa_stream *s, int success, void *userdata)
+{
#ifdef QT_PA_DEBUG
- qDebug() << self << "stream_flush_callback";
+ qDebug() << "stream_flush_reload_callback";
#endif
- QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s));
+ Q_UNUSED(s);
+ QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata);
+ QSoundEffectPrivate *self = ref->soundEffect();
+ ref->release();
+ if (!self)
+ return;
+
+ if (!success)
+ qWarning("QSoundEffect(pulseaudio): faild to drain");
+
+ QMetaObject::invokeMethod(self, "emptyComplete", Qt::QueuedConnection, Q_ARG(void*, s), Q_ARG(bool, true));
}
void QSoundEffectPrivate::stream_write_done_callback(void *p)
diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h
index 6bf2416cf..020aa031a 100644
--- a/src/multimedia/audio/qsoundeffect_pulse_p.h
+++ b/src/multimedia/audio/qsoundeffect_pulse_p.h
@@ -117,7 +117,7 @@ private Q_SLOTS:
void underRun();
void prepare();
void streamReady();
- void emptyComplete(void *stream);
+ void emptyComplete(void *stream, bool reload);
void handleAvailabilityChanged(bool available);
@@ -125,7 +125,12 @@ private:
void playAvailable();
void playSample();
- void emptyStream();
+ enum EmptyStreamOption {
+ ReloadSampleWhenDone = 0x1
+ };
+ Q_DECLARE_FLAGS(EmptyStreamOptions, EmptyStreamOption)
+ void emptyStream(EmptyStreamOptions options = EmptyStreamOptions());
+
void createPulseStream();
void unloadPulseStream();
@@ -140,6 +145,7 @@ private:
static void stream_underrun_callback(pa_stream *s, void *userdata);
static void stream_cork_callback(pa_stream *s, int success, void *userdata);
static void stream_flush_callback(pa_stream *s, int success, void *userdata);
+ static void stream_flush_reload_callback(pa_stream *s, int success, void *userdata);
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);
diff --git a/src/multimedia/controls/qmediaplayercontrol.cpp b/src/multimedia/controls/qmediaplayercontrol.cpp
index cd56dffcb..46de05b51 100644
--- a/src/multimedia/controls/qmediaplayercontrol.cpp
+++ b/src/multimedia/controls/qmediaplayercontrol.cpp
@@ -175,6 +175,8 @@ QMediaPlayerControl::QMediaPlayerControl(QObject *parent):
\fn QMediaPlayerControl::setVolume(int volume)
Sets the audio \a volume of a player control.
+
+ The volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
*/
/*!
diff --git a/src/multimedia/controls/qmediarecordercontrol.cpp b/src/multimedia/controls/qmediarecordercontrol.cpp
index 4654d16eb..611f1fdcc 100644
--- a/src/multimedia/controls/qmediarecordercontrol.cpp
+++ b/src/multimedia/controls/qmediarecordercontrol.cpp
@@ -160,13 +160,15 @@ QMediaRecorderControl::~QMediaRecorderControl()
/*!
\fn qreal QMediaRecorderControl::volume() const
- Returns the linear audio gain of media recorder.
+ Returns the audio volume of a media recorder control.
*/
/*!
\fn void QMediaRecorderControl::setVolume(qreal gain)
- Sets the linear audio \a gain of a media recorder.
+ Sets the audio \a volume of a media recorder control.
+
+ The volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
*/
/*!
diff --git a/src/multimedia/doc/src/qtmultimedia-examples.qdoc b/src/multimedia/doc/src/qtmultimedia-examples.qdoc
index 582efc5e1..dd35aeb1a 100644
--- a/src/multimedia/doc/src/qtmultimedia-examples.qdoc
+++ b/src/multimedia/doc/src/qtmultimedia-examples.qdoc
@@ -32,6 +32,6 @@
\brief Demonstrates the multimedia functionality provided by Qt.
The \l{Qt Multimedia} module provides low-level audio support on Linux,
- Windows and OS X. It also provides audio plugin API to allow developers
+ Windows and \macos. It also provides audio plugin API to allow developers
implement their own audio support for custom devices and platforms.
*/
diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp
index c5261921a..648c13220 100644
--- a/src/multimedia/playback/qmediaplayer.cpp
+++ b/src/multimedia/playback/qmediaplayer.cpp
@@ -1372,8 +1372,14 @@ QList<QAudio::Role> QMediaPlayer::supportedAudioRoles() const
\property QMediaPlayer::volume
\brief the current playback volume.
- The playback volume is linear in effect and the value can range from 0 -
- 100, values outside this range will be clamped.
+ The playback volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
+ Values outside this range will be clamped.
+
+ By default the volume is \c 100.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
/*!
diff --git a/src/multimedia/playback/qmediaplaylist.cpp b/src/multimedia/playback/qmediaplaylist.cpp
index 4ffcad398..97fe75044 100644
--- a/src/multimedia/playback/qmediaplaylist.cpp
+++ b/src/multimedia/playback/qmediaplaylist.cpp
@@ -448,10 +448,12 @@ bool QMediaPlaylist::clear()
bool QMediaPlaylistPrivate::readItems(QMediaPlaylistReader *reader)
{
+ QList<QMediaContent> items;
+
while (!reader->atEnd())
- playlist()->addMedia(reader->readItem());
+ items.append(reader->readItem());
- return true;
+ return playlist()->addMedia(items);
}
bool QMediaPlaylistPrivate::writeItems(QMediaPlaylistWriter *writer)
diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp
index a5f4c15ce..7b0234988 100644
--- a/src/multimedia/recording/qmediarecorder.cpp
+++ b/src/multimedia/recording/qmediarecorder.cpp
@@ -556,7 +556,16 @@ void QMediaRecorder::setMuted(bool muted)
/*!
\property QMediaRecorder::volume
- \brief the linear audio gain of media recorder.
+ \brief the current recording audio volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
qreal QMediaRecorder::volume() const
diff --git a/src/multimedia/video/qabstractvideobuffer.cpp b/src/multimedia/video/qabstractvideobuffer.cpp
index 877fe3544..50e38a98c 100644
--- a/src/multimedia/video/qabstractvideobuffer.cpp
+++ b/src/multimedia/video/qabstractvideobuffer.cpp
@@ -98,7 +98,7 @@ int QAbstractVideoBufferPrivate::map(
\value NoHandle The buffer has no handle, its data can only be accessed by mapping the buffer.
\value GLTextureHandle The handle of the buffer is an OpenGL texture ID.
\value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
- \value CoreImageHandle The handle contains pointer to OS X CIImage.
+ \value CoreImageHandle The handle contains pointer to \macos CIImage.
\value QPixmapHandle The handle of the buffer is a QPixmap.
\value EGLImageHandle The handle of the buffer is an EGLImageKHR.
\value UserHandle Start value for user defined handle types.
diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
index 87bb08e5c..473a18884 100644
--- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm
@@ -41,6 +41,8 @@
#include "avfmediaplayerservice.h"
#include "avfvideooutput.h"
+#include <qpointer.h>
+
#import <AVFoundation/AVFoundation.h>
QT_USE_NAMESPACE
@@ -111,15 +113,23 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
//Create an asset for inspection of a resource referenced by a given URL.
//Load the values for the asset keys "tracks", "playable".
- AVURLAsset *asset = [AVURLAsset URLAssetWithURL:m_URL options:nil];
- NSArray *requestedKeys = [NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil];
+ // use __block to avoid maintaining strong references on variables captured by the
+ // following block callback
+ __block AVURLAsset *asset = [[AVURLAsset URLAssetWithURL:m_URL options:nil] retain];
+ __block NSArray *requestedKeys = [[NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil] retain];
+
+ __block AVFMediaPlayerSessionObserver *blockSelf = self;
+ QPointer<AVFMediaPlayerSession> session(m_session);
// Tells the asset to load the values of any of the specified keys that are not already loaded.
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
^{
dispatch_async( dispatch_get_main_queue(),
^{
- [self prepareToPlayAsset:asset withKeys:requestedKeys];
+ if (session)
+ [blockSelf prepareToPlayAsset:asset withKeys:requestedKeys];
+ [asset release];
+ [requestedKeys release];
});
}];
}
diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
index 3b270f9b6..7eb5a71cf 100644
--- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
+++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm
@@ -45,6 +45,12 @@
#include <QtGui/QPaintEvent>
#include <QtGui/QPainter>
+#if defined(Q_OS_MACOS)
+#import <AppKit/AppKit.h>
+#else
+#import <UIKit/UIKit.h>
+#endif
+
QT_USE_NAMESPACE
AVFVideoWidget::AVFVideoWidget(QWidget *parent)
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index 509057ba1..5587b479c 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -174,6 +174,8 @@ QVideoFrame::PixelFormat pixelFormatFromMediaSubtype(GUID uid)
return QVideoFrame::Format_YUYV;
else if (uid == MEDIASUBTYPE_NV12)
return QVideoFrame::Format_NV12;
+ else if (uid == MEDIASUBTYPE_MJPG)
+ return QVideoFrame::Format_Jpeg;
else if (uid == MEDIASUBTYPE_IMC1)
return QVideoFrame::Format_IMC1;
else if (uid == MEDIASUBTYPE_IMC2)
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index 4dc8bec3d..3c44dd1ed 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -47,6 +47,22 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qurl.h>
+static const GUID directshow_subtypes[] =
+{
+ MEDIASUBTYPE_NULL,
+ MEDIASUBTYPE_Avi,
+ MEDIASUBTYPE_Asf,
+ MEDIASUBTYPE_MPEG1Video,
+ MEDIASUBTYPE_QTMovie,
+ MEDIASUBTYPE_WAVE,
+ MEDIASUBTYPE_AIFF,
+ MEDIASUBTYPE_AU,
+ MEDIASUBTYPE_DssVideo,
+ MEDIASUBTYPE_MPEG1Audio,
+ MEDIASUBTYPE_MPEG1System,
+ MEDIASUBTYPE_MPEG1VideoCD
+};
+
DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
: m_ref(1)
, m_state(State_Stopped)
@@ -65,13 +81,26 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
//
// The filter works in pull mode, the downstream filter is responsible for requesting
// samples from this one.
-
- m_outputType.majortype = MEDIATYPE_Stream;
- m_outputType.subtype = MEDIASUBTYPE_NULL; // Wildcard
- m_outputType.bFixedSizeSamples = TRUE;
- m_outputType.lSampleSize = 1;
-
- m_supportedMediaTypes.append(m_outputType);
+ //
+ AM_MEDIA_TYPE type =
+ {
+ MEDIATYPE_Stream, // majortype
+ MEDIASUBTYPE_NULL, // subtype
+ TRUE, // bFixedSizeSamples
+ FALSE, // bTemporalCompression
+ 1, // lSampleSize
+ GUID_NULL, // formattype
+ 0, // pUnk
+ 0, // cbFormat
+ 0, // pbFormat
+ };
+
+ static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
+
+ for (int i = 0; i < count; ++i) {
+ type.subtype = directshow_subtypes[i];
+ m_supportedMediaTypes.append(type);
+ }
}
DirectShowIOSource::~DirectShowIOSource()
@@ -328,14 +357,40 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
return VFW_E_ALREADY_CONNECTED;
// If we get a type from the graph manager, check that we support that
- if (pmt && (pmt->majortype != MEDIATYPE_Stream || pmt->subtype != MEDIASUBTYPE_NULL))
+ if (pmt && pmt->majortype != MEDIATYPE_Stream)
return VFW_E_TYPE_NOT_ACCEPTED;
// This filter only works in pull mode, the downstream filter must query for the
// AsyncReader interface during ReceiveConnection().
// If it doesn't, we can't connect to it.
m_queriedForAsyncReader = false;
- HRESULT hr = pReceivePin->ReceiveConnection(this, pmt ? pmt : &m_outputType);
+ HRESULT hr = 0;
+ // Negotiation of media type
+ // - Complete'ish type (Stream with subtype specified).
+ if (pmt && pmt->subtype != MEDIASUBTYPE_NULL /* aka. GUID_NULL */) {
+ hr = pReceivePin->ReceiveConnection(this, pmt);
+ // Update the media type for the current connection.
+ if (SUCCEEDED(hr))
+ m_connectionMediaType = *pmt;
+ } else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified).
+ m_connectionMediaType = *pmt;
+ // Check if the receiving pin accepts any of the streaming subtypes.
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ m_connectionMediaType.subtype = t.subtype;
+ hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType);
+ if (SUCCEEDED(hr))
+ break;
+ }
+ } else { // - No media type specified.
+ // Check if the receiving pin accepts any of the streaming types.
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ hr = pReceivePin->ReceiveConnection(this, &t);
+ if (SUCCEEDED(hr)) {
+ m_connectionMediaType = t;
+ break;
+ }
+ }
+ }
if (SUCCEEDED(hr) && m_queriedForAsyncReader) {
m_peerPin = pReceivePin;
@@ -348,6 +403,8 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
}
if (!m_queriedForAsyncReader)
hr = VFW_E_NO_TRANSPORT;
+
+ m_connectionMediaType.clear();
}
return hr;
@@ -420,7 +477,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
return VFW_E_NOT_CONNECTED;
} else {
- DirectShowMediaType::copy(pmt, m_outputType);
+ DirectShowMediaType::copy(pmt, m_connectionMediaType);
return S_OK;
}
diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h
index efcde7a27..702bfed61 100644
--- a/src/plugins/directshow/player/directshowiosource.h
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -123,7 +123,7 @@ private:
IReferenceClock *m_clock;
IMemAllocator *m_allocator;
IPin *m_peerPin;
- DirectShowMediaType m_outputType;
+ DirectShowMediaType m_connectionMediaType;
QList<DirectShowMediaType> m_supportedMediaTypes;
QString m_filterName;
const QString m_pinId;
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index 26f2380b2..70d77a380 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -114,11 +114,18 @@ QAudio::State QOpenSLESAudioOutput::state() const
void QOpenSLESAudioOutput::start(QIODevice *device)
{
Q_ASSERT(device);
+
+ if (m_state != QAudio::StoppedState)
+ stop();
+
if (!preparePlayer())
return;
m_pullMode = true;
m_audioSource = device;
+ m_nextBuffer = 0;
+ m_processedBytes = 0;
+ m_availableBuffers = BUFFER_COUNT;
setState(QAudio::ActiveState);
setError(QAudio::NoError);
@@ -136,6 +143,9 @@ void QOpenSLESAudioOutput::start(QIODevice *device)
m_processedBytes += readSize;
}
+ if (m_processedBytes < 1)
+ onEOSEvent();
+
// Change the state to playing.
// We need to do this after filling the buffers or processedBytes might get corrupted.
startPlayer();
@@ -143,10 +153,15 @@ void QOpenSLESAudioOutput::start(QIODevice *device)
QIODevice *QOpenSLESAudioOutput::start()
{
+ if (m_state != QAudio::StoppedState)
+ stop();
+
if (!preparePlayer())
return Q_NULLPTR;
m_pullMode = false;
+ m_processedBytes = 0;
+ m_availableBuffers = BUFFER_COUNT;
m_audioSource = new SLIODevicePrivate(this);
m_audioSource->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
@@ -372,7 +387,10 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
if (!m_pullMode) { // We're in push mode.
// Signal that there is a new open slot in the buffer and return
- m_availableBuffers.fetchAndAddRelease(1);
+ const int val = m_availableBuffers.fetchAndAddRelease(1) + 1;
+ if (val == BUFFER_COUNT)
+ QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection);
+
return;
}
@@ -380,8 +398,11 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
const int index = m_nextBuffer * m_bufferSize;
const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize);
- if (1 > readSize)
+ if (readSize < 1) {
+ QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection);
return;
+ }
+
if (SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf,
m_buffers + index,
@@ -606,6 +627,12 @@ void QOpenSLESAudioOutput::stopPlayer()
{
setState(QAudio::StoppedState);
+ if (m_audioSource && !m_pullMode) {
+ m_audioSource->close();
+ delete m_audioSource;
+ m_audioSource = Q_NULLPTR;
+ }
+
// We need to change the state manually...
if (m_playItf)
(*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED);
diff --git a/src/plugins/videonode/videonode.pro b/src/plugins/videonode/videonode.pro
index b7b18cdcf..5fbcaecd4 100644
--- a/src/plugins/videonode/videonode.pro
+++ b/src/plugins/videonode/videonode.pro
@@ -1,4 +1,5 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += gui-private
config_gpu_vivante {
SUBDIRS += imx6
diff --git a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
index 0fa618fe4..e1a46841d 100644
--- a/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
+++ b/src/plugins/wasapi/qwasapiaudiodeviceinfo.cpp
@@ -54,7 +54,7 @@ QWasapiAudioDeviceInfo::QWasapiAudioDeviceInfo(QByteArray dev, QAudio::Mode mode
QAudioFormat referenceFormat = m_interface->m_mixFormat;
- const int rates[] = {8000, 11025, 160000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
+ const int rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000};
for (int rate : rates) {
QAudioFormat f = referenceFormat;
f.setSampleRate(rate);
diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp
index 3bcf50367..22a77df38 100644
--- a/src/plugins/wasapi/qwasapiaudioinput.cpp
+++ b/src/plugins/wasapi/qwasapiaudioinput.cpp
@@ -120,7 +120,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len)
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);
+ emit m_input->notify();
m_input->m_openTimeOffset = m_input->m_openTime.elapsed();
}
@@ -128,8 +128,7 @@ qint64 WasapiInputDevicePrivate::readData(char* data, qint64 len)
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));
+ emit m_input->stateChanged(m_input->m_currentState);
}
return readBytes;
}
@@ -192,13 +191,9 @@ qreal QWasapiAudioInput::volume() const
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;
+ m_processing = true;
do {
waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
if (waitRet != WAIT_OBJECT_0) {
@@ -210,67 +205,75 @@ void QWasapiAudioInput::process()
if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
break;
+ QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
+ } while (m_processing);
+}
- if (!m_pullMode) {
- QMetaObject::invokeMethod(m_eventDevice, "readyRead", Qt::QueuedConnection);
- ResetEvent(m_event);
- continue;
- }
+void QWasapiAudioInput::processBuffer()
+{
+ if (!m_pullMode) {
+ emit m_eventDevice->readyRead();
+ ResetEvent(m_event);
+ return;
+ }
- quint32 packetFrames;
- hr = m_capture->GetNextPacketSize(&packetFrames);
+ QMutexLocker locker(&m_mutex);
+ const quint32 channelCount = m_currentFormat.channelCount();
+ const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
+ BYTE* buffer;
+ HRESULT hr;
- 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);
- }
+ 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;
+ emit errorChanged(m_currentError);
+ // 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);
+ const qint64 written = m_eventDevice->write(reinterpret_cast<const char *>(buffer), writeBytes);
- if (Q_UNLIKELY(flags & AUDCLNT_BUFFERFLAGS_SILENT))
- delete [] buffer;
+ 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));
- }
+ if (written < static_cast<qint64>(writeBytes)) {
+ if (m_currentError != QAudio::UnderrunError) {
+ m_currentError = QAudio::UnderrunError;
+ emit errorChanged(m_currentError);
}
- hr = m_capture->ReleaseBuffer(packetFrames);
- if (hr != S_OK)
- qFatal("Could not release buffer");
+ }
+ hr = m_capture->ReleaseBuffer(packetFrames);
+ if (hr != S_OK)
+ qFatal("Could not release buffer");
- m_bytesProcessed += writeBytes;
+ m_bytesProcessed += writeBytes;
- hr = m_capture->GetNextPacketSize(&packetFrames);
- }
- ResetEvent(m_event);
+ 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);
+ if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
+ emit notify();
+ m_openTimeOffset = m_openTime.elapsed();
+ }
+ m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
}
bool QWasapiAudioInput::initStart(bool pull)
diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h
index cb2f46436..3fd7315c1 100644
--- a/src/plugins/wasapi/qwasapiaudioinput.h
+++ b/src/plugins/wasapi/qwasapiaudioinput.h
@@ -88,6 +88,8 @@ public:
qreal volume() const Q_DECL_OVERRIDE;
void process();
+public slots:
+ void processBuffer();
private:
bool initStart(bool pull);
friend class WasapiInputDevicePrivate;
@@ -112,6 +114,7 @@ private:
quint32 m_bufferBytes;
HANDLE m_event;
QWasapiProcessThread *m_eventThread;
+ QAtomicInt m_processing;
QIODevice *m_eventDevice;
};
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp
index 53f4f2710..1b0f64451 100644
--- a/src/plugins/wasapi/qwasapiaudiooutput.cpp
+++ b/src/plugins/wasapi/qwasapiaudiooutput.cpp
@@ -206,13 +206,9 @@ qreal QWasapiAudioOutput::volume() const
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;
+ m_processing = true;
do {
waitRet = WaitForSingleObjectEx(m_event, 2000, FALSE);
if (waitRet != WAIT_OBJECT_0) {
@@ -224,51 +220,59 @@ void QWasapiAudioOutput::process()
if (m_currentState != QAudio::ActiveState && m_currentState != QAudio::IdleState)
break;
+ QMetaObject::invokeMethod(this, "processBuffer", Qt::QueuedConnection);
+ } while (m_processing);
+}
- quint32 paddingFrames;
- hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
+void QWasapiAudioOutput::processBuffer()
+{
+ QMutexLocker locker(&m_mutex);
- 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 channelCount = m_currentFormat.channelCount();
+ const quint32 sampleBytes = m_currentFormat.sampleSize() / 8;
+ BYTE* buffer;
+ HRESULT hr;
- 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));
- }
- }
+ quint32 paddingFrames;
+ hr = m_interface->m_client->GetCurrentPadding(&paddingFrames);
+ const quint32 availableFrames = m_bufferFrames - paddingFrames;
+ hr = m_renderer->GetBuffer(availableFrames, &buffer);
+ if (hr != S_OK) {
+ m_currentError = QAudio::UnderrunError;
+ emit errorChanged(m_currentError);
+ // Also Error Buffers need to be released
hr = m_renderer->ReleaseBuffer(availableFrames, 0);
- if (hr != S_OK)
- qFatal("Could not release buffer");
ResetEvent(m_event);
+ return;
+ }
- if (m_interval && m_openTime.elapsed() - m_openTimeOffset > m_interval) {
- QMetaObject::invokeMethod(this, "notify", Qt::QueuedConnection);
- m_openTimeOffset = m_openTime.elapsed();
+ const quint32 readBytes = availableFrames * channelCount * sampleBytes;
+ const 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;
+ emit errorChanged(m_currentError);
}
+ if (m_currentState != QAudio::IdleState) {
+ m_currentState = QAudio::IdleState;
+ emit stateChanged(m_currentState);
+ }
+ }
+
+ 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) {
+ emit notify();
+ m_openTimeOffset = m_openTime.elapsed();
+ }
- m_bytesProcessed += read;
- processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
- } while (processing);
+ m_bytesProcessed += read;
+ m_processing = m_currentState == QAudio::ActiveState || m_currentState == QAudio::IdleState;
}
bool QWasapiAudioOutput::initStart(bool pull)
diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h
index 247a07160..118731af9 100644
--- a/src/plugins/wasapi/qwasapiaudiooutput.h
+++ b/src/plugins/wasapi/qwasapiaudiooutput.h
@@ -89,6 +89,8 @@ public:
qreal volume() const Q_DECL_OVERRIDE;
void process();
+public slots:
+ void processBuffer();
private:
bool initStart(bool pull);
friend class WasapiOutputDevicePrivate;
@@ -113,6 +115,7 @@ private:
quint32 m_bufferBytes;
HANDLE m_event;
QWasapiProcessThread *m_eventThread;
+ QAtomicInt m_processing;
QIODevice *m_eventDevice;
};
diff --git a/src/plugins/wasapi/qwasapiutils.cpp b/src/plugins/wasapi/qwasapiutils.cpp
index 6340a3b01..727c94c23 100644
--- a/src/plugins/wasapi/qwasapiutils.cpp
+++ b/src/plugins/wasapi/qwasapiutils.cpp
@@ -182,6 +182,13 @@ QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
{
qCDebug(lcMmUtils) << __FUNCTION__ << mode;
+ QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
+ QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds;
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // Initialize
+ availableDevices(mode);
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // No audio devices at all
+ return QByteArray();
+
ComPtr<IMediaDeviceStatics> mediaDeviceStatics;
HRESULT hr;
@@ -198,7 +205,9 @@ QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
const wchar_t *dadWStr = defaultAudioDevice.GetRawBuffer(&dADSize);
const QString defaultAudioDeviceId = QString::fromWCharArray(dadWStr, dADSize);
- return defaultAudioDeviceId.toLocal8Bit();
+ Q_ASSERT(deviceIds.indexOf(defaultAudioDeviceId) != -1);
+
+ return deviceNames.at(deviceIds.indexOf(defaultAudioDeviceId));
}
QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index c32a5f2e2..f81a2e94d 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -42,6 +42,7 @@
#include "qwinrtvideodeviceselectorcontrol.h"
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtimageencodercontrol.h"
+#include "qwinrtcameraflashcontrol.h"
#include "qwinrtcamerafocuscontrol.h"
#include "qwinrtcameralockscontrol.h"
@@ -554,6 +555,7 @@ public:
QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
+ QPointer<QWinRTCameraFlashControl> cameraFlashControl;
QPointer<QWinRTCameraFocusControl> cameraFocusControl;
QPointer<QWinRTCameraLocksControl> cameraLocksControl;
QAtomicInt framesMapped;
@@ -578,6 +580,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
d->imageEncoderControl = new QWinRTImageEncoderControl(this);
+ d->cameraFlashControl = new QWinRTCameraFlashControl(this);
d->cameraFocusControl = new QWinRTCameraFocusControl(this);
d->cameraLocksControl = new QWinRTCameraLocksControl(this);
@@ -815,6 +818,12 @@ QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
return d->imageEncoderControl;
}
+QCameraFlashControl *QWinRTCameraControl::cameraFlashControl() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->cameraFlashControl;
+}
+
QCameraFocusControl *QWinRTCameraControl::cameraFocusControl() const
{
Q_D(const QWinRTCameraControl);
@@ -940,6 +949,8 @@ HRESULT QWinRTCameraControl::initialize()
hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
Q_ASSERT_SUCCEEDED(hr);
+ d->cameraFlashControl->initialize(advancedVideoDeviceController);
+
boolean isFocusSupported;
hr = d->focusControl->get_Supported(&isFocusSupported);
Q_ASSERT_SUCCEEDED(hr);
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index 85dd4d44b..f978a8b2c 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -69,6 +69,7 @@ class QVideoRendererControl;
class QVideoDeviceSelectorControl;
class QCameraImageCaptureControl;
class QImageEncoderControl;
+class QCameraFlashControl;
class QCameraFocusControl;
class QCameraLocksControl;
@@ -95,6 +96,7 @@ public:
QVideoDeviceSelectorControl *videoDeviceSelector() const;
QCameraImageCaptureControl *imageCaptureControl() const;
QImageEncoderControl *imageEncoderControl() const;
+ QCameraFlashControl *cameraFlashControl() const;
QCameraFocusControl *cameraFocusControl() const;
QCameraLocksControl *cameraLocksControl() const;
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.cpp b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
new file mode 100644
index 000000000..1ea877672
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** 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 "qwinrtcameraflashcontrol.h"
+#include "qwinrtcameracontrol.h"
+#include <QtCore/QTimer>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#include <windows.media.devices.h>
+#include <wrl.h>
+#include <functional>
+
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::Media::Devices;
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraFlashControlPrivate
+{
+public:
+ ComPtr<IFlashControl> flashControl;
+
+ QList<QCameraExposure::FlashModes> supportedModes;
+ QCameraExposure::FlashModes currentModes;
+ bool initialized;
+};
+
+QWinRTCameraFlashControl::QWinRTCameraFlashControl(QWinRTCameraControl *parent)
+ : QCameraFlashControl(parent), d_ptr(new QWinRTCameraFlashControlPrivate)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << parent;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+ d->currentModes = QCameraExposure::FlashOff;
+}
+
+void QWinRTCameraFlashControl::initialize(Microsoft::WRL::ComPtr<IAdvancedVideoCaptureDeviceController2> &controller)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+
+ d->supportedModes.clear();
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d, controller]() {
+ HRESULT hr;
+ hr = controller->get_FlashControl(&d->flashControl);
+ RETURN_HR_IF_FAILED("Could not access flash control.");
+
+ boolean oldAuto;
+ boolean oldEnabled;
+ // IFlashControl::get_Supported() is only valid for additional
+ // controls (RedEye, etc.) so we have to manually try to set
+ // and reset flash
+ if (SUCCEEDED(d->flashControl->get_Auto(&oldAuto))) {
+ hr = d->flashControl->put_Auto(!oldAuto);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Auto(oldAuto);
+ d->supportedModes.append(QCameraExposure::FlashAuto);
+ }
+ }
+
+ if (SUCCEEDED(d->flashControl->get_Enabled(&oldEnabled))) {
+ hr = d->flashControl->put_Enabled(!oldEnabled);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Enabled(oldEnabled);
+ d->supportedModes.append(QCameraExposure::FlashOff);
+ d->supportedModes.append(QCameraExposure::FlashOn);
+ }
+ }
+
+ boolean val;
+ hr = d->flashControl->get_Supported(&val);
+ if (SUCCEEDED(hr) && val) {
+ hr = d->flashControl->get_RedEyeReductionSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashRedEyeReduction);
+
+ // ### There is no Qt API to actually set the power values.
+ // However query if the camera could theoretically do it
+ hr = d->flashControl->get_PowerSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashManual);
+ }
+
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+ d->initialized = true;
+ setFlashMode(d->currentModes);
+}
+
+QCameraExposure::FlashModes QWinRTCameraFlashControl::flashMode() const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ return d->currentModes;
+}
+
+void QWinRTCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ Q_D(QWinRTCameraFlashControl);
+
+ if (!d->initialized) {
+ d->currentModes = mode;
+ return;
+ }
+
+ if (!isFlashModeSupported(mode))
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, mode]() {
+ HRESULT hr;
+ if (mode.testFlag(QCameraExposure::FlashAuto)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode auto.");
+ d->currentModes = QCameraExposure::FlashAuto;
+ } else if (mode.testFlag(QCameraExposure::FlashOn)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(false);
+ RETURN_OK_IF_FAILED("Could not disable flash auto mode.");
+ d->currentModes = QCameraExposure::FlashOn;
+ } else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_RedEyeReduction(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode red eye reduction.");
+ d->currentModes = QCameraExposure::FlashRedEyeReduction;
+ } else {
+ hr = d->flashControl->put_Enabled(false);
+ RETURN_OK_IF_FAILED("Could not set flash mode off.");
+ d->currentModes = QCameraExposure::FlashOff;
+ }
+ return S_OK;
+ });
+}
+
+bool QWinRTCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ return d->initialized ? d->supportedModes.contains(mode) : false;
+}
+
+bool QWinRTCameraFlashControl::isFlashReady() const
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ // No native API to query state
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.h b/src/plugins/winrt/qwinrtcameraflashcontrol.h
new file mode 100644
index 000000000..335329037
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 QWINRTCAMERAFLASHCONTROL_H
+#define QWINRTCAMERAFLASHCONTROL_H
+#include <qcameraflashcontrol.h>
+
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Media {
+ namespace Devices {
+ struct IAdvancedVideoCaptureDeviceController2;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraControl;
+class QWinRTCameraFlashControlPrivate;
+class QWinRTCameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraFlashControl(QWinRTCameraControl *parent);
+
+ void initialize(Microsoft::WRL::ComPtr<ABI::Windows::Media::Devices::IAdvancedVideoCaptureDeviceController2> &controller);
+
+ QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE;
+ void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE;
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE;
+
+ bool isFlashReady() const Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWinRTCameraFlashControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraFlashControl)
+};
+
+#endif // QWINRTCAMERAFLASHCONTROL_H
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
index ef637ac37..aeefc9241 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
@@ -79,7 +79,41 @@ QCameraFocus::FocusModes QWinRTCameraFocusControl::focusMode() const
void QWinRTCameraFocusControl::setFocusMode(QCameraFocus::FocusModes modes)
{
- QMetaObject::invokeMethod(this, "applyFocusMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusModes, modes));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusModes == modes)
+ return;
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!modes) {
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
+ return;
+ }
+ if (!d->focusModeInitialized) {
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
+ return;
+ }
+ if (!isFocusModeSupported(modes)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
+ return;
+ }
+ if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
+ if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ } else if (!d->imageCaptureIdle) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
+ return;
+ }
+ }
+ if (!cameraControl->setFocus(modes))
+ return;
+ if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
+ cameraControl->focus();
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
}
bool QWinRTCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes modes) const
@@ -96,7 +130,32 @@ QCameraFocus::FocusPointMode QWinRTCameraFocusControl::focusPointMode() const
void QWinRTCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
- QMetaObject::invokeMethod(this, "applyFocusPointMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusPointMode, mode));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode == mode)
+ return;
+
+ if (!d->focusModeInitialized) {
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
+ return;
+ }
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!d->supportedFocusPointModes.contains(mode)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
+ return;
+ }
+ if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
+ d->focusPoint = QPointF(0.5, 0.5);
+ // Don't apply focus point focus settings if camera is in continuous focus mode
+ if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
+ changeFocusCustomPoint(d->focusPoint);
+ } else if (QCameraFocus::FocusPointCustom == mode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ }
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
}
bool QWinRTCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
@@ -113,7 +172,20 @@ QPointF QWinRTCameraFocusControl::customFocusPoint() const
void QWinRTCameraFocusControl::setCustomFocusPoint(const QPointF &point)
{
- QMetaObject::invokeMethod(this, "applyFocusCustomPoint", Qt::QueuedConnection, Q_ARG(const QPointF, point));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
+ return;
+ }
+ if (d->focusPoint == point)
+ return;
+ if (changeFocusCustomPoint(point)) {
+ d->focusPoint = point;
+ emit customFocusPointChanged(point);
+ }
+
}
QCameraFocusZoneList QWinRTCameraFocusControl::focusZones() const
@@ -176,92 +248,6 @@ void QWinRTCameraFocusControl::imageCaptureQueueChanged(bool isEmpty)
d->imageCaptureIdle = isEmpty;
}
-void QWinRTCameraFocusControl::applyFocusCustomPoint(const QPointF &point)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
- return;
- }
- if (d->focusPoint == point)
- return;
- if (changeFocusCustomPoint(point)) {
- d->focusPoint = point;
- emit customFocusPointChanged(point);
- }
-}
-
-void QWinRTCameraFocusControl::applyFocusMode(QCameraFocus::FocusModes modes)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusModes == modes)
- return;
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!modes) {
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
- return;
- }
- if (!d->focusModeInitialized) {
- d->focusModes = modes;
- emit focusModeChanged(modes);
- return;
- }
- if (!isFocusModeSupported(modes)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
- return;
- }
- if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
- if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- } else if (!d->imageCaptureIdle) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
- return;
- }
- }
- if (!cameraControl->setFocus(modes))
- return;
- if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
- cameraControl->focus();
- d->focusModes = modes;
- emit focusModeChanged(modes);
-}
-
-void QWinRTCameraFocusControl::applyFocusPointMode(QCameraFocus::FocusPointMode mode)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode == mode)
- return;
-
- if (!d->focusModeInitialized) {
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
- return;
- }
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!d->supportedFocusPointModes.contains(mode)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
- return;
- }
- if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
- d->focusPoint = QPointF(0.5, 0.5);
- // Don't apply focus point focus settings if camera is in continuous focus mode
- if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
- changeFocusCustomPoint(d->focusPoint);
- } else if (QCameraFocus::FocusPointCustom == mode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- }
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
-}
-
bool QWinRTCameraFocusControl::changeFocusCustomPoint(const QPointF &point)
{
Q_D(QWinRTCameraFocusControl);
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.h b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
index 6ec2ea67a..0a8c0afcf 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.h
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
@@ -68,9 +68,6 @@ private slots:
void imageCaptureQueueChanged(bool isEmpty);
private:
- Q_INVOKABLE void applyFocusCustomPoint(const QPointF &point);
- Q_INVOKABLE void applyFocusMode(QCameraFocus::FocusModes modes);
- Q_INVOKABLE void applyFocusPointMode(QCameraFocus::FocusPointMode mode);
bool changeFocusCustomPoint(const QPointF &point);
QScopedPointer<QWinRTCameraFocusControlPrivate> d_ptr;
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
index f76edae51..d0327a708 100644
--- a/src/plugins/winrt/qwinrtcameraservice.cpp
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -50,6 +50,7 @@
#include <QtMultimedia/QVideoRendererControl>
#include <QtMultimedia/QVideoDeviceSelectorControl>
#include <QtMultimedia/QImageEncoderControl>
+#include <QtMultimedia/QCameraFlashControl>
#include <QtMultimedia/QCameraFocusControl>
#include <QtMultimedia/QCameraLocksControl>
#include <QtMultimedia/QMediaVideoProbeControl>
@@ -98,6 +99,9 @@ QMediaControl *QWinRTCameraService::requestControl(const char *name)
if (qstrcmp(name, QImageEncoderControl_iid) == 0)
return d->cameraControl->imageEncoderControl();
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return d->cameraControl->cameraFlashControl();
+
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return d->cameraControl->cameraFocusControl();
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index 87e44cce2..940064f46 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -6,6 +6,7 @@ LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11 -lruntimeobject
HEADERS += \
qwinrtabstractvideorenderercontrol.h \
qwinrtcameracontrol.h \
+ qwinrtcameraflashcontrol.h \
qwinrtcamerafocuscontrol.h \
qwinrtcameraimagecapturecontrol.h \
qwinrtcamerainfocontrol.h \
@@ -23,6 +24,7 @@ HEADERS += \
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
qwinrtcameracontrol.cpp \
+ qwinrtcameraflashcontrol.cpp \
qwinrtcamerafocuscontrol.cpp \
qwinrtcameraimagecapturecontrol.cpp \
qwinrtcamerainfocontrol.cpp \