Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- `Other` - for technical stuff.

## [Unreleased]
### Improved
- Don't start playing until external tracks are loaded and ready ([@Secozzi](https://github.com/Secozzi)) ([#160](https://github.com/quickdesh/Animiru/pull/160))

### Fixed
- Fix tracks not being selected when switching episodes ([@Secozzi](https://github.com/Secozzi)) ([#160](https://github.com/quickdesh/Animiru/pull/160))

## [v0.19.7.5] - 2026-06-08
### Improved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,12 @@ class PlayerActivity : BaseActivity() {
}
}

val videoOptions = video.mpvArgs.joinToString(",") { (option, value) ->
// We handle selecting these in the viewmodel
val mpvOpts = listOf(
Pair("sid", "no"),
Pair("aid", "no"),
)
val videoOptions = (video.mpvArgs + mpvOpts).joinToString(",") { (option, value) ->
"$option=\"$value\""
}

Expand Down Expand Up @@ -1112,8 +1117,7 @@ class PlayerActivity : BaseActivity() {
setMpvMediaTitle()
setupPlayerOrientation()
setupChapters()
viewModel.setPausedState()
viewModel.updateIsLoadingEpisode(false)
viewModel.checkFileLoaded()

// aniSkip stuff
viewModel.viewModelScope.launchIO {
Expand Down
52 changes: 41 additions & 11 deletions app/src/main/java/eu/kanade/tachiyomi/ui/player/PlayerViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ class PlayerViewModel @JvmOverloads constructor(

val isLoading = MutableStateFlow(true)
val hasLoadedTracks = MutableStateFlow(false)
val hasLoadedSubs = MutableStateFlow(false)
val hasLoadedAudio = MutableStateFlow(false)

private val _externalSubtitleTracks = MutableStateFlow<List<VideoTrack.External>>(emptyList())
val externalSubtitleTracks = _externalSubtitleTracks.asStateFlow()
Expand Down Expand Up @@ -485,6 +487,8 @@ class PlayerViewModel @JvmOverloads constructor(
updateSubtitleTrackAt(idx) {
it.copy(id = track.id, state = TrackState.Loaded)
}
hasLoadedSubs.update { _ -> true }
checkFileLoaded()
selectSubById(track.id)
}

Expand All @@ -500,6 +504,8 @@ class PlayerViewModel @JvmOverloads constructor(
updateAudioTrackAt(idx) {
it.copy(id = track.id, state = TrackState.Loaded)
}
hasLoadedAudio.update { _ -> true }
checkFileLoaded()
selectAudioById(track.id, false)
}
}
Expand All @@ -522,16 +528,20 @@ class PlayerViewModel @JvmOverloads constructor(
tracks = embeddedSubs.map { VideoTrack.Internal(it) } + externalSubs,
subtitle = true,
)
preferredSubtitle?.let {
selectSub(it)
if (preferredSubtitle == null) {
hasLoadedSubs.update { _ -> true }
} else {
selectSub(preferredSubtitle)
}

val preferredAudio = trackSelect.getPreferredTrackIndex(
tracks = embeddedAudio.map { VideoTrack.Internal(it) } + externalAudio,
subtitle = false,
)
preferredAudio?.let {
selectAudio(it, true)
if (preferredAudio == null) {
hasLoadedAudio.update { _ -> true }
} else {
selectAudio(preferredAudio, true)
}
}

Expand Down Expand Up @@ -577,10 +587,14 @@ class PlayerViewModel @JvmOverloads constructor(
)
}
} else {
hasLoadedSubs.update { _ -> true }
checkFileLoaded()
selectSubById(track.id)
}
}
is VideoTrack.Internal -> {
hasLoadedSubs.update { _ -> true }
checkFileLoaded()
selectSubById(track.data.id)
}
}
Expand All @@ -602,10 +616,14 @@ class PlayerViewModel @JvmOverloads constructor(
)
}
} else {
hasLoadedAudio.update { _ -> true }
checkFileLoaded()
selectAudioById(track.id, force)
}
}
is VideoTrack.Internal -> {
hasLoadedAudio.update { _ -> true }
checkFileLoaded()
selectAudioById(track.data.id, force)
}
}
Expand All @@ -619,6 +637,8 @@ class PlayerViewModel @JvmOverloads constructor(
updateSubtitleTrackAt(subtitleIdx) {
it.copy(state = TrackState.Error)
}
hasLoadedSubs.update { _ -> true }
checkFileLoaded()
}
val audioIdx = externalAudioTracks.value.indexOfFirst {
it.data.url == url
Expand All @@ -627,6 +647,8 @@ class PlayerViewModel @JvmOverloads constructor(
updateAudioTrackAt(audioIdx) {
it.copy(state = TrackState.Error)
}
hasLoadedAudio.update { _ -> true }
checkFileLoaded()
}
}

Expand Down Expand Up @@ -717,14 +739,22 @@ class PlayerViewModel @JvmOverloads constructor(
}
}

fun setPausedState() {
pausedState.value?.let {
if (it) {
pause()
} else {
unpause()
/**
* Check when file has loaded and see if the player can be (un)paused.
*
* If external subs/audio tracks was selected, wait until mpv has fetched them.
*/
fun checkFileLoaded() {
if (isLoadingEpisode.value && hasLoadedSubs.value && hasLoadedAudio.value) {
_isLoadingEpisode.update { _ -> false }
pausedState.value?.let {
if (it) {
pause()
} else {
unpause()
}
_pausedState.update { _ -> null }
}
_pausedState.update { _ -> null }
}
}

Expand Down
Loading