mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Setting for subtitle margin & fix subtitle opacity settings (#338)
Adds a subtitle style option to set the margin below unstyled subtitles. This is roughly the percent of the screen below the subtitles. It applies to both ExoPlayer & MPV. Also fixes font & background opacity not being applied in some cases. Fixes #225 Closes #178
This commit is contained in:
parent
7f50cd83ee
commit
296d7b9226
8 changed files with 130 additions and 49 deletions
|
|
@ -152,4 +152,5 @@ fun SubtitlePreferences.Builder.resetSubtitles() {
|
|||
backgroundColor = SubtitleSettings.BackgroundColor.defaultValue.toArgb()
|
||||
backgroundOpacity = SubtitleSettings.BackgroundOpacity.defaultValue.toInt()
|
||||
backgroundStyle = SubtitleSettings.BackgroundStylePref.defaultValue
|
||||
margin = SubtitleSettings.Margin.defaultValue.toInt()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ import com.github.damontecres.wholphin.preferences.AppPreference
|
|||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.preferences.updateInterfacePreferences
|
||||
import com.github.damontecres.wholphin.preferences.updatePlaybackOverrides
|
||||
import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences
|
||||
import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel
|
||||
import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings
|
||||
import com.github.damontecres.wholphin.util.Version
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import timber.log.Timber
|
||||
|
|
@ -97,7 +99,7 @@ suspend fun upgradeApp(
|
|||
current: Version,
|
||||
appPreferences: DataStore<AppPreferences>,
|
||||
) {
|
||||
if (previous.isEqualOrBefore(Version.Companion.fromString("0.1.0-2-g0"))) {
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.1.0-2-g0"))) {
|
||||
appPreferences.updateData {
|
||||
it.updatePlaybackOverrides {
|
||||
ac3Supported = AppPreference.Ac3Supported.defaultValue
|
||||
|
|
@ -107,21 +109,28 @@ suspend fun upgradeApp(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (previous.isEqualOrBefore(Version.Companion.fromString("0.2.3-6-g0"))) {
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.2.3-6-g0"))) {
|
||||
appPreferences.updateData {
|
||||
it.updateInterfacePreferences {
|
||||
navDrawerSwitchOnFocus = AppPreference.NavDrawerSwitchOnFocus.defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
if (previous.isEqualOrBefore(Version.Companion.fromString("0.2.5-11-g0"))) {
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.2.5-11-g0"))) {
|
||||
appPreferences.updateData {
|
||||
it.updateInterfacePreferences {
|
||||
showClock = AppPreference.ShowClock.defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
if (previous.isEqualOrBefore(Version.Companion.fromString("0.2.7-1-g0"))) {
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.2.7-1-g0"))) {
|
||||
PreferencesViewModel.resetSubtitleSettings(appPreferences)
|
||||
}
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.3.2-4-g0"))) {
|
||||
appPreferences.updateData {
|
||||
it.updateSubtitlePreferences {
|
||||
margin = SubtitleSettings.Margin.defaultValue.toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import androidx.compose.ui.focus.focusRequester
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.input.key.onKeyEvent
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
|
|
@ -117,6 +118,7 @@ fun PlaybackPage(
|
|||
LoadingState.Success -> {
|
||||
val prefs = preferences.appPreferences.playbackPreferences
|
||||
val scope = rememberCoroutineScope()
|
||||
val configuration = LocalConfiguration.current
|
||||
val density = LocalDensity.current
|
||||
|
||||
val player = viewModel.player
|
||||
|
|
@ -142,11 +144,11 @@ fun PlaybackPage(
|
|||
val subtitleSearchLanguage by viewModel.subtitleSearchLanguage.observeAsState(Locale.current.language)
|
||||
|
||||
var playbackDialog by remember { mutableStateOf<PlaybackDialogType?>(null) }
|
||||
|
||||
OneTimeLaunchedEffect {
|
||||
if (prefs.playerBackend == PlayerBackend.MPV) {
|
||||
scope.launch(Dispatchers.Main + ExceptionHandler()) {
|
||||
preferences.appPreferences.interfacePreferences.subtitlesPreferences.applyToMpv(
|
||||
configuration,
|
||||
density,
|
||||
)
|
||||
}
|
||||
|
|
@ -322,6 +324,7 @@ fun PlaybackPage(
|
|||
preferences.appPreferences.interfacePreferences.subtitlesPreferences.let {
|
||||
setStyle(it.toSubtitleStyle())
|
||||
setFixedTextSize(Dimension.SP, it.fontSize.toFloat())
|
||||
setBottomPaddingFraction(it.margin.toFloat() / 100f)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ fun PreferencesContent(
|
|||
modifier: Modifier = Modifier,
|
||||
viewModel: PreferencesViewModel = hiltViewModel(),
|
||||
updateVM: UpdateViewModel = hiltViewModel(),
|
||||
onFocus: (Int, Int) -> Unit = { _, _ -> },
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -216,6 +217,7 @@ fun PreferencesContent(
|
|||
if (focused) {
|
||||
focusedIndex = Pair(groupIndex, prefIndex)
|
||||
if (movementSounds) playOnClickSound(context)
|
||||
onFocus.invoke(groupIndex, prefIndex)
|
||||
}
|
||||
}
|
||||
when (pref) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.github.damontecres.wholphin.ui.preferences.subtitle
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Typeface
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.ui.CaptionStyleCompat
|
||||
|
|
@ -21,6 +23,7 @@ import com.github.damontecres.wholphin.ui.indexOfFirstOrNull
|
|||
import com.github.damontecres.wholphin.ui.preferences.PreferenceGroup
|
||||
import com.github.damontecres.wholphin.util.mpv.MPVLib
|
||||
import com.github.damontecres.wholphin.util.mpv.setPropertyColor
|
||||
import timber.log.Timber
|
||||
|
||||
object SubtitleSettings {
|
||||
val FontSize =
|
||||
|
|
@ -183,6 +186,23 @@ object SubtitleSettings {
|
|||
valueToIndex = { it.number },
|
||||
)
|
||||
|
||||
val Margin =
|
||||
AppSliderPreference(
|
||||
title = R.string.subtitle_margin,
|
||||
defaultValue = 8,
|
||||
min = 0,
|
||||
max = 100,
|
||||
interval = 1,
|
||||
getter = {
|
||||
it.interfacePreferences.subtitlesPreferences.margin
|
||||
.toLong()
|
||||
},
|
||||
setter = { prefs, value ->
|
||||
prefs.updateSubtitlePreferences { margin = value.toInt() }
|
||||
},
|
||||
summarizer = { value -> value?.let { "$it%" } },
|
||||
)
|
||||
|
||||
val Reset =
|
||||
AppClickablePreference(
|
||||
title = R.string.reset,
|
||||
|
|
@ -223,16 +243,23 @@ object SubtitleSettings {
|
|||
PreferenceGroup(
|
||||
title = R.string.more,
|
||||
preferences =
|
||||
listOf(Reset),
|
||||
listOf(
|
||||
Margin,
|
||||
Reset,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private fun combine(
|
||||
color: Int,
|
||||
opacity: Int,
|
||||
) = ((opacity / 100.0 * 255).toInt().shl(24)).or(color.and(0x00FFFFFF))
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
fun SubtitlePreferences.toSubtitleStyle(): CaptionStyleCompat {
|
||||
val fo = (fontOpacity / 100.0 * 255).toInt().shl(24)
|
||||
val bg = (backgroundOpacity / 100.0 * 255).toInt().shl(24).or(backgroundColor)
|
||||
val bg = combine(backgroundColor, backgroundOpacity)
|
||||
return CaptionStyleCompat(
|
||||
fo.or(fontColor),
|
||||
combine(fontColor, fontOpacity),
|
||||
if (backgroundStyle == BackgroundStyle.BG_WRAP)bg else 0,
|
||||
if (backgroundStyle == BackgroundStyle.BG_BOXED) bg else 0,
|
||||
when (edgeStyle) {
|
||||
|
|
@ -240,7 +267,7 @@ object SubtitleSettings {
|
|||
EdgeStyle.EDGE_SOLID -> CaptionStyleCompat.EDGE_TYPE_OUTLINE
|
||||
EdgeStyle.EDGE_SHADOW -> CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW
|
||||
},
|
||||
fo.or(edgeColor),
|
||||
combine(edgeColor, fontOpacity),
|
||||
when {
|
||||
fontBold && fontItalic -> Typeface.defaultFromStyle(Typeface.BOLD_ITALIC)
|
||||
fontBold -> Typeface.defaultFromStyle(Typeface.BOLD)
|
||||
|
|
@ -250,11 +277,14 @@ object SubtitleSettings {
|
|||
)
|
||||
}
|
||||
|
||||
fun SubtitlePreferences.applyToMpv(density: Density) {
|
||||
fun SubtitlePreferences.applyToMpv(
|
||||
configuration: Configuration,
|
||||
density: Density,
|
||||
) {
|
||||
val fo = (fontOpacity / 100.0 * 255).toInt().shl(24)
|
||||
val fc = Color(fo.or(fontColor))
|
||||
val bg = Color((backgroundOpacity / 100.0 * 255).toInt().shl(24).or(backgroundColor))
|
||||
val edge = Color(fo.or(edgeColor))
|
||||
val fc = Color(combine(fontColor, fontOpacity))
|
||||
val bg = Color(combine(backgroundColor, backgroundOpacity))
|
||||
val edge = Color(combine(edgeColor, fontOpacity))
|
||||
|
||||
// TODO weird, but seems to get the size to be very close to matching sizes between renderers
|
||||
val fontSizePx = with(density) { fontSize.sp.toPx() * .8 }.toInt()
|
||||
|
|
@ -262,6 +292,11 @@ object SubtitleSettings {
|
|||
MPVLib.setPropertyColor("sub-color", fc)
|
||||
MPVLib.setPropertyColor("sub-outline-color", edge)
|
||||
|
||||
val heightInPx = with(density) { configuration.screenHeightDp.dp.toPx() }
|
||||
val margin = (heightInPx * (margin.toFloat() / 100f) * .8).toInt()
|
||||
MPVLib.setPropertyInt("sub-margin-y", margin)
|
||||
Timber.d("MPV subtitles: fontSizePx=%s, margin=$margin", fontSizePx, margin)
|
||||
|
||||
when (edgeStyle) {
|
||||
EdgeStyle.EDGE_NONE,
|
||||
EdgeStyle.UNRECOGNIZED,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import com.github.damontecres.wholphin.ui.preferences.PreferenceScreenOption
|
|||
import com.github.damontecres.wholphin.ui.preferences.PreferencesContent
|
||||
import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel
|
||||
import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.toSubtitleStyle
|
||||
import timber.log.Timber
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Composable
|
||||
|
|
@ -48,8 +47,9 @@ fun SubtitleStylePage(
|
|||
preferences = it
|
||||
}
|
||||
}
|
||||
Timber.v("SubtitleStylePage")
|
||||
val prefs = preferences.interfacePreferences.subtitlesPreferences
|
||||
var focusedOnMargin by remember { mutableStateOf(false) }
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
) {
|
||||
|
|
@ -68,45 +68,74 @@ fun SubtitleStylePage(
|
|||
Modifier
|
||||
.fillMaxSize(),
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(16.dp)
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
val examples =
|
||||
mapOf(
|
||||
"Subtitles will look like this" to 48.dp,
|
||||
"This is another example" to 24.dp,
|
||||
"Longer multi line subtitles will\nlook like this" to 0.dp,
|
||||
)
|
||||
examples.forEach { (text, padding) ->
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
SubtitleView(context)
|
||||
},
|
||||
update = {
|
||||
it.setStyle(prefs.toSubtitleStyle())
|
||||
it.setFixedTextSize(Dimension.SP, prefs.fontSize.toFloat())
|
||||
it.setCues(
|
||||
listOf(
|
||||
Cue.Builder().setText(text).build(),
|
||||
),
|
||||
)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = padding),
|
||||
)
|
||||
if (!focusedOnMargin) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(16.dp)
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
val examples =
|
||||
mapOf(
|
||||
"Subtitles will look like this" to 48.dp,
|
||||
"This is another example" to 24.dp,
|
||||
"Longer multi line subtitles will\nlook like this" to 0.dp,
|
||||
)
|
||||
examples.forEach { (text, padding) ->
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
SubtitleView(context)
|
||||
},
|
||||
update = {
|
||||
it.setStyle(prefs.toSubtitleStyle())
|
||||
it.setFixedTextSize(Dimension.SP, prefs.fontSize.toFloat())
|
||||
it.setCues(
|
||||
listOf(
|
||||
Cue.Builder().setText(text).build(),
|
||||
),
|
||||
)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = padding),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Margin
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
SubtitleView(context)
|
||||
},
|
||||
update = {
|
||||
it.setStyle(prefs.toSubtitleStyle())
|
||||
it.setFixedTextSize(Dimension.SP, prefs.fontSize.toFloat())
|
||||
it.setCues(
|
||||
listOf(
|
||||
Cue.Builder().setText("Subtitles margin below here").build(),
|
||||
),
|
||||
)
|
||||
it.setBottomPaddingFraction(prefs.margin.toFloat() / 100f)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
PreferencesContent(
|
||||
initialPreferences = preferences,
|
||||
preferenceScreenOption = PreferenceScreenOption.SUBTITLES,
|
||||
onFocus = { groupIndex, prefIndex ->
|
||||
|
||||
focusedOnMargin =
|
||||
SubtitleSettings.preferences.getOrNull(groupIndex)?.preferences?.getOrNull(
|
||||
prefIndex,
|
||||
) == SubtitleSettings.Margin
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxHeight()
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ message SubtitlePreferences{
|
|||
BackgroundStyle background_style = 8;
|
||||
bool font_bold = 9;
|
||||
bool font_italic = 10;
|
||||
int32 margin = 11;
|
||||
}
|
||||
|
||||
message InterfacePreferences {
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@
|
|||
<string name="remove">Remove</string>
|
||||
<string name="dolby_vision">Dolby Vision</string>
|
||||
<string name="dolby_atmos">Dolby Atmos</string>
|
||||
<string name="subtitle_margin">Margin</string>
|
||||
|
||||
<string-array name="theme_song_volume">
|
||||
<item>Disabled</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue