Add equalizer shortcut

This commit is contained in:
vfsfitvnm 2022-06-12 22:25:01 +02:00
parent 6737a7b003
commit 13881c2d43
3 changed files with 84 additions and 11 deletions

View file

@ -58,6 +58,8 @@ val DeleteSongCacheCommand = SessionCommand("DeleteSongCacheCommand", Bundle.EMP
val SetSkipSilenceCommand = SessionCommand("SetSkipSilenceCommand", Bundle.EMPTY)
val GetAudioSessionIdCommand = SessionCommand("GetAudioSessionIdCommand", Bundle.EMPTY)
@ExperimentalAnimationApi
@ExperimentalFoundationApi
class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
@ -107,6 +109,8 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
)
.build()
player.repeatMode = preferences.repeatMode
player.skipSilenceEnabled = preferences.skipSilence
player.playWhenReady = true
@ -189,6 +193,7 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
.add(GetCacheSizeCommand)
.add(DeleteSongCacheCommand)
.add(SetSkipSilenceCommand)
.add(GetAudioSessionIdCommand)
.build()
val playerCommands = Player.Commands.Builder().addAllCommands().build()
return MediaSession.ConnectionResult.accept(sessionCommands, playerCommands)
@ -230,6 +235,9 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
SetSkipSilenceCommand -> {
player.skipSilenceEnabled = args.getBoolean("skipSilence")
}
GetAudioSessionIdCommand -> {
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS, bundleOf("audioSessionId" to player.audioSessionId)))
}
}
return super.onCustomCommand(session, controller, customCommand, args)

View file

@ -188,8 +188,8 @@ fun SettingsScreen() {
Entry(
color = colorPalette.magenta,
icon = R.drawable.play,
title = "Player",
description = "Tune the player behavior",
title = "Player & Audio",
description = "Player and audio settings",
route = playerSettingsRoute,
)
@ -311,23 +311,38 @@ fun SwitchSettingEntry(
}
@Composable
@NonRestartableComposable
fun SettingsEntry(
title: String,
text: String,
modifier: Modifier = Modifier,
onClick: () -> Unit
onClick: () -> Unit,
isEnabled: Boolean = true
) {
BaseSettingsEntry(
title = title,
text = text,
val typography = LocalTypography.current
val colorPalette = LocalColorPalette.current
Column(
modifier = modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = onClick
onClick = onClick,
enabled = isEnabled
)
)
.padding(start = 24.dp)
.padding(horizontal = 32.dp, vertical = 16.dp)
.fillMaxWidth()
) {
BasicText(
text = title,
style = typography.xs.semiBold.copy(color = if (isEnabled) colorPalette.text else colorPalette.darkGray),
)
BasicText(
text = text,
style = typography.xs.semiBold.copy(color = if (isEnabled) colorPalette.textSecondary else colorPalette.darkGray),
)
}
}
@Composable

View file

@ -1,17 +1,27 @@
package it.vfsfitvnm.vimusic.ui.screens.settings
import android.content.Intent
import android.media.audiofx.AudioEffect
import android.os.Bundle
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.media3.common.C
import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.services.GetAudioSessionIdCommand
import it.vfsfitvnm.vimusic.services.SetSkipSilenceCommand
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.*
@ -20,6 +30,8 @@ import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.LocalPreferences
import it.vfsfitvnm.vimusic.utils.LocalYoutubePlayer
import it.vfsfitvnm.vimusic.utils.semiBold
import kotlinx.coroutines.guava.await
@ExperimentalAnimationApi
@Composable
@ -43,11 +55,32 @@ fun PlayerSettingsScreen() {
}
host {
val context = LocalContext.current
val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current
val preferences = LocalPreferences.current
val mediaController = LocalYoutubePlayer.current?.mediaController
val activityResultLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
}
val audioSessionId by produceState(initialValue = C.AUDIO_SESSION_ID_UNSET) {
val hasEqualizer = context.packageManager.resolveActivity(
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL),
0
) != null
println("hasEqualizer? $hasEqualizer")
if (hasEqualizer) {
value =
mediaController?.sendCustomCommand(GetAudioSessionIdCommand, Bundle.EMPTY)
?.await()?.extras?.getInt("audioSessionId", C.AUDIO_SESSION_ID_UNSET)
?: C.AUDIO_SESSION_ID_UNSET
}
}
Column(
modifier = Modifier
.background(colorPalette.background)
@ -70,7 +103,7 @@ fun PlayerSettingsScreen() {
)
BasicText(
text = "Player",
text = "Player & Audio",
style = typography.m.semiBold
)
@ -96,10 +129,27 @@ fun PlayerSettingsScreen() {
text = "Skip silent parts during playback",
isChecked = preferences.skipSilence,
onCheckedChange = {
mediaController?.sendCustomCommand(SetSkipSilenceCommand, bundleOf("skipSilence" to it))
mediaController?.sendCustomCommand(
SetSkipSilenceCommand,
bundleOf("skipSilence" to it)
)
preferences.skipSilence = it
}
)
SettingsEntry(
title = "Equalizer",
text = "Interact with the system equalizer",
onClick = {
activityResultLauncher.launch(
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply {
putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId)
putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC)
}
)
},
isEnabled = audioSessionId != C.AUDIO_SESSION_ID_UNSET && audioSessionId != AudioEffect.ERROR_BAD_VALUE
)
}
}
}