Fix:Android check local media progress after a pause reverting to previous progress #290

This commit is contained in:
advplyr 2022-07-21 17:54:00 -05:00
parent 1f60a552e5
commit 2a87f1de28
4 changed files with 91 additions and 24 deletions

View file

@ -46,7 +46,10 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
} else {
return
}
} else if (playerNotificationService.getCurrentPlaybackSessionId() != currentSessionId) {
currentLocalMediaProgress = null
}
listeningTimerRunning = true
lastSyncTime = System.currentTimeMillis()
currentPlaybackSession = playerNotificationService.getCurrentPlaybackSessionCopy()
@ -63,13 +66,30 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
}
}
fun stop() {
fun stop(cb: () -> Unit) {
if (!listeningTimerRunning) return
Log.d(tag, "stop: Stopping listening for $currentDisplayTitle")
val currentTime = playerNotificationService.getCurrentTimeSeconds()
sync(currentTime) {
reset()
cb()
}
}
fun pause(cb: () -> Unit) {
if (!listeningTimerRunning) return
Log.d(tag, "pause: Pausing progress syncer for $currentDisplayTitle")
val currentTime = playerNotificationService.getCurrentTimeSeconds()
sync(currentTime) {
listeningTimerTask?.cancel()
listeningTimerTask = null
listeningTimerRunning = false
lastSyncTime = 0L
failedSyncs = 0
cb()
}
}
@ -77,7 +97,6 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
currentPlaybackSession?.let {
it.updatedAt = mediaProgress.lastUpdate
it.currentTime = mediaProgress.currentTime
DeviceManager.dbManager.saveLocalPlaybackSession(it)
saveLocalProgress(it)
}

View file

@ -71,32 +71,36 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
if (player.isPlaying) {
Log.d(tag, "SeekBackTime: Player is playing")
if (lastPauseTime > 0 && DeviceManager.deviceData.deviceSettings?.disableAutoRewind != true) {
var seekBackTime = 0L
if (onSeekBack) onSeekBack = false
else {
Log.d(tag, "SeekBackTime: playing started now set seek back time $lastPauseTime")
var backTime = calcPauseSeekBackTime()
if (backTime > 0) {
seekBackTime = calcPauseSeekBackTime()
if (seekBackTime > 0) {
// Current chapter is used so that seek back does not go back to the previous chapter
val currentChapter = playerNotificationService.getCurrentBookChapter()
val minSeekBackTime = currentChapter?.startMs ?: 0
val currentTime = playerNotificationService.getCurrentTime()
val newTime = currentTime - backTime
val newTime = currentTime - seekBackTime
if (newTime < minSeekBackTime) {
backTime = currentTime - minSeekBackTime
seekBackTime = currentTime - minSeekBackTime
}
Log.d(tag, "SeekBackTime $backTime")
Log.d(tag, "SeekBackTime $seekBackTime")
onSeekBack = true
playerNotificationService.seekBackward(backTime)
}
}
// Check if playback session still exists or sync media progress if updated
val pauseLength: Long = System.currentTimeMillis() - lastPauseTime
if (pauseLength > PAUSE_LEN_BEFORE_RECHECK) {
val shouldCarryOn = playerNotificationService.checkCurrentSessionProgress()
val shouldCarryOn = playerNotificationService.checkCurrentSessionProgress(seekBackTime)
if (!shouldCarryOn) return
}
if (seekBackTime > 0L) {
playerNotificationService.seekBackward(seekBackTime)
}
}
} else {
Log.d(tag, "SeekBackTime: Player not playing set last pause time")
@ -104,12 +108,13 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
}
// Start/stop progress sync interval
Log.d(tag, "Playing ${playerNotificationService.getCurrentBookTitle()}")
if (player.isPlaying) {
player.volume = 1F // Volume on sleep timer might have decreased this
playerNotificationService.mediaProgressSyncer.start()
} else {
playerNotificationService.mediaProgressSyncer.stop()
playerNotificationService.mediaProgressSyncer.pause {
Log.d(tag, "Media Progress Syncer paused and synced")
}
}
playerNotificationService.clientEventEmitter?.onPlayingUpdate(player.isPlaying)

View file

@ -550,10 +550,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
// Called from PlayerListener play event
// check with server if progress has updated since last play and sync progress update
fun checkCurrentSessionProgress():Boolean {
fun checkCurrentSessionProgress(seekBackTime:Long):Boolean {
if (currentPlaybackSession == null) return true
currentPlaybackSession?.let { playbackSession ->
mediaProgressSyncer.currentPlaybackSession?.let { playbackSession ->
if (!apiHandler.isOnline() || playbackSession.isLocalLibraryItemOnly) {
return true // carry on
}
@ -575,16 +575,28 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
Log.d(tag, "checkCurrentSessionProgress: Media progress was updated since last play time updating from ${playbackSession.currentTime} to ${mediaProgress.currentTime}")
mediaProgressSyncer.syncFromServerProgress(mediaProgress)
// Update current playback session stored in PNS since MediaProgressSyncer version is a copy
mediaProgressSyncer.currentPlaybackSession?.let { updatedPlaybackSession ->
currentPlaybackSession = updatedPlaybackSession
}
Handler(Looper.getMainLooper()).post {
seekPlayer(playbackSession.currentTimeMs)
// Should already be playing
currentPlayer.volume = 1F // Volume on sleep timer might have decreased this
mediaProgressSyncer.start()
clientEventEmitter?.onPlayingUpdate(true)
}
} else {
Handler(Looper.getMainLooper()).post {
if (seekBackTime > 0L) {
seekBackward(seekBackTime)
}
// Should already be playing
currentPlayer.volume = 1F // Volume on sleep timer might have decreased this
mediaProgressSyncer.start()
clientEventEmitter?.onPlayingUpdate(true)
}
}
Handler(Looper.getMainLooper()).post {
// Should already be playing
currentPlayer.volume = 1F // Volume on sleep timer might have decreased this
mediaProgressSyncer.start()
clientEventEmitter?.onPlayingUpdate(true)
}
}
} else {
@ -607,6 +619,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
} else {
Log.d(tag, "checkCurrentSessionProgress: Playback session still available on server")
Handler(Looper.getMainLooper()).post {
if (seekBackTime > 0L) {
seekBackward(seekBackTime)
}
currentPlayer.volume = 1F // Volume on sleep timer might have decreased this
mediaProgressSyncer.start()
clientEventEmitter?.onPlayingUpdate(true)
@ -673,7 +689,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
Log.d(tag, "closePlayback")
if (mediaProgressSyncer.listeningTimerRunning) {
Log.i(tag, "About to close playback so stopping media progress syncer first")
mediaProgressSyncer.stop()
mediaProgressSyncer.stop {
Log.d(tag, "Media Progress syncer stopped and synced")
}
}
try {

View file

@ -177,7 +177,21 @@ class AbsAudioPlayer : Plugin() {
Handler(Looper.getMainLooper()).post {
Log.d(tag, "prepareLibraryItem: Preparing Local Media item ${jacksonMapper.writeValueAsString(it)}")
val playbackSession = it.getPlaybackSession(episode)
playerNotificationService.preparePlayer(playbackSession, playWhenReady, playbackRate)
if (playerNotificationService.mediaProgressSyncer.listeningTimerRunning) { // If progress syncing then first stop before preparing next
playerNotificationService.mediaProgressSyncer.stop {
Log.d(tag, "Media progress syncer was already syncing - stopped")
Handler(Looper.getMainLooper()).post { // TODO: This was needed again which is probably a design a flaw
playerNotificationService.preparePlayer(
playbackSession,
playWhenReady,
playbackRate
)
}
}
} else {
playerNotificationService.preparePlayer(playbackSession, playWhenReady, playbackRate)
}
}
return call.resolve(JSObject())
}
@ -188,9 +202,20 @@ class AbsAudioPlayer : Plugin() {
if (it == null) {
call.resolve(JSObject("{\"error\":\"Server play request failed\"}"))
} else {
Handler(Looper.getMainLooper()).post {
Log.d(tag, "Preparing Player TEST ${jacksonMapper.writeValueAsString(it)}")
playerNotificationService.preparePlayer(it, playWhenReady, playbackRate)
Log.d(tag, "Preparing Player playback session ${jacksonMapper.writeValueAsString(it)}")
if (playerNotificationService.mediaProgressSyncer.listeningTimerRunning) { // If progress syncing then first stop before preparing next
playerNotificationService.mediaProgressSyncer.stop {
Log.d(tag, "Media progress syncer was already syncing - stopped")
Handler(Looper.getMainLooper()).post { // TODO: This was needed again which is probably a design a flaw
playerNotificationService.preparePlayer(it, playWhenReady, playbackRate)
}
}
} else {
playerNotificationService.preparePlayer(it, playWhenReady, playbackRate)
}
}
call.resolve(JSObject(jacksonMapper.writeValueAsString(it)))