mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 15:32:01 +00:00
fix: ios player not recreating after switching source/episode
This commit is contained in:
parent
c890cc3400
commit
4f62be91b8
1 changed files with 123 additions and 121 deletions
|
|
@ -34,180 +34,182 @@ actual fun PlatformPlayerSurface(
|
|||
onError: (String?) -> Unit,
|
||||
) {
|
||||
sanitizePlaybackResponseHeaders(sourceResponseHeaders)
|
||||
val latestOnControllerReady = rememberUpdatedState(onControllerReady)
|
||||
val latestOnSnapshot = rememberUpdatedState(onSnapshot)
|
||||
val latestOnError = rememberUpdatedState(onError)
|
||||
|
||||
val bridge = remember(sourceUrl) {
|
||||
val bridge = remember {
|
||||
NuvioPlayerBridgeFactory.create()
|
||||
}
|
||||
|
||||
if (bridge == null) {
|
||||
LaunchedEffect(Unit) {
|
||||
onError("MPV player engine not available. Please rebuild the app.")
|
||||
latestOnError.value("MPV player engine not available. Please rebuild the app.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create controller
|
||||
LaunchedEffect(bridge) {
|
||||
onControllerReady(
|
||||
object : PlayerEngineController {
|
||||
override fun play() {
|
||||
bridge.play()
|
||||
}
|
||||
val controller = remember(bridge) {
|
||||
object : PlayerEngineController {
|
||||
override fun play() {
|
||||
bridge.play()
|
||||
}
|
||||
|
||||
override fun pause() {
|
||||
bridge.pause()
|
||||
}
|
||||
override fun pause() {
|
||||
bridge.pause()
|
||||
}
|
||||
|
||||
override fun seekTo(positionMs: Long) {
|
||||
bridge.seekTo(positionMs)
|
||||
}
|
||||
override fun seekTo(positionMs: Long) {
|
||||
bridge.seekTo(positionMs)
|
||||
}
|
||||
|
||||
override fun seekBy(offsetMs: Long) {
|
||||
bridge.seekBy(offsetMs)
|
||||
}
|
||||
override fun seekBy(offsetMs: Long) {
|
||||
bridge.seekBy(offsetMs)
|
||||
}
|
||||
|
||||
override fun retry() {
|
||||
bridge.retry()
|
||||
}
|
||||
override fun retry() {
|
||||
bridge.retry()
|
||||
}
|
||||
|
||||
override fun setPlaybackSpeed(speed: Float) {
|
||||
bridge.setPlaybackSpeed(speed)
|
||||
}
|
||||
override fun setPlaybackSpeed(speed: Float) {
|
||||
bridge.setPlaybackSpeed(speed)
|
||||
}
|
||||
|
||||
override fun getAudioTracks(): List<AudioTrack> {
|
||||
val count = bridge.getAudioTrackCount()
|
||||
return (0 until count).map { i ->
|
||||
AudioTrack(
|
||||
index = bridge.getAudioTrackIndex(i),
|
||||
id = bridge.getAudioTrackId(i),
|
||||
label = bridge.getAudioTrackLabel(i),
|
||||
language = bridge.getAudioTrackLang(i),
|
||||
isSelected = bridge.isAudioTrackSelected(i),
|
||||
)
|
||||
}
|
||||
override fun getAudioTracks(): List<AudioTrack> {
|
||||
val count = bridge.getAudioTrackCount()
|
||||
return (0 until count).map { i ->
|
||||
AudioTrack(
|
||||
index = bridge.getAudioTrackIndex(i),
|
||||
id = bridge.getAudioTrackId(i),
|
||||
label = bridge.getAudioTrackLabel(i),
|
||||
language = bridge.getAudioTrackLang(i),
|
||||
isSelected = bridge.isAudioTrackSelected(i),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSubtitleTracks(): List<SubtitleTrack> {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
val tracks = (0 until count).map { i ->
|
||||
val trackId = bridge.getSubtitleTrackId(i)
|
||||
val trackLabel = bridge.getSubtitleTrackLabel(i)
|
||||
val trackLanguage = bridge.getSubtitleTrackLang(i)
|
||||
SubtitleTrack(
|
||||
index = bridge.getSubtitleTrackIndex(i),
|
||||
id = trackId,
|
||||
override fun getSubtitleTracks(): List<SubtitleTrack> {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
val tracks = (0 until count).map { i ->
|
||||
val trackId = bridge.getSubtitleTrackId(i)
|
||||
val trackLabel = bridge.getSubtitleTrackLabel(i)
|
||||
val trackLanguage = bridge.getSubtitleTrackLang(i)
|
||||
SubtitleTrack(
|
||||
index = bridge.getSubtitleTrackIndex(i),
|
||||
id = trackId,
|
||||
label = trackLabel,
|
||||
language = trackLanguage,
|
||||
isSelected = bridge.isSubtitleTrackSelected(i),
|
||||
isForced = inferForcedSubtitleTrack(
|
||||
label = trackLabel,
|
||||
language = trackLanguage,
|
||||
isSelected = bridge.isSubtitleTrackSelected(i),
|
||||
isForced = inferForcedSubtitleTrack(
|
||||
label = trackLabel,
|
||||
language = trackLanguage,
|
||||
trackId = trackId,
|
||||
),
|
||||
)
|
||||
}
|
||||
Logger.d(TAG) { "getSubtitleTracks: found ${tracks.size} tracks" }
|
||||
return tracks
|
||||
trackId = trackId,
|
||||
),
|
||||
)
|
||||
}
|
||||
Logger.d(TAG) { "getSubtitleTracks: found ${tracks.size} tracks" }
|
||||
return tracks
|
||||
}
|
||||
|
||||
override fun selectAudioTrack(index: Int) {
|
||||
// Convert from logical track index to mpv track id
|
||||
val count = bridge.getAudioTrackCount()
|
||||
override fun selectAudioTrack(index: Int) {
|
||||
// Convert from logical track index to mpv track id
|
||||
val count = bridge.getAudioTrackCount()
|
||||
if (count <= 0) return
|
||||
|
||||
val trackId = (0 until count)
|
||||
.firstNotNullOfOrNull { at ->
|
||||
if (bridge.getAudioTrackIndex(at) == index) {
|
||||
bridge.getAudioTrackId(at).toIntOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
?: if (index in 0 until count) {
|
||||
bridge.getAudioTrackId(index).toIntOrNull() ?: (index + 1)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (trackId != null) {
|
||||
bridge.selectAudioTrack(trackId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun selectSubtitleTrack(index: Int) {
|
||||
if (index < 0) {
|
||||
bridge.selectSubtitleTrack(-1) // disable
|
||||
} else {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
if (count <= 0) return
|
||||
|
||||
val trackId = (0 until count)
|
||||
.firstNotNullOfOrNull { at ->
|
||||
if (bridge.getAudioTrackIndex(at) == index) {
|
||||
bridge.getAudioTrackId(at).toIntOrNull()
|
||||
if (bridge.getSubtitleTrackIndex(at) == index) {
|
||||
bridge.getSubtitleTrackId(at).toIntOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
?: if (index in 0 until count) {
|
||||
bridge.getAudioTrackId(index).toIntOrNull() ?: (index + 1)
|
||||
bridge.getSubtitleTrackId(index).toIntOrNull() ?: (index + 1)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (trackId != null) {
|
||||
bridge.selectAudioTrack(trackId)
|
||||
bridge.selectSubtitleTrack(trackId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun selectSubtitleTrack(index: Int) {
|
||||
if (index < 0) {
|
||||
bridge.selectSubtitleTrack(-1) // disable
|
||||
override fun setSubtitleUri(url: String) {
|
||||
Logger.d(TAG) { "setSubtitleUri: $url" }
|
||||
bridge.setSubtitleUrl(url)
|
||||
}
|
||||
|
||||
override fun clearExternalSubtitle() {
|
||||
bridge.clearExternalSubtitle()
|
||||
}
|
||||
|
||||
override fun clearExternalSubtitleAndSelect(trackIndex: Int) {
|
||||
val trackId = if (trackIndex < 0) {
|
||||
-1
|
||||
} else {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
if (count <= 0) {
|
||||
trackIndex + 1
|
||||
} else {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
if (count <= 0) return
|
||||
|
||||
val trackId = (0 until count)
|
||||
(0 until count)
|
||||
.firstNotNullOfOrNull { at ->
|
||||
if (bridge.getSubtitleTrackIndex(at) == index) {
|
||||
if (bridge.getSubtitleTrackIndex(at) == trackIndex) {
|
||||
bridge.getSubtitleTrackId(at).toIntOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
?: if (index in 0 until count) {
|
||||
bridge.getSubtitleTrackId(index).toIntOrNull() ?: (index + 1)
|
||||
?: if (trackIndex in 0 until count) {
|
||||
bridge.getSubtitleTrackId(trackIndex).toIntOrNull() ?: (trackIndex + 1)
|
||||
} else {
|
||||
null
|
||||
trackIndex + 1
|
||||
}
|
||||
|
||||
if (trackId != null) {
|
||||
bridge.selectSubtitleTrack(trackId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setSubtitleUri(url: String) {
|
||||
Logger.d(TAG) { "setSubtitleUri: $url" }
|
||||
bridge.setSubtitleUrl(url)
|
||||
}
|
||||
|
||||
override fun clearExternalSubtitle() {
|
||||
bridge.clearExternalSubtitle()
|
||||
}
|
||||
|
||||
override fun clearExternalSubtitleAndSelect(trackIndex: Int) {
|
||||
val trackId = if (trackIndex < 0) {
|
||||
-1
|
||||
} else {
|
||||
val count = bridge.getSubtitleTrackCount()
|
||||
if (count <= 0) {
|
||||
trackIndex + 1
|
||||
} else {
|
||||
(0 until count)
|
||||
.firstNotNullOfOrNull { at ->
|
||||
if (bridge.getSubtitleTrackIndex(at) == trackIndex) {
|
||||
bridge.getSubtitleTrackId(at).toIntOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
?: if (trackIndex in 0 until count) {
|
||||
bridge.getSubtitleTrackId(trackIndex).toIntOrNull() ?: (trackIndex + 1)
|
||||
} else {
|
||||
trackIndex + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
bridge.clearExternalSubtitleAndSelect(trackId)
|
||||
}
|
||||
|
||||
override fun applySubtitleStyle(style: SubtitleStyleState) {
|
||||
bridge.applySubtitleStyle(
|
||||
textColor = style.textColor.toMpvColorString(),
|
||||
outlineSize = if (style.outlineEnabled) 1.65f else 0f,
|
||||
fontSize = style.toMpvSubtitleFontSize(),
|
||||
subPos = style.toMpvSubtitlePosition(),
|
||||
)
|
||||
}
|
||||
bridge.clearExternalSubtitleAndSelect(trackId)
|
||||
}
|
||||
)
|
||||
|
||||
override fun applySubtitleStyle(style: SubtitleStyleState) {
|
||||
bridge.applySubtitleStyle(
|
||||
textColor = style.textColor.toMpvColorString(),
|
||||
outlineSize = if (style.outlineEnabled) 1.65f else 0f,
|
||||
fontSize = style.toMpvSubtitleFontSize(),
|
||||
subPos = style.toMpvSubtitlePosition(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(controller, sourceUrl, sourceAudioUrl, sourceHeaders, sourceResponseHeaders) {
|
||||
latestOnControllerReady.value(controller)
|
||||
}
|
||||
|
||||
// Load file and set initial state
|
||||
|
|
|
|||
Loading…
Reference in a new issue