diff --git a/app/src/main/java/live/mehiz/mpvkt/preferences/AudioPreferences.kt b/app/src/main/java/live/mehiz/mpvkt/preferences/AudioPreferences.kt index c09c70b..752a495 100644 --- a/app/src/main/java/live/mehiz/mpvkt/preferences/AudioPreferences.kt +++ b/app/src/main/java/live/mehiz/mpvkt/preferences/AudioPreferences.kt @@ -1,9 +1,21 @@ package live.mehiz.mpvkt.preferences +import androidx.annotation.StringRes +import live.mehiz.mpvkt.R import live.mehiz.mpvkt.preferences.preference.PreferenceStore +import live.mehiz.mpvkt.preferences.preference.getEnum class AudioPreferences(preferenceStore: PreferenceStore) { val preferredLanguages = preferenceStore.getString("audio_preferred_languages") val defaultAudioDelay = preferenceStore.getInt("audio_delay_default") val audioPitchCorrection = preferenceStore.getBoolean("audio_pitch_correction", true) + val audioChannels = preferenceStore.getEnum("audio_channels", AudioChannels.AutoSafe) +} + +enum class AudioChannels(@StringRes val title: Int, val property: String, val value: String) { + Auto(R.string.pref_audio_channels_auto, "audio-channels", "audio-safe"), + AutoSafe(R.string.pref_audio_channels_auto_safe, "audio-channels", "auto"), + Mono(R.string.pref_audio_channels_mono, "audio-channels", "mono"), + Stereo(R.string.pref_audio_channels_stereo, "audio-channels", "stereo"), + ReverseStereo(R.string.pref_audio_channels_stereo_reversed, "af", "pan=[stereo|c0=c1|c1=c0]"), } diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt b/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt index 17ac62a..3e770d4 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt @@ -209,6 +209,7 @@ class PlayerActivity : AppCompatActivity() { MPVLib.setPropertyString("alang", audioPreferences.preferredLanguages.get()) MPVLib.setPropertyDouble("audio-delay", audioPreferences.defaultAudioDelay.get() / 1000.0) MPVLib.setPropertyBoolean("audio-pitch-correction", audioPreferences.audioPitchCorrection.get()) + audioPreferences.audioChannels.get().let { MPVLib.setPropertyString(it.property, it.value) } val request = AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN).also { it.setAudioAttributes( diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreDialog.kt b/app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreSheet.kt similarity index 62% rename from app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreDialog.kt rename to app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreSheet.kt index c2e3265..99e453b 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreDialog.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/player/controls/components/sheets/MoreSheet.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items import androidx.compose.material3.FilterChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -15,6 +16,8 @@ import androidx.compose.ui.unit.dp import `is`.xyz.mpv.MPVLib import live.mehiz.mpvkt.R import live.mehiz.mpvkt.preferences.AdvancedPreferences +import live.mehiz.mpvkt.preferences.AudioChannels +import live.mehiz.mpvkt.preferences.AudioPreferences import live.mehiz.mpvkt.preferences.preference.collectAsState import live.mehiz.mpvkt.presentation.components.PlayerSheet import org.koin.compose.koinInject @@ -25,6 +28,7 @@ fun MoreSheet( modifier: Modifier = Modifier ) { val advancedPreferences = koinInject() + val audioPreferences = koinInject() val statisticsPage by advancedPreferences.enabledStatisticsPage.collectAsState() PlayerSheet( onDismissRequest, @@ -34,6 +38,7 @@ fun MoreSheet( modifier = Modifier .fillMaxWidth() .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text(stringResource(R.string.player_sheets_stats_page_title)) LazyRow( @@ -44,11 +49,7 @@ fun MoreSheet( label = { Text( stringResource( - if (page == 0) { - R.string.player_sheets_tracks_off - } else { - R.string.player_sheets_stats_page_chip - }, + if (page == 0) R.string.player_sheets_tracks_off else R.string.player_sheets_stats_page_chip, page, ), ) @@ -66,6 +67,27 @@ fun MoreSheet( ) } } + Text(text = stringResource(id = R.string.pref_audio_channels)) + val audioChannels by audioPreferences.audioChannels.collectAsState() + LazyRow( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(AudioChannels.entries) { + FilterChip( + selected = audioChannels == it, + onClick = { + audioPreferences.audioChannels.set(it) + if (it == AudioChannels.ReverseStereo) { + MPVLib.setPropertyString(AudioChannels.AutoSafe.property, AudioChannels.AutoSafe.value) + } else { + MPVLib.setPropertyString(AudioChannels.ReverseStereo.property, "") + } + MPVLib.setPropertyString(it.property, it.value) + }, + label = { Text(text = stringResource(id = it.title)) }, + ) + } + } } } } diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AppearancePreferencesScreen.kt b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AppearancePreferencesScreen.kt index 67fb27f..dbc67a6 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AppearancePreferencesScreen.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AppearancePreferencesScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import live.mehiz.mpvkt.R import live.mehiz.mpvkt.preferences.AppearancePreferences @@ -64,7 +65,7 @@ object AppearancePreferencesScreen : Screen() { val darkMode by preferences.darkMode.collectAsState() MultiChoiceSegmentedButton( choices = DarkMode.entries.map { context.getString(it.titleRes) }.toImmutableList(), - selectedIndices = listOf(DarkMode.entries.indexOf(darkMode)).toImmutableList(), + selectedIndices = persistentListOf(DarkMode.entries.indexOf(darkMode)), onClick = { preferences.darkMode.set(DarkMode.entries[it]) } ) } diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AudioPreferencesScreen.kt b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AudioPreferencesScreen.kt index 3a9757d..8f66834 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AudioPreferencesScreen.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/AudioPreferencesScreen.kt @@ -15,14 +15,20 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import live.mehiz.mpvkt.R +import live.mehiz.mpvkt.preferences.AudioChannels import live.mehiz.mpvkt.preferences.AudioPreferences +import live.mehiz.mpvkt.preferences.preference.collectAsState import live.mehiz.mpvkt.presentation.Screen import me.zhanghai.compose.preference.ProvidePreferenceLocals +import me.zhanghai.compose.preference.listPreference import me.zhanghai.compose.preference.switchPreference import me.zhanghai.compose.preference.textFieldPreference import org.koin.compose.koinInject @@ -31,8 +37,11 @@ object AudioPreferencesScreen : Screen() { @OptIn(ExperimentalMaterial3Api::class) @Composable override fun Content() { + val context = LocalContext.current val navigator = LocalNavigator.currentOrThrow val preferences = koinInject() + val audioChannels by preferences.audioChannels.collectAsState() + Scaffold( topBar = { TopAppBar( @@ -43,7 +52,7 @@ object AudioPreferencesScreen : Screen() { IconButton(onClick = { navigator.pop() }) { Icon(Icons.AutoMirrored.Default.ArrowBack, null) } - } + }, ) }, ) { padding -> @@ -51,7 +60,7 @@ object AudioPreferencesScreen : Screen() { LazyColumn( modifier = Modifier .fillMaxSize() - .padding(padding) + .padding(padding), ) { textFieldPreference( preferences.preferredLanguages.key(), @@ -65,7 +74,7 @@ object AudioPreferencesScreen : Screen() { TextField( value, onValueChange, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) } }, @@ -76,6 +85,14 @@ object AudioPreferencesScreen : Screen() { title = { Text(stringResource(R.string.pref_audio_pitch_correction_title)) }, summary = { Text(stringResource(R.string.pref_audio_pitch_correction_summary)) }, ) + listPreference( + preferences.audioChannels.key(), + defaultValue = preferences.audioChannels.defaultValue().name, + values = AudioChannels.entries.map { it.name }, + valueToText = { AnnotatedString(context.getString(enumValueOf(it).title)) }, + title = { Text(text = stringResource(id = R.string.pref_audio_channels)) }, + summary = { Text(text = context.getString(enumValueOf(it).title)) }, + ) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 558ca30..f7e1630 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,12 @@ Audio Enable audio pitch correction Prevents the audio from becoming high-pitched at faster speeds and low-pitched at slower speeds. + Audio channels + Auto + Auto Safe + Mono + Stereo + Reversed Stereo Advanced pick mpv configuration storage location