mirror of
https://github.com/FluxaMedia/fluxa-desktop.git
synced 2026-08-18 13:05:54 +00:00
Fix player loader blocked by subtitle loading
This commit is contained in:
parent
987b11cc12
commit
aff8aaef58
3 changed files with 41 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
CLAUDE.md
|
||||
AGENTS.md
|
||||
node_modules/
|
||||
dist/
|
||||
src-tauri/target/
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ type MpvTerminateDestroy = unsafe extern "C" fn(*mut MpvHandle);
|
|||
type MpvSetOptionString =
|
||||
unsafe extern "C" fn(*mut MpvHandle, *const c_char, *const c_char) -> c_int;
|
||||
type MpvCommandString = unsafe extern "C" fn(*mut MpvHandle, *const c_char) -> c_int;
|
||||
type MpvCommandAsync = unsafe extern "C" fn(*mut MpvHandle, u64, *const *const c_char) -> c_int;
|
||||
type MpvGetProperty =
|
||||
unsafe extern "C" fn(*mut MpvHandle, *const c_char, c_int, *mut c_void) -> c_int;
|
||||
type MpvFree = unsafe extern "C" fn(*mut c_void);
|
||||
|
|
@ -122,6 +123,7 @@ struct MpvApi {
|
|||
mpv_terminate_destroy: MpvTerminateDestroy,
|
||||
mpv_set_option_string: MpvSetOptionString,
|
||||
mpv_command_string: MpvCommandString,
|
||||
mpv_command_async: MpvCommandAsync,
|
||||
mpv_get_property: MpvGetProperty,
|
||||
mpv_free: MpvFree,
|
||||
mpv_error_string: MpvErrorString,
|
||||
|
|
@ -158,6 +160,9 @@ impl MpvApi {
|
|||
let mpv_command_string = *library
|
||||
.get::<MpvCommandString>(b"mpv_command_string\0")
|
||||
.map_err(load_error)?;
|
||||
let mpv_command_async = *library
|
||||
.get::<MpvCommandAsync>(b"mpv_command_async\0")
|
||||
.map_err(load_error)?;
|
||||
let mpv_get_property = *library
|
||||
.get::<MpvGetProperty>(b"mpv_get_property\0")
|
||||
.map_err(load_error)?;
|
||||
|
|
@ -194,6 +199,7 @@ impl MpvApi {
|
|||
mpv_terminate_destroy,
|
||||
mpv_set_option_string,
|
||||
mpv_command_string,
|
||||
mpv_command_async,
|
||||
mpv_get_property,
|
||||
mpv_free,
|
||||
mpv_error_string,
|
||||
|
|
@ -569,12 +575,11 @@ impl MpvRenderer {
|
|||
title: Option<&str>,
|
||||
language: Option<&str>,
|
||||
) -> Result<(), String> {
|
||||
let escaped_url = command_quote(url);
|
||||
let escaped_title = command_quote(title.unwrap_or("Subtitle"));
|
||||
let escaped_language = command_quote(language.unwrap_or(""));
|
||||
self.command_string(&format!(
|
||||
"sub-add {escaped_url} auto {escaped_title} {escaped_language}"
|
||||
))
|
||||
let title = title.unwrap_or("Subtitle");
|
||||
match language.filter(|value| !value.is_empty()) {
|
||||
Some(language) => self.command_async_args(&["sub-add", url, "auto", title, language]),
|
||||
None => self.command_async_args(&["sub-add", url, "auto", title]),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
|
||||
|
|
@ -603,6 +608,25 @@ impl MpvRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn command_async_args(&self, args: &[&str]) -> Result<(), String> {
|
||||
let c_args = args
|
||||
.iter()
|
||||
.map(|arg| CString::new(*arg).map_err(|error| error.to_string()))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let mut raw_args = c_args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
|
||||
raw_args.push(ptr::null());
|
||||
|
||||
let result = unsafe { (self.api.mpv_command_async)(self.handle, 0, raw_args.as_ptr()) };
|
||||
if result < 0 {
|
||||
Err(format!(
|
||||
"mpv async command failed: {}",
|
||||
self.api.error_string(result)
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_frame(&mut self, width: i32, height: i32) -> Result<PlayerFrame, String> {
|
||||
if !self.loaded {
|
||||
return Err("player has not loaded media yet".to_string());
|
||||
|
|
@ -1133,10 +1157,6 @@ impl MpvRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn command_quote(value: &str) -> String {
|
||||
format!("\"{}\"", value.replace('\\', "\\\\").replace('"', "\\\""))
|
||||
}
|
||||
|
||||
// Linux-only OpenGL proc address resolution
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
|
|||
|
|
@ -486,8 +486,17 @@ export function ReactPlayerOverlay({ closePlayer, onFirstFrame, initialTitle, in
|
|||
|
||||
if (!firstFrameFiredRef.current && onFirstFrame) {
|
||||
const noVideoTrack = status.trackListReady && !status.hasVideoTrack;
|
||||
const hasVideoDimensions =
|
||||
(parseFloat(status.width ?? '0') || 0) > 0 &&
|
||||
(parseFloat(status.height ?? '0') || 0) > 0;
|
||||
const playbackAdvancing =
|
||||
status.loaded &&
|
||||
status.pause !== 'yes' &&
|
||||
status.pausedForCache !== 'yes' &&
|
||||
pos > 0.15;
|
||||
const voReady = !noVideoTrack && status.voConfigured === 'yes' && status.framesRendered >= 2;
|
||||
if (voReady || noVideoTrack) {
|
||||
const activeVideoPlayback = !noVideoTrack && status.hasVideoTrack && hasVideoDimensions && playbackAdvancing;
|
||||
if (voReady || activeVideoPlayback || noVideoTrack) {
|
||||
firstFrameFiredRef.current = true;
|
||||
sendCmd('set pause no');
|
||||
onFirstFrame();
|
||||
|
|
|
|||
Loading…
Reference in a new issue