mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-07-29 07:58:43 +02:00
Merge pull request #1730 from eagleeyetom/feature/cast-volume-fix
Android: fix Cast volume to control receiver
This commit is contained in:
@@ -76,7 +76,10 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||
COMMAND_GET_MEDIA_ITEMS_METADATA,
|
||||
COMMAND_SET_MEDIA_ITEMS_METADATA,
|
||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
||||
COMMAND_GET_TRACKS)
|
||||
COMMAND_GET_TRACKS,
|
||||
COMMAND_GET_DEVICE_VOLUME,
|
||||
COMMAND_SET_DEVICE_VOLUME,
|
||||
COMMAND_ADJUST_DEVICE_VOLUME)
|
||||
.build()
|
||||
|
||||
var currentPlaybackState = Player.STATE_IDLE
|
||||
@@ -861,27 +864,48 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||
}
|
||||
|
||||
override fun getDeviceVolume(): Int {
|
||||
return 0
|
||||
val session = castContext.sessionManager.currentCastSession
|
||||
return if (session != null && !session.isMute) {
|
||||
(session.volume * 100).toInt()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
override fun isDeviceMuted(): Boolean {
|
||||
return false
|
||||
val session = castContext.sessionManager.currentCastSession
|
||||
return session?.isMute ?: false
|
||||
}
|
||||
|
||||
override fun setDeviceVolume(volume: Int) {
|
||||
|
||||
val session = castContext.sessionManager.currentCastSession
|
||||
try {
|
||||
val clamped = volume.coerceIn(0, 100)
|
||||
session?.volume = clamped / 100.0
|
||||
} catch (e: Exception) {
|
||||
Log.e(tag, "Failed to set cast device volume", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun increaseDeviceVolume() {
|
||||
|
||||
val currentVolume = getDeviceVolume()
|
||||
val newVolume = (currentVolume + 1).coerceAtMost(100)
|
||||
setDeviceVolume(newVolume)
|
||||
}
|
||||
|
||||
override fun decreaseDeviceVolume() {
|
||||
|
||||
val currentVolume = getDeviceVolume()
|
||||
val newVolume = (currentVolume - 1).coerceAtLeast(0)
|
||||
setDeviceVolume(newVolume)
|
||||
}
|
||||
|
||||
override fun setDeviceMuted(muted: Boolean) {
|
||||
|
||||
val session = castContext.sessionManager.currentCastSession
|
||||
try {
|
||||
session?.isMute = muted
|
||||
} catch (e: Exception) {
|
||||
Log.e(tag, "Failed to set cast device mute state", e)
|
||||
}
|
||||
}
|
||||
|
||||
inner class StatusListener() : RemoteMediaClient.Callback(), SessionManagerListener<CastSession>, RemoteMediaClient.ProgressListener {
|
||||
|
||||
@@ -18,6 +18,8 @@ import android.support.v4.media.MediaDescriptionCompat
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import android.support.v4.media.session.MediaControllerCompat
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import androidx.media.VolumeProviderCompat
|
||||
import android.media.AudioManager
|
||||
import android.support.v4.media.session.PlaybackStateCompat
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
@@ -94,6 +96,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
private lateinit var mediaSessionConnector: MediaSessionConnector
|
||||
private lateinit var playerNotificationManager: PlayerNotificationManager
|
||||
lateinit var mediaSession: MediaSessionCompat
|
||||
private var remoteVolumeProvider: VolumeProviderCompat? = null
|
||||
private lateinit var transportControls: MediaControllerCompat.TransportControls
|
||||
|
||||
lateinit var mediaManager: MediaManager
|
||||
@@ -705,11 +708,13 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
Log.d(tag, "switchToPlayer: Using Cast Player " + castPlayer?.deviceInfo)
|
||||
mediaSessionConnector.setPlayer(castPlayer)
|
||||
playerNotificationManager.setPlayer(castPlayer)
|
||||
setMediaSessionToCastVolume()
|
||||
castPlayer as CastPlayer
|
||||
} else {
|
||||
Log.d(tag, "switchToPlayer: Using ExoPlayer")
|
||||
mediaSessionConnector.setPlayer(mPlayer)
|
||||
playerNotificationManager.setPlayer(mPlayer)
|
||||
setMediaSessionToLocalVolume()
|
||||
mPlayer
|
||||
}
|
||||
|
||||
@@ -726,6 +731,44 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setMediaSessionToCastVolume() {
|
||||
val currentVol = try { castPlayer?.getDeviceVolume() ?: 0 } catch (e: Exception) { 0 }
|
||||
val provider = object : VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 100, currentVol) {
|
||||
override fun onSetVolumeTo(volume: Int) {
|
||||
val clamped = volume.coerceIn(0, 100)
|
||||
try {
|
||||
castPlayer?.setDeviceVolume(clamped)
|
||||
val actual = castPlayer?.getDeviceVolume() ?: clamped
|
||||
setCurrentVolume(actual)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
override fun onAdjustVolume(direction: Int) {
|
||||
val current = try { castPlayer?.getDeviceVolume() ?: currentVolume } catch (_: Exception) { currentVolume }
|
||||
val step = if (direction > 0) 1 else if (direction < 0) -1 else 0
|
||||
if (step == 0) return
|
||||
var target = (current + step).coerceIn(0, 100)
|
||||
try {
|
||||
castPlayer?.setDeviceVolume(target)
|
||||
var actual = castPlayer?.getDeviceVolume() ?: current
|
||||
// If device ignored tiny step, try nudging up to 3 steps total.
|
||||
if (actual == current) {
|
||||
target = (current + step * 3).coerceIn(0, 100)
|
||||
castPlayer?.setDeviceVolume(target)
|
||||
actual = castPlayer?.getDeviceVolume() ?: current
|
||||
}
|
||||
setCurrentVolume(actual)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
}
|
||||
remoteVolumeProvider = provider
|
||||
mediaSession.setPlaybackToRemote(provider)
|
||||
}
|
||||
|
||||
private fun setMediaSessionToLocalVolume() {
|
||||
mediaSession.setPlaybackToLocal(AudioManager.STREAM_MUSIC)
|
||||
remoteVolumeProvider = null
|
||||
}
|
||||
|
||||
fun getCurrentTrackStartOffsetMs(): Long {
|
||||
return if (currentPlayer.mediaItemCount > 1) {
|
||||
val windowIndex = currentPlayer.currentMediaItemIndex
|
||||
|
||||
Reference in New Issue
Block a user