Files
multi_render_blender/src/main/PathResolver.js

263 lines
8.5 KiB
JavaScript

const path = require("path");
const fs = require("fs");
const { app } = require("electron");
const { execFileSync } = require("child_process");
const STR_EXE_NAME = process.platform === "win32" ? "blender.exe" : "blender";
const STR_CONFIG_FILE = "blender_path.json";
const STR_FFMPEG_CONFIG_FILE = "ffmpeg_path.json";
const PathResolver = {
_str_blender_path: null,
_is_found: false,
_str_ffmpeg_path: null,
_is_ffmpeg_found: false,
load_saved_path: () => {
let str_config_path = PathResolver._get_config_path();
try {
if (fs.existsSync(str_config_path)) {
let str_content = fs.readFileSync(str_config_path, "utf8");
let obj_data = JSON.parse(str_content);
if (obj_data.str_path && fs.existsSync(obj_data.str_path)) {
PathResolver._str_blender_path = obj_data.str_path;
PathResolver._is_found = true;
return;
}
}
} catch (obj_err) {
console.error("PathResolver: impossible de lire la config :", obj_err.message);
}
let str_detected = PathResolver.auto_detect();
if (str_detected) {
PathResolver._str_blender_path = str_detected;
PathResolver._is_found = true;
} else {
PathResolver._str_blender_path = "blender";
PathResolver._is_found = false;
}
},
get_blender_path: () => {
if (!PathResolver._str_blender_path) {
PathResolver.load_saved_path();
}
return PathResolver._str_blender_path;
},
is_found: () => {
return PathResolver._is_found;
},
set_blender_path: (str_path) => {
if (!str_path || !fs.existsSync(str_path)) {
return { is_success: false, str_error: "Fichier introuvable : " + str_path };
}
PathResolver._str_blender_path = str_path;
PathResolver._is_found = true;
let str_config_path = PathResolver._get_config_path();
try {
let str_dir = path.dirname(str_config_path);
if (!fs.existsSync(str_dir)) {
fs.mkdirSync(str_dir, { recursive: true });
}
fs.writeFileSync(str_config_path, JSON.stringify({ str_path: str_path }, null, 4), "utf8");
} catch (obj_err) {
console.error("PathResolver: impossible de sauvegarder :", obj_err.message);
}
return { is_success: true, str_path: str_path };
},
auto_detect: () => {
if (process.platform === "win32") {
return PathResolver._auto_detect_windows();
}
return PathResolver._auto_detect_linux();
},
get_status: () => {
return {
str_path: PathResolver._str_blender_path || "blender",
is_found: PathResolver._is_found,
};
},
// ── FFmpeg ───────────────────────────────────────────────
load_saved_ffmpeg_path: () => {
let str_config_path = PathResolver._get_ffmpeg_config_path();
try {
if (fs.existsSync(str_config_path)) {
let str_content = fs.readFileSync(str_config_path, "utf8");
let obj_data = JSON.parse(str_content);
if (obj_data.str_path && fs.existsSync(obj_data.str_path)) {
PathResolver._str_ffmpeg_path = obj_data.str_path;
PathResolver._is_ffmpeg_found = true;
return;
}
}
} catch (obj_err) {
console.error("PathResolver: impossible de lire la config ffmpeg :", obj_err.message);
}
let str_detected = PathResolver._auto_detect_ffmpeg();
if (str_detected) {
PathResolver._str_ffmpeg_path = str_detected;
PathResolver._is_ffmpeg_found = true;
} else {
PathResolver._str_ffmpeg_path = "ffmpeg";
PathResolver._is_ffmpeg_found = false;
}
},
get_ffmpeg_path: () => {
if (!PathResolver._str_ffmpeg_path) {
PathResolver.load_saved_ffmpeg_path();
}
return PathResolver._str_ffmpeg_path;
},
set_ffmpeg_path: (str_path) => {
if (!str_path || !fs.existsSync(str_path)) {
return { is_success: false, str_error: "Fichier introuvable : " + str_path };
}
PathResolver._str_ffmpeg_path = str_path;
PathResolver._is_ffmpeg_found = true;
let str_config_path = PathResolver._get_ffmpeg_config_path();
try {
let str_dir = path.dirname(str_config_path);
if (!fs.existsSync(str_dir)) {
fs.mkdirSync(str_dir, { recursive: true });
}
fs.writeFileSync(str_config_path, JSON.stringify({ str_path: str_path }, null, 4), "utf8");
} catch (obj_err) {
console.error("PathResolver: impossible de sauvegarder ffmpeg :", obj_err.message);
}
return { is_success: true, str_path: str_path };
},
get_ffmpeg_status: () => {
return {
str_path: PathResolver._str_ffmpeg_path || "ffmpeg",
is_found: PathResolver._is_ffmpeg_found,
};
},
_auto_detect_ffmpeg: () => {
let str_cmd = process.platform === "win32" ? "where" : "which";
let str_exe = process.platform === "win32" ? "ffmpeg.exe" : "ffmpeg";
try {
let str_result = execFileSync(str_cmd, [str_exe], { encoding: "utf8", timeout: 5000 }).trim();
let str_first = str_result.split("\n")[0].trim();
if (str_first && fs.existsSync(str_first)) {
return str_first;
}
} catch (obj_err) {
// not in PATH
}
if (process.platform !== "win32") {
let LIST_PATHS = [
"/usr/bin/ffmpeg",
"/usr/local/bin/ffmpeg",
"/snap/bin/ffmpeg",
];
for (let str_p of LIST_PATHS) {
if (fs.existsSync(str_p)) {
return str_p;
}
}
}
return null;
},
// ── Private ──────────────────────────────────────────────
_get_config_path: () => {
return path.join(app.getPath("userData"), STR_CONFIG_FILE);
},
_get_ffmpeg_config_path: () => {
return path.join(app.getPath("userData"), STR_FFMPEG_CONFIG_FILE);
},
_auto_detect_linux: () => {
let LIST_PATHS = [
"/usr/bin/blender",
"/snap/bin/blender",
"/usr/local/bin/blender",
"/opt/blender/blender",
];
try {
let str_result = execFileSync("which", ["blender"], { encoding: "utf8", timeout: 5000 }).trim();
if (str_result && fs.existsSync(str_result)) {
return str_result;
}
} catch (obj_err) {
// which not found or blender not in PATH
}
for (let str_path of LIST_PATHS) {
if (fs.existsSync(str_path)) {
return str_path;
}
}
return null;
},
_auto_detect_windows: () => {
try {
let str_result = execFileSync("where", ["blender.exe"], { encoding: "utf8", timeout: 5000 }).trim();
let str_first = str_result.split("\n")[0].trim();
if (str_first && fs.existsSync(str_first)) {
return str_first;
}
} catch (obj_err) {
// where not found or blender not in PATH
}
let LIST_BASES = [
process.env.PROGRAMFILES || "C:\\Program Files",
process.env["PROGRAMFILES(X86)"] || "C:\\Program Files (x86)",
];
for (let str_base of LIST_BASES) {
let str_foundation = path.join(str_base, "Blender Foundation");
if (!fs.existsSync(str_foundation)) {
continue;
}
try {
let list_dirs = fs.readdirSync(str_foundation);
for (let str_dir of list_dirs) {
let str_exe = path.join(str_foundation, str_dir, STR_EXE_NAME);
if (fs.existsSync(str_exe)) {
return str_exe;
}
}
} catch (obj_err) {
// permission denied or similar
}
}
return null;
},
};
module.exports = PathResolver;