From 62ba0054c429428c657b98ad5f2b02ecc44bcac6 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 13 Oct 2023 12:07:34 +0800 Subject: [PATCH 1/5] Better diagnoses from command line --- app/src/converter.js | 3 ++ app/src/main.js | 84 +++++++++++++++++++++++++------------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/app/src/converter.js b/app/src/converter.js index bc7e2463..0fe98d71 100644 --- a/app/src/converter.js +++ b/app/src/converter.js @@ -33,6 +33,8 @@ function ExecConverter(args) { }); } +exports.star_listening = () => { + const convertChildren = new Map(); rpc.listen({ @@ -231,6 +233,7 @@ rpc.listen({ }, }); +} exports.info = () => { return new Promise((resolve, reject) => { diff --git a/app/src/main.js b/app/src/main.js index c49d404d..28a1c5eb 100644 --- a/app/src/main.js +++ b/app/src/main.js @@ -1,4 +1,30 @@ const config = require('config.json'); +const converter = require('./converter'); +const os = require("os"); + +function info() { + let result = { + id: config.meta.id, + name: config.meta.name, + version: config.meta.version, + binary: process.execPath, + displayName: config.meta.name, + description: config.meta.description, + target: config.target, + home: os.homedir() || "" + }; + return converter.info().then((convInfo) => { + return Object.assign(result, { + converterBinary: convInfo.converterBinary, + converterBase: convInfo.program, + converterBaseVersion: convInfo.version + }); + }).catch((error) => { + return Object.assign(result, { + converterError: error.message + }); + }); +} if (process.argv[2] == "install") { require("./native-autoinstall").install(); @@ -6,26 +32,28 @@ if (process.argv[2] == "install") { require("./native-autoinstall").uninstall(); } else if (process.argv[2] == "--version") { console.log(config.meta.version); +} else if (process.argv[2] == "--info") { + info().then(info => { + console.log(JSON.stringify(info, null, " ")); + }).catch(error => { + console.error(error); + }); } else if (process.argv[2] == "--help") { let help = ` -vdhcoapp --help # this help -vdhcoapp --version # show coapp version -vdhcoapp install # register browser JSON files in browser-specific locations. -vdhcoapp uninstall # remove JSON files. +Commands: + vdhcoapp install # register browser JSON files in browser-specific locations. + vdhcoapp uninstall # remove JSON files. -Extra options: +Options: + --help # this help + --info # list extra info from converter + --version # show coapp version --user # force installation in user mode (automatic if run as non-root user) --system # force installation system wide (automatic if run as root user) `; console.log(help); } else { - console.error(` -vdhcoapp is running successfully. This is not intended to be used directly from the command line. You should press Ctrl+C to exit. If your browser is unable to detect the coapp, run: "vdhcoapp install". -`); - - const os = require("os"); - require('./native-messaging'); const logger = require('./logger'); const rpc = require('./weh-rpc'); @@ -33,12 +61,13 @@ vdhcoapp is running successfully. This is not intended to be used directly from rpc.setLogger(logger); rpc.setDebugLevel(2); - const converter = require('./converter'); require('./file'); require('./downloads'); require('./request'); require('./vm'); + converter.star_listening(); + rpc.listen({ // In test suite quit: () => { @@ -53,29 +82,12 @@ vdhcoapp is running successfully. This is not intended to be used directly from return arg; }, // In test suite - info: () => { - let result = { - id: config.meta.id, - name: config.meta.name, - version: config.meta.version, - binary: process.execPath, - displayName: config.meta.name, - description: config.meta.description, - target_os: config.target.os, - target_arch: config.target.arch, - home: os.homedir() || "" - }; - return converter.info().then((convInfo) => { - return Object.assign(result, { - converterBinary: convInfo.converterBinary, - converterBase: convInfo.program, - converterBaseVersion: convInfo.version - }); - }).catch((error) => { - return Object.assign(result, { - converterError: error.message - }); - }); - } + info, }); + + let m = `vdhcoapp is running successfully. `; + m += `This is not intended to be used directly from the command line. `; + m += `You should press Ctrl+C to exit. `; + m += `If your browser is unable to detect the coapp, run: "vdhcoapp install".`; + console.error(m); } From 52d67f9486075185df145967d76c93bb8f232b5e Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 13 Oct 2023 12:48:31 +0800 Subject: [PATCH 2/5] support for node 10 --- app/src/native-autoinstall.js | 21 +++-- app/src/open2.js | 3 + build.sh | 144 +++++++++++++++++++++++----------- 3 files changed, 115 insertions(+), 53 deletions(-) create mode 100644 app/src/open2.js diff --git a/app/src/native-autoinstall.js b/app/src/native-autoinstall.js index 1c21d1f2..37593555 100644 --- a/app/src/native-autoinstall.js +++ b/app/src/native-autoinstall.js @@ -1,9 +1,15 @@ const os = require("os"); -const fs = require("node:fs/promises"); const path = require("path"); const { spawn, exec } = require('child_process'); const config = require('config.json'); +let fs; +if (process.versions.node.startsWith("10")) { + fs = require('fs').promises; +} else { + fs = require('node:fs/promises'); +} + const STORES = Object.keys(config.store); function exec_p(cmd) { @@ -101,17 +107,18 @@ async function SetupFiles(platform, mode, uninstall) { for (let op of ops) { if (uninstall) { try { + await fs.unlink(op.path); console.log(`Removing file ${op.path}`); - await fs.rm(op.path, { force: true }); - } catch (err) { - DisplayMessage("Cannot delete manifest file: " + err.message, op.path); - process.exit(1); - } + } catch (_) { } } else { try { console.log(`Writing ${op.path}`); let dir = path.dirname(op.path); - await fs.mkdir(dir, { recursive: true }); + try { + await fs.mkdir(dir, { recursive: true }); + } catch (_) { + // With node 10, this fails if directory exists. + } const data = new Uint8Array(Buffer.from(op.content)); await fs.writeFile(op.path, data); } catch (err) { diff --git a/app/src/open2.js b/app/src/open2.js new file mode 100644 index 00000000..e4232ff4 --- /dev/null +++ b/app/src/open2.js @@ -0,0 +1,3 @@ +// This is a no-op open module for Node 10. +export default function open() { +} diff --git a/build.sh b/build.sh index 388ecc00..ce14350e 100755 --- a/build.sh +++ b/build.sh @@ -19,34 +19,6 @@ if ! [ -x "$(command -v yq)" ]; then error "yq not installed. See https://github.com/mikefarah/yq/#install" fi -if ! [ -x "$(command -v node)" ]; then - error "Node not installed" -fi - -if [[ $(node -v) != v18.* ]] -then - error "Wrong version of Node (expected v18)" -fi - -if ! [ -x "$(command -v esbuild)" ]; then - log "Installing esbuild" - npm install -g esbuild -fi - -if ! [ -x "$(command -v pkg)" ]; then - log "Installing pkg" - npm install -g pkg -fi - -if ! [ -x "$(command -v ejs)" ]; then - log "Installing ejs" - npm install -g ejs -fi - -if [ ! -d "app/node_modules" ]; then - (cd app/ ; npm install) -fi - dist_dir_name=dist host_os=$(uname -s) @@ -72,6 +44,7 @@ skip_packaging=0 skip_signing=0 skip_bundling=0 skip_notary=0 +target_node=18 while [[ "$#" -gt 0 ]]; do case $1 in @@ -82,13 +55,15 @@ while [[ "$#" -gt 0 ]]; do echo "--skip-packaging # skip packaging operations (including signing)" echo "--skip-signing # do not sign the binaries" echo "--skip-notary # do not send pkg to Apple's notary service" - echo "--target # os: linux / mac / windows, arch: x86_64 / i686 / arm64" + echo "--force-node10 # use node 10. Automatic for win7-* and *-i686" + echo "--target # os: linux / mac / windows / win7, arch: x86_64 / i686 / arm64" exit 0 ;; --all) build_all=1 ;; --skip-bundling) skip_bundling=1 ;; --skip-packaging) skip_packaging=1 ; skip_signing=1 ; skip_notary=1 ;; --skip-signing) skip_signing=1 ; skip_notary=1 ;; + --force-node10) target_node=10 ;; --skip-notary) skip_notary=1 ;; --target) target="$2"; shift ;; *) error "Unknown parameter passed: $1" ;; @@ -97,10 +72,13 @@ while [[ "$#" -gt 0 ]]; do done case $target in + linux-i686 | \ linux-aarch64 | \ linux-x86_64 | \ windows-x86_64 | \ windows-i686 | \ + win7-x86_64 | \ + win7-i686 | \ mac-x86_64 | \ mac-arm64) ;; @@ -112,25 +90,85 @@ esac target_os=$(echo $target | cut -f1 -d-) target_arch=$(echo $target | cut -f2 -d-) +target_dist_dir_rel=$dist_dir_name/$target_os/$target_arch +target_dist_dir=$PWD/$target_dist_dir_rel +dist_dir=$PWD/$dist_dir_name + +if [ $target_os == "win7" ]; then + target_os="windows" + target=$target_os-$target_arch + target_node=10 +fi + +if [ $target_arch == "i686" ]; then + target_node=10 +fi + +if ! [ -x "$(command -v node)" ]; then + error "Node not installed" +fi + +if [ $target_node == 10 ]; then + if [[ $(node -v) != v10.* ]] + then + error "Wrong version of Node (expected v10)" + fi +else + if [[ $(node -v) != v18.* ]] + then + error "Wrong version of Node (expected v18)" + fi +fi + +if ! [ -x "$(command -v esbuild)" ]; then + log "Installing esbuild" + npm install -g esbuild +fi + +if ! [ -x "$(command -v pkg)" ]; then + log "Installing pkg" + if [ $target_node == 10 ]; then + npm install -g pkg@4.4.9 + else + npm install -g pkg + fi +fi + +if [ $target_node == 10 ]; then + if [[ $(pkg -v) != 4.4.9 ]] + then + error "Wrong version of Pkg (expected 4.4.9)" + fi +fi + +if ! [ -x "$(command -v ejs)" ]; then + log "Installing ejs" + npm install -g ejs +fi + +if [ ! -d "app/node_modules" ]; then + (cd app/ ; npm install) +fi + node_arch=$target_arch deb_arch=$target_arch if [ $target == "linux-aarch64" ]; then node_arch="arm64" deb_arch="arm64" fi +if [ $target_arch == "i686" ]; then + node_arch="x86" +fi if [ $target == "linux-x86_64" ]; then deb_arch="amd64" fi -target_dist_dir_rel=$dist_dir_name/$target_os/$target_arch -target_dist_dir=$PWD/$target_dist_dir_rel -dist_dir=$PWD/$dist_dir_name - log "Building for $target on $host" log "Skipping bundling: $skip_bundling" log "Skipping packaging: $skip_packaging" log "Skipping signing: $skip_signing" log "Skipping notary: $skip_notary" +log "Node version: $target_node" log "Installation destination: $target_dist_dir_rel" if [ $target_os == "windows" ]; @@ -148,7 +186,8 @@ mkdir -p $target_dist_dir log "Creating config.json" yq . -o yaml ./config.toml | \ yq e ".target.os = \"$target_os\"" |\ - yq e ".target.arch = \"$target_arch\"" -o json \ + yq e ".target.arch = \"$target_arch\"" |\ + yq e ".target.node = \"$target_node\"" -o json \ > $target_dist_dir/config.json # Extract all toml data into shell variables. @@ -171,14 +210,13 @@ if [ $build_all == 1 ]; then log "Building for Mac Intel" arch -x86_64 ./build.sh - log "Building for Mac arm64" - ./build.sh --target mac-arm64 - - log "Building for Linux x86_64" - ./build.sh --target linux-x86_64 - - log "Building for Linux aarch64" - ./build.sh --target linux-aarch64 + # FIXME: linux-i686 can't be built under Mac as it needs to Node 10. + # To compile for linux-i686 build from a Linux i686 system. + for target in "mac-arm64 linux-x86_64 linux-aarch64 win7-i686 win7-x86_64 windows-i686 windows-x86_64" + do + log "Building for $target" + ./build.sh --target $target + done exit 0 fi @@ -188,18 +226,32 @@ if [ ! $skip_bundling == 1 ]; then # - hardcoding import.meta.url because the `open` module requires it. # - faking an electron module because `got` requires on (but it's never used) log "Bundling JS code into single file" + + if [ $target_node == 10 ]; then + declare -a opts=("--target=es6" "--alias:open=open2") + else + declare -a opts=("--target=esnext" \ + "--banner:js=const _importMetaUrl=require('url').pathToFileURL(__filename)" \ + "--define:import.meta.url=_importMetaUrl") + fi + NODE_PATH=app/src:$target_dist_dir esbuild ./app/src/main.js \ + "${opts[@]}" \ --format=cjs \ - --banner:js="const _importMetaUrl=require('url').pathToFileURL(__filename)" \ - --define:import.meta.url='_importMetaUrl' \ --bundle --platform=node \ --tree-shaking=true \ --alias:electron=electron2 \ --outfile=$dist_dir/bundled.js + if [ $target_node == 10 ]; then + declare -a opts=("$dist_dir/bundled.js" "--no-bytecode" "--public") + else + declare -a opts=("$dist_dir/bundled.js") + fi + log "Bundling Node binary with code" - pkg $dist_dir/bundled.js \ - --target node18-$target_os-$node_arch \ + pkg "${opts[@]}" \ + --target node$target_node-$target_os-$node_arch \ --output $target_dist_dir/$package_binary_name$exe_extension else log "Skipping bundling" From 3dd7649c4f975979a75941896ee91cc9807868bd Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 13 Oct 2023 13:48:09 +0800 Subject: [PATCH 3/5] fix build --all --- build.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index ce14350e..831ebea2 100755 --- a/build.sh +++ b/build.sh @@ -210,9 +210,19 @@ if [ $build_all == 1 ]; then log "Building for Mac Intel" arch -x86_64 ./build.sh + targets=("mac-arm64" "linux-x86_64" "linux-aarch64" "windows-x86_64") + for target in "${targets[@]}" + do + log "Building for $target" + ./build.sh --target $target + done + + fnm use 10 + # FIXME: linux-i686 can't be built under Mac as it needs to Node 10. # To compile for linux-i686 build from a Linux i686 system. - for target in "mac-arm64 linux-x86_64 linux-aarch64 win7-i686 win7-x86_64 windows-i686 windows-x86_64" + targets=("win7-i686" "win7-x86_64" "windows-i686") + for target in "${targets[@]}" do log "Building for $target" ./build.sh --target $target From 352eb02a34d26e7b5c1d009fb27e11fef8246dc6 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 13 Oct 2023 12:53:42 +0800 Subject: [PATCH 4/5] Version Bump 2.0.3 --- .github/workflows/test.yaml | 2 +- config.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d20d1373..77430f99 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -13,5 +13,5 @@ jobs: - run: eslint app tests/*.mjs - run: sudo snap install yq - run: ./build.sh - - run: sudo dpkg -i ./dist/linux/x86_64/vdhcoapp-2.0.2-linux-x86_64.deb + - run: sudo dpkg -i ./dist/linux/x86_64/vdhcoapp-2.0.3-linux-x86_64.deb - run: ./tests/test.mjs /opt/vdhcoapp/vdhcoapp --with-network diff --git a/config.toml b/config.toml index 19410632..ea44fa28 100644 --- a/config.toml +++ b/config.toml @@ -3,7 +3,7 @@ id = "net.downloadhelper.coapp" name = "VdhCoApp" long_name = "DownloadHelper CoApp" description = "Video DownloadHelper companion app" -version = "2.0.2" +version = "2.0.3" [package] binary_name = "vdhcoapp" # .exe added automatically From 0a5d3a112f5eb1d981b96a2c314f2337673451bd Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 13 Oct 2023 13:56:31 +0800 Subject: [PATCH 5/5] formatting & eslint --- app/src/converter.js | 344 +++++++++++++++++----------------- app/src/main.js | 4 +- app/src/native-autoinstall.js | 4 +- tests/codecs.mjs | 49 +---- tests/test.mjs | 4 +- 5 files changed, 181 insertions(+), 224 deletions(-) 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); }