Skip to content

Commit

Permalink
[feature] Support selecting subtitle track
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed May 15, 2024
1 parent 2543a39 commit e587d96
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 14 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ android {
minSdk = 24
targetSdk = 34
versionCode = 16
versionName = "1.1-beta24"
versionName = "1.1-beta25"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
1 change: 0 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:extractNativeLibs="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
7 changes: 5 additions & 2 deletions app/src/main/java/com/skyd/anivu/ui/mpv/MPVView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,17 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att
MPVLib.removeObserver(o)
}

data class Track(val mpvId: Int, val name: String)
data class Track(val trackId: Int, val name: String)

var tracks = mapOf<String, MutableList<Track>>(
"audio" to arrayListOf(),
"video" to arrayListOf(),
"sub" to arrayListOf()
)

val subtitleTrack: List<Track>
get() = tracks["sub"].orEmpty().toList()

fun loadTracks() {
for (list in tracks.values) {
list.clear()
Expand Down Expand Up @@ -173,7 +176,7 @@ class MPVView(context: Context, attrs: AttributeSet?) : SurfaceView(context, att
context.getString(R.string.ui_track, mpvId)
tracks.getValue(type).add(
Track(
mpvId = mpvId,
trackId = mpvId,
name = trackName
)
)
Expand Down
94 changes: 84 additions & 10 deletions app/src/main/java/com/skyd/anivu/ui/mpv/PlayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import androidx.compose.material.icons.outlined.ArrowBackIosNew
import androidx.compose.material.icons.rounded.BrightnessHigh
import androidx.compose.material.icons.rounded.BrightnessLow
import androidx.compose.material.icons.rounded.BrightnessMedium
import androidx.compose.material.icons.rounded.ClosedCaption
import androidx.compose.material.icons.rounded.FastForward
import androidx.compose.material.icons.rounded.FastRewind
import androidx.compose.material.icons.rounded.Pause
Expand Down Expand Up @@ -114,13 +115,18 @@ sealed interface PlayerCommand {
data object GetVideoOffsetX : PlayerCommand
data object GetVideoOffsetY : PlayerCommand
data class SetSpeed(val speed: Float) : PlayerCommand
data class SetSubtitleTrack(val trackId: Int) : PlayerCommand
data object GetSpeed : PlayerCommand
data object LoadAllTracks : PlayerCommand
data object GetSubtitleTrack : PlayerCommand
}

private fun MPVView.solveCommand(
command: PlayerCommand,
uri: () -> Uri,
isPlayingChanged: (Boolean) -> Unit,
onSubtitleTrack: (subtitleTrack: List<MPVView.Track>) -> Unit,
onSubtitleTrackChanged: (Int) -> Unit,
onVideoZoom: (Float) -> Unit,
videoOffset: () -> Offset,
onVideoOffset: (Offset) -> Unit,
Expand Down Expand Up @@ -164,6 +170,12 @@ private fun MPVView.solveCommand(
command.speed.toDouble()

PlayerCommand.GetSpeed -> onSpeedChanged(playbackSpeed.toFloat())
PlayerCommand.LoadAllTracks -> loadTracks()
PlayerCommand.GetSubtitleTrack -> onSubtitleTrack(subtitleTrack)
is PlayerCommand.SetSubtitleTrack -> {
sid = command.trackId
onSubtitleTrackChanged(command.trackId)
}
}
}

Expand All @@ -184,6 +196,15 @@ fun PlayerView(
var currentPosition by rememberSaveable { mutableIntStateOf(0) }
var isSeeking by rememberSaveable { mutableStateOf(false) }
var speed by rememberSaveable { mutableFloatStateOf(1f) }
var subtitleTrackMenuState by remember {
mutableStateOf(
SubtitleTrackMenuState(
expanded = false,
currentSubtitleTrack = MPVView.Track(0, ""),
subtitleTrack = emptyList(),
)
)
}
var videoRotate by rememberSaveable { mutableIntStateOf(0) }
var videoZoom by rememberSaveable { mutableFloatStateOf(1f) }
var videoOffset by rememberSaveable(saver = snapshotStateOffsetSaver()) { mutableStateOf(Offset.Zero) }
Expand All @@ -196,6 +217,7 @@ fun PlayerView(
"video-pan-x" -> commandQueue.trySend(PlayerCommand.GetVideoOffsetX)
"video-pan-y" -> commandQueue.trySend(PlayerCommand.GetVideoOffsetY)
"speed" -> commandQueue.trySend(PlayerCommand.GetSpeed)
"track-list" -> commandQueue.trySend(PlayerCommand.LoadAllTracks)
}
}

Expand Down Expand Up @@ -255,6 +277,19 @@ fun PlayerView(
command = command,
uri = { uri },
isPlayingChanged = { isPlaying = it },
onSubtitleTrack = {
subtitleTrackMenuState = subtitleTrackMenuState.copy(
expanded = true,
currentSubtitleTrack = subtitleTrack.find { it.trackId == sid }!!,
subtitleTrack = subtitleTrack,
)
},
onSubtitleTrackChanged = { newTrackId ->
subtitleTrackMenuState = subtitleTrackMenuState.copy(
expanded = false,
currentSubtitleTrack = subtitleTrack.find { it.trackId == newTrackId }!!,
)
},
onVideoZoom = { videoZoom = it },
videoOffset = { videoOffset },
onVideoOffset = { videoOffset = it },
Expand Down Expand Up @@ -284,14 +319,16 @@ fun PlayerView(
onPlayOrPause = { commandQueue.trySend(PlayerCommand.PlayOrPause) },
speed = { speed },
onSpeedChanged = { commandQueue.trySend(PlayerCommand.SetSpeed(it)) },
subtitleTrackMenuState = { subtitleTrackMenuState },
onDismissSubtitleTrackMenu = {
subtitleTrackMenuState = subtitleTrackMenuState.copy(expanded = false)
},
onRequestSubtitleTrack = { commandQueue.trySend(PlayerCommand.GetSubtitleTrack) },
onSubtitleTrackChanged = { commandQueue.trySend(PlayerCommand.SetSubtitleTrack(it.trackId)) },
videoRotate = { videoRotate.toFloat() },
videoZoom = { videoZoom },
onVideoRotate = {
commandQueue.trySend(PlayerCommand.Rotate(it.toInt()))
},
onVideoZoom = {
commandQueue.trySend(PlayerCommand.Zoom(it))
},
onVideoRotate = { commandQueue.trySend(PlayerCommand.Rotate(it.toInt())) },
onVideoZoom = { commandQueue.trySend(PlayerCommand.Zoom(it)) },
videoOffset = { videoOffset },
onVideoOffset = { commandQueue.trySend(PlayerCommand.VideoOffset(it)) }
)
Expand Down Expand Up @@ -344,6 +381,10 @@ private fun PlayerController(
onPlayOrPause: () -> Unit,
speed: () -> Float,
onSpeedChanged: (Float) -> Unit,
subtitleTrackMenuState: () -> SubtitleTrackMenuState,
onDismissSubtitleTrackMenu: () -> Unit,
onRequestSubtitleTrack: () -> Unit,
onSubtitleTrackChanged: (MPVView.Track) -> Unit,
videoRotate: () -> Float,
onVideoRotate: (Float) -> Unit,
videoZoom: () -> Float,
Expand Down Expand Up @@ -384,6 +425,12 @@ private fun PlayerController(
var backwardRippleStartControllerOffset by remember { mutableStateOf(Offset.Zero) }

var isLongPressing by remember { mutableStateOf(false) }

LaunchedEffect(subtitleTrackMenuState()) {
if (subtitleTrackMenuState().expanded) cancelAutoHideControllerRunnable()
else restartAutoHideControllerRunnable()
}

CompositionLocalProvider(LocalContentColor provides Color.White) {
Box(
modifier = Modifier
Expand Down Expand Up @@ -496,7 +543,11 @@ private fun PlayerController(
currentPosition = currentPosition,
duration = duration,
onPositionChanged = onSeekTo,
onRestartAutoHideControllerRunnable = restartAutoHideControllerRunnable
subtitleTrackMenuState = subtitleTrackMenuState,
onDismissSubtitleTrackMenu = onDismissSubtitleTrackMenu,
onRequestSubtitleTrack = onRequestSubtitleTrack,
onSubtitleTrackChanged = onSubtitleTrackChanged,
onRestartAutoHideControllerRunnable = restartAutoHideControllerRunnable,
)

// +85s button
Expand Down Expand Up @@ -728,7 +779,7 @@ private fun Forward85s(
.padding(horizontal = 16.dp, vertical = 10.dp),
text = stringResource(id = R.string.player_forward_85s),
style = MaterialTheme.typography.labelLarge,
fontSize = TextUnit(16f, TextUnitType.Sp),
fontSize = TextUnit(18f, TextUnitType.Sp),
color = Color.White,
)
}
Expand Down Expand Up @@ -788,6 +839,10 @@ private fun BottomBar(
currentPosition: () -> Int,
duration: () -> Int,
onPositionChanged: (position: Int) -> Unit,
subtitleTrackMenuState: () -> SubtitleTrackMenuState,
onDismissSubtitleTrackMenu: () -> Unit,
onRequestSubtitleTrack: () -> Unit,
onSubtitleTrackChanged: (MPVView.Track) -> Unit,
onRestartAutoHideControllerRunnable: () -> Unit,
) {
Column(
Expand All @@ -807,7 +862,7 @@ private fun BottomBar(
.padding(horizontal = 6.dp)
) {
Row(
modifier = Modifier.padding(horizontal = 10.dp),
modifier = Modifier.padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
val sliderInteractionSource = remember { MutableInteractionSource() }
Expand Down Expand Up @@ -889,7 +944,26 @@ private fun BottomBar(
imageVector = if (isPlaying()) Icons.Rounded.Pause else Icons.Rounded.PlayArrow,
contentDescription = stringResource(if (isPlaying()) R.string.pause else R.string.play),
)
Spacer(modifier = Modifier.width(10.dp))

Spacer(modifier = Modifier.weight(1f))

Box {
Icon(
modifier = Modifier
.clip(CircleShape)
.size(45.dp)
.clickable(onClick = onRequestSubtitleTrack)
.padding(9.dp),
imageVector = Icons.Rounded.ClosedCaption,
contentDescription = stringResource(R.string.player_subtitle_track),
)

SubtitleTrackMenu(
onDismissRequest = onDismissSubtitleTrackMenu,
subtitleTrackMenuState = subtitleTrackMenuState,
onSubtitleTrackChanged = onSubtitleTrackChanged,
)
}
}
}
}
Expand Down
55 changes: 55 additions & 0 deletions app/src/main/java/com/skyd/anivu/ui/mpv/SubtitleTrack.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.skyd.anivu.ui.mpv

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Check
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.MenuDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.skyd.anivu.R

data class SubtitleTrackMenuState(
val expanded: Boolean,
val currentSubtitleTrack: MPVView.Track,
val subtitleTrack: List<MPVView.Track>,
)

@Composable
internal fun SubtitleTrackMenu(
onDismissRequest: () -> Unit,
subtitleTrackMenuState: () -> SubtitleTrackMenuState,
onSubtitleTrackChanged: (MPVView.Track) -> Unit,
) {
val state = subtitleTrackMenuState()
DropdownMenu(
expanded = state.expanded,
onDismissRequest = onDismissRequest,
containerColor = ControllerLabelGray,
shadowElevation = 0.dp,
) {
repeat(state.subtitleTrack.size) { index ->
val track = state.subtitleTrack[index]
DropdownMenuItem(
text = { Text(track.name) },
onClick = { onSubtitleTrackChanged(track) },
leadingIcon = {
if (state.currentSubtitleTrack.trackId == track.trackId) {
Icon(
imageVector = Icons.Rounded.Check,
contentDescription = stringResource(id = R.string.item_selected)
)
}
},
colors = MenuDefaults.itemColors().copy(
textColor = Color.White,
leadingIconColor = Color.White,
)
)
}
}
}
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@
<string name="player_config_fragment_advanced_category">高级</string>
<string name="player_config_advanced_screen_name">高级播放器设置</string>
<string name="player_config_advanced_screen_mpv_config">编辑 mpv.conf</string>
<string name="player_subtitle_track">字幕轨道</string>
<string name="item_selected">已选</string>
<plurals name="rss_sync_frequency_minute">
<item quantity="other">每 %d 分钟</item>
</plurals>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@
<string name="player_config_fragment_advanced_category">Advanced</string>
<string name="player_config_advanced_screen_name">Advanced config</string>
<string name="player_config_advanced_screen_mpv_config">Edit mpv.conf</string>
<string name="player_subtitle_track">Subtitle track</string>
<string name="item_selected">Selected</string>
<plurals name="rss_sync_frequency_minute">
<item quantity="one">Every %d minute</item>
<item quantity="other">Every %d minutes</item>
Expand Down

0 comments on commit e587d96

Please sign in to comment.