diff --git a/app/src/converter.js b/app/src/converter.js index 0fe98d71..82183c0d 100644 --- a/app/src/converter.js +++ b/app/src/converter.js @@ -35,205 +35,205 @@ function ExecConverter(args) { exports.star_listening = () => { -const convertChildren = new Map(); + const convertChildren = new Map(); -rpc.listen({ + rpc.listen({ - "abortConvert": (pid) => { - let child = convertChildren.get(pid); - if (child && child.exitCode == null) { - child.kill(); - } - }, + "abortConvert": (pid) => { + let child = convertChildren.get(pid); + if (child && child.exitCode == null) { + child.kill(); + } + }, - // FIXME: Partly in test suite. But just for hls retrieval. - "convert": async (args = ["-h"], options = {}) => { - // `-progress pipe:1` send program-friendly progress information to stdin every 500ms. - // `-hide_banner -loglevel error`: make the output less noisy. + // FIXME: Partly in test suite. But just for hls retrieval. + "convert": async (args = ["-h"], options = {}) => { + // `-progress pipe:1` send program-friendly progress information to stdin every 500ms. + // `-hide_banner -loglevel error`: make the output less noisy. - // This should never happen, but just in case a third party does a convert request - // with the old version of ffmpeg arguments, let's rewrite the arguments to fit - // the new syntax. - let fixed = false; - for (let i = 0; i < args.length; i++) { - if (args[i].startsWith("[1:v][2:v] overlay=") && !args[i].endsWith("[m]")) { - args[i] += " [m]"; - fixed = true; - } - if (fixed && args[i] == "1:v") { - args[i] = "[m]"; + // This should never happen, but just in case a third party does a convert request + // with the old version of ffmpeg arguments, let's rewrite the arguments to fit + // the new syntax. + let fixed = false; + for (let i = 0; i < args.length; i++) { + if (args[i].startsWith("[1:v][2:v] overlay=") && !args[i].endsWith("[m]")) { + args[i] += " [m]"; + fixed = true; + } + if (fixed && args[i] == "1:v") { + args[i] = "[m]"; + } } - } - const ffmpeg_base_args = "-progress pipe:1 -hide_banner -loglevel error"; - args = [...ffmpeg_base_args.split(" "), ...args]; + const ffmpeg_base_args = "-progress pipe:1 -hide_banner -loglevel error"; + args = [...ffmpeg_base_args.split(" "), ...args]; - const child = spawn(ffmpeg, args); + const child = spawn(ffmpeg, args); - if (!child.pid) { - throw new Error("Process creation failed"); - } + if (!child.pid) { + throw new Error("Process creation failed"); + } - convertChildren.set(child.pid, child); + convertChildren.set(child.pid, child); - let stderr = ""; + let stderr = ""; - let on_exit = new Promise((resolve) => { - child.on("exit", (code) => { - convertChildren.delete(child.pid); - resolve({exitCode: code, pid: child.pid, stderr}); + let on_exit = new Promise((resolve) => { + child.on("exit", (code) => { + convertChildren.delete(child.pid); + resolve({exitCode: code, pid: child.pid, stderr}); + }); }); - }); - child.stderr.on("data", (data) => stderr += data); + child.stderr.on("data", (data) => stderr += data); - if (options.startHandler) { - rpc.call("convertStartNotification", options.startHandler, child.pid); - } + if (options.startHandler) { + rpc.call("convertStartNotification", options.startHandler, child.pid); + } - const PROPS_RE = new RegExp("\\S+=\\s*\\S+"); - const NAMEVAL_RE = new RegExp("(\\S+)=\\s*(\\S+)"); - let progressInfo = {}; + const PROPS_RE = new RegExp("\\S+=\\s*\\S+"); + const NAMEVAL_RE = new RegExp("(\\S+)=\\s*(\\S+)"); + let progressInfo = {}; - const on_line = async (line) => { - let props = line.match(PROPS_RE) || []; - props.forEach((prop) => { - let m = NAMEVAL_RE.exec(prop); - if (m) { - progressInfo[m[1]] = m[2]; - } - }); - // last line of block is "progress" - if (progressInfo["progress"]) { - let info = progressInfo; - progressInfo = {}; - if (typeof info["out_time_ms"] !== "undefined") { - // out_time_ms is in ns, not ms. - const seconds = parseInt(info["out_time_ms"]) / 1_000_000; - try { - await rpc.call("convertOutput", options.progressTime, seconds, info); - } catch (_) { - // Extension stopped caring - child.kill(); + const on_line = async (line) => { + let props = line.match(PROPS_RE) || []; + props.forEach((prop) => { + let m = NAMEVAL_RE.exec(prop); + if (m) { + progressInfo[m[1]] = m[2]; + } + }); + // last line of block is "progress" + if (progressInfo["progress"]) { + let info = progressInfo; + progressInfo = {}; + if (typeof info["out_time_ms"] !== "undefined") { + // out_time_ms is in ns, not ms. + const seconds = parseInt(info["out_time_ms"]) / 1_000_000; + try { + await rpc.call("convertOutput", options.progressTime, seconds, info); + } catch (_) { + // Extension stopped caring + child.kill(); + } } } - } - }; - - if (options.progressTime) { - child.stdout.on("data", (lines) => { - lines.toString("utf-8").split("\n").forEach(on_line); - }); - } + }; - return on_exit; - }, - // FIXME: Partly in test suite. But just for hls retrieval. - "probe": (input, json = false) => { - return new Promise((resolve, reject) => { - let args = []; - if (json) { - args = ["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams"]; + if (options.progressTime) { + child.stdout.on("data", (lines) => { + lines.toString("utf-8").split("\n").forEach(on_line); + }); } - args.push(input); - let probeProcess = spawn(ffprobe, args); - let stdout = ""; - let stderr = ""; - probeProcess.stdout.on("data", (data) => stdout += data); - probeProcess.stderr.on("data", (data) => stderr += data); - probeProcess.on("exit", (exitCode) => { - if (exitCode !== 0) { - return reject(new Error("Exit code: " + exitCode + "\n" + stderr)); - } + + return on_exit; + }, + // FIXME: Partly in test suite. But just for hls retrieval. + "probe": (input, json = false) => { + return new Promise((resolve, reject) => { + let args = []; if (json) { - // FIXME: not parsed? - resolve(stdout); - } else { - let info = {}; - let m = /([0-9]{2,})x([0-9]{2,})/g.exec(stderr); - if (m) { - info.width = parseInt(m[1]); - info.height = parseInt(m[2]); - } - m = /Duration: ([0-9]{2}):([0-9]{2}):([0-9]{2})\.([0-9]{2})/g.exec(stderr); - if (m) { - info.duration = parseInt(m[1]) * 3600 + parseInt(m[2]) * 60 + parseInt(m[3]); - } - m = /Video:\s+([^\s\(,]+)/g.exec(stderr); - if (m) { - info.videoCodec = m[1]; - } - m = /Audio:\s+([^\s\(,]+)/g.exec(stderr); - if (m) { - info.audioCodec = m[1]; - } - m = /([0-9]+(?:\.[0-9]+)?)\s+fps\b/g.exec(stderr); - if (m) { - info.fps = parseFloat(m[1]); - } - resolve(info); + args = ["-v", "quiet", "-print_format", "json", "-show_format", "-show_streams"]; } - }); - }); - }, - // FIXME: test (partly because open result is untested) - "play": (filePath) => { - return new Promise((resolve, _reject) => { - open(filePath); - resolve(); - }); - }, - // In test suite - "codecs": () => { - return ExecConverter(["-codecs"]) - .then((out) => { - let lines = out.split("\n"); - let result = {}; - lines.forEach((line) => { - let m = /^\s*(\.|D)(\.|E)(\.|V|A|S)(\.|I)(\.|L)(\.|S)\s+([^\s]+)\s+(.*?)\s*$/.exec(line); - if (!m || m[7] === '=') { - return; + args.push(input); + let probeProcess = spawn(ffprobe, args); + let stdout = ""; + let stderr = ""; + probeProcess.stdout.on("data", (data) => stdout += data); + probeProcess.stderr.on("data", (data) => stderr += data); + probeProcess.on("exit", (exitCode) => { + if (exitCode !== 0) { + return reject(new Error("Exit code: " + exitCode + "\n" + stderr)); } - result[m[7]] = { - d: m[1] != ".", - e: m[2] != ".", - t: m[3] == "." && null || m[3], - i: m[4] != ".", - l: m[5] != ".", - s: m[6] != ".", - _: m[8] - }; - }); - return result; - }); - }, - // In test suite - "formats": () => { - return ExecConverter(["-formats"]) - .then((out) => { - let lines = out.split("\n"); - let result = {}; - lines.forEach((line) => { - let m = /^\s*(\.| |D)(\.| |E)\s+([^\s]+)\s+(.*?)\s*$/.exec(line); - if (!m || m[3] === '=') { - return; + if (json) { + // FIXME: not parsed? + resolve(stdout); + } else { + let info = {}; + let m = /([0-9]{2,})x([0-9]{2,})/g.exec(stderr); + if (m) { + info.width = parseInt(m[1]); + info.height = parseInt(m[2]); + } + m = /Duration: ([0-9]{2}):([0-9]{2}):([0-9]{2})\.([0-9]{2})/g.exec(stderr); + if (m) { + info.duration = parseInt(m[1]) * 3600 + parseInt(m[2]) * 60 + parseInt(m[3]); + } + m = /Video:\s+([^\s\(,]+)/g.exec(stderr); + if (m) { + info.videoCodec = m[1]; + } + m = /Audio:\s+([^\s\(,]+)/g.exec(stderr); + if (m) { + info.audioCodec = m[1]; + } + m = /([0-9]+(?:\.[0-9]+)?)\s+fps\b/g.exec(stderr); + if (m) { + info.fps = parseFloat(m[1]); + } + resolve(info); } - result[m[3]] = { - d: m[1] == "D", - e: m[2] == "E", - _: m[4] - }; }); - return result; }); - }, - // In test suite, but just to check if not throwing. - "open": (filePath, options = {}) => { - return open(filePath, options); - }, + }, + // FIXME: test (partly because open result is untested) + "play": (filePath) => { + return new Promise((resolve, _reject) => { + open(filePath); + resolve(); + }); + }, + // In test suite + "codecs": () => { + return ExecConverter(["-codecs"]) + .then((out) => { + let lines = out.split("\n"); + let result = {}; + lines.forEach((line) => { + let m = /^\s*(\.|D)(\.|E)(\.|V|A|S)(\.|I)(\.|L)(\.|S)\s+([^\s]+)\s+(.*?)\s*$/.exec(line); + if (!m || m[7] === '=') { + return; + } + result[m[7]] = { + d: m[1] != ".", + e: m[2] != ".", + t: m[3] == "." && null || m[3], + i: m[4] != ".", + l: m[5] != ".", + s: m[6] != ".", + _: m[8] + }; + }); + return result; + }); + }, + // In test suite + "formats": () => { + return ExecConverter(["-formats"]) + .then((out) => { + let lines = out.split("\n"); + let result = {}; + lines.forEach((line) => { + let m = /^\s*(\.| |D)(\.| |E)\s+([^\s]+)\s+(.*?)\s*$/.exec(line); + if (!m || m[3] === '=') { + return; + } + result[m[3]] = { + d: m[1] == "D", + e: m[2] == "E", + _: m[4] + }; + }); + return result; + }); + }, + // In test suite, but just to check if not throwing. + "open": (filePath, options = {}) => { + return open(filePath, options); + }, -}); -} + }); +}; exports.info = () => { return new Promise((resolve, reject) => { diff --git a/app/src/main.js b/app/src/main.js index 28a1c5eb..47b92de1 100644 --- a/app/src/main.js +++ b/app/src/main.js @@ -33,9 +33,9 @@ if (process.argv[2] == "install") { } else if (process.argv[2] == "--version") { console.log(config.meta.version); } else if (process.argv[2] == "--info") { - info().then(info => { + info().then((info) => { console.log(JSON.stringify(info, null, " ")); - }).catch(error => { + }).catch((error) => { console.error(error); }); } else if (process.argv[2] == "--help") { diff --git a/app/src/native-autoinstall.js b/app/src/native-autoinstall.js index 37593555..556a22bf 100644 --- a/app/src/native-autoinstall.js +++ b/app/src/native-autoinstall.js @@ -109,7 +109,9 @@ async function SetupFiles(platform, mode, uninstall) { try { await fs.unlink(op.path); console.log(`Removing file ${op.path}`); - } catch (_) { } + } catch (_) { + // Nothing to unlink + } } else { try { console.log(`Writing ${op.path}`); diff --git a/tests/codecs.mjs b/tests/codecs.mjs index 3b52481a..5051ee4f 100644 --- a/tests/codecs.mjs +++ b/tests/codecs.mjs @@ -1021,15 +1021,6 @@ export const expected_codecs = { s: false, _: 'Escape 130' }, - evc: { - d: false, - e: false, - t: 'V', - i: false, - l: true, - s: false, - _: 'MPEG-5 EVC (Essential Video Coding)' - }, exr: { d: true, e: true, @@ -1381,7 +1372,7 @@ export const expected_codecs = { i: true, l: true, s: true, - _: 'JPEG 2000 (encoders: jpeg2000 libopenjpeg )' + _: 'JPEG 2000 (decoders: jpeg2000 libopenjpeg ) (encoders: jpeg2000 libopenjpeg )' }, jpegls: { d: true, e: true, t: 'V', i: true, l: true, s: true, _: 'JPEG-LS' }, jpegxl: { @@ -1630,7 +1621,7 @@ export const expected_codecs = { }, msrle: { d: true, - e: true, + e: false, t: 'V', i: false, l: false, @@ -1799,15 +1790,6 @@ export const expected_codecs = { s: true, _: 'PC Paintbrush PCX image' }, - pdv: { - d: true, - e: false, - t: 'V', - i: false, - l: true, - s: false, - _: 'PDV (PlayDate Video)' - }, pfm: { d: true, e: true, @@ -2042,15 +2024,6 @@ export const expected_codecs = { s: true, _: 'innoHeim/Rsupport Screen Capture Codec' }, - rtv1: { - d: true, - e: false, - t: 'V', - i: true, - l: true, - s: false, - _: 'RTV1 (RivaTuner Video)' - }, rv10: { d: true, e: true, @@ -2530,15 +2503,6 @@ export const expected_codecs = { s: false, _: 'Sierra VMD video' }, - vmix: { - d: true, - e: false, - t: 'V', - i: true, - l: true, - s: false, - _: 'vMix Video' - }, vmnc: { d: true, e: false, @@ -2926,15 +2890,6 @@ export const expected_codecs = { s: false, _: 'ATSC A/52A (AC-3) (decoders: ac3 ac3_fixed ) (encoders: ac3 ac3_fixed )' }, - ac4: { - d: false, - e: false, - t: 'A', - i: false, - l: true, - s: false, - _: 'AC-4' - }, 'acelp.kelvin': { d: true, e: false, diff --git a/tests/test.mjs b/tests/test.mjs index ea2f1ac2..cbeedbd9 100755 --- a/tests/test.mjs +++ b/tests/test.mjs @@ -191,9 +191,9 @@ let old_coapp; let os_arch = os.arch(); if (os_arch == "arm64") { - assert("info.target_arch", info.target_arch, "arm64"); + assert("info.target.arch", info.target.arch, "arm64"); } else if (os_arch == "x64") { - assert("info.target_arch", info.target_arch, "x86_64"); + assert("info.target.arch", info.target.arch, "x86_64"); } else { assert_true("info.target_arch", false); }