diff options
author | Liang Qi <liang.qi@qt.io> | 2016-10-12 06:29:43 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-10-12 06:30:01 +0200 |
commit | 030e19816a8933a8c6c0a4d8193251446d4ee514 (patch) | |
tree | 827cfc97a1a8f0f660238e2a3b5472669f0f2077 | |
parent | 1c6c85cd7c619cc15c099ae63a5d22bcf661847c (diff) | |
parent | c7433f84288a33d6a5ea411dabf1618afcacfaf1 (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Change-Id: I126bc73db5b5d9b6c26cb9ff5da7ed13a16b378b
-rw-r--r-- | src/imports/multimedia/qdeclarativeplaylist.cpp | 2 | ||||
-rw-r--r-- | src/multimedia/audio/qaudioinput.cpp | 3 | ||||
-rw-r--r-- | src/multimedia/audio/qaudiooutput.cpp | 3 | ||||
-rw-r--r-- | src/multimedia/audio/qsoundeffect.cpp | 6 | ||||
-rw-r--r-- | src/multimedia/controls/qmediarecordercontrol.cpp | 2 | ||||
-rw-r--r-- | src/multimedia/playback/qmedianetworkplaylistprovider.cpp | 2 | ||||
-rw-r--r-- | src/multimedia/playback/qmediaplayer.cpp | 4 | ||||
-rw-r--r-- | src/multimedia/recording/qmediarecorder.cpp | 4 | ||||
-rw-r--r-- | src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.h | 2 | ||||
-rw-r--r-- | src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.mm | 110 | ||||
-rw-r--r-- | src/plugins/winrt/qwinrtcameracontrol.cpp | 98 | ||||
-rw-r--r-- | tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp | 12 | ||||
-rw-r--r-- | tests/auto/integration/qsoundeffect/BLACKLIST | 4 |
13 files changed, 141 insertions, 111 deletions
diff --git a/src/imports/multimedia/qdeclarativeplaylist.cpp b/src/imports/multimedia/qdeclarativeplaylist.cpp index e8df8c376..549e0702d 100644 --- a/src/imports/multimedia/qdeclarativeplaylist.cpp +++ b/src/imports/multimedia/qdeclarativeplaylist.cpp @@ -510,7 +510,7 @@ bool QDeclarativePlaylist::removeItem(int index) /*! \qmlmethod bool QtMultimedia::Playlist::removeItems(int start, int end) - Removes items in the playlist from \a start to \end inclusive. + Removes items in the playlist from \a start to \a end inclusive. Returns true if the items are removed successfully. diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index ad54521fa..872dce819 100644 --- a/src/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/audio/qaudioinput.cpp @@ -343,7 +343,8 @@ int QAudioInput::notifyInterval() const */ void QAudioInput::setVolume(qreal volume) { - d->setVolume(volume); + qreal v = qBound(qreal(0.0), volume, qreal(1.0)); + d->setVolume(v); } /*! diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index 670dca7bc..e37da9bdf 100644 --- a/src/multimedia/audio/qaudiooutput.cpp +++ b/src/multimedia/audio/qaudiooutput.cpp @@ -364,7 +364,8 @@ QAudio::State QAudioOutput::state() const */ void QAudioOutput::setVolume(qreal volume) { - d->setVolume(volume); + qreal v = qBound(qreal(0.0), volume, qreal(1.0)); + d->setVolume(v); } /*! diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp index d3b818073..f8b8d7b18 100644 --- a/src/multimedia/audio/qsoundeffect.cpp +++ b/src/multimedia/audio/qsoundeffect.cpp @@ -298,11 +298,7 @@ qreal QSoundEffect::volume() const */ void QSoundEffect::setVolume(qreal volume) { - if (volume < qreal(0.0) || volume > qreal(1.0)) { - qWarning("SoundEffect: volume should be between 0.0 and 1.0"); - return; - } - + volume = qBound(qreal(0.0), volume, qreal(1.0)); if (qFuzzyCompare(d->volume(), volume)) return; diff --git a/src/multimedia/controls/qmediarecordercontrol.cpp b/src/multimedia/controls/qmediarecordercontrol.cpp index 611f1fdcc..e4667d369 100644 --- a/src/multimedia/controls/qmediarecordercontrol.cpp +++ b/src/multimedia/controls/qmediarecordercontrol.cpp @@ -164,7 +164,7 @@ QMediaRecorderControl::~QMediaRecorderControl() */ /*! - \fn void QMediaRecorderControl::setVolume(qreal gain) + \fn void QMediaRecorderControl::setVolume(qreal volume) Sets the audio \a volume of a media recorder control. diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp index 67ce123d8..7de90d9a1 100644 --- a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp +++ b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp @@ -74,7 +74,7 @@ void QMediaNetworkPlaylistProviderPrivate::_q_handleParserError(QPlaylistFilePar QMediaPlaylist::Error playlistError = QMediaPlaylist::NoError; - switch ((QPlaylistFileParser::ParserError)err) { + switch (err) { case QPlaylistFileParser::NoError: return; case QPlaylistFileParser::FormatError: diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 648c13220..191095e82 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -962,8 +962,8 @@ void QMediaPlayer::setPlaybackRate(qreal rate) Sets the current \a media source. If a \a stream is supplied; media data will be read from it instead of resolving the media - source. In this case the media source may still be used to resolve additional information - about the media such as mime type. + source. In this case the media source may still be used to resolve additional information + about the media such as mime type. The \a stream must be open and readable. Setting the media to a null QMediaContent will cause the player to discard all information relating to the current media source and to cease all I/O operations related diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index 7b0234988..d3962b78f 100644 --- a/src/multimedia/recording/qmediarecorder.cpp +++ b/src/multimedia/recording/qmediarecorder.cpp @@ -578,8 +578,10 @@ void QMediaRecorder::setVolume(qreal volume) { Q_D(QMediaRecorder); - if (d->control) + if (d->control) { + volume = qMax(qreal(0.0), volume); d->control->setVolume(volume); + } } /*! diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.h index 6721b0c85..396550047 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.h @@ -64,7 +64,7 @@ private Q_SLOTS: private: AVFMediaPlayerSession *m_session; - QMap<QString, QVariant> m_tags; + QVariantMap m_tags; void *m_asset; }; diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.mm index 2414ff361..39783680b 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayermetadatacontrol.mm @@ -81,6 +81,41 @@ QStringList AVFMediaPlayerMetaDataControl::availableMetaData() const return m_tags.keys(); } +static QString itemKey(AVMetadataItem *item) +{ + NSString *keyString = [item commonKey]; + + if (keyString.length != 0) { + if ([keyString isEqualToString:AVMetadataCommonKeyTitle]) { + return QMediaMetaData::Title; + } else if ([keyString isEqualToString: AVMetadataCommonKeySubject]) { + return QMediaMetaData::SubTitle; + } else if ([keyString isEqualToString: AVMetadataCommonKeyDescription]) { + return QMediaMetaData::Description; + } else if ([keyString isEqualToString: AVMetadataCommonKeyPublisher]) { + return QMediaMetaData::Publisher; + } else if ([keyString isEqualToString: AVMetadataCommonKeyCreationDate]) { + return QMediaMetaData::Date; + } else if ([keyString isEqualToString: AVMetadataCommonKeyType]) { + return QMediaMetaData::MediaType; + } else if ([keyString isEqualToString: AVMetadataCommonKeyLanguage]) { + return QMediaMetaData::Language; + } else if ([keyString isEqualToString: AVMetadataCommonKeyCopyrights]) { + return QMediaMetaData::Copyright; + } else if ([keyString isEqualToString: AVMetadataCommonKeyAlbumName]) { + return QMediaMetaData::AlbumTitle; + } else if ([keyString isEqualToString: AVMetadataCommonKeyAuthor]) { + return QMediaMetaData::Author; + } else if ([keyString isEqualToString: AVMetadataCommonKeyArtist]) { + return QMediaMetaData::ContributingArtist; + } else if ([keyString isEqualToString: AVMetadataCommonKeyArtwork]) { + return QMediaMetaData::PosterUrl; + } + } + + return QString(); +} + void AVFMediaPlayerMetaDataControl::updateTags() { #ifdef QT_DEBUG_AVF @@ -89,67 +124,38 @@ void AVFMediaPlayerMetaDataControl::updateTags() AVAsset *currentAsset = (AVAsset*)m_session->currentAssetHandle(); //Don't read the tags from the same asset more than once - if (currentAsset == m_asset) { + if (currentAsset == m_asset) return; - } m_asset = currentAsset; + QVariantMap oldTags = m_tags; //Since we've changed assets, clear old tags m_tags.clear(); - - NSArray *metadataFormats = [currentAsset availableMetadataFormats]; - for ( NSString *format in metadataFormats) { -#ifdef QT_DEBUG_AVF - qDebug() << "format: " << [format UTF8String]; -#endif - NSArray *metadataItems = [currentAsset metadataForFormat:format]; - for (AVMetadataItem* item in metadataItems) { - NSString *keyString = [item commonKey]; - NSString *value = [item stringValue]; - - if (keyString.length != 0) { - //Process "commonMetadata" tags here: - if ([keyString isEqualToString:AVMetadataCommonKeyTitle]) { - m_tags.insert(QMediaMetaData::Title, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyCreator]) { - m_tags.insert(QMediaMetaData::Author, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeySubject]) { - m_tags.insert(QMediaMetaData::SubTitle, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyDescription]) { - m_tags.insert(QMediaMetaData::Description, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyPublisher]) { - m_tags.insert(QMediaMetaData::Publisher, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyContributor]) { - m_tags.insert(QMediaMetaData::ContributingArtist, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyCreationDate]) { - m_tags.insert(QMediaMetaData::Date, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyType]) { - m_tags.insert(QMediaMetaData::MediaType, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyLanguage]) { - m_tags.insert(QMediaMetaData::Language, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyCopyrights]) { - m_tags.insert(QMediaMetaData::Copyright, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyAlbumName]) { - m_tags.insert(QMediaMetaData::AlbumTitle, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyAuthor]) { - m_tags.insert(QMediaMetaData::Author, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyArtist]) { - m_tags.insert(QMediaMetaData::AlbumArtist, QString([value UTF8String])); - } else if ([keyString isEqualToString: AVMetadataCommonKeyArtwork]) { - m_tags.insert(QMediaMetaData::PosterUrl, QString([value UTF8String])); + bool changed = false; + + // TODO: also process ID3, iTunes and QuickTime metadata + + NSArray *metadataItems = [currentAsset commonMetadata]; + for (AVMetadataItem* item in metadataItems) { + const QString key = itemKey(item); + if (!key.isEmpty()) { + const QString value = QString::fromNSString([item stringValue]); + if (!value.isNull()) { + m_tags.insert(key, value); + if (value != oldTags.value(key)) { + changed = true; + Q_EMIT metaDataChanged(key, value); } } - - if ([format isEqualToString:AVMetadataFormatID3Metadata]) { - //TODO: Process ID3 metadata - } else if ([format isEqualToString:AVMetadataFormatiTunesMetadata]) { - //TODO: Process iTunes metadata - } else if ([format isEqualToString:AVMetadataFormatQuickTimeUserData]) { - //TODO: Process QuickTime metadata - } } } - Q_EMIT metaDataChanged(); + if (oldTags.isEmpty() != m_tags.isEmpty()) { + Q_EMIT metaDataAvailableChanged(!m_tags.isEmpty()); + changed = true; + } + + if (changed) + Q_EMIT metaDataChanged(); } diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp index f81a2e94d..a28d57219 100644 --- a/src/plugins/winrt/qwinrtcameracontrol.cpp +++ b/src/plugins/winrt/qwinrtcameracontrol.cpp @@ -884,7 +884,8 @@ HRESULT QWinRTCameraControl::initialize() emit statusChanged(d->status); } - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + boolean isFocusSupported; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, &isFocusSupported]() { HRESULT hr; ComPtr<IInspectable> capture; hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_Media_Capture_MediaCapture).Get(), @@ -951,7 +952,6 @@ HRESULT QWinRTCameraControl::initialize() d->cameraFlashControl->initialize(advancedVideoDeviceController); - boolean isFocusSupported; hr = d->focusControl->get_Supported(&isFocusSupported); Q_ASSERT_SUCCEEDED(hr); if (isFocusSupported) { @@ -960,11 +960,7 @@ HRESULT QWinRTCameraControl::initialize() qCDebug(lcMMCamera) << "Focus supported, but no control for regions of interest available"; hr = initializeFocus(); Q_ASSERT_SUCCEEDED(hr); - } else { - d->cameraFocusControl->setSupportedFocusMode(0); - d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>()); } - d->cameraLocksControl->initialize(); Q_ASSERT_SUCCEEDED(hr); ComPtr<IMediaDeviceController> deviceController; @@ -1040,6 +1036,12 @@ HRESULT QWinRTCameraControl::initialize() return S_OK; }); + if (!isFocusSupported) { + d->cameraFocusControl->setSupportedFocusMode(0); + d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>()); + } + d->cameraLocksControl->initialize(); + if (SUCCEEDED(hr) && d->state != QCamera::LoadedState) { d->state = QCamera::LoadedState; emit stateChanged(d->state); @@ -1239,30 +1241,34 @@ bool QWinRTCameraControl::focus() { Q_D(QWinRTCameraControl); HRESULT hr; - AsyncStatus status = AsyncStatus::Completed; - if (d->focusOperation) { - ComPtr<IAsyncInfo> info; - hr = d->focusOperation.As(&info); - Q_ASSERT_SUCCEEDED(hr); - info->get_Status(&status); - } - - if (!d->focusControl || status == AsyncStatus::Started) + if (!d->focusControl) return false; QEventDispatcherWinRT::runOnXamlThread([&d, &hr]() { + if (d->focusOperation) { + ComPtr<IAsyncInfo> info; + hr = d->focusOperation.As(&info); + Q_ASSERT_SUCCEEDED(hr); + + AsyncStatus status = AsyncStatus::Completed; + hr = info->get_Status(&status); + Q_ASSERT_SUCCEEDED(hr); + if (status == AsyncStatus::Started) + return E_ASYNC_OPERATION_NOT_STARTED; + } + hr = d->focusControl->FocusAsync(&d->focusOperation); Q_ASSERT_SUCCEEDED(hr); + + const long errorCode = HRESULT_CODE(hr); + if (errorCode == ERROR_OPERATION_IN_PROGRESS + || errorCode == ERROR_WRITE_PROTECT) { + return E_ASYNC_OPERATION_NOT_STARTED; + } + Q_ASSERT_SUCCEEDED(hr); return S_OK; }); - const long errorCode = HRESULT_CODE(hr); - if (errorCode == ERROR_OPERATION_IN_PROGRESS - || errorCode == ERROR_WRITE_PROTECT) { - return false; - } - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(d->focusOperation, QWinRTFunctions::ProcessThreadEvents); - Q_ASSERT_SUCCEEDED(hr); + return hr == S_OK; } @@ -1283,15 +1289,22 @@ bool QWinRTCameraControl::lockFocus() Q_D(QWinRTCameraControl); if (!d->focusControl) return false; - ComPtr<IFocusControl2> focusControl2; - HRESULT hr = d->focusControl.As(&focusControl2); - Q_ASSERT_SUCCEEDED(hr); + + bool result = false; ComPtr<IAsyncAction> op; - hr = focusControl2->LockAsync(&op); - if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) - return false; - Q_ASSERT_SUCCEEDED(hr); - return QWinRTFunctions::await(op) == S_OK; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() { + ComPtr<IFocusControl2> focusControl2; + HRESULT hr = d->focusControl.As(&focusControl2); + Q_ASSERT_SUCCEEDED(hr); + hr = focusControl2->LockAsync(&op); + if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) + return S_OK; + Q_ASSERT_SUCCEEDED(hr); + result = true; + return hr; + }); + return result ? (QWinRTFunctions::await(op) == S_OK) : false; } bool QWinRTCameraControl::unlockFocus() @@ -1299,15 +1312,22 @@ bool QWinRTCameraControl::unlockFocus() Q_D(QWinRTCameraControl); if (!d->focusControl) return false; - ComPtr<IFocusControl2> focusControl2; - HRESULT hr = d->focusControl.As(&focusControl2); - Q_ASSERT_SUCCEEDED(hr); + + bool result = false; ComPtr<IAsyncAction> op; - hr = focusControl2->UnlockAsync(&op); - if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) - return false; - Q_ASSERT_SUCCEEDED(hr); - return QWinRTFunctions::await(op) == S_OK; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() { + ComPtr<IFocusControl2> focusControl2; + HRESULT hr = d->focusControl.As(&focusControl2); + Q_ASSERT_SUCCEEDED(hr); + hr = focusControl2->UnlockAsync(&op); + if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) + return S_OK; + Q_ASSERT_SUCCEEDED(hr); + result = true; + return hr; + }); + return result ? (QWinRTFunctions::await(op) == S_OK) : false; } #else // !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) diff --git a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp index ca1f2b67e..f167bf8ec 100644 --- a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp +++ b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp @@ -525,8 +525,8 @@ void tst_QAudioOutput::pull() // Wait until playback finishes QTRY_VERIFY2(audioFile->atEnd(), "didn't play to EOF"); - QTRY_VERIFY2((stateSignal.count() == 1), - QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QTRY_VERIFY(stateSignal.count() > 0); + QCOMPARE(qvariant_cast<QAudio::State>(stateSignal.last().at(0)), QAudio::IdleState); QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); stateSignal.clear(); @@ -702,8 +702,8 @@ void tst_QAudioOutput::push() QTest::qWait(3000); // 3 seconds should be plenty QVERIFY2(audioFile->atEnd(), "didn't play to EOF"); - QVERIFY2((stateSignal.count() == 1), - QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY(stateSignal.count() > 0); + QCOMPARE(qvariant_cast<QAudio::State>(stateSignal.last().at(0)), QAudio::IdleState); QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); stateSignal.clear(); @@ -837,8 +837,8 @@ void tst_QAudioOutput::pushSuspendResume() QTest::qWait(1000); // 1 seconds should be plenty QVERIFY2(audioFile->atEnd(), "didn't play to EOF"); - QVERIFY2((stateSignal.count() == 1), - QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY(stateSignal.count() > 0); + QCOMPARE(qvariant_cast<QAudio::State>(stateSignal.last().at(0)), QAudio::IdleState); QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); stateSignal.clear(); diff --git a/tests/auto/integration/qsoundeffect/BLACKLIST b/tests/auto/integration/qsoundeffect/BLACKLIST index 692a9afd3..0f872a576 100644 --- a/tests/auto/integration/qsoundeffect/BLACKLIST +++ b/tests/auto/integration/qsoundeffect/BLACKLIST @@ -1,2 +1,6 @@ [testSetSourceWhileLoading] linux + +#QTBUG-55735 +[testSetSourceWhilePlaying] +linux |