mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-28 22:08:47 +02:00
Android cleaning up chromecast player and more failed attempts
This commit is contained in:
parent
e5c8d5d4d4
commit
ef65b4c278
7 changed files with 112 additions and 51 deletions
|
@ -11,6 +11,7 @@ import com.google.android.gms.cast.framework.media.CastMediaOptions
|
|||
class CastOptionsProvider : OptionsProvider {
|
||||
override fun getCastOptions(context: Context): CastOptions {
|
||||
Log.d("CastOptionsProvider", "getCastOptions")
|
||||
var appId = "FD1F76C5"
|
||||
return CastOptions.Builder()
|
||||
.setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID).setCastMediaOptions(
|
||||
CastMediaOptions.Builder()
|
||||
|
|
|
@ -9,6 +9,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.MediaMetadata
|
||||
import com.google.android.gms.cast.MediaInfo
|
||||
import com.google.android.gms.cast.MediaQueueItem
|
||||
import com.google.android.gms.common.images.WebImage
|
||||
|
||||
// TODO: enum or something in kotlin?
|
||||
val PLAYMETHOD_DIRECTPLAY = 0
|
||||
|
@ -135,12 +138,41 @@ class PlaybackSession(
|
|||
var mediaMetadata = this.getExoMediaMetadata(audioTrack)
|
||||
var mediaUri = this.getContentUri(audioTrack)
|
||||
var mimeType = audioTrack.mimeType
|
||||
var mediaItem = MediaItem.Builder().setUri(mediaUri).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||
|
||||
var queueItem = getQueueItem(audioTrack) // Queue item used in exo player CastManager
|
||||
var mediaItem = MediaItem.Builder().setUri(mediaUri).setTag(queueItem).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||
mediaItems.add(mediaItem)
|
||||
}
|
||||
return mediaItems
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
fun getCastMediaMetadata(audioTrack:AudioTrack):com.google.android.gms.cast.MediaMetadata {
|
||||
var castMetadata = com.google.android.gms.cast.MediaMetadata(com.google.android.gms.cast.MediaMetadata.MEDIA_TYPE_AUDIOBOOK_CHAPTER)
|
||||
castMetadata.addImage(WebImage(getCoverUri()))
|
||||
castMetadata.putString(com.google.android.gms.cast.MediaMetadata.KEY_TITLE, displayTitle)
|
||||
castMetadata.putString(com.google.android.gms.cast.MediaMetadata.KEY_ARTIST, displayAuthor)
|
||||
castMetadata.putInt(com.google.android.gms.cast.MediaMetadata.KEY_TRACK_NUMBER, audioTrack.index)
|
||||
return castMetadata
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
fun getQueueItem(audioTrack:AudioTrack):MediaQueueItem {
|
||||
var castMetadata = getCastMediaMetadata(audioTrack)
|
||||
|
||||
var mediaUri = getContentUri(audioTrack)
|
||||
var mediaInfoBuilder = MediaInfo.Builder(mediaUri.toString())
|
||||
mediaInfoBuilder.setContentUrl(mediaUri.toString())
|
||||
mediaInfoBuilder.setMetadata(castMetadata)
|
||||
mediaInfoBuilder.setContentType(audioTrack.mimeType)
|
||||
var mediaInfo = mediaInfoBuilder.build()
|
||||
|
||||
var queueItem = MediaQueueItem.Builder(mediaInfo)
|
||||
queueItem.setItemId(audioTrack.index)
|
||||
queueItem.setPlaybackDuration(audioTrack.duration)
|
||||
return queueItem.build()
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
fun clone():PlaybackSession {
|
||||
return PlaybackSession(id,userId,libraryItemId,episodeId,mediaType,mediaMetadata,chapters,displayTitle,displayAuthor,coverPath,duration,playMethod,startedAt,updatedAt,timeListening,audioTracks,currentTime,libraryItem,localLibraryItem,serverConnectionConfigId,serverAddress)
|
||||
|
|
|
@ -9,17 +9,19 @@ import androidx.mediarouter.app.MediaRouteChooserDialog
|
|||
import androidx.mediarouter.media.MediaRouteSelector
|
||||
import androidx.mediarouter.media.MediaRouter
|
||||
import com.getcapacitor.PluginCall
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.ext.cast.CastPlayer
|
||||
import com.google.android.exoplayer2.ext.cast.MediaItemConverter
|
||||
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener
|
||||
import com.google.android.gms.cast.Cast
|
||||
import com.google.android.gms.cast.CastDevice
|
||||
import com.google.android.gms.cast.CastMediaControlIntent
|
||||
import com.google.android.gms.cast.MediaQueueItem
|
||||
import com.google.android.gms.cast.framework.*
|
||||
import org.json.JSONObject
|
||||
import java.util.ArrayList
|
||||
|
||||
class CastManager constructor(playerNotificationService:PlayerNotificationService) {
|
||||
private val tag = "SleepTimerManager"
|
||||
private val tag = "CastManager"
|
||||
private val playerNotificationService:PlayerNotificationService = playerNotificationService
|
||||
|
||||
private var newConnectionListener: SessionListener? = null
|
||||
|
@ -291,6 +293,22 @@ class CastManager constructor(playerNotificationService:PlayerNotificationServic
|
|||
}
|
||||
}
|
||||
|
||||
inner class CustomConverter : MediaItemConverter {
|
||||
override fun toMediaQueueItem(mediaItem: MediaItem): MediaQueueItem {
|
||||
// The MediaQueueItem you build is expected to be in the tag.
|
||||
var queueItem = (mediaItem.playbackProperties!!.tag as MediaQueueItem?)!!
|
||||
Log.d(tag, "Test toMediaQueueItem ${queueItem.media!!.contentUrl} | ${queueItem.playbackDuration} | ${queueItem.itemId}")
|
||||
return queueItem
|
||||
}
|
||||
|
||||
override fun toMediaItem(mediaQueueItem: MediaQueueItem): MediaItem {
|
||||
return MediaItem.Builder()
|
||||
.setUri(mediaQueueItem.media!!.contentUrl)
|
||||
.setTag(mediaQueueItem)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenForConnection(callback: ConnectionCallback) {
|
||||
// We should only ever have one of these listeners active at a time, so remove previous
|
||||
getSessionManager()?.removeSessionManagerListener(newConnectionListener, CastSession::class.java)
|
||||
|
@ -302,7 +320,8 @@ class CastManager constructor(playerNotificationService:PlayerNotificationServic
|
|||
|
||||
try {
|
||||
val castContext = CastContext.getSharedInstance(mainActivity)
|
||||
playerNotificationService.castPlayer = CastPlayer(castContext).apply {
|
||||
|
||||
playerNotificationService.castPlayer = CastPlayer(castContext, CustomConverter()).apply {
|
||||
setSessionAvailabilityListener(CastSessionAvailabilityListener())
|
||||
addListener(PlayerListener(playerNotificationService))
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
|
|||
import com.google.android.exoplayer2.source.MediaSource
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView
|
||||
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
||||
import com.google.android.exoplayer2.upstream.*
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -184,8 +185,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
|
||||
currentPlayer = mPlayer
|
||||
|
||||
var client: OkHttpClient = OkHttpClient()
|
||||
|
||||
// Initialize API
|
||||
apiHandler = ApiHandler(ctx)
|
||||
|
||||
|
@ -220,9 +219,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
isActive = true
|
||||
}
|
||||
|
||||
|
||||
Log.d(tag, "Media Session Set")
|
||||
|
||||
val mediaController = MediaControllerCompat(ctx, mediaSession.sessionToken)
|
||||
|
||||
// This is for Media Browser
|
||||
|
@ -293,10 +289,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
|
||||
var metadata = playbackSession.getMediaMetadataCompat()
|
||||
mediaSession.setMetadata(metadata)
|
||||
|
||||
var mediaItems = playbackSession.getMediaItems()
|
||||
|
||||
if (mPlayer == currentPlayer) {
|
||||
|
||||
var mediaSource:MediaSource
|
||||
|
||||
if (playbackSession.isLocal) {
|
||||
|
@ -316,24 +311,25 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
}
|
||||
mPlayer.setMediaSource(mediaSource)
|
||||
|
||||
} else if (castPlayer != null) {
|
||||
castPlayer?.addMediaItem(mediaItems[0]) // TODO: Media items never actually get added, not sure what is going on....
|
||||
Log.d(tag, "Cast Player ADDED MEDIA ITEM ${castPlayer?.currentMediaItem} | ${castPlayer?.duration} | ${castPlayer?.mediaItemCount}")
|
||||
}
|
||||
|
||||
// Add remaining media items if multi-track
|
||||
if (mediaItems.size > 1) {
|
||||
mPlayer.addMediaItems(mediaItems.subList(1, mediaItems.size))
|
||||
Log.d(tag, "mPlayer total media items ${mPlayer.mediaItemCount}")
|
||||
currentPlayer.addMediaItems(mediaItems.subList(1, mediaItems.size))
|
||||
Log.d(tag, "currentPlayer total media items ${currentPlayer.mediaItemCount}")
|
||||
|
||||
var currentTrackIndex = playbackSession.getCurrentTrackIndex()
|
||||
var currentTrackTime = playbackSession.getCurrentTrackTimeMs()
|
||||
Log.d(tag, "mPlayer current track index $currentTrackIndex & current track time $currentTrackTime")
|
||||
mPlayer.seekTo(currentTrackIndex, currentTrackTime)
|
||||
Log.d(tag, "currentPlayer current track index $currentTrackIndex & current track time $currentTrackTime")
|
||||
currentPlayer.seekTo(currentTrackIndex, currentTrackTime)
|
||||
} else {
|
||||
mPlayer.seekTo(playbackSession.currentTimeMs)
|
||||
}
|
||||
} else if (castPlayer != null) {
|
||||
//// var mediaQueue = currentAudiobookStreamData!!.getCastQueue()
|
||||
// // TODO: Start position will need to be adjusted if using multi-track queue
|
||||
//// castPlayer?.setMediaItems(mediaQueue, 0, 0)
|
||||
currentPlayer.seekTo(playbackSession.currentTimeMs)
|
||||
}
|
||||
|
||||
Log.d(tag, "Prepare complete for session ${currentPlaybackSession?.displayTitle} | ${currentPlayer.mediaItemCount}")
|
||||
currentPlayer.playWhenReady = playWhenReady
|
||||
currentPlayer.setPlaybackSpeed(1f) // TODO: Playback speed should come from settings
|
||||
currentPlayer.prepare()
|
||||
|
@ -349,9 +345,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
mediaSessionConnector.setPlayer(mPlayer)
|
||||
mPlayer
|
||||
}
|
||||
if (currentPlaybackSession != null) {
|
||||
Log.d(tag, "switchToPlayer: Initing current ab stream data")
|
||||
preparePlayer(currentPlaybackSession!!, false)
|
||||
currentPlaybackSession?.let {
|
||||
Log.d(tag, "switchToPlayer: Preparing current playback session ${it.displayTitle}")
|
||||
preparePlayer(it, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,6 +400,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
if (currentPlayer == castPlayer) {
|
||||
Log.d(tag, "CAST Player set on play ${currentPlayer.isLoading} || ${currentPlayer.duration} | ${currentPlayer.currentPosition}")
|
||||
}
|
||||
|
||||
currentPlayer.play()
|
||||
}
|
||||
|
||||
|
@ -411,6 +408,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
currentPlayer.pause()
|
||||
}
|
||||
|
||||
fun playPause():Boolean {
|
||||
return if (currentPlayer.isPlaying) {
|
||||
pause()
|
||||
false
|
||||
} else {
|
||||
play()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun seekPlayer(time: Long) {
|
||||
if (currentPlayer.mediaItemCount > 1) {
|
||||
currentPlaybackSession?.currentTime = time / 1000.0
|
||||
|
|
|
@ -147,6 +147,14 @@ class AbsAudioPlayer : Plugin() {
|
|||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun playPause(call: PluginCall) {
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
var playing = playerNotificationService.playPause()
|
||||
call.resolve(JSObject("{\"playing\":$playing}"))
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun seekPlayer(call: PluginCall) {
|
||||
var time:Long = call.getString("timeMs", "0")!!.toLong()
|
||||
|
@ -246,7 +254,7 @@ class AbsAudioPlayer : Plugin() {
|
|||
@PluginMethod
|
||||
fun requestSession(call: PluginCall) {
|
||||
Log.d(tag, "CAST REQUEST SESSION PLUGIN")
|
||||
|
||||
call.resolve()
|
||||
playerNotificationService.castManager.requestSession(mainActivity, object : CastManager.RequestSessionCallback() {
|
||||
override fun onError(errorCode: Int) {
|
||||
Log.e(tag, "CAST REQUEST SESSION CALLBACK ERROR $errorCode")
|
||||
|
|
|
@ -109,7 +109,7 @@ export default {
|
|||
playbackSession: null,
|
||||
// Others
|
||||
showChapterModal: false,
|
||||
showCastBtn: false,
|
||||
showCastBtn: true,
|
||||
showFullscreen: false,
|
||||
totalDuration: 0,
|
||||
currentPlaybackRate: 1,
|
||||
|
@ -455,15 +455,9 @@ export default {
|
|||
}
|
||||
this.seek(time)
|
||||
},
|
||||
playPauseClick() {
|
||||
async playPauseClick() {
|
||||
if (this.isLoading) return
|
||||
if (this.isPaused) {
|
||||
console.log('playPause PLAY')
|
||||
this.play()
|
||||
} else {
|
||||
console.log('playPause PAUSE')
|
||||
this.pause()
|
||||
}
|
||||
this.isPlaying = !!((await AbsAudioPlayer.playPause()) || {}).playing
|
||||
},
|
||||
play() {
|
||||
AbsAudioPlayer.playPlayer()
|
||||
|
|
|
@ -120,7 +120,7 @@ export default {
|
|||
return this.media.coverPath || this.placeholderUrl
|
||||
},
|
||||
hasCover() {
|
||||
return !!this.media.coverPath
|
||||
return !!this.media.coverPath || this.localCover
|
||||
},
|
||||
sizeMultiplier() {
|
||||
var baseSize = this.squareAspectRatio ? 192 : 120
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue