diff --git a/README.md b/README.md index bca2e0b..a202dff 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Run this on the Linux desktop client that should receive `mpv-handler://` links, https://github.com/akiirui/mpv-handler/releases/latest/download/mpv-handler-linux-amd64.zip ``` -The upstream project currently publishes an official Linux release for `amd64` only. On Raspberry Pi or other ARM Linux systems, build or obtain a compatible `mpv-handler` binary first, then point `--root` at that extracted folder instead. +The upstream project currently publishes an official Linux release for `amd64` only. On Raspberry Pi or other ARM Linux systems, `npm run setup:mpv-handler` now tries to build a compatible binary automatically from upstream source if both `git` and Rust `cargo` are installed. If you prefer not to build locally, pass `--skip-source-build` and provide `--root` with a compatible extracted folder instead. 3. Run the helper against the extracted folder: @@ -92,7 +92,7 @@ The upstream project currently publishes an official Linux release for `amd64` o npm run setup:mpv-handler -- --root /path/to/extracted/mpv-handler-linux-amd64 ``` -On Linux the helper copies the binary and desktop files into `~/.local`, writes `config.toml` to `~/.config/mpv-handler/config.toml` (or `$XDG_CONFIG_HOME/mpv-handler/config.toml`), and runs `xdg-mime` for both protocol handlers. +On Linux the helper copies the binary and desktop files into `~/.local`, writes `config.toml` to `~/.config/mpv-handler/config.toml` (or `$XDG_CONFIG_HOME/mpv-handler/config.toml`), and runs `xdg-mime` for both protocol handlers. On non-`x64` Linux it also auto-builds a staged `mpv-handler` root under `~/.cache/api-mediaplayer/` before installing, unless you pass `--skip-source-build`. ### Android diff --git a/scripts/README.md b/scripts/README.md index 7596aa7..4d960b4 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -35,7 +35,7 @@ npm run uninstall:mpv-handler https://github.com/akiirui/mpv-handler/releases/latest/download/mpv-handler-linux-amd64.zip ``` -The official upstream Linux release is currently `amd64` only. On Raspberry Pi or other ARM Linux systems, build or obtain a compatible `mpv-handler` binary first and point `--root` at that extracted folder. +The official upstream Linux release is currently `amd64` only. On Raspberry Pi or other ARM Linux systems, `npm run setup:mpv-handler` now tries to build a compatible `mpv-handler` binary automatically from upstream source if both `git` and Rust `cargo` are installed. If you do not want that behavior, pass `--skip-source-build` and provide `--root` yourself. 2. Point the helper at that extracted folder: @@ -45,7 +45,7 @@ npm run setup:mpv-handler -- --root /path/to/extracted/mpv-handler-linux-amd64 Run this on the Linux desktop client that should handle `mpv-handler://`, not on the machine that is only serving the web app. -The helper copies files into `~/.local/bin` and `~/.local/share/applications`, writes config to `~/.config/mpv-handler/config.toml` (or `$XDG_CONFIG_HOME/mpv-handler/config.toml`), and runs `xdg-mime` for both protocol handlers. +The helper copies files into `~/.local/bin` and `~/.local/share/applications`, writes config to `~/.config/mpv-handler/config.toml` (or `$XDG_CONFIG_HOME/mpv-handler/config.toml`), and runs `xdg-mime` for both protocol handlers. On non-`x64` Linux it will first build and stage upstream source into `~/.cache/api-mediaplayer/` unless you pass `--skip-source-build`. ## Useful flags @@ -54,6 +54,7 @@ npm run setup:mpv-handler -- --help npm run setup:mpv-handler -- --root /path/to/mpv-handler npm run setup:mpv-handler -- --mpv /path/to/mpv npm run setup:mpv-handler -- --ytdl /path/to/yt-dlp +npm run setup:mpv-handler -- --skip-source-build npm run setup:mpv-handler -- --skip-config npm run setup:mpv-handler -- --dry-run ``` @@ -72,6 +73,7 @@ npm run setup:mpv-handler -- --dry-run ### Linux - validates the extracted upstream release layout +- auto-builds upstream source on non-`x64` Linux when no compatible local root is available and `git` plus `cargo` are installed - creates or updates `config.toml` - copies the handler binary to `~/.local/bin/mpv-handler` - copies the desktop entries to `~/.local/share/applications` diff --git a/scripts/setup-mpv-handler.mjs b/scripts/setup-mpv-handler.mjs index b3b182f..297f918 100644 --- a/scripts/setup-mpv-handler.mjs +++ b/scripts/setup-mpv-handler.mjs @@ -9,6 +9,8 @@ import { fileURLToPath } from 'node:url' const scriptPath = fileURLToPath(import.meta.url) const scriptDir = path.dirname(scriptPath) const templateConfigPath = path.join(scriptDir, 'config.toml') +const UPSTREAM_MPV_HANDLER_REPO = 'https://github.com/akiirui/mpv-handler.git' +const UPSTREAM_MPV_HANDLER_REF = 'v0.4.2' const usage = `Usage: npm run setup:mpv-handler @@ -19,6 +21,7 @@ Options: --root Path to the extracted mpv-handler folder. --mpv Override the mpv executable path written to config.toml. --ytdl Override the yt-dlp executable path written to config.toml. + --skip-source-build Linux only. Do not auto-build mpv-handler from source on non-x64 systems. --skip-config Do not create or update config.toml. --keep-existing Windows only. Keep existing protocol keys instead of replacing them. --dry-run Print the actions without changing files or running installers. @@ -35,6 +38,7 @@ function parseArgs(argv) { root: '', mpv: '', ytdl: '', + skipSourceBuild: false, skipConfig: false, keepExisting: false, dryRun: false, @@ -54,6 +58,11 @@ function parseArgs(argv) { continue } + if (value === '--skip-source-build') { + options.skipSourceBuild = true + continue + } + if (value === '--keep-existing') { options.keepExisting = true continue @@ -136,7 +145,7 @@ function looksLikeRoot(rootPath) { return requiredFiles.every((fileName) => isFile(path.join(rootPath, fileName))) } -function resolveRoot(options) { +function findRoot(options) { const candidates = [] if (options.root) candidates.push(path.resolve(options.root)) candidates.push(scriptDir) @@ -151,14 +160,78 @@ function resolveRoot(options) { } } + return '' +} + +function getLinuxCacheDir() { + const xdgCacheHome = process.env.XDG_CACHE_HOME?.trim() + return xdgCacheHome + ? path.join(xdgCacheHome, 'api-mediaplayer') + : path.join(os.homedir(), '.cache', 'api-mediaplayer') +} + +function runCommandOrFail(command, args, options) { + const result = spawnSync(command, args, options) + if (result.status === 0) return result + + const reason = result.error?.message || `exit code ${result.status ?? 'unknown'}` + fail(`${command} failed (${reason}).`) +} + +function prepareLinuxSourceBuildRoot(options) { + const gitPath = resolveOnPath(['git']) + const cargoPath = resolveOnPath(['cargo']) + + if (!gitPath || !cargoPath) { + fail(`Could not find a Linux mpv-handler release for ${process.arch}, and automatic source build requires both git and cargo on PATH. Install them or rerun with --root pointing at a compatible extracted mpv-handler folder.`) + } + + const cacheDir = getLinuxCacheDir() + const sourceDir = path.join(cacheDir, `mpv-handler-src-${UPSTREAM_MPV_HANDLER_REF}`) + const stageDir = path.join(cacheDir, `mpv-handler-linux-${process.arch}`) + + if (options.dryRun) { + console.log(`Dry run: would clone ${UPSTREAM_MPV_HANDLER_REPO} at ${UPSTREAM_MPV_HANDLER_REF} into ${sourceDir}`) + console.log(`Dry run: would build mpv-handler with cargo in ${sourceDir}`) + console.log(`Dry run: would stage Linux assets into ${stageDir}`) + return stageDir + } + + mkdirSync(cacheDir, { recursive: true }) + + if (!existsSync(sourceDir)) { + runCommandOrFail(gitPath, ['clone', '--depth', '1', '--branch', UPSTREAM_MPV_HANDLER_REF, UPSTREAM_MPV_HANDLER_REPO, sourceDir], { stdio: 'inherit' }) + } + + runCommandOrFail(cargoPath, ['build', '--release'], { cwd: sourceDir, stdio: 'inherit' }) + + mkdirSync(stageDir, { recursive: true }) + + copyFileSync(path.join(sourceDir, 'target', 'release', 'mpv-handler'), path.join(stageDir, 'mpv-handler')) + copyFileSync(path.join(sourceDir, 'share', 'linux', 'mpv-handler.desktop'), path.join(stageDir, 'mpv-handler.desktop')) + copyFileSync(path.join(sourceDir, 'share', 'linux', 'mpv-handler-debug.desktop'), path.join(stageDir, 'mpv-handler-debug.desktop')) + copyFileSync(path.join(sourceDir, 'share', 'linux', 'config.toml'), path.join(stageDir, 'config.toml')) + chmodSync(path.join(stageDir, 'mpv-handler'), 0o755) + + return stageDir +} + +function resolveRoot(options) { + const resolvedRoot = findRoot(options) + if (resolvedRoot) return resolvedRoot + if (process.platform === 'win32') { fail('Could not find mpv-handler files. Re-run with --root pointing at the extracted mpv-handler folder.') } if (process.platform === 'linux') { + if (process.arch !== 'x64' && !options.skipSourceBuild) { + return prepareLinuxSourceBuildRoot(options) + } + const archHint = process.arch === 'x64' ? 'Download and extract the upstream archive, then pass --root /path/to/extracted/mpv-handler-linux-amd64.' - : `The upstream project only publishes an official linux-amd64 archive. On ${process.arch}, build or obtain a compatible mpv-handler binary and pass --root /path/to/extracted/mpv-handler.` + : `The upstream project only publishes an official linux-amd64 archive. Install git and cargo to allow automatic source builds, or build/obtain a compatible mpv-handler binary and pass --root /path/to/extracted/mpv-handler.` fail(`Could not find a Linux mpv-handler release. ${archHint}`) }