Updates to audio player plugin to method naming and using seconds for time values. Adding web audio player to run in browser.

This commit is contained in:
advplyr 2022-04-11 18:38:01 -05:00
parent c94e57f55e
commit 6e8d84496b
10 changed files with 367 additions and 119 deletions

View file

@ -0,0 +1,11 @@
package com.audiobookshelf.app.data
enum class PlayerState {
IDLE, BUFFERING, READY, ENDED
}
data class PlaybackMetadata(
val duration:Double,
val currentTime:Double,
val playerState:PlayerState
)

View file

@ -141,7 +141,7 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
playerNotificationService.seekBackward(seekAmount)
}
KeyEvent.KEYCODE_MEDIA_STOP -> {
playerNotificationService.terminateStream()
playerNotificationService.closePlayback()
}
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
if (playerNotificationService.mPlayer.isPlaying) {

View file

@ -1,6 +1,7 @@
package com.audiobookshelf.app.player
import android.util.Log
import com.audiobookshelf.app.data.PlayerState
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
@ -32,22 +33,21 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
Log.d(tag, "STATE_READY : " + playerNotificationService.mPlayer.duration.toString())
if (lastPauseTime == 0L) {
playerNotificationService.sendClientMetadata("ready_no_sync")
lastPauseTime = -1;
} else playerNotificationService.sendClientMetadata("ready")
}
playerNotificationService.sendClientMetadata(PlayerState.READY)
}
if (playerNotificationService.currentPlayer.playbackState == Player.STATE_BUFFERING) {
Log.d(tag, "STATE_BUFFERING : " + playerNotificationService.mPlayer.currentPosition.toString())
if (lastPauseTime == 0L) playerNotificationService.sendClientMetadata("buffering_no_sync")
else playerNotificationService.sendClientMetadata("buffering")
playerNotificationService.sendClientMetadata(PlayerState.BUFFERING)
}
if (playerNotificationService.currentPlayer.playbackState == Player.STATE_ENDED) {
Log.d(tag, "STATE_ENDED")
playerNotificationService.sendClientMetadata("ended")
playerNotificationService.sendClientMetadata(PlayerState.ENDED)
}
if (playerNotificationService.currentPlayer.playbackState == Player.STATE_IDLE) {
Log.d(tag, "STATE_IDLE")
playerNotificationService.sendClientMetadata("idle")
playerNotificationService.sendClientMetadata(PlayerState.IDLE)
}
}

View file

