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

View File

@@ -188,8 +188,8 @@ fun SettingsScreen() {
Entry( Entry(
color = colorPalette.magenta, color = colorPalette.magenta,
icon = R.drawable.play, icon = R.drawable.play,
title = "Player", title = "Player & Audio",
description = "Tune the player behavior", description = "Player and audio settings",
route = playerSettingsRoute, route = playerSettingsRoute,
) )
@@ -311,23 +311,38 @@ fun SwitchSettingEntry(
} }
@Composable @Composable
@NonRestartableComposable
fun SettingsEntry( fun SettingsEntry(
title: String, title: String,
text: String, text: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: () -> Unit onClick: () -> Unit,
isEnabled: Boolean = true
) { ) {
BaseSettingsEntry( val typography = LocalTypography.current
title = title, val colorPalette = LocalColorPalette.current
text = text,
Column(
modifier = modifier modifier = modifier
.clickable( .clickable(
indication = rememberRipple(bounded = true), indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() }, 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 @Composable

View File

@@ -1,17 +1,27 @@
package it.vfsfitvnm.vimusic.ui.screens.settings 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.animation.ExperimentalAnimationApi
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.media3.common.C
import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.services.GetAudioSessionIdCommand
import it.vfsfitvnm.vimusic.services.SetSkipSilenceCommand import it.vfsfitvnm.vimusic.services.SetSkipSilenceCommand
import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.* 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.LocalPreferences
import it.vfsfitvnm.vimusic.utils.LocalYoutubePlayer import it.vfsfitvnm.vimusic.utils.LocalYoutubePlayer
import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.semiBold
import kotlinx.coroutines.guava.await
@ExperimentalAnimationApi @ExperimentalAnimationApi
@Composable @Composable
@@ -43,11 +55,32 @@ fun PlayerSettingsScreen() {
} }
host { host {
val context = LocalContext.current
val colorPalette = LocalColorPalette.current val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current val typography = LocalTypography.current
val preferences = LocalPreferences.current val preferences = LocalPreferences.current
val mediaController = LocalYoutubePlayer.current?.mediaController 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( Column(
modifier = Modifier modifier = Modifier
.background(colorPalette.background) .background(colorPalette.background)
@@ -70,7 +103,7 @@ fun PlayerSettingsScreen() {
) )
BasicText( BasicText(
text = "Player", text = "Player & Audio",
style = typography.m.semiBold style = typography.m.semiBold
) )
@@ -96,10 +129,27 @@ fun PlayerSettingsScreen() {
text = "Skip silent parts during playback", text = "Skip silent parts during playback",
isChecked = preferences.skipSilence, isChecked = preferences.skipSilence,
onCheckedChange = { onCheckedChange = {
mediaController?.sendCustomCommand(SetSkipSilenceCommand, bundleOf("skipSilence" to it)) mediaController?.sendCustomCommand(
SetSkipSilenceCommand,
bundleOf("skipSilence" to it)
)
preferences.skipSilence = 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
)
} }
} }
} }