@openmixer/plugin-qualify 0.20.0 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/plugin-qualify-records-package.mjs +9 -7
- package/bin/plugin-qualify-sync.mjs +1 -0
- package/bin/plugin-qualify.mjs +34 -0
- package/catalogs/ca.json +8 -0
- package/dist/clap-loader.js +2 -1
- package/dist/clap-loader.js.map +1 -1
- package/dist/clap-qualify.d.ts +11 -0
- package/dist/clap-qualify.js +16 -0
- package/dist/clap-qualify.js.map +1 -1
- package/dist/distributed-records.d.ts +16 -3
- package/dist/distributed-records.js +38 -4
- package/dist/distributed-records.js.map +1 -1
- package/dist/host-admission.d.ts +25 -0
- package/dist/host-admission.js +41 -5
- package/dist/host-admission.js.map +1 -1
- package/dist/hostd-search-path.d.ts +38 -0
- package/dist/hostd-search-path.js +58 -0
- package/dist/hostd-search-path.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/jack-registry.js +1 -1
- package/dist/judged-layer.d.ts +91 -0
- package/dist/judged-layer.js +144 -0
- package/dist/judged-layer.js.map +1 -0
- package/dist/judgement-line.d.ts +6 -0
- package/dist/judgement-line.js +20 -0
- package/dist/judgement-line.js.map +1 -0
- package/dist/lv2-loader.d.ts +33 -1
- package/dist/lv2-loader.js +82 -19
- package/dist/lv2-loader.js.map +1 -1
- package/dist/measurement/cli.d.ts +2 -0
- package/dist/measurement/cli.js +25 -2
- package/dist/measurement/cli.js.map +1 -1
- package/dist/measurement/format.d.ts +2 -0
- package/dist/measurement/format.js +5 -0
- package/dist/measurement/format.js.map +1 -1
- package/dist/measurement/vocabulary.js +3 -3
- package/dist/measurement/vocabulary.js.map +1 -1
- package/dist/measurement-grid.d.ts +1 -1
- package/dist/measurement-grid.js +5 -3
- package/dist/measurement-grid.js.map +1 -1
- package/dist/pins-file.d.ts +3 -2
- package/dist/pins-file.js +3 -2
- package/dist/pins-file.js.map +1 -1
- package/dist/probe-judge.js +5 -0
- package/dist/probe-judge.js.map +1 -1
- package/dist/probe-output.d.ts +10 -0
- package/dist/probe-output.js +16 -0
- package/dist/probe-output.js.map +1 -1
- package/dist/probe-runner.js +24 -5
- package/dist/probe-runner.js.map +1 -1
- package/dist/qualification-record.d.ts +13 -0
- package/dist/qualification-record.js +25 -3
- package/dist/qualification-record.js.map +1 -1
- package/dist/qualify-adapter-pass.d.ts +1 -2
- package/dist/qualify-adapter-pass.js +6 -6
- package/dist/qualify-adapter-pass.js.map +1 -1
- package/dist/qualify-declarations.d.ts +23 -6
- package/dist/qualify-declarations.js +25 -6
- package/dist/qualify-declarations.js.map +1 -1
- package/dist/qualify-isolated.d.ts +14 -3
- package/dist/qualify-isolated.js +22 -9
- package/dist/qualify-isolated.js.map +1 -1
- package/dist/qualify-pool.js +4 -3
- package/dist/qualify-pool.js.map +1 -1
- package/dist/qualify-rejudge.js +3 -3
- package/dist/qualify-rejudge.js.map +1 -1
- package/dist/qualify-sync.d.ts +18 -6
- package/dist/qualify-sync.js +68 -38
- package/dist/qualify-sync.js.map +1 -1
- package/dist/records-package.d.ts +31 -4
- package/dist/records-package.js +149 -24
- package/dist/records-package.js.map +1 -1
- package/dist/run-home.d.ts +4 -0
- package/dist/run-home.js +26 -0
- package/dist/run-home.js.map +1 -0
- package/fixtures/records-rpi5-0.19.1/http___drumkv1.sourceforge.net_lv2@0.2-7d179bdcf9e5.default.probe.json +58 -0
- package/fixtures/records-rpi5-0.19.1/http___drumkv1.sourceforge.net_lv2@0.2-7d179bdcf9e5.default.qualification.json +305 -0
- package/fixtures/records-rpi5-0.19.1/http___samplv1.sourceforge.net_lv2@0.2-c9cd8fb3102f.default.probe.json +58 -0
- package/fixtures/records-rpi5-0.19.1/http___samplv1.sourceforge.net_lv2@0.2-c9cd8fb3102f.default.qualification.json +301 -0
- package/package.json +7 -5
- package/schema/codes.json +15 -0
- package/src/clap-loader.ts +2 -1
- package/src/clap-qualify.ts +25 -0
- package/src/distributed-records.ts +41 -4
- package/src/host-admission.ts +52 -5
- package/src/hostd-search-path.ts +85 -0
- package/src/index.ts +2 -0
- package/src/jack-registry.ts +1 -1
- package/src/judged-layer.ts +197 -0
- package/src/judgement-line.ts +22 -0
- package/src/lv2-loader.ts +89 -17
- package/src/measurement/cli.ts +26 -2
- package/src/measurement/format.ts +8 -0
- package/src/measurement/vocabulary.ts +3 -3
- package/src/measurement-grid.ts +5 -3
- package/src/pins-file.ts +3 -2
- package/src/probe-judge.ts +5 -0
- package/src/probe-output.ts +23 -0
- package/src/probe-runner.ts +25 -4
- package/src/qualification-record.ts +32 -3
- package/src/qualify-adapter-pass.ts +6 -5
- package/src/qualify-declarations.ts +27 -6
- package/src/qualify-isolated.ts +24 -9
- package/src/qualify-pool.ts +4 -3
- package/src/qualify-rejudge.ts +3 -3
- package/src/qualify-sync.ts +74 -41
- package/src/records-package.ts +156 -25
- package/src/run-home.ts +28 -0
- package/tools/_declarations.py +2 -1
- package/tools/descriptors.py +40 -3
- package/tools/gen-python-declarations.mjs +1 -0
- package/tools/isolated-step.mjs +24 -3
- package/tools/lv2-measure.mjs +21 -2
- package/tools/mod-host-admit.mjs +57 -1
- package/tools/scan.py +29 -5
package/dist/host-admission.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { spawnSync } from "node:child_process";
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { withRunHome } from "./run-home.js";
|
|
13
14
|
import { ADMIT_STEP_MS_ENV } from "./qualify-declarations.js";
|
|
14
15
|
/** The profile ids whose verdict is measured by a run. */
|
|
15
16
|
export const ADMITTED_HOSTS = ["mod-host", "jalv"];
|
|
@@ -52,6 +53,21 @@ export const SILENT_PEAK = 1e-6;
|
|
|
52
53
|
export const ADAPTER_SILENT_CODE = `${ADAPTER_HOST}.silent-under-note`;
|
|
53
54
|
export const ADAPTER_LEVEL_UNMEASURED_CODE = `${ADAPTER_HOST}.level-unmeasured`;
|
|
54
55
|
const UNPROVEN_SOUND = [ADAPTER_SILENT_CODE, ADAPTER_LEVEL_UNMEASURED_CODE];
|
|
56
|
+
/**
|
|
57
|
+
* An instrument that declares content it plays from and stayed silent under the notes even so: the content could not be
|
|
58
|
+
* given (the host refused the sample) or the sample did not reach the keys played. Its silence says nothing of the plugin,
|
|
59
|
+
* so the note test is not observable for it: the run admits it, and the record names this code and the content (#318).
|
|
60
|
+
* No other host is asked instead.
|
|
61
|
+
*/
|
|
62
|
+
export const ADAPTER_CONTENT_UNOBSERVED_CODE = `${ADAPTER_HOST}.silent-needs-content`;
|
|
63
|
+
/** The run's content, as a reason's params carry it: the declared parameters, the ones loaded, the ones refused. */
|
|
64
|
+
function contentParams(content) {
|
|
65
|
+
return {
|
|
66
|
+
content: content.params.join(" "),
|
|
67
|
+
loaded: content.loaded.join(" "),
|
|
68
|
+
...(content.refused === undefined || content.refused.length === 0 ? {} : { refused: content.refused.join("; ") }),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
55
71
|
/** The rating a run that did not admit the plugin gives its host's verdict. */
|
|
56
72
|
export function admissionRating(admission) {
|
|
57
73
|
return !admission.measured || UNPROVEN_SOUND.includes(admission.code ?? "") ? "unknown" : "unsuitable";
|
|
@@ -61,6 +77,18 @@ export function admissionRating(admission) {
|
|
|
61
77
|
* which says nothing of the plugin. omx-clap-host opens JACK at the first add since 0.26.1, so a host with no server answers these.
|
|
62
78
|
*/
|
|
63
79
|
const JACK_CLIENT_RESPS = [-201, -202];
|
|
80
|
+
/** The name of the reason a run stops on when no JACK server answers: the admission cannot say anything of any plugin. */
|
|
81
|
+
export const NO_JACK_SERVER = "no JACK server";
|
|
82
|
+
/**
|
|
83
|
+
* The refusal to go on when an admission found no JACK client to have (`<host>.no-jack-client`): the server the host is
|
|
84
|
+
* pointed at (the default one, or `JACK_DEFAULT_SERVER`) is not there, and every plugin would be recorded with the same
|
|
85
|
+
* resp -201 as if it were the plugin's. `undefined` for any other run.
|
|
86
|
+
*/
|
|
87
|
+
export function noJackServerProblem(admission) {
|
|
88
|
+
if (admission === undefined || admission.measured || !admission.code?.endsWith(".no-jack-client"))
|
|
89
|
+
return undefined;
|
|
90
|
+
return `${NO_JACK_SERVER}: ${admission.host} could not open a JACK client (resp ${String(admission.params["resp"] ?? "-201")}), so nothing is learned of any plugin; start the JACK server it is pointed at (JACK_DEFAULT_SERVER names it) and run again`;
|
|
91
|
+
}
|
|
64
92
|
/** The verdict of a run of a host that speaks mod-host's protocol: the first step that did not answer `resp 0` decides. */
|
|
65
93
|
export function classifyProtocolRun(host, run) {
|
|
66
94
|
if (!run.installed)
|
|
@@ -88,8 +116,16 @@ export function classifyProtocolRun(host, run) {
|
|
|
88
116
|
const { peak, problem } = run.sound;
|
|
89
117
|
if (peak === undefined)
|
|
90
118
|
return { host, measured: true, admitted: false, code: ADAPTER_LEVEL_UNMEASURED_CODE, params: { problem: problem ?? "no figure" } };
|
|
91
|
-
|
|
92
|
-
|
|
119
|
+
const notes = run.sound.notes === undefined ? {} : { notes: run.sound.notes };
|
|
120
|
+
const content = run.sound.content;
|
|
121
|
+
if (!(peak > SILENT_PEAK)) {
|
|
122
|
+
if (content !== undefined && content.params.length > 0)
|
|
123
|
+
return { host, measured: true, admitted: true, code: ADAPTER_CONTENT_UNOBSERVED_CODE, params: { peak, ...notes, ...contentParams(content) } };
|
|
124
|
+
return { host, measured: true, admitted: false, code: ADAPTER_SILENT_CODE, params: { peak, ...notes } };
|
|
125
|
+
}
|
|
126
|
+
// it sounded on the content it was given: the record says which
|
|
127
|
+
if (content !== undefined && content.loaded.length > 0)
|
|
128
|
+
return { ...admitted(host), params: { peak, ...notes, ...contentParams(content) } };
|
|
93
129
|
}
|
|
94
130
|
return admitted(host);
|
|
95
131
|
}
|
|
@@ -124,14 +160,14 @@ export const SPAWNED_ADMISSIONS = {
|
|
|
124
160
|
// two commands at the limit the pass gives each, and the tool's own start and end: it kills the host itself first
|
|
125
161
|
const stepMs = Number(env?.[ADMIT_STEP_MS_ENV] ?? 0);
|
|
126
162
|
const timeout = stepMs > 0 ? 2 * stepMs + 15000 : MOD_HOST_ADMISSION_MS;
|
|
127
|
-
const r = spawnSync(process.execPath, [MOD_HOST_ADMIT, uri, ADAPTER_HOST], { encoding: "utf8", timeout, killSignal: "SIGKILL",
|
|
163
|
+
const r = spawnSync(process.execPath, [MOD_HOST_ADMIT, uri, ADAPTER_HOST], { encoding: "utf8", timeout, killSignal: "SIGKILL", env: withRunHome(env ?? process.env) });
|
|
128
164
|
if (r.error !== undefined || r.status !== 0) {
|
|
129
165
|
throw new Error(`${ADAPTER_HOST} admission of ${uri} gave no answer (${r.error?.message ?? `exit ${String(r.status)}`}): ${(r.stderr ?? "").trim()}`);
|
|
130
166
|
}
|
|
131
167
|
return JSON.parse(r.stdout);
|
|
132
168
|
},
|
|
133
169
|
modHost(uri, env) {
|
|
134
|
-
const r = spawnSync(process.execPath, [MOD_HOST_ADMIT, uri], { encoding: "utf8", timeout: MOD_HOST_ADMISSION_MS,
|
|
170
|
+
const r = spawnSync(process.execPath, [MOD_HOST_ADMIT, uri], { encoding: "utf8", timeout: MOD_HOST_ADMISSION_MS, env: withRunHome(env ?? process.env) });
|
|
135
171
|
if (r.error !== undefined || r.status !== 0) {
|
|
136
172
|
throw new Error(`mod-host admission of ${uri} gave no answer (${r.error?.message ?? `exit ${String(r.status)}`}): ${(r.stderr ?? "").trim()}`);
|
|
137
173
|
}
|
|
@@ -141,7 +177,7 @@ export const SPAWNED_ADMISSIONS = {
|
|
|
141
177
|
// SIGKILL at the deadline: jalv hosting some plugins ignores SIGTERM, and one stuck in jack_client_open never reaches
|
|
142
178
|
// the loop that reads the flag TERM sets, so a TERM left spawnSync waiting with it (#187). Alive at the deadline is
|
|
143
179
|
// all the verdict asks, so nothing is lost by not letting it exit cleanly.
|
|
144
|
-
const r = spawnSync("jalv", ["-n", "plugin-qualify", uri], { encoding: "utf8", timeout: JALV_HOSTED_MS, killSignal: "SIGKILL", input: "",
|
|
180
|
+
const r = spawnSync("jalv", ["-n", "plugin-qualify", uri], { encoding: "utf8", timeout: JALV_HOSTED_MS, killSignal: "SIGKILL", input: "", env: withRunHome(env ?? process.env) });
|
|
145
181
|
const code = r.error?.code;
|
|
146
182
|
if (code === "ENOENT")
|
|
147
183
|
return { installed: false, stillRunning: false, status: null, signal: null, stderr: "" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-admission.js","sourceRoot":"","sources":["../src/host-admission.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"host-admission.js","sourceRoot":"","sources":["../src/host-admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Where plugin-hostd took a list from: its settings file, its environment (`LV2_PATH`, `CLAP_PATH`) or its default. */
|
|
2
|
+
export type SearchPathSource = "file" | "env" | "default";
|
|
3
|
+
export interface HostdSearchPath {
|
|
4
|
+
/** The LV2 directories, in the order the daemon searches them: `lv2_path` then `lv2_extra`. */
|
|
5
|
+
readonly lv2: readonly string[];
|
|
6
|
+
/** The CLAP directories, in the order the daemon searches them. */
|
|
7
|
+
readonly clap: readonly string[];
|
|
8
|
+
/** Where each of `lv2_path`, `lv2_extra` and `clap_path` came from. */
|
|
9
|
+
readonly sources: Readonly<Record<"lv2_path" | "lv2_extra" | "clap_path", SearchPathSource>>;
|
|
10
|
+
}
|
|
11
|
+
export interface SearchPathRunResult {
|
|
12
|
+
readonly status: number | null;
|
|
13
|
+
readonly stdout: string;
|
|
14
|
+
readonly stderr: string;
|
|
15
|
+
/** The daemon is not installed. */
|
|
16
|
+
readonly missing?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** One run of `plugin-hostd --search-path`, with `-c <conf>` when a settings file is named. */
|
|
19
|
+
export type SearchPathRun = (conf: string | undefined, env: Readonly<Record<string, string | undefined>>) => SearchPathRunResult;
|
|
20
|
+
export declare const SPAWNED_SEARCH_PATH: SearchPathRun;
|
|
21
|
+
/** The lines `plugin-hostd --search-path` prints, read: `<key> TAB <source> TAB <value>`; why not, when one is missing. */
|
|
22
|
+
export declare function parseSearchPath(stdout: string): {
|
|
23
|
+
ok: true;
|
|
24
|
+
path: HostdSearchPath;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
/** The directories plugin-hostd searches with the settings file `conf` (its own default when undefined); why not, when it cannot say. */
|
|
30
|
+
export declare function hostdSearchPath(conf: string | undefined, env?: Readonly<Record<string, string | undefined>>, run?: SearchPathRun): {
|
|
31
|
+
ok: true;
|
|
32
|
+
path: HostdSearchPath;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
error: string;
|
|
36
|
+
};
|
|
37
|
+
/** What the run says when a list is not the settings file's: the running daemon, started with another environment, may search other directories. */
|
|
38
|
+
export declare function searchPathWarnings(path: HostdSearchPath, conf: string | undefined): string[];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* The directories the sync scans, as plugin-hostd searches them (plugin-qualify#9). One definition of the search path:
|
|
5
|
+
* the daemon's, which `plugin-hostd --search-path [-c <file>]` prints from the code it searches with (plugin-hostd 0.20.3
|
|
6
|
+
* and later). This module never works the lists out itself: it runs the daemon on its settings file and reads the
|
|
7
|
+
* `lv2` and `clap` lines, and where each list came from (`file`, `env` or `default`).
|
|
8
|
+
*/
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { HOSTD_ENV } from "./hostd-pin-files.js";
|
|
11
|
+
export const SPAWNED_SEARCH_PATH = (conf, env) => {
|
|
12
|
+
const r = spawnSync(env[HOSTD_ENV] ?? "plugin-hostd", [...(conf === undefined ? [] : ["-c", conf]), "--search-path"], { encoding: "utf8", timeout: 30000, env: { ...env } });
|
|
13
|
+
const missing = r.error?.code === "ENOENT";
|
|
14
|
+
return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "", ...(missing ? { missing } : {}) };
|
|
15
|
+
};
|
|
16
|
+
const SOURCES = ["file", "env", "default"];
|
|
17
|
+
const dirList = (text) => text.split(":").filter((d) => d !== "");
|
|
18
|
+
/** The lines `plugin-hostd --search-path` prints, read: `<key> TAB <source> TAB <value>`; why not, when one is missing. */
|
|
19
|
+
export function parseSearchPath(stdout) {
|
|
20
|
+
const rows = new Map();
|
|
21
|
+
for (const line of stdout.split("\n")) {
|
|
22
|
+
const f = line.split("\t");
|
|
23
|
+
if (f.length >= 2 && f[0] !== undefined && f[1] !== undefined)
|
|
24
|
+
rows.set(f[0], { source: f[1], value: f.slice(2).join("\t") });
|
|
25
|
+
}
|
|
26
|
+
for (const key of ["lv2_path", "lv2_extra", "clap_path"]) {
|
|
27
|
+
const r = rows.get(key);
|
|
28
|
+
if (r === undefined || !SOURCES.includes(r.source))
|
|
29
|
+
return { ok: false, error: `plugin-hostd --search-path printed no ${key} with its source` };
|
|
30
|
+
}
|
|
31
|
+
const lv2 = rows.get("lv2");
|
|
32
|
+
const clap = rows.get("clap");
|
|
33
|
+
if (lv2?.source !== "effective" || clap?.source !== "effective")
|
|
34
|
+
return { ok: false, error: "plugin-hostd --search-path printed no effective lv2 and clap lists" };
|
|
35
|
+
const src = (key) => rows.get(key).source;
|
|
36
|
+
return { ok: true, path: { lv2: dirList(lv2.value), clap: dirList(clap.value), sources: { lv2_path: src("lv2_path"), lv2_extra: src("lv2_extra"), clap_path: src("clap_path") } } };
|
|
37
|
+
}
|
|
38
|
+
/** The directories plugin-hostd searches with the settings file `conf` (its own default when undefined); why not, when it cannot say. */
|
|
39
|
+
export function hostdSearchPath(conf, env = process.env, run = SPAWNED_SEARCH_PATH) {
|
|
40
|
+
const r = run(conf, env);
|
|
41
|
+
if (r.missing)
|
|
42
|
+
return { ok: false, error: "plugin-hostd is not installed: the directories scanned are the ones plugin-hostd searches" };
|
|
43
|
+
if (r.status !== 0) {
|
|
44
|
+
const why = /unrecognized option|^Usage:/m.test(r.stdout + r.stderr)
|
|
45
|
+
? "this plugin-hostd has no --search-path (plugin-hostd 0.20.3 or later names the directories it searches)"
|
|
46
|
+
: r.stderr.trim().split("\n").pop() || `plugin-hostd --search-path exited ${String(r.status)}`;
|
|
47
|
+
return { ok: false, error: why };
|
|
48
|
+
}
|
|
49
|
+
return parseSearchPath(r.stdout);
|
|
50
|
+
}
|
|
51
|
+
/** What the run says when a list is not the settings file's: the running daemon, started with another environment, may search other directories. */
|
|
52
|
+
export function searchPathWarnings(path, conf) {
|
|
53
|
+
const where = conf ?? "plugin-hostd's own settings file";
|
|
54
|
+
return ["lv2_path", "clap_path"]
|
|
55
|
+
.filter((k) => path.sources[k] !== "file")
|
|
56
|
+
.map((k) => `${k} is plugin-hostd's ${path.sources[k] === "env" ? `environment (${k === "lv2_path" ? "LV2_PATH" : "CLAP_PATH"})` : "default"}, not ${where}: the running daemon may search other directories; write ${k} in ${where}`);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=hostd-search-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostd-search-path.js","sourceRoot":"","sources":["../src/hostd-search-path.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export * from "./cost-fields.js";
|
|
|
22
22
|
export * from "./probe-output.js";
|
|
23
23
|
export * from "./probe-judge.js";
|
|
24
24
|
export * from "./qualification-record.js";
|
|
25
|
+
export * from "./judgement-line.js";
|
|
26
|
+
export * from "./judged-layer.js";
|
|
25
27
|
export * from "./probe-runner.js";
|
|
26
28
|
export * from "./measurement-grid.js";
|
|
27
29
|
export * from "./memory-bound.js";
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,8 @@ export * from "./cost-fields.js";
|
|
|
24
24
|
export * from "./probe-output.js";
|
|
25
25
|
export * from "./probe-judge.js";
|
|
26
26
|
export * from "./qualification-record.js";
|
|
27
|
+
export * from "./judgement-line.js";
|
|
28
|
+
export * from "./judged-layer.js";
|
|
27
29
|
export * from "./probe-runner.js";
|
|
28
30
|
export * from "./measurement-grid.js";
|
|
29
31
|
export * from "./memory-bound.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;GAGG;AACH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;GAGG;AACH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
package/dist/jack-registry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* JACK's table of its servers, /dev/shm/jack-shm-registry: a header, then eight rows of a pid and a name
|
|
5
5
|
* (`jack-<uid>:<server>:`). A server that is killed never clears its row, and once the eight are taken no server starts.
|
|
6
|
-
* The adapter pass starts and stops servers of its own, `omx-qualify-<pid>-<quantum>`; a row of one of those whose
|
|
6
|
+
* The adapter pass starts and stops servers of its own, `omx-qualify-<pid>-<rate>-<quantum>`; a row of one of those whose
|
|
7
7
|
* process is gone is freed (pid 0, name empty) before the next start, as jackd frees its own row when it ends well.
|
|
8
8
|
* Rows of any other server are never touched, and a file of another layout is left as it is.
|
|
9
9
|
*/
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type PinVerdict } from "./pins-file.js";
|
|
2
|
+
import { type QualificationRecord } from "./qualification-record.js";
|
|
3
|
+
/** The host a judged layer is written for: the one that runs plugins, in workers of its own (PLUGIN_DB_ISOLATION_HOSTS). */
|
|
4
|
+
export declare const JUDGED_HOST = "plugin-hostd";
|
|
5
|
+
/**
|
|
6
|
+
* The hosting epoch of each host a layer is written for. The epoch is the host owner's to move, when a release of it
|
|
7
|
+
* changes how it hosts; plugin-hostd has declared no hosting change since records were written, so its epoch is 0.
|
|
8
|
+
*/
|
|
9
|
+
export declare const HOSTING_EPOCH: {
|
|
10
|
+
readonly "plugin-hostd": 0;
|
|
11
|
+
};
|
|
12
|
+
/** The plugin-db envelope version this writes (plugin-db data/store.schema.json). */
|
|
13
|
+
export declare const PLUGIN_DB_ENVELOPE = 1;
|
|
14
|
+
/** The pin a layer is written for, as plugin-db's pinned layer holds it. */
|
|
15
|
+
export interface LayerPin {
|
|
16
|
+
/** The `omx-files/1` SHA-256 of the plugin's files. */
|
|
17
|
+
readonly files: string;
|
|
18
|
+
/** `<scheme>:<sha256>` of the parameter layout, or null when the pin holds none. */
|
|
19
|
+
readonly layout: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface JudgedCell {
|
|
22
|
+
readonly rate: number;
|
|
23
|
+
readonly quantum: number;
|
|
24
|
+
readonly latencyMs?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface JudgedBody {
|
|
27
|
+
readonly verdict: PinVerdict;
|
|
28
|
+
readonly machineClass: string;
|
|
29
|
+
readonly host: {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly version: string;
|
|
32
|
+
readonly hostingEpoch: number;
|
|
33
|
+
};
|
|
34
|
+
readonly rules: string;
|
|
35
|
+
readonly recordSchema: string;
|
|
36
|
+
readonly cells: readonly JudgedCell[];
|
|
37
|
+
readonly conditions: Readonly<Record<string, string>>;
|
|
38
|
+
readonly latencyLineMs: number;
|
|
39
|
+
}
|
|
40
|
+
export interface JudgedLayer {
|
|
41
|
+
readonly envelope: typeof PLUGIN_DB_ENVELOPE;
|
|
42
|
+
readonly layer: "judged";
|
|
43
|
+
readonly address: string;
|
|
44
|
+
readonly pin: LayerPin;
|
|
45
|
+
readonly writer: "plugin-qualify";
|
|
46
|
+
readonly body: JudgedBody;
|
|
47
|
+
}
|
|
48
|
+
/** What the converter is given beside the record: the class word, the pin, and the rules when the record states none. */
|
|
49
|
+
export interface JudgedLayerInput {
|
|
50
|
+
/** The machine class word the record was measured on (`rpi5`, `x86-64`): the set's host class. */
|
|
51
|
+
readonly machineClass: string;
|
|
52
|
+
readonly pin: LayerPin;
|
|
53
|
+
/** plugin-db's address; by default `<format>:<id>`. */
|
|
54
|
+
readonly address?: string;
|
|
55
|
+
/** The rules of a record that states none: the plugin-qualify version that judged its set (the set's provenance). */
|
|
56
|
+
readonly judgedBy?: string;
|
|
57
|
+
}
|
|
58
|
+
/** Why a record has no judged layer, when it has none. */
|
|
59
|
+
export type NoLayer = {
|
|
60
|
+
readonly layer: null;
|
|
61
|
+
readonly reason: string;
|
|
62
|
+
};
|
|
63
|
+
/** The cells of the record: each measured rate and quantum, with its latency in milliseconds when one was measured. */
|
|
64
|
+
export declare function judgedCells(record: QualificationRecord): JudgedCell[];
|
|
65
|
+
/**
|
|
66
|
+
* The judged layer of a record, or why there is none. The verdict is the isolated tier host's, as the pins file gives
|
|
67
|
+
* it; the host is plugin-hostd at the probe runner's version, which is plugin-hostd's.
|
|
68
|
+
*/
|
|
69
|
+
export declare function judgedLayerOf(record: QualificationRecord, input: JudgedLayerInput): JudgedLayer | NoLayer;
|
|
70
|
+
export interface JudgedLayerArgs {
|
|
71
|
+
readonly record: string;
|
|
72
|
+
readonly machineClass: string;
|
|
73
|
+
readonly files: string;
|
|
74
|
+
readonly layout: string | null;
|
|
75
|
+
readonly judgedBy?: string;
|
|
76
|
+
readonly address?: string;
|
|
77
|
+
/** Print the body only, as `plugin-db put <address> judged --writer plugin-qualify` reads it from stdin. */
|
|
78
|
+
readonly body: boolean;
|
|
79
|
+
}
|
|
80
|
+
export declare function judgedLayerHelpText(): string;
|
|
81
|
+
export type ParsedJudgedLayerArgs = {
|
|
82
|
+
ok: true;
|
|
83
|
+
args: JudgedLayerArgs;
|
|
84
|
+
} | {
|
|
85
|
+
ok: true;
|
|
86
|
+
help: true;
|
|
87
|
+
} | {
|
|
88
|
+
ok: false;
|
|
89
|
+
error: string;
|
|
90
|
+
};
|
|
91
|
+
export declare function parseJudgedLayerArgs(argv: readonly string[]): ParsedJudgedLayerArgs;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* The judged layer of a plugin-db entry, from a qualification record: plugin-qualify is that layer's one writer
|
|
5
|
+
* (plugin-db's records design note, FreeMixer/plugin-db#10). The reader never parses a record; it reads the layer this writes, so every field
|
|
6
|
+
* the state function reads is set here, from the record and from what plugin-qualify declares once:
|
|
7
|
+
*
|
|
8
|
+
* - the latency line (`LATENCY_LINE_MS`), written beside each cell's figure (`latencyMs`), so a surface shows the
|
|
9
|
+
* figure within or over the line and keeps no tier word (openmixer plugin-system design 7.15);
|
|
10
|
+
* - the rules the record was judged by (`judgementRules`), the minor of the plugin-qualify that judged it: a rule
|
|
11
|
+
* changes only in a minor, so a patch release leaves every record current;
|
|
12
|
+
* - the hosting epoch of the host the verdict is for (`HOSTING_EPOCH`).
|
|
13
|
+
*
|
|
14
|
+
* One layer is one verdict under one host: the host plugin-hostd runs a plugin with. Its verdict is the one the pins
|
|
15
|
+
* file gives the same bytes (`pinVerdictOf` of the isolated tier's host, omx-clap-host, which is plugin-hostd's
|
|
16
|
+
* worker). A record whose verdict for that host was not measured has no judged layer: the reader then answers
|
|
17
|
+
* unqualified, with its reason.
|
|
18
|
+
*/
|
|
19
|
+
import { judgementRules, latencyMsOf, LATENCY_LINE_MS } from "./judgement-line.js";
|
|
20
|
+
import { pinVerdictOf } from "./pins-file.js";
|
|
21
|
+
import { QUALIFICATION_RECORD_SCHEMA, ISOLATED_TIER_HOST } from "./qualification-record.js";
|
|
22
|
+
/** The host a judged layer is written for: the one that runs plugins, in workers of its own (PLUGIN_DB_ISOLATION_HOSTS). */
|
|
23
|
+
export const JUDGED_HOST = "plugin-hostd";
|
|
24
|
+
/**
|
|
25
|
+
* The hosting epoch of each host a layer is written for. The epoch is the host owner's to move, when a release of it
|
|
26
|
+
* changes how it hosts; plugin-hostd has declared no hosting change since records were written, so its epoch is 0.
|
|
27
|
+
*/
|
|
28
|
+
export const HOSTING_EPOCH = { [JUDGED_HOST]: 0 };
|
|
29
|
+
/** The plugin-db envelope version this writes (plugin-db data/store.schema.json). */
|
|
30
|
+
export const PLUGIN_DB_ENVELOPE = 1;
|
|
31
|
+
/** The version of a tool named `<name> <version>` in the record's `tool`. */
|
|
32
|
+
function versionOf(record, name) {
|
|
33
|
+
for (const v of Object.values(record.tool)) {
|
|
34
|
+
const m = new RegExp(`^${name.replace(/[-.]/g, "\\$&")} (\\S+)$`).exec(v);
|
|
35
|
+
if (m)
|
|
36
|
+
return m[1];
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/** The cells of the record: each measured rate and quantum, with its latency in milliseconds when one was measured. */
|
|
41
|
+
export function judgedCells(record) {
|
|
42
|
+
return record.measurements.grid
|
|
43
|
+
.filter((p) => p.outcome === "probe.ok")
|
|
44
|
+
.map((p) => {
|
|
45
|
+
const frames = p.latency.measuredFrames;
|
|
46
|
+
return { rate: p.rate, quantum: p.quantum, ...(frames === undefined ? {} : { latencyMs: latencyMsOf(frames, p.rate) }) };
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The judged layer of a record, or why there is none. The verdict is the isolated tier host's, as the pins file gives
|
|
51
|
+
* it; the host is plugin-hostd at the probe runner's version, which is plugin-hostd's.
|
|
52
|
+
*/
|
|
53
|
+
export function judgedLayerOf(record, input) {
|
|
54
|
+
if (record.schema !== QUALIFICATION_RECORD_SCHEMA)
|
|
55
|
+
return { layer: null, reason: `record schema ${JSON.stringify(record.schema)} is not ${QUALIFICATION_RECORD_SCHEMA}` };
|
|
56
|
+
const tierHost = ISOLATED_TIER_HOST[record.plugin.format];
|
|
57
|
+
const v = record.verdicts.find((r) => r.host === tierHost);
|
|
58
|
+
if (v === undefined)
|
|
59
|
+
return { layer: null, reason: `no verdict under ${tierHost ?? `a host for ${record.plugin.format}`}` };
|
|
60
|
+
const verdict = v.measured ? pinVerdictOf(v.rating) : undefined;
|
|
61
|
+
if (verdict === undefined)
|
|
62
|
+
return { layer: null, reason: `${tierHost}: not measured (${v.deciding ?? v.rating})` };
|
|
63
|
+
const hostVersion = versionOf(record, "plugin-hostd-probe");
|
|
64
|
+
if (hostVersion === undefined)
|
|
65
|
+
return { layer: null, reason: "the record names no plugin-hostd-probe version" };
|
|
66
|
+
const rules = record.rules ?? (input.judgedBy === undefined ? undefined : judgementRules(input.judgedBy));
|
|
67
|
+
if (rules === undefined)
|
|
68
|
+
return { layer: null, reason: "the record states no rules, and no judgedBy was given" };
|
|
69
|
+
return {
|
|
70
|
+
envelope: PLUGIN_DB_ENVELOPE,
|
|
71
|
+
layer: "judged",
|
|
72
|
+
address: input.address ?? `${record.plugin.format}:${record.plugin.id}`,
|
|
73
|
+
pin: input.pin,
|
|
74
|
+
writer: "plugin-qualify",
|
|
75
|
+
body: {
|
|
76
|
+
verdict,
|
|
77
|
+
machineClass: input.machineClass,
|
|
78
|
+
host: { name: JUDGED_HOST, version: hostVersion, hostingEpoch: HOSTING_EPOCH[JUDGED_HOST] },
|
|
79
|
+
rules,
|
|
80
|
+
recordSchema: record.schema,
|
|
81
|
+
cells: judgedCells(record),
|
|
82
|
+
conditions: {},
|
|
83
|
+
latencyLineMs: record.latencyLineMs ?? LATENCY_LINE_MS,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function judgedLayerHelpText() {
|
|
88
|
+
return [
|
|
89
|
+
"usage: plugin-qualify judged-layer <record.qualification.json> --machine-class <word> --files <sha256>",
|
|
90
|
+
" [--layout <scheme>:<sha256>] [--judged-by <version>] [--address <address>] [--body]",
|
|
91
|
+
"",
|
|
92
|
+
"Print the plugin-db judged layer of a qualification record, for the pin plugin-db holds (its files digest and",
|
|
93
|
+
"layout). --judged-by names the plugin-qualify that judged a record stating no rules (the set's provenance). --body",
|
|
94
|
+
"prints the body only, for `plugin-db put <address> judged --writer plugin-qualify`. A record whose verdict under",
|
|
95
|
+
"plugin-hostd's worker was not measured has no layer: the reason is printed and the exit status is 1.",
|
|
96
|
+
"",
|
|
97
|
+
].join("\n");
|
|
98
|
+
}
|
|
99
|
+
export function parseJudgedLayerArgs(argv) {
|
|
100
|
+
const opts = {};
|
|
101
|
+
const files = [];
|
|
102
|
+
let body = false;
|
|
103
|
+
for (let i = 0; i < argv.length; i++) {
|
|
104
|
+
const a = argv[i];
|
|
105
|
+
if (a === "--help" || a === "-h")
|
|
106
|
+
return { ok: true, help: true };
|
|
107
|
+
if (a === "--body")
|
|
108
|
+
body = true;
|
|
109
|
+
else if (["--machine-class", "--files", "--layout", "--judged-by", "--address"].includes(a)) {
|
|
110
|
+
const v = argv[++i];
|
|
111
|
+
if (v === undefined || v.startsWith("--"))
|
|
112
|
+
return { ok: false, error: `${a} needs a value` };
|
|
113
|
+
opts[a] = v;
|
|
114
|
+
}
|
|
115
|
+
else if (a.startsWith("--"))
|
|
116
|
+
return { ok: false, error: `unknown option ${a}` };
|
|
117
|
+
else
|
|
118
|
+
files.push(a);
|
|
119
|
+
}
|
|
120
|
+
if (files.length !== 1)
|
|
121
|
+
return { ok: false, error: "name one record" };
|
|
122
|
+
const machineClass = opts["--machine-class"];
|
|
123
|
+
const pinFiles = opts["--files"];
|
|
124
|
+
if (machineClass === undefined)
|
|
125
|
+
return { ok: false, error: "--machine-class is required" };
|
|
126
|
+
if (pinFiles === undefined || !/^[0-9a-f]{64}$/.test(pinFiles))
|
|
127
|
+
return { ok: false, error: "--files must be the 64 hex digits of the files pin" };
|
|
128
|
+
const layout = opts["--layout"] ?? null;
|
|
129
|
+
if (layout !== null && !/^[^:]+:[0-9a-f]{64}$/.test(layout))
|
|
130
|
+
return { ok: false, error: "--layout must be <scheme>:<sha256>" };
|
|
131
|
+
return {
|
|
132
|
+
ok: true,
|
|
133
|
+
args: {
|
|
134
|
+
record: files[0],
|
|
135
|
+
machineClass,
|
|
136
|
+
files: pinFiles,
|
|
137
|
+
layout,
|
|
138
|
+
body,
|
|
139
|
+
...(opts["--judged-by"] === undefined ? {} : { judgedBy: opts["--judged-by"] }),
|
|
140
|
+
...(opts["--address"] === undefined ? {} : { address: opts["--address"] }),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=judged-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judged-layer.js","sourceRoot":"","sources":["../src/judged-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The latency line, in milliseconds: declared once, here, and written into every record and judged layer. */
|
|
2
|
+
export declare const LATENCY_LINE_MS = 5;
|
|
3
|
+
/** A measured latency in milliseconds at its rate, rounded to the microsecond. */
|
|
4
|
+
export declare const latencyMsOf: (frames: number, rate: number) => number;
|
|
5
|
+
/** The rules a plugin-qualify of this version judges by: `plugin-qualify-rules/<major>.<minor>`. */
|
|
6
|
+
export declare function judgementRules(version?: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* What plugin-qualify's judgement declares once and writes into every record (and so into every judged layer): the
|
|
5
|
+
* latency line and the rules a record was judged by (openmixer plugin-system design 7.15, plugin-db records.md).
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
/** The latency line, in milliseconds: declared once, here, and written into every record and judged layer. */
|
|
9
|
+
export const LATENCY_LINE_MS = 5;
|
|
10
|
+
/** A measured latency in milliseconds at its rate, rounded to the microsecond. */
|
|
11
|
+
export const latencyMsOf = (frames, rate) => Math.round((frames * 1e9) / rate) / 1e6;
|
|
12
|
+
const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
13
|
+
/** The rules a plugin-qualify of this version judges by: `plugin-qualify-rules/<major>.<minor>`. */
|
|
14
|
+
export function judgementRules(version = VERSION) {
|
|
15
|
+
const m = /^(\d+)\.(\d+)\.\d+/.exec(version);
|
|
16
|
+
if (m === null)
|
|
17
|
+
throw new Error(`judgementRules: ${JSON.stringify(version)} is no version`);
|
|
18
|
+
return `plugin-qualify-rules/${m[1]}.${m[2]}`;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=judgement-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judgement-line.js","sourceRoot":"","sources":["../src/judgement-line.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,sDAAsD;AACtD;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,8GAA8G;AAC9G,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC;AAE7G,MAAM,OAAO,GAAW,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AAE9G,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,UAAkB,OAAO;IACtD,MAAM,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5F,OAAO,wBAAwB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC"}
|
package/dist/lv2-loader.d.ts
CHANGED
|
@@ -1,17 +1,49 @@
|
|
|
1
1
|
import type { PluginLoader } from "./loader.js";
|
|
2
|
+
/**
|
|
3
|
+
* The path a file IRI names, as lilv and serd read it: a `file:` URI loses its scheme and authority, and the percent
|
|
4
|
+
* escapes of its path are decoded (`libSurge%20XT.so` is `libSurge XT.so` on the disk). A relative IRI is decoded the
|
|
5
|
+
* same way. A malformed escape leaves the text as written: the name is then looked up as it stands and not found, which
|
|
6
|
+
* is its own, named failure.
|
|
7
|
+
*/
|
|
8
|
+
export declare function iriPath(iri: string): string;
|
|
2
9
|
/** A plugin a manifest declares, with the files it names for it, each relative to the bundle, in the order named. */
|
|
3
10
|
export interface ManifestPlugin {
|
|
4
11
|
readonly uri: string;
|
|
5
12
|
readonly files: readonly string[];
|
|
6
|
-
/** The basename of its `lv2:binary
|
|
13
|
+
/** The basename of its `lv2:binary` as it is on the disk (the IRI's escapes decoded), when it names one. `files` keep the IRI's word, which is what a pin holds. */
|
|
7
14
|
readonly binary?: string;
|
|
8
15
|
}
|
|
16
|
+
/** A statement of a Turtle text: the subject and predicate expanded, the object as written and, when it names one, expanded. */
|
|
17
|
+
export interface TurtleTriple {
|
|
18
|
+
readonly subject: string;
|
|
19
|
+
readonly predicate: string;
|
|
20
|
+
/** The object's token: an `iri` is as written (a relative one stays relative), a `literal` carries no text. */
|
|
21
|
+
readonly object: {
|
|
22
|
+
readonly kind: "iri" | "name" | "literal";
|
|
23
|
+
readonly text: string;
|
|
24
|
+
};
|
|
25
|
+
/** The object expanded: an absolute or relative IRI, or a prefixed name with a known prefix. */
|
|
26
|
+
readonly objectIri?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The statements of a Turtle text, as plugin-hostd reads a manifest to pin a plugin: statements of IRIs and prefixed
|
|
30
|
+
* names, with blank nodes and collections stepped over, not a whole Turtle parser. `lv2`, `rdfs` and `rdf` read even
|
|
31
|
+
* when a file leaves them undeclared.
|
|
32
|
+
*/
|
|
33
|
+
export declare function turtleTriples(ttl: string): TurtleTriple[];
|
|
9
34
|
/**
|
|
10
35
|
* Every plugin a bundle manifest declares and the files it names for it with `lv2:binary` or `rdfs:seeAlso`: the
|
|
11
36
|
* files plugin-hostd's pin holds besides `manifest.ttl` itself. A file named outside the bundle (an absolute IRI) is
|
|
12
37
|
* not one of them.
|
|
13
38
|
*/
|
|
14
39
|
export declare function manifestPlugins(ttl: string): ManifestPlugin[];
|
|
40
|
+
/**
|
|
41
|
+
* The content an LV2 plugin declares it plays from: the parameters it lists as `patch:writable` whose `rdfs:range` is
|
|
42
|
+
* `atom:Path` (a sampler's sample, a drum machine's kit), sorted. Read from the bundle on the search path whose
|
|
43
|
+
* manifest declares `uri`, in the manifest and every file it names for the plugin. Empty when the plugin declares none
|
|
44
|
+
* or no bundle on the path holds it (#318).
|
|
45
|
+
*/
|
|
46
|
+
export declare function lv2ContentParams(uri: string, env: Readonly<Record<string, string | undefined>>, home?: string): string[];
|
|
15
47
|
/** The plugins a bundle manifest declares, each with its `lv2:binary` basename. */
|
|
16
48
|
export declare function pluginsInManifest(ttl: string): {
|
|
17
49
|
uri: string;
|