summaryrefslogtreecommitdiffstats
path: root/src/plugins/android/src
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-10-05 14:02:02 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-10-05 14:02:02 +0200
commit51c15a0f0f8ba127b667c4700e4e055c681077d3 (patch)
treecd972bad814f685aba05e6dc6f596603875bd6f8 /src/plugins/android/src
parent704e120042a504cfe5ff76f6f35133f47d067028 (diff)
parent83c49ab485026f35fbd9b5f8242be967a0a24e8b (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Diffstat (limited to 'src/plugins/android/src')
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp47
-rw-r--r--src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h2
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp61
-rw-r--r--src/plugins/android/src/wrappers/jni/androidmediaplayer.h2
4 files changed, 108 insertions, 4 deletions
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
index 9631a6ba7..df1463a87 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
@@ -93,7 +93,9 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
mPendingVolume(-1),
mPendingMute(-1),
mReloadingMedia(false),
- mActiveStateChangeNotifiers(0)
+ mActiveStateChangeNotifiers(0),
+ mPendingPlaybackRate(1.0),
+ mHasPendingPlaybackRate(false)
{
connect(mMediaPlayer,SIGNAL(bufferingChanged(qint32)),
this,SLOT(onBufferingChanged(qint32)));
@@ -290,12 +292,45 @@ void QAndroidMediaPlayerControl::updateAvailablePlaybackRanges()
qreal QAndroidMediaPlayerControl::playbackRate() const
{
- return 1.0f;
+ if (mHasPendingPlaybackRate ||
+ (mState & (AndroidMediaPlayer::Initialized
+ | AndroidMediaPlayer::Prepared
+ | AndroidMediaPlayer::Started
+ | AndroidMediaPlayer::Paused
+ | AndroidMediaPlayer::PlaybackCompleted
+ | AndroidMediaPlayer::Error)) == 0) {
+ return mPendingPlaybackRate;
+ }
+
+ return mMediaPlayer->playbackRate();
}
void QAndroidMediaPlayerControl::setPlaybackRate(qreal rate)
{
- Q_UNUSED(rate);
+ if ((mState & (AndroidMediaPlayer::Initialized
+ | AndroidMediaPlayer::Prepared
+ | AndroidMediaPlayer::Started
+ | AndroidMediaPlayer::Paused
+ | AndroidMediaPlayer::PlaybackCompleted
+ | AndroidMediaPlayer::Error)) == 0) {
+ if (mPendingPlaybackRate != rate) {
+ mPendingPlaybackRate = rate;
+ mHasPendingPlaybackRate = true;
+ Q_EMIT playbackRateChanged(rate);
+ }
+ return;
+ }
+
+ bool succeeded = mMediaPlayer->setPlaybackRate(rate);
+
+ if (mHasPendingPlaybackRate) {
+ mHasPendingPlaybackRate = false;
+ mPendingPlaybackRate = qreal(1.0);
+ if (!succeeded)
+ Q_EMIT playbackRateChanged(playbackRate());
+ } else if (succeeded) {
+ Q_EMIT playbackRateChanged(rate);
+ }
}
QMediaContent QAndroidMediaPlayerControl::media() const
@@ -379,6 +414,9 @@ void QAndroidMediaPlayerControl::play()
setMedia(mMediaContent, mMediaStream);
}
+ if (!mMediaContent.isNull())
+ setState(QMediaPlayer::PlayingState);
+
if ((mState & (AndroidMediaPlayer::Prepared
| AndroidMediaPlayer::Started
| AndroidMediaPlayer::Paused
@@ -387,7 +425,6 @@ void QAndroidMediaPlayerControl::play()
return;
}
- setState(QMediaPlayer::PlayingState);
mMediaPlayer->play();
}
@@ -718,6 +755,8 @@ void QAndroidMediaPlayerControl::flushPendingStates()
setVolume(mPendingVolume);
if (mPendingMute != -1)
setMuted((mPendingMute == 1));
+ if (mHasPendingPlaybackRate)
+ setPlaybackRate(mPendingPlaybackRate);
switch (newState) {
case QMediaPlayer::PlayingState:
diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
index 04f728a59..119add7f8 100644
--- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
+++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h
@@ -117,6 +117,8 @@ private:
int mPendingMute;
bool mReloadingMedia;
int mActiveStateChangeNotifiers;
+ qreal mPendingPlaybackRate;
+ bool mHasPendingPlaybackRate; // we need this because the rate can theoretically be negative
void setState(QMediaPlayer::State state);
void setMediaStatus(QMediaPlayer::MediaStatus status);
diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
index 582d8aa9d..b81f98cbd 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
+++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp
@@ -109,6 +109,33 @@ bool AndroidMediaPlayer::isMuted()
return mMediaPlayer.callMethod<jboolean>("isMuted");
}
+qreal AndroidMediaPlayer::playbackRate()
+{
+ qreal rate(1.0);
+
+ if (QtAndroidPrivate::androidSdkVersion() < 23)
+ return rate;
+
+ QJNIObjectPrivate player = mMediaPlayer.callObjectMethod("getMediaPlayerHandle", "()Landroid/media/MediaPlayer;");
+ if (player.isValid()) {
+ QJNIObjectPrivate playbackParams = player.callObjectMethod("getPlaybackParams", "()Landroid/media/PlaybackParams;");
+ if (playbackParams.isValid()) {
+ const qreal speed = playbackParams.callMethod<jfloat>("getSpeed", "()F");
+ QJNIEnvironmentPrivate env;
+ if (env->ExceptionCheck()) {
+#ifdef QT_DEBUG
+ env->ExceptionDescribe();
+#endif // QT_DEBUG
+ env->ExceptionClear();
+ } else {
+ rate = speed;
+ }
+ }
+ }
+
+ return rate;
+}
+
jobject AndroidMediaPlayer::display()
{
return mMediaPlayer.callObjectMethod("display", "()Landroid/view/SurfaceHolder;").object();
@@ -155,6 +182,40 @@ void AndroidMediaPlayer::setVolume(int volume)
mMediaPlayer.callMethod<void>("setVolume", "(I)V", jint(volume));
}
+bool AndroidMediaPlayer::setPlaybackRate(qreal rate)
+{
+ if (QtAndroidPrivate::androidSdkVersion() < 23) {
+ qWarning("Setting the playback rate on a media player requires Android 6.0 (API level 23) or later");
+ return false;
+ }
+
+ QJNIEnvironmentPrivate env;
+
+ QJNIObjectPrivate player = mMediaPlayer.callObjectMethod("getMediaPlayerHandle", "()Landroid/media/MediaPlayer;");
+ if (player.isValid()) {
+ QJNIObjectPrivate playbackParams = player.callObjectMethod("getPlaybackParams", "()Landroid/media/PlaybackParams;");
+ if (playbackParams.isValid()) {
+ playbackParams.callObjectMethod("setSpeed", "(F)Landroid/media/PlaybackParams;", jfloat(rate));
+ // pitch can only be > 0
+ if (!qFuzzyIsNull(rate))
+ playbackParams.callObjectMethod("setPitch", "(F)Landroid/media/PlaybackParams;", jfloat(qAbs(rate)));
+ player.callMethod<void>("setPlaybackParams", "(Landroid/media/PlaybackParams;)V", playbackParams.object());
+ if (Q_UNLIKELY(env->ExceptionCheck())) {
+#ifdef QT_DEBUG
+ env->ExceptionDescribe();
+#endif // QT_DEBUG
+ env->ExceptionClear();
+ qWarning() << "Invalid playback rate" << rate;
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
void AndroidMediaPlayer::setDisplay(AndroidSurfaceTexture *surfaceTexture)
{
mMediaPlayer.callMethod<void>("setDisplay",
diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.h b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
index 28bfa3662..a7284bb0c 100644
--- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
+++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.h
@@ -103,6 +103,7 @@ public:
bool isPlaying();
int volume();
bool isMuted();
+ qreal playbackRate();
jobject display();
void play();
@@ -113,6 +114,7 @@ public:
void setDataSource(const QString &path);
void prepareAsync();
void setVolume(int volume);
+ bool setPlaybackRate(qreal rate);
void setDisplay(AndroidSurfaceTexture *surfaceTexture);
static bool initJNI(JNIEnv *env);