tauri-plugin-libmpv-api
Version:
A Tauri plugin for embedding the mpv player in your app via libmpv.
227 lines (222 loc) • 8.44 kB
JavaScript
;
var fs = require('fs');
var path = require('path');
var os = require('os');
var promises = require('stream/promises');
var SevenZip = require('7z-wasm');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
const TARGET_DIR = path__namespace.join(process.cwd(), 'src-tauri', 'lib');
const TEMP_DIR = path__namespace.join(TARGET_DIR, 'temp');
const WRAPPER_BASE_URL = "https://github.com/nini22P/libmpv-wrapper/releases/latest/download";
const MPV_BASE_URL = "https://github.com/zhongfly/mpv-winbuild/releases/latest/download";
const COLORS = {
Reset: "\x1b[0m",
Red: "\x1b[31m",
Green: "\x1b[32m",
Yellow: "\x1b[33m",
Cyan: "\x1b[36m",
Gray: "\x1b[90m",
};
function log(message, color = COLORS.Reset) {
console.log(`${color}${message}${COLORS.Reset}`);
}
function errorExit(message) {
console.error(`${COLORS.Red}Error: ${message}${COLORS.Reset}`);
process.exit(1);
}
function getSystemInfo() {
const platform = os__namespace.platform();
const arch = os__namespace.arch();
let osName = '', archName = '', wrapperLibName = '';
if (platform === 'win32') {
osName = 'windows';
wrapperLibName = 'libmpv-wrapper.dll';
}
else if (platform === 'darwin') {
osName = 'macos';
wrapperLibName = 'libmpv-wrapper.dylib';
}
else if (platform === 'linux') {
osName = 'linux';
wrapperLibName = 'libmpv-wrapper.so';
}
else {
errorExit(`Unsupported platform: ${platform}`);
}
if (arch === 'x64')
archName = 'x86_64';
else if (arch === 'arm64')
archName = 'aarch64';
else
errorExit(`Unsupported architecture: ${arch}`);
return { platform, osName, archName, wrapperLibName };
}
async function downloadFile(url, destPath) {
const res = await fetch(url);
if (!res.ok)
throw new Error(`Failed to fetch ${url}: ${res.statusText}`);
if (!res.body)
throw new Error(`Response body is empty for ${url}`);
const fileStream = fs.createWriteStream(destPath);
await promises.pipeline(res.body, fileStream);
}
async function extractArchive(archivePath, extractDir) {
if (fs__namespace.existsSync(extractDir)) {
fs__namespace.rmSync(extractDir, { recursive: true, force: true });
}
fs__namespace.mkdirSync(extractDir, { recursive: true });
const archiveName = path__namespace.basename(archivePath);
const archiveDir = path__namespace.dirname(archivePath);
log(` Extracting ${archiveName}...`, COLORS.Cyan);
const sevenZip = await SevenZip({
print: (s) => { },
printErr: (s) => { }
});
const mountSrc = "/archive_source";
const mountDest = "/archive_dest";
sevenZip.FS.mkdir(mountSrc);
sevenZip.FS.mkdir(mountDest);
sevenZip.FS.mount(sevenZip.NODEFS, { root: archiveDir }, mountSrc);
sevenZip.FS.mount(sevenZip.NODEFS, { root: extractDir }, mountDest);
const vArchivePath = `${mountSrc}/${archiveName}`;
const args = ["x", vArchivePath, `-o${mountDest}`, "-y"];
try {
sevenZip.callMain(args);
}
catch (err) {
if (err && err.status === 0) ;
else {
throw new Error(`7z extraction failed: ${err}`);
}
}
finally {
try {
sevenZip.FS.unmount(mountSrc);
sevenZip.FS.unmount(mountDest);
}
catch (e) { }
}
}
function findAndMove(searchDir, fileName, destDir) {
let foundPath = null;
function search(dir) {
const files = fs__namespace.readdirSync(dir);
for (const file of files) {
const fullPath = path__namespace.join(dir, file);
if (file.startsWith('.'))
continue;
try {
const stat = fs__namespace.statSync(fullPath);
if (stat.isDirectory()) {
search(fullPath);
}
else if (file === fileName) {
foundPath = fullPath;
return;
}
}
catch (e) { }
if (foundPath)
return;
}
}
search(searchDir);
if (foundPath) {
const destPath = path__namespace.join(destDir, fileName);
fs__namespace.renameSync(foundPath, destPath);
log(` -> ${fileName} downloaded successfully.`, COLORS.Green);
}
else {
throw new Error(`${fileName} not found in extracted files.`);
}
}
async function runSetup() {
const { platform, osName, archName, wrapperLibName } = getSystemInfo();
log(`Detected System: ${osName} (${archName})`, COLORS.Yellow);
if (!fs__namespace.existsSync(TEMP_DIR))
fs__namespace.mkdirSync(TEMP_DIR, { recursive: true });
if (!fs__namespace.existsSync(TARGET_DIR))
fs__namespace.mkdirSync(TARGET_DIR, { recursive: true });
log("\n[1/2] Processing libmpv-wrapper...", COLORS.Cyan);
try {
const shaUrl = `${WRAPPER_BASE_URL}/sha256.txt`;
const response = await fetch(shaUrl);
const shaContent = await response.text();
const searchKey = `libmpv-wrapper-${osName}-${archName}`;
const line = shaContent.split('\n').find(l => l.includes(searchKey));
if (!line)
throw new Error(`Could not find '${searchKey}' in SHA256 file.`);
const fileName = line.trim().split(/\s+/).pop();
log(` Found file: ${fileName}`, COLORS.Yellow);
const zipPath = path__namespace.join(TEMP_DIR, fileName);
log(" Downloading...");
await downloadFile(`${WRAPPER_BASE_URL}/${fileName}`, zipPath);
const extractDir = path__namespace.join(TEMP_DIR, 'wrapper_extract');
await extractArchive(zipPath, extractDir);
findAndMove(extractDir, wrapperLibName, TARGET_DIR);
}
catch (err) {
errorExit(`Failed to process libmpv-wrapper: ${err}`);
}
if (platform === 'win32') {
log("\n[2/2] Processing libmpv (Windows)...", COLORS.Cyan);
try {
const shaUrl = `${MPV_BASE_URL}/sha256.txt`;
const response = await fetch(shaUrl);
const shaContent = await response.text();
const searchKey = `mpv-dev-lgpl-${archName}`;
const line = shaContent.split('\n').find(l => l.includes(searchKey) && !l.includes('v3'));
if (!line)
throw new Error(`Could not find '${searchKey}' (non-v3) in SHA256 file.`);
const fileName = line.trim().split(/\s+/).pop();
log(` Found file: ${fileName}`, COLORS.Yellow);
const archivePath = path__namespace.join(TEMP_DIR, fileName);
log(" Downloading (this file is large)...");
await downloadFile(`${MPV_BASE_URL}/${fileName}`, archivePath);
const extractDir = path__namespace.join(TEMP_DIR, 'libmpv_extract');
await extractArchive(archivePath, extractDir);
findAndMove(extractDir, 'libmpv-2.dll', TARGET_DIR);
}
catch (err) {
errorExit(`Failed to process libmpv: ${err}`);
}
}
else {
log("\n[2/2] Skipping libmpv download (Non-Windows)", COLORS.Gray);
log("NOTE: On macOS/Linux, ensure system libmpv is installed.", COLORS.Yellow);
}
log("\nCleaning up temporary files...", COLORS.Gray);
try {
fs__namespace.rmSync(TEMP_DIR, { recursive: true, force: true });
}
catch (e) { }
log("\nSUCCESS! Libraries are set up in src-tauri/lib", COLORS.Green);
}
const args = process.argv.slice(2);
if (args[0] === 'setup-lib') {
runSetup();
}
else {
console.log("Usage: npx tauri-plugin-libmpv-api setup-lib");
console.log("\nCommands:");
console.log(" setup-lib Download and configure libmpv libraries automatically.");
}