2023-07-01 11:37:36 +02:00
|
|
|
package com.cappielloantonio.tempo.service
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
|
import android.app.PendingIntent.FLAG_IMMUTABLE
|
|
|
|
|
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
|
|
|
|
import android.app.TaskStackBuilder
|
|
|
|
|
import android.content.Intent
|
2025-09-08 19:28:34 +02:00
|
|
|
import android.os.Binder
|
2023-07-01 11:37:36 +02:00
|
|
|
import android.os.Bundle
|
2025-09-08 19:28:34 +02:00
|
|
|
import android.os.IBinder
|
2023-07-01 11:37:36 +02:00
|
|
|
import androidx.media3.common.*
|
|
|
|
|
import androidx.media3.common.util.UnstableApi
|
2024-03-11 15:13:13 +08:00
|
|
|
import androidx.media3.exoplayer.DefaultLoadControl
|
2023-07-01 11:37:36 +02:00
|
|
|
import androidx.media3.exoplayer.ExoPlayer
|
2023-07-02 23:38:33 +02:00
|
|
|
import androidx.media3.exoplayer.source.TrackGroupArray
|
|
|
|
|
import androidx.media3.exoplayer.trackselection.TrackSelectionArray
|
2023-07-01 11:37:36 +02:00
|
|
|
import androidx.media3.session.*
|
|
|
|
|
import androidx.media3.session.MediaSession.ControllerInfo
|
|
|
|
|
import com.cappielloantonio.tempo.R
|
|
|
|
|
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
|
|
|
|
import com.cappielloantonio.tempo.util.Constants
|
|
|
|
|
import com.cappielloantonio.tempo.util.DownloadUtil
|
2025-09-05 11:19:47 +02:00
|
|
|
import com.cappielloantonio.tempo.util.DynamicMediaSourceFactory
|
2024-03-11 15:13:13 +08:00
|
|
|
import com.cappielloantonio.tempo.util.Preferences
|
2023-07-02 23:38:33 +02:00
|
|
|
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
2023-07-01 11:37:36 +02:00
|
|
|
import com.google.common.collect.ImmutableList
|
|
|
|
|
import com.google.common.util.concurrent.Futures
|
|
|
|
|
import com.google.common.util.concurrent.ListenableFuture
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@UnstableApi
|
2023-07-01 18:11:44 +02:00
|
|
|
class MediaService : MediaLibraryService() {
|
2023-07-01 11:37:36 +02:00
|
|
|
private val librarySessionCallback = CustomMediaLibrarySessionCallback()
|
|
|
|
|
|
|
|
|
|
private lateinit var player: ExoPlayer
|
|
|
|
|
private lateinit var mediaLibrarySession: MediaLibrarySession
|
2025-07-01 09:31:36 +09:30
|
|
|
private lateinit var shuffleCommands: List<CommandButton>
|
|
|
|
|
private lateinit var repeatCommands: List<CommandButton>
|
2025-09-08 19:28:34 +02:00
|
|
|
lateinit var equalizerManager: EqualizerManager
|
2023-07-01 11:37:36 +02:00
|
|
|
|
|
|
|
|
private var customLayout = ImmutableList.of<CommandButton>()
|
|
|
|
|
|
2025-09-08 19:28:34 +02:00
|
|
|
inner class LocalBinder : Binder() {
|
|
|
|
|
fun getEqualizerManager(): EqualizerManager {
|
|
|
|
|
return this@MediaService.equalizerManager
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private val binder = LocalBinder()
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
companion object {
|
|
|
|
|
private const val CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON =
|
|
|
|
|
"android.media3.session.demo.SHUFFLE_ON"
|
|
|
|
|
private const val CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF =
|
|
|
|
|
"android.media3.session.demo.SHUFFLE_OFF"
|
2025-07-01 09:31:36 +09:30
|
|
|
private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF =
|
|
|
|
|
"android.media3.session.demo.REPEAT_OFF"
|
|
|
|
|
private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE =
|
|
|
|
|
"android.media3.session.demo.REPEAT_ONE"
|
|
|
|
|
private const val CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL =
|
|
|
|
|
"android.media3.session.demo.REPEAT_ALL"
|
2025-09-08 19:28:34 +02:00
|
|
|
const val ACTION_BIND_EQUALIZER = "com.cappielloantonio.tempo.service.BIND_EQUALIZER"
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onCreate() {
|
|
|
|
|
super.onCreate()
|
|
|
|
|
|
|
|
|
|
initializeCustomCommands()
|
|
|
|
|
initializePlayer()
|
|
|
|
|
initializeMediaLibrarySession()
|
|
|
|
|
initializePlayerListener()
|
2025-09-08 19:28:34 +02:00
|
|
|
initializeEqualizerManager()
|
2023-07-01 11:37:36 +02:00
|
|
|
|
2023-07-01 18:11:44 +02:00
|
|
|
setPlayer(player)
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onGetSession(controllerInfo: ControllerInfo): MediaLibrarySession {
|
|
|
|
|
return mediaLibrarySession
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onDestroy() {
|
2025-09-08 19:28:34 +02:00
|
|
|
equalizerManager.release()
|
2023-07-01 11:37:36 +02:00
|
|
|
releasePlayer()
|
|
|
|
|
super.onDestroy()
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-08 19:28:34 +02:00
|
|
|
override fun onBind(intent: Intent?): IBinder? {
|
|
|
|
|
// Check if the intent is for our custom equalizer binder
|
|
|
|
|
if (intent?.action == ACTION_BIND_EQUALIZER) {
|
|
|
|
|
return binder
|
|
|
|
|
}
|
|
|
|
|
// Otherwise, handle it as a normal MediaLibraryService connection
|
|
|
|
|
return super.onBind(intent)
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
private inner class CustomMediaLibrarySessionCallback : MediaLibrarySession.Callback {
|
|
|
|
|
|
|
|
|
|
override fun onConnect(
|
|
|
|
|
session: MediaSession,
|
|
|
|
|
controller: ControllerInfo
|
|
|
|
|
): MediaSession.ConnectionResult {
|
|
|
|
|
val connectionResult = super.onConnect(session, controller)
|
|
|
|
|
val availableSessionCommands = connectionResult.availableSessionCommands.buildUpon()
|
|
|
|
|
|
2025-07-01 09:31:36 +09:30
|
|
|
shuffleCommands.forEach { commandButton ->
|
2023-07-01 11:37:36 +02:00
|
|
|
// TODO: Aggiungere i comandi personalizzati
|
|
|
|
|
// commandButton.sessionCommand?.let { availableSessionCommands.add(it) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MediaSession.ConnectionResult.accept(
|
|
|
|
|
availableSessionCommands.build(),
|
|
|
|
|
connectionResult.availablePlayerCommands
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onPostConnect(session: MediaSession, controller: ControllerInfo) {
|
|
|
|
|
if (!customLayout.isEmpty() && controller.controllerVersion != 0) {
|
|
|
|
|
ignoreFuture(mediaLibrarySession.setCustomLayout(controller, customLayout))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-01 09:31:36 +09:30
|
|
|
fun buildCustomLayout(player: Player): ImmutableList<CommandButton> {
|
|
|
|
|
val shuffle = shuffleCommands[if (player.shuffleModeEnabled) 1 else 0]
|
|
|
|
|
val repeat = when (player.repeatMode) {
|
|
|
|
|
Player.REPEAT_MODE_ONE -> repeatCommands[1]
|
|
|
|
|
Player.REPEAT_MODE_ALL -> repeatCommands[2]
|
|
|
|
|
else -> repeatCommands[0]
|
|
|
|
|
}
|
|
|
|
|
return ImmutableList.of(shuffle, repeat)
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
override fun onCustomCommand(
|
|
|
|
|
session: MediaSession,
|
|
|
|
|
controller: ControllerInfo,
|
|
|
|
|
customCommand: SessionCommand,
|
|
|
|
|
args: Bundle
|
|
|
|
|
): ListenableFuture<SessionResult> {
|
2025-07-01 09:31:36 +09:30
|
|
|
when (customCommand.customAction) {
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON -> player.shuffleModeEnabled = true
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF -> player.shuffleModeEnabled = false
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF,
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL,
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> {
|
|
|
|
|
val nextMode = when (player.repeatMode) {
|
|
|
|
|
Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
|
|
|
|
|
Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
|
|
|
|
|
else -> Player.REPEAT_MODE_OFF
|
|
|
|
|
}
|
|
|
|
|
player.repeatMode = nextMode
|
|
|
|
|
}
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-01 09:31:36 +09:30
|
|
|
customLayout = librarySessionCallback.buildCustomLayout(player)
|
|
|
|
|
session.setCustomLayout(customLayout)
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onAddMediaItems(
|
|
|
|
|
mediaSession: MediaSession,
|
|
|
|
|
controller: ControllerInfo,
|
|
|
|
|
mediaItems: List<MediaItem>
|
|
|
|
|
): ListenableFuture<List<MediaItem>> {
|
2025-08-11 20:58:06 +02:00
|
|
|
val updatedMediaItems = mediaItems.map { mediaItem ->
|
|
|
|
|
val mediaMetadata = mediaItem.mediaMetadata
|
|
|
|
|
|
|
|
|
|
val newMetadata = mediaMetadata.buildUpon()
|
|
|
|
|
.setArtist(
|
|
|
|
|
if (mediaMetadata.artist != null) mediaMetadata.artist
|
|
|
|
|
else mediaMetadata.extras?.getString("uri") ?: ""
|
|
|
|
|
)
|
|
|
|
|
.build()
|
|
|
|
|
|
|
|
|
|
mediaItem.buildUpon()
|
|
|
|
|
.setUri(mediaItem.requestMetadata.mediaUri)
|
|
|
|
|
.setMediaMetadata(newMetadata)
|
2023-07-01 11:37:36 +02:00
|
|
|
.setMimeType(MimeTypes.BASE_TYPE_AUDIO)
|
|
|
|
|
.build()
|
|
|
|
|
}
|
|
|
|
|
return Futures.immediateFuture(updatedMediaItems)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun initializeCustomCommands() {
|
2025-07-01 09:31:36 +09:30
|
|
|
shuffleCommands = listOf(
|
|
|
|
|
getShuffleCommandButton(
|
|
|
|
|
SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON, Bundle.EMPTY)
|
|
|
|
|
),
|
|
|
|
|
getShuffleCommandButton(
|
|
|
|
|
SessionCommand(CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_OFF, Bundle.EMPTY)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
repeatCommands = listOf(
|
|
|
|
|
getRepeatCommandButton(
|
|
|
|
|
SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_OFF, Bundle.EMPTY)
|
|
|
|
|
),
|
|
|
|
|
getRepeatCommandButton(
|
|
|
|
|
SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE, Bundle.EMPTY)
|
|
|
|
|
),
|
|
|
|
|
getRepeatCommandButton(
|
|
|
|
|
SessionCommand(CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL, Bundle.EMPTY)
|
2023-07-01 11:37:36 +02:00
|
|
|
)
|
2025-07-01 09:31:36 +09:30
|
|
|
)
|
2023-07-01 11:37:36 +02:00
|
|
|
|
2025-07-01 09:31:36 +09:30
|
|
|
customLayout = ImmutableList.of(shuffleCommands[0], repeatCommands[0])
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun initializePlayer() {
|
|
|
|
|
player = ExoPlayer.Builder(this)
|
|
|
|
|
.setRenderersFactory(getRenderersFactory())
|
2025-09-05 04:46:01 +02:00
|
|
|
.setMediaSourceFactory(DynamicMediaSourceFactory(this))
|
2023-07-01 11:37:36 +02:00
|
|
|
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
|
|
|
|
.setHandleAudioBecomingNoisy(true)
|
|
|
|
|
.setWakeMode(C.WAKE_MODE_NETWORK)
|
2024-03-11 15:13:13 +08:00
|
|
|
.setLoadControl(initializeLoadControl())
|
2023-07-01 11:37:36 +02:00
|
|
|
.build()
|
2025-07-01 09:31:36 +09:30
|
|
|
|
|
|
|
|
player.shuffleModeEnabled = Preferences.isShuffleModeEnabled()
|
|
|
|
|
player.repeatMode = Preferences.getRepeatMode()
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 19:28:34 +02:00
|
|
|
private fun initializeEqualizerManager() {
|
|
|
|
|
equalizerManager = EqualizerManager()
|
|
|
|
|
val audioSessionId = player.audioSessionId
|
|
|
|
|
if (equalizerManager.attachToSession(audioSessionId)) {
|
|
|
|
|
val enabled = Preferences.isEqualizerEnabled()
|
|
|
|
|
equalizerManager.setEnabled(enabled)
|
|
|
|
|
|
|
|
|
|
val bands = equalizerManager.getNumberOfBands()
|
|
|
|
|
val savedLevels = Preferences.getEqualizerBandLevels(bands)
|
2025-09-08 20:08:05 +02:00
|
|
|
for (i in 0 until bands) {
|
|
|
|
|
equalizerManager.setBandLevel(i.toShort(), savedLevels[i])
|
2025-09-08 19:28:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
private fun initializeMediaLibrarySession() {
|
|
|
|
|
val sessionActivityPendingIntent =
|
|
|
|
|
TaskStackBuilder.create(this).run {
|
|
|
|
|
addNextIntent(Intent(this@MediaService, MainActivity::class.java))
|
|
|
|
|
getPendingIntent(0, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mediaLibrarySession =
|
|
|
|
|
MediaLibrarySession.Builder(this, player, librarySessionCallback)
|
|
|
|
|
.setSessionActivity(sessionActivityPendingIntent)
|
|
|
|
|
.build()
|
|
|
|
|
|
|
|
|
|
if (!customLayout.isEmpty()) {
|
|
|
|
|
mediaLibrarySession.setCustomLayout(customLayout)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun initializePlayerListener() {
|
|
|
|
|
player.addListener(object : Player.Listener {
|
|
|
|
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
|
|
|
|
if (mediaItem == null) return
|
|
|
|
|
|
2023-07-01 18:11:44 +02:00
|
|
|
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_SEEK || reason == Player.MEDIA_ITEM_TRANSITION_REASON_AUTO) {
|
2023-07-01 11:37:36 +02:00
|
|
|
MediaManager.setLastPlayedTimestamp(mediaItem)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-02 23:38:33 +02:00
|
|
|
override fun onTracksChanged(tracks: Tracks) {
|
|
|
|
|
ReplayGainUtil.setReplayGain(player, tracks)
|
2024-02-18 19:35:49 +01:00
|
|
|
MediaManager.scrobble(player.currentMediaItem, false)
|
2024-06-02 19:26:32 +02:00
|
|
|
|
|
|
|
|
if (player.currentMediaItemIndex + 1 == player.mediaItemCount)
|
|
|
|
|
MediaManager.continuousPlay(player.currentMediaItem)
|
2023-07-02 23:38:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
|
|
|
|
if (!isPlaying) {
|
|
|
|
|
MediaManager.setPlayingPausedTimestamp(
|
|
|
|
|
player.currentMediaItem,
|
|
|
|
|
player.currentPosition
|
|
|
|
|
)
|
2024-01-28 15:46:36 +01:00
|
|
|
} else {
|
|
|
|
|
MediaManager.scrobble(player.currentMediaItem, false)
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 23:45:34 +02:00
|
|
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
|
|
|
|
super.onPlaybackStateChanged(playbackState)
|
|
|
|
|
if (!player.hasNextMediaItem() &&
|
|
|
|
|
playbackState == Player.STATE_ENDED &&
|
|
|
|
|
player.mediaMetadata.extras?.getString("type") == Constants.MEDIA_TYPE_MUSIC
|
|
|
|
|
) {
|
2024-01-22 21:41:54 -05:00
|
|
|
MediaManager.scrobble(player.currentMediaItem, true)
|
2023-07-29 23:45:34 +02:00
|
|
|
MediaManager.saveChronology(player.currentMediaItem)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
override fun onPositionDiscontinuity(
|
|
|
|
|
oldPosition: Player.PositionInfo,
|
|
|
|
|
newPosition: Player.PositionInfo,
|
|
|
|
|
reason: Int
|
|
|
|
|
) {
|
|
|
|
|
super.onPositionDiscontinuity(oldPosition, newPosition, reason)
|
|
|
|
|
|
2023-07-01 18:11:44 +02:00
|
|
|
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
|
2023-07-01 11:37:36 +02:00
|
|
|
if (oldPosition.mediaItem?.mediaMetadata?.extras?.getString("type") == Constants.MEDIA_TYPE_MUSIC) {
|
2024-01-22 21:41:54 -05:00
|
|
|
MediaManager.scrobble(oldPosition.mediaItem, true)
|
2023-07-01 11:37:36 +02:00
|
|
|
MediaManager.saveChronology(oldPosition.mediaItem)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newPosition.mediaItem?.mediaMetadata?.extras?.getString("type") == Constants.MEDIA_TYPE_MUSIC) {
|
|
|
|
|
MediaManager.setLastPlayedTimestamp(newPosition.mediaItem)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-01 09:31:36 +09:30
|
|
|
|
|
|
|
|
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
|
|
|
|
|
Preferences.setShuffleModeEnabled(shuffleModeEnabled)
|
|
|
|
|
customLayout = librarySessionCallback.buildCustomLayout(player)
|
|
|
|
|
mediaLibrarySession.setCustomLayout(customLayout)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onRepeatModeChanged(repeatMode: Int) {
|
|
|
|
|
Preferences.setRepeatMode(repeatMode)
|
|
|
|
|
customLayout = librarySessionCallback.buildCustomLayout(player)
|
|
|
|
|
mediaLibrarySession.setCustomLayout(customLayout)
|
|
|
|
|
}
|
2023-07-01 11:37:36 +02:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 18:11:44 +02:00
|
|
|
private fun setPlayer(player: Player) {
|
|
|
|
|
mediaLibrarySession.player = player
|
2023-07-01 11:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun releasePlayer() {
|
|
|
|
|
player.release()
|
|
|
|
|
mediaLibrarySession.release()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressLint("PrivateResource")
|
|
|
|
|
private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton {
|
|
|
|
|
val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON
|
|
|
|
|
return CommandButton.Builder()
|
|
|
|
|
.setDisplayName(
|
|
|
|
|
getString(
|
|
|
|
|
if (isOn) R.string.exo_controls_shuffle_on_description
|
|
|
|
|
else R.string.exo_controls_shuffle_off_description
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.setSessionCommand(sessionCommand)
|
|
|
|
|
.setIconResId(if (isOn) R.drawable.exo_icon_shuffle_off else R.drawable.exo_icon_shuffle_on)
|
|
|
|
|
.build()
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-01 09:31:36 +09:30
|
|
|
@SuppressLint("PrivateResource")
|
|
|
|
|
private fun getRepeatCommandButton(sessionCommand: SessionCommand): CommandButton {
|
|
|
|
|
val icon = when (sessionCommand.customAction) {
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> R.drawable.exo_icon_repeat_one
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL -> R.drawable.exo_icon_repeat_all
|
|
|
|
|
else -> R.drawable.exo_icon_repeat_off
|
|
|
|
|
}
|
|
|
|
|
val description = when (sessionCommand.customAction) {
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ONE -> R.string.exo_controls_repeat_one_description
|
|
|
|
|
CUSTOM_COMMAND_TOGGLE_REPEAT_MODE_ALL -> R.string.exo_controls_repeat_all_description
|
|
|
|
|
else -> R.string.exo_controls_repeat_off_description
|
|
|
|
|
}
|
|
|
|
|
return CommandButton.Builder()
|
|
|
|
|
.setDisplayName(getString(description))
|
|
|
|
|
.setSessionCommand(sessionCommand)
|
|
|
|
|
.setIconResId(icon)
|
|
|
|
|
.build()
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
private fun ignoreFuture(customLayout: ListenableFuture<SessionResult>) {
|
|
|
|
|
/* Do nothing. */
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 15:13:13 +08:00
|
|
|
private fun initializeLoadControl(): DefaultLoadControl {
|
|
|
|
|
return DefaultLoadControl.Builder()
|
|
|
|
|
.setBufferDurationsMs(
|
|
|
|
|
(DefaultLoadControl.DEFAULT_MIN_BUFFER_MS * Preferences.getBufferingStrategy()).toInt(),
|
|
|
|
|
(DefaultLoadControl.DEFAULT_MAX_BUFFER_MS * Preferences.getBufferingStrategy()).toInt(),
|
|
|
|
|
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
|
|
|
|
|
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
|
|
|
|
|
)
|
|
|
|
|
.build()
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-01 11:37:36 +02:00
|
|
|
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)
|
|
|
|
|
}
|