op2
This commit is contained in:
@@ -20,6 +20,27 @@ const QJS_REPO_URL: &str = "https://bellard.org/quickjs/binary_releases";
|
||||
const FFMPEG_GITHUB_API: &str = "https://api.github.com/repos/BtbN/FFmpeg-Builds/releases/latest";
|
||||
const FFMPEG_EVERMEET_BASE: &str = "https://evermeet.cx/ffmpeg";
|
||||
|
||||
#[derive(serde::Serialize, Clone, Debug)]
|
||||
pub struct RuntimeStatus {
|
||||
pub ffmpeg_source: String,
|
||||
pub ffmpeg_version: String,
|
||||
pub js_runtime_name: String,
|
||||
pub js_runtime_source: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum FfmpegLocation {
|
||||
System,
|
||||
Managed(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum JsRuntime {
|
||||
Deno,
|
||||
Node,
|
||||
ManagedQuickJs(PathBuf),
|
||||
}
|
||||
|
||||
pub fn get_ytdlp_binary_name() -> &'static str {
|
||||
if cfg!(target_os = "windows") {
|
||||
"yt-dlp.exe"
|
||||
@@ -79,10 +100,7 @@ pub fn get_ffmpeg_path(app: &AppHandle) -> Result<PathBuf> {
|
||||
}
|
||||
|
||||
pub fn check_binaries(app: &AppHandle) -> bool {
|
||||
let ytdlp = get_ytdlp_path(app).map(|p| p.exists()).unwrap_or(false);
|
||||
let qjs = get_qjs_path(app).map(|p| p.exists()).unwrap_or(false);
|
||||
let ffmpeg = get_ffmpeg_path(app).map(|p| p.exists()).unwrap_or(false);
|
||||
ytdlp && qjs && ffmpeg
|
||||
get_ytdlp_path(app).map(|p| p.exists()).unwrap_or(false)
|
||||
}
|
||||
|
||||
// --- yt-dlp Logic ---
|
||||
@@ -436,6 +454,10 @@ pub async fn update_ffmpeg(app: &AppHandle) -> Result<String> {
|
||||
}
|
||||
|
||||
pub fn get_ffmpeg_version(app: &AppHandle) -> Result<String> {
|
||||
if let Some(version) = run_version_command("ffmpeg", "-version") {
|
||||
return Ok(version);
|
||||
}
|
||||
|
||||
let path = get_ffmpeg_path(app)?;
|
||||
if !path.exists() {
|
||||
return Ok("未安装".to_string());
|
||||
@@ -505,37 +527,138 @@ pub async fn ensure_binaries(app: &AppHandle) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let qjs = get_qjs_path(app)?;
|
||||
if !qjs.exists() {
|
||||
download_qjs(app).await?;
|
||||
} else {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
std::process::Command::new("xattr")
|
||||
.arg("-d")
|
||||
.arg("com.apple.quarantine")
|
||||
.arg(&qjs)
|
||||
.output()
|
||||
.ok();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_version_command(command: &str, arg: &str) -> Option<String> {
|
||||
let mut cmd = std::process::Command::new(command);
|
||||
cmd.arg(arg);
|
||||
#[cfg(target_os = "windows")]
|
||||
cmd.creation_flags(0x08000000);
|
||||
|
||||
cmd.output()
|
||||
.ok()
|
||||
.filter(|output| output.status.success())
|
||||
.and_then(|output| first_non_empty_line(&output))
|
||||
}
|
||||
|
||||
pub fn resolve_ffmpeg(app: &AppHandle, allow_download: bool) -> Result<Option<FfmpegLocation>> {
|
||||
if run_version_command("ffmpeg", "-version").is_some() {
|
||||
return Ok(Some(FfmpegLocation::System));
|
||||
}
|
||||
|
||||
let managed = get_ffmpeg_path(app)?;
|
||||
if managed.exists() {
|
||||
return Ok(Some(FfmpegLocation::Managed(managed)));
|
||||
}
|
||||
|
||||
if allow_download {
|
||||
return Ok(Some(FfmpegLocation::Managed(managed)));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub async fn ensure_ffmpeg_available(app: &AppHandle) -> Result<Option<FfmpegLocation>> {
|
||||
if let Some(location) = resolve_ffmpeg(app, false)? {
|
||||
return Ok(Some(location));
|
||||
}
|
||||
|
||||
let path = download_ffmpeg(app).await?;
|
||||
Ok(Some(FfmpegLocation::Managed(path)))
|
||||
}
|
||||
|
||||
pub fn resolve_js_runtime(app: &AppHandle, allow_download: bool) -> Result<Option<JsRuntime>> {
|
||||
if run_version_command("deno", "--version").is_some() {
|
||||
return Ok(Some(JsRuntime::Deno));
|
||||
}
|
||||
|
||||
if run_version_command("node", "--version").is_some() {
|
||||
return Ok(Some(JsRuntime::Node));
|
||||
}
|
||||
|
||||
let managed = get_qjs_path(app)?;
|
||||
if managed.exists() {
|
||||
return Ok(Some(JsRuntime::ManagedQuickJs(managed)));
|
||||
}
|
||||
|
||||
if allow_download {
|
||||
return Ok(Some(JsRuntime::ManagedQuickJs(managed)));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub async fn ensure_js_runtime_available(app: &AppHandle) -> Result<Option<JsRuntime>> {
|
||||
if let Some(runtime) = resolve_js_runtime(app, false)? {
|
||||
return Ok(Some(runtime));
|
||||
}
|
||||
|
||||
let path = download_qjs(app).await?;
|
||||
Ok(Some(JsRuntime::ManagedQuickJs(path)))
|
||||
}
|
||||
|
||||
impl FfmpegLocation {
|
||||
pub fn source_label(&self) -> &'static str {
|
||||
match self {
|
||||
FfmpegLocation::System => "system",
|
||||
FfmpegLocation::Managed(_) => "managed",
|
||||
}
|
||||
}
|
||||
|
||||
let ffmpeg = get_ffmpeg_path(app)?;
|
||||
if !ffmpeg.exists() {
|
||||
download_ffmpeg(app).await?;
|
||||
} else {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
std::process::Command::new("xattr")
|
||||
.arg("-d")
|
||||
.arg("com.apple.quarantine")
|
||||
.arg(&ffmpeg)
|
||||
.output()
|
||||
.ok();
|
||||
pub fn version(&self, app: &AppHandle) -> Result<String> {
|
||||
match self {
|
||||
FfmpegLocation::System => Ok(run_version_command("ffmpeg", "-version").unwrap_or_else(|| "未知".to_string())),
|
||||
FfmpegLocation::Managed(_) => get_ffmpeg_version(app),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl JsRuntime {
|
||||
pub fn source_label(&self) -> &'static str {
|
||||
match self {
|
||||
JsRuntime::Deno | JsRuntime::Node => "system",
|
||||
JsRuntime::ManagedQuickJs(_) => "managed",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_name(&self, app: &AppHandle) -> Result<String> {
|
||||
match self {
|
||||
JsRuntime::Deno => Ok(run_version_command("deno", "--version").unwrap_or_else(|| "deno".to_string())),
|
||||
JsRuntime::Node => Ok(run_version_command("node", "--version").unwrap_or_else(|| "node".to_string())),
|
||||
JsRuntime::ManagedQuickJs(_) => get_qjs_version(app),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yt_dlp_argument(&self) -> String {
|
||||
match self {
|
||||
JsRuntime::Deno => "deno".to_string(),
|
||||
JsRuntime::Node => "node".to_string(),
|
||||
JsRuntime::ManagedQuickJs(path) => format!("quickjs:{}", path.to_string_lossy()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_runtime_status(app: &AppHandle) -> Result<RuntimeStatus> {
|
||||
let ffmpeg = resolve_ffmpeg(app, false)?;
|
||||
let js_runtime = resolve_js_runtime(app, false)?;
|
||||
|
||||
let (ffmpeg_source, ffmpeg_version) = match ffmpeg {
|
||||
Some(location) => (location.source_label().to_string(), location.version(app)?),
|
||||
None => ("unavailable".to_string(), "未安装".to_string()),
|
||||
};
|
||||
|
||||
let (js_runtime_name, js_runtime_source) = match js_runtime {
|
||||
Some(runtime) => (runtime.display_name(app)?, runtime.source_label().to_string()),
|
||||
None => ("未安装".to_string(), "unavailable".to_string()),
|
||||
};
|
||||
|
||||
Ok(RuntimeStatus {
|
||||
ffmpeg_source,
|
||||
ffmpeg_version,
|
||||
js_runtime_name,
|
||||
js_runtime_source,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user