@ -18,9 +18,7 @@ import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.media.MediaBrowserServiceCompat
import androidx.media.utils.MediaConstants
import com.audiobookshelf.app.data.LibraryItem
import com.audiobookshelf.app.data.LocalMediaProgress
import com.audiobookshelf.app.data.PlaybackSession
import com.audiobookshelf.app.data.*
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.media.MediaManager
import com.audiobookshelf.app.server.ApiHandler
@ -52,7 +50,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
fun onPlaybackSession(playbackSession:PlaybackSession)
fun onPlaybackClosed()
fun onPlayingUpdate(isPlaying: Boolean)
fun onMetadata(metadata: JSObject)
fun onMetadata(metadata: PlaybackMetadata)
fun onPrepare(audiobookId: String, playWhenReady: Boolean)
fun onSleepTimerEnded(currentPosition: Long)
fun onSleepTimerSet(sleepTimeRemaining: Int)
@ -375,6 +373,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
}
fun getBufferedTimeSeconds() : Double {
return getBufferedTime() / 1000.0
}
fun getDuration() : Long {
return currentPlayer.duration
}
@ -441,20 +443,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
currentPlayer.setPlaybackSpeed(speed)
}
fun terminateStream() {
fun closePlayback() {
currentPlayer.clearMediaItems()
currentPlaybackSession = null
clientEventEmitter?.onPlaybackClosed()
PlayerListener.lastPauseTime = 0
}
fun sendClientMetadata(stateName: String) {
var metadata = JSObject()
var duration = currentPlaybackSession?.getTotalDuration() ?: 0
metadata.put("duration", duration)
metadata.put("currentTime", getCurrentTime())
metadata.put("stateName", stateName)
clientEventEmitter?.onMetadata(metadata)
fun sendClientMetadata(playerState: PlayerState) {
var duration = currentPlaybackSession?.getTotalDuration() ?: 0.0
clientEventEmitter?.onMetadata(PlaybackMetadata(duration, getCurrentTimeSeconds(), playerState))
}
//

View file

@ -7,6 +7,7 @@ import android.util.Log
import androidx.core.content.ContextCompat
import com.audiobookshelf.app.MainActivity
import com.audiobookshelf.app.data.LocalMediaProgress
import com.audiobookshelf.app.data.PlaybackMetadata
import com.audiobookshelf.app.data.PlaybackSession
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.player.CastManager
@ -46,8 +47,8 @@ class AbsAudioPlayer : Plugin() {
emit("onPlayingUpdate", isPlaying)
}
override fun onMetadata(metadata: JSObject) {
notifyListeners("onMetadata", metadata)
override fun onMetadata(metadata: PlaybackMetadata) {
notifyListeners("onMetadata", JSObject(jacksonObjectMapper().writeValueAsString(metadata)))
}
override fun onPrepare(audiobookId: String, playWhenReady: Boolean) {
@ -123,8 +124,8 @@ class AbsAudioPlayer : Plugin() {
@PluginMethod
fun getCurrentTime(call: PluginCall) {
Handler(Looper.getMainLooper()).post() {
var currentTime = playerNotificationService.getCurrentTime()
var bufferedTime = playerNotificationService.getBufferedTime()
var currentTime = playerNotificationService.getCurrentTimeSeconds()
var bufferedTime = playerNotificationService.getBufferedTimeSeconds()
val ret = JSObject()
ret.put("value", currentTime)
ret.put("bufferedTime", bufferedTime)
@ -157,35 +158,35 @@ class AbsAudioPlayer : Plugin() {
}
@PluginMethod
fun seekPlayer(call: PluginCall) {
var time:Long = call.getString("timeMs", "0")!!.toLong()
fun seek(call: PluginCall) {
var time:Int = call.getInt("value", 0) ?: 0 // Value in seconds
Handler(Looper.getMainLooper()).post() {
playerNotificationService.seekPlayer(time)
playerNotificationService.seekPlayer(time * 1000L) // convert to ms
call.resolve()
}
}
@PluginMethod
fun seekForward(call: PluginCall) {
var amount:Long = call.getString("amount", "0")!!.toLong()
var amount:Int = call.getInt("value", 0) ?: 0
Handler(Looper.getMainLooper()).post() {
playerNotificationService.seekForward(amount)
playerNotificationService.seekForward(amount * 1000L) // convert to ms
call.resolve()
}
}
@PluginMethod
fun seekBackward(call: PluginCall) {
var amount:Long = call.getString("amount", "0")!!.toLong()
var amount:Int = call.getInt("value", 0) ?: 0 // Value in seconds
Handler(Looper.getMainLooper()).post() {
playerNotificationService.seekBackward(amount)
playerNotificationService.seekBackward(amount * 1000L) // convert to ms
call.resolve()
}
}
@PluginMethod
fun setPlaybackSpeed(call: PluginCall) {
var playbackSpeed:Float = call.getFloat("speed", 1.0f)!!
var playbackSpeed:Float = call.getFloat("value", 1.0f) ?: 1.0f
Handler(Looper.getMainLooper()).post() {
playerNotificationService.setPlaybackSpeed(playbackSpeed)
@ -194,9 +195,9 @@ class AbsAudioPlayer : Plugin() {
}
@PluginMethod
fun terminateStream(call: PluginCall) {
fun closePlayback(call: PluginCall) {
Handler(Looper.getMainLooper()).post() {
playerNotificationService.terminateStream()
playerNotificationService.closePlayback()
call.resolve()
}
}