mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-07 09:22:10 +01:00
feat(android,ios): play the subtitle files beside an episode
The bridge's open_subtitles opens and publishes them and names the one to turn on. The native player holds them until mpv has the episode loaded, adds them with sub-add, and releases them instead when another episode was loaded in the meantime.
This commit is contained in:
1 parent
f0fe90f0fe
commit
7790ae9cbb
6 files changed
+311
-5
No files matched your search
@@ -19,6 +19,7 @@ import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
import uniffi.pstr_android.ChapterPlan
|
||||
import uniffi.pstr_android.ChapterRecord
|
||||
import uniffi.pstr_android.SubtitleFilesRecord
|
||||
import uniffi.pstr_android.chapterPlan
|
||||
|
||||
/**
|
||||
@@ -292,6 +293,30 @@ class NativeMpvHost private constructor(private val nativeHandle: Long) : Libmpv
|
||||
|
||||
override fun releaseNativeStream(nativeHandle: ULong) = pstrAndroidStreamRelease(nativeHandle.toLong())
|
||||
|
||||
/**
|
||||
* Hand mpv the subtitle files beside [media], the episode [play] loaded.
|
||||
*
|
||||
* Native code holds them until mpv has the file loaded, since an external
|
||||
* track belongs to the file open at the time, and releases them instead
|
||||
* if another episode has been loaded since. [SubtitleFilesRecord.preferred]
|
||||
* is turned on only when the file has no subtitle of its own playing;
|
||||
* pass [subtitles] false to turn none on.
|
||||
*/
|
||||
fun addSubtitles(media: String, files: SubtitleFilesRecord, subtitles: Boolean) {
|
||||
val generation = currentGeneration.toLong()
|
||||
val added = withOpenHandle { handle ->
|
||||
files.files.forEachIndexed { index, file ->
|
||||
if (currentMedia == media) {
|
||||
val select = subtitles && files.preferred == index.toUInt()
|
||||
nativeAddSubtitle(handle, generation, file.handle.toLong(), file.title, file.language, select)
|
||||
} else {
|
||||
pstrAndroidStreamRelease(file.handle.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
if (added == null) files.files.forEach { pstrAndroidStreamRelease(it.handle.toLong()) }
|
||||
}
|
||||
|
||||
private fun startPolling() {
|
||||
if (poller?.isActive == true) return
|
||||
// Off the main thread deliberately: `nativeState` and `nativeTracks`
|
||||
@@ -414,6 +439,14 @@ class NativeMpvHost private constructor(private val nativeHandle: Long) : Libmpv
|
||||
subtitles: Boolean,
|
||||
hardwareDecoding: Boolean,
|
||||
): Boolean
|
||||
private external fun nativeAddSubtitle(
|
||||
handle: Long,
|
||||
generation: Long,
|
||||
stream: Long,
|
||||
title: String,
|
||||
language: String?,
|
||||
select: Boolean,
|
||||
)
|
||||
private external fun nativePause(handle: Long, paused: Boolean)
|
||||
private external fun nativeSeek(handle: Long, position: Double)
|
||||
private external fun nativeVolume(handle: Long, volume: Double)
|
||||
|
||||
@@ -250,11 +250,19 @@ fun PlayerScreen(
|
||||
startup.audioLanguage, startup.subtitleLanguage, startup.subtitles,
|
||||
SettingsStore(context).hardwareDecoding,
|
||||
)
|
||||
|
||||
// After the load, because mpv keeps none of the three across one.
|
||||
nativeHost.setVolume(startup.volume)
|
||||
nativeHost.setMuted(startup.muted)
|
||||
nativeHost.setSpeed(startup.speed)
|
||||
session.transferToPlayer()
|
||||
// While mpv opens the episode, and off the spinner's path: the host
|
||||
// holds them until it has the file.
|
||||
launch(Dispatchers.IO) {
|
||||
val files = NativeRuntime.engine()
|
||||
.openSubtitles(episode.shareId, episode.linkId, startup.subtitleLanguage)
|
||||
nativeHost.addSubtitles(key, files, startup.subtitles)
|
||||
}
|
||||
}.onFailure { playbackError = it.message ?: "Playback failed" }
|
||||
opening = false
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user