From 274a683be7a70885ea0c5accc9721d7d940b56f0 Mon Sep 17 00:00:00 2001 From: svd Date: Tue, 26 Oct 2021 10:19:54 +0800 Subject: [PATCH 1/6] =?UTF-8?q?restore=20from=20App=20=E2=80=9Cstop"=20&?= =?UTF-8?q?=20"destroyed",=20get=20data=20from=20player,=20avoid=20progres?= =?UTF-8?q?s=20loss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/AudioPlayerMini.vue | 26 ++++++++++++++++++++++++-- components/app/StreamContainer.vue | 9 +++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/components/AudioPlayerMini.vue b/components/AudioPlayerMini.vue index 55a49541..aaf505f4 100644 --- a/components/AudioPlayerMini.vue +++ b/components/AudioPlayerMini.vue @@ -198,11 +198,33 @@ export default { this.pause() } }, - set(audiobookStreamData) { + async set(audiobookStreamData, stream, fromAppDestroy) { this.isResetting = false this.initObject = { ...audiobookStreamData } + var init = true + if (!!stream) { + console.log(JSON.stringify(stream)) + var data = await MyNativeAudio.getStreamSyncData() + console.log('getStreamSyncData', JSON.stringify(data)) + console.log('lastUpdate', !!stream.lastUpdate ? stream.lastUpdate : 0) + //Same audiobook + if (data.id == stream.id && (data.isPlaying || (data.lastPauseTime >= (!!stream.lastUpdate ? stream.lastUpdate : 0)))) { + console.log('Same audiobook') + this.isPaused = !data.isPlaying + this.currentTime = Number((data.currentTime / 1000).toFixed(2)) + this.timeupdate() + if (data.isPlaying) { + console.log('playing - continue') + if (fromAppDestroy) this.startPlayInterval() + } + else console.log('paused and newer') + if (!fromAppDestroy) return + init = false + this.initObject.startTime = String(Math.floor(this.currentTime * 1000)) + } + } this.currentPlaybackRate = this.initObject.playbackSpeed - MyNativeAudio.initPlayer(this.initObject).then((res) => { + if (init) MyNativeAudio.initPlayer(this.initObject).then((res) => { if (res && res.success) { console.log('Success init audio player') } else { diff --git a/components/app/StreamContainer.vue b/components/app/StreamContainer.vue index 9413e78a..1883ea68 100644 --- a/components/app/StreamContainer.vue +++ b/components/app/StreamContainer.vue @@ -269,7 +269,7 @@ export default { isLocal: true } - this.$refs.audioPlayerMini.set(audiobookStreamData) + this.$refs.audioPlayerMini.set(audiobookStreamData, null, false) }, streamOpen(stream) { if (this.download) { @@ -286,8 +286,6 @@ export default { return } - this.stream = stream - // Update local remove current this.$localStore.setCurrent(null) @@ -298,6 +296,7 @@ export default { if (playOnLoad) this.$store.commit('setPlayOnLoad', false) var audiobookStreamData = { + id: stream.id, title: this.title, author: this.author, playWhenReady: !!playOnLoad, @@ -309,7 +308,9 @@ export default { playlistUrl: this.$server.url + playlistUrl, token: this.$store.getters['user/getToken'] } - this.$refs.audioPlayerMini.set(audiobookStreamData) + this.$refs.audioPlayerMini.set(audiobookStreamData, stream, !this.stream) + + this.stream = stream }, audioPlayerMounted() { console.log('Audio Player Mounted', this.$server.stream) From b9de9cf9b0917efe3dea868fc0e982d1776972d5 Mon Sep 17 00:00:00 2001 From: svd Date: Tue, 26 Oct 2021 10:24:48 +0800 Subject: [PATCH 2/6] native plugin: add getStreamSyncData() --- .../com/audiobookshelf/app/MyNativeAudio.kt | 20 +++++++++++++++++++ .../app/PlayerNotificationService.kt | 18 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt b/android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt index 8cab491c..b1104a4d 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt @@ -85,6 +85,26 @@ class MyNativeAudio : Plugin() { } } + @PluginMethod + fun getStreamSyncData(call: PluginCall) { + Handler(Looper.getMainLooper()).post() { + var isPlaying = playerNotificationService.getPlayStatus() + var lastPauseTime = playerNotificationService.getTheLastPauseTime() + Log.d(tag, "Get Last Pause Time $lastPauseTime") + var currentTime = playerNotificationService.getCurrentTime() + Log.d(tag, "Get Current Time $currentTime") + //if (!isPlaying) currentTime -= playerNotificationService.calcPauseSeekBackTime() + var id = playerNotificationService.getCurrentAudiobookId() + Log.d(tag, "Get Current id $id") + val ret = JSObject() + ret.put("lastPauseTime", lastPauseTime) + ret.put("currentTime", currentTime) + ret.put("isPlaying", isPlaying) + ret.put("id", id) + call.resolve(ret) + } + } + @PluginMethod fun pausePlayer(call: PluginCall) { Handler(Looper.getMainLooper()).post() { diff --git a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt index 22fab7db..20acb6e5 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt @@ -81,6 +81,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { var mediaButtonClickTimeout: Long = 1000 //ms var seekAmount: Long = 20000 //ms + private var lastPauseTime: Long = 0 //ms + fun setCustomObjectListener(mylistener: MyCustomObjectListener) { listener = mylistener } @@ -472,6 +474,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { mPlayer.prepare() mPlayer.playWhenReady = currentAudiobook!!.playWhenReady mPlayer.setPlaybackSpeed(audiobook.playbackSpeed) + + lastPauseTime = 0 } @@ -479,6 +483,18 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { return mPlayer.currentPosition } + fun getTheLastPauseTime() : Long { + return lastPauseTime + } + + fun getPlayStatus() : Boolean { + return mPlayer.isPlaying + } + + fun getCurrentAudiobookId() : String { + return currentAudiobook?.id.toString() + } + fun play() { if (mPlayer.isPlaying) { Log.d(tag, "Already playing") @@ -489,6 +505,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { fun pause() { mPlayer.pause() + lastPauseTime = System.currentTimeMillis() } fun seekPlayer(time: Long) { @@ -511,6 +528,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { if (mPlayer.playbackState == Player.STATE_READY) { mPlayer.clearMediaItems() } + lastPauseTime = 0 } fun sendClientMetadata(stateName: String) { From 02c0a3428e0d4eae5b4a622c9d12a27b062fbea1 Mon Sep 17 00:00:00 2001 From: svd Date: Tue, 26 Oct 2021 10:32:21 +0800 Subject: [PATCH 3/6] native plugin: change setMediaSource() to the api with startPositionMs, avoid call output-0.ts (will cause server retranscoding) --- .../com/audiobookshelf/app/PlayerNotificationService.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt index 20acb6e5..6c6f9251 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt @@ -382,10 +382,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { if (mPlayer.playbackState == Player.STATE_READY) { Log.d(tag, "STATE_READY : " + mPlayer.duration.toString()) - if (!currentAudiobook!!.hasPlayerLoaded && currentAudiobook!!.startTime > 0) { + /*if (!currentAudiobook!!.hasPlayerLoaded && currentAudiobook!!.startTime > 0) { Log.d(tag, "Should seek to ${currentAudiobook!!.startTime}") mPlayer.seekTo(currentAudiobook!!.startTime) - } + }*/ currentAudiobook!!.hasPlayerLoaded = true sendClientMetadata("ready") @@ -470,7 +470,8 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { } - mPlayer.setMediaSource(mediaSource, true) + //mPlayer.setMediaSource(mediaSource, true) + mPlayer.setMediaSource(mediaSource, currentAudiobook!!.startTime) mPlayer.prepare() mPlayer.playWhenReady = currentAudiobook!!.playWhenReady mPlayer.setPlaybackSpeed(audiobook.playbackSpeed) From 4935155078dfd7cfec512abb4635ef4df74295cc Mon Sep 17 00:00:00 2001 From: svd Date: Tue, 26 Oct 2021 10:36:08 +0800 Subject: [PATCH 4/6] add auto seekback --- .../app/PlayerNotificationService.kt | 19 ++++++++++++++++ components/AudioPlayerMini.vue | 22 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt index 6c6f9251..c1fc72f5 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt @@ -488,6 +488,19 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { return lastPauseTime } + fun calcPauseSeekBackTime() : Long { + if (lastPauseTime <= 0) return 0 + var time: Long = System.currentTimeMillis() - lastPauseTime + var seekback: Long = 0 + if (time < 3) seekback = 0 + else if (time < 60000) seekback = time / 6 + else if (time < 300000) seekback = 15000 + else if (time < 1800000) seekback = 20000 + else if (time < 3600000) seekback = 25000 + else seekback = 29500 + return seekback + } + fun getPlayStatus() : Boolean { return mPlayer.isPlaying } @@ -501,6 +514,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { Log.d(tag, "Already playing") return } + if (lastPauseTime > 0) { + var backTime = calcPauseSeekBackTime() + if (backTime >= mPlayer.currentPosition) backTime = mPlayer.currentPosition - 500 + Log.d(tag, "SeekBackTime $backTime") + seekBackward(backTime) + } mPlayer.play() } diff --git a/components/AudioPlayerMini.vue b/components/AudioPlayerMini.vue index aaf505f4..905ae743 100644 --- a/components/AudioPlayerMini.vue +++ b/components/AudioPlayerMini.vue @@ -198,6 +198,17 @@ export default { this.pause() } }, + calcSeekBackTime(lastUpdate) { + var time = Date.now() - lastUpdate + var seekback = 0 + if (time < 3) seekback = 0 + else if (time < 60000) seekback = time / 6 + else if (time < 300000) seekback = 15000 + else if (time < 1800000) seekback = 20000 + else if (time < 3600000) seekback = 25000 + else seekback = 29500 + return seekback + }, async set(audiobookStreamData, stream, fromAppDestroy) { this.isResetting = false this.initObject = { ...audiobookStreamData } @@ -222,6 +233,17 @@ export default { init = false this.initObject.startTime = String(Math.floor(this.currentTime * 1000)) } + //new audiobook stream or sync from other client + else if (stream.clientCurrentTime > 0) { + console.log('new audiobook stream or sync from other client') + if (!!stream.lastUpdate) { + var backTime = this.calcSeekBackTime(stream.lastUpdate) + var currentTime = Math.floor(stream.clientCurrentTime * 1000) + if (backTime >= currentTime) backTime = currentTime - 500 + console.log('SeekBackTime', backTime) + this.initObject.startTime = String(Math.floor(currentTime - backTime)) + } + } } this.currentPlaybackRate = this.initObject.playbackSpeed if (init) MyNativeAudio.initPlayer(this.initObject).then((res) => { From 504393ff2bf32890a453c70df18c3fbccf48ea22 Mon Sep 17 00:00:00 2001 From: svd Date: Tue, 26 Oct 2021 11:10:33 +0800 Subject: [PATCH 5/6] del debug log --- components/AudioPlayerMini.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/AudioPlayerMini.vue b/components/AudioPlayerMini.vue index 2010f3b0..0fe73f24 100644 --- a/components/AudioPlayerMini.vue +++ b/components/AudioPlayerMini.vue @@ -214,9 +214,10 @@ export default { async set(audiobookStreamData, stream, fromAppDestroy) { this.isResetting = false this.initObject = { ...audiobookStreamData } + var init = true if (!!stream) { - console.log(JSON.stringify(stream)) + //console.log(JSON.stringify(stream)) var data = await MyNativeAudio.getStreamSyncData() console.log('getStreamSyncData', JSON.stringify(data)) console.log('lastUpdate', !!stream.lastUpdate ? stream.lastUpdate : 0) @@ -247,6 +248,7 @@ export default { } } } + this.currentPlaybackRate = this.initObject.playbackSpeed if (init) MyNativeAudio.initPlayer(this.initObject).then((res) => { if (res && res.success) { From 2b14460bf16dc64d05a2f10bf4bc7889cc9b0ef7 Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 26 Oct 2021 16:42:11 -0500 Subject: [PATCH 6/6] fix min pause time to 3000 ms --- .../app/PlayerNotificationService.kt | 2 +- components/AudioPlayerMini.vue | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt index c1fc72f5..6c15b91b 100644 --- a/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt +++ b/android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt @@ -492,7 +492,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() { if (lastPauseTime <= 0) return 0 var time: Long = System.currentTimeMillis() - lastPauseTime var seekback: Long = 0 - if (time < 3) seekback = 0 + if (time < 3000) seekback = 0 else if (time < 60000) seekback = time / 6 else if (time < 300000) seekback = 15000 else if (time < 1800000) seekback = 20000 diff --git a/components/AudioPlayerMini.vue b/components/AudioPlayerMini.vue index 0fe73f24..7661c3e6 100644 --- a/components/AudioPlayerMini.vue +++ b/components/AudioPlayerMini.vue @@ -203,7 +203,7 @@ export default { calcSeekBackTime(lastUpdate) { var time = Date.now() - lastUpdate var seekback = 0 - if (time < 3) seekback = 0 + if (time < 3000) seekback = 0 else if (time < 60000) seekback = time / 6 else if (time < 300000) seekback = 15000 else if (time < 1800000) seekback = 20000 @@ -214,15 +214,15 @@ export default { async set(audiobookStreamData, stream, fromAppDestroy) { this.isResetting = false this.initObject = { ...audiobookStreamData } - + var init = true if (!!stream) { //console.log(JSON.stringify(stream)) var data = await MyNativeAudio.getStreamSyncData() console.log('getStreamSyncData', JSON.stringify(data)) - console.log('lastUpdate', !!stream.lastUpdate ? stream.lastUpdate : 0) + console.log('lastUpdate', stream.lastUpdate || 0) //Same audiobook - if (data.id == stream.id && (data.isPlaying || (data.lastPauseTime >= (!!stream.lastUpdate ? stream.lastUpdate : 0)))) { + if (data.id == stream.id && (data.isPlaying || data.lastPauseTime >= (stream.lastUpdate || 0))) { console.log('Same audiobook') this.isPaused = !data.isPlaying this.currentTime = Number((data.currentTime / 1000).toFixed(2)) @@ -230,8 +230,7 @@ export default { if (data.isPlaying) { console.log('playing - continue') if (fromAppDestroy) this.startPlayInterval() - } - else console.log('paused and newer') + } else console.log('paused and newer') if (!fromAppDestroy) return init = false this.initObject.startTime = String(Math.floor(this.currentTime * 1000)) @@ -250,13 +249,14 @@ export default { } this.currentPlaybackRate = this.initObject.playbackSpeed - if (init) MyNativeAudio.initPlayer(this.initObject).then((res) => { - if (res && res.success) { - console.log('Success init audio player') - } else { - console.error('Failed to init audio player') - } - }) + if (init) + MyNativeAudio.initPlayer(this.initObject).then((res) => { + if (res && res.success) { + console.log('Success init audio player') + } else { + console.error('Failed to init audio player') + } + }) if (audiobookStreamData.isLocal) { this.setStreamReady()