@openmixer/plugin-qualify 0.10.1 → 0.12.0
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/README.md +52 -10
- package/bin/plugin-qualify.mjs +61 -28
- package/dist/clap-loader.d.ts +1 -1
- package/dist/clap-loader.js +3 -3
- package/dist/clap-loader.js.map +1 -1
- package/dist/clap-qualify.d.ts +60 -51
- package/dist/clap-qualify.js +143 -91
- package/dist/clap-qualify.js.map +1 -1
- package/dist/cost-fields.d.ts +26 -0
- package/dist/cost-fields.js +30 -0
- package/dist/cost-fields.js.map +1 -1
- package/dist/hosting-codes.d.ts +1 -0
- package/dist/hosting-codes.js +1 -0
- package/dist/hosting-codes.js.map +1 -1
- package/dist/hosting-suitability.d.ts +22 -3
- package/dist/hosting-suitability.js +25 -5
- package/dist/hosting-suitability.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/judge-cli.d.ts +41 -0
- package/dist/judge-cli.js +114 -0
- package/dist/judge-cli.js.map +1 -0
- package/dist/measurement/cli.d.ts +7 -0
- package/dist/measurement/cli.js +14 -0
- package/dist/measurement/cli.js.map +1 -1
- package/dist/measurement/format.d.ts +44 -4
- package/dist/measurement/format.js +46 -3
- package/dist/measurement/format.js.map +1 -1
- package/dist/measurement/probe-json.js +4 -0
- package/dist/measurement/probe-json.js.map +1 -1
- package/dist/measurement/sweep-jsonl.js +2 -1
- package/dist/measurement/sweep-jsonl.js.map +1 -1
- package/dist/measurement/vocabulary.d.ts +9 -0
- package/dist/measurement/vocabulary.js +33 -0
- package/dist/measurement/vocabulary.js.map +1 -1
- package/dist/probe-judge.d.ts +65 -0
- package/dist/probe-judge.js +217 -0
- package/dist/probe-judge.js.map +1 -0
- package/dist/probe-output-fixtures.d.ts +25 -0
- package/dist/probe-output-fixtures.js +134 -0
- package/dist/probe-output-fixtures.js.map +1 -0
- package/dist/probe-output.d.ts +153 -0
- package/dist/probe-output.js +374 -0
- package/dist/probe-output.js.map +1 -0
- package/dist/probe-runner.d.ts +79 -0
- package/dist/probe-runner.js +191 -0
- package/dist/probe-runner.js.map +1 -0
- package/dist/qualification-record.d.ts +82 -0
- package/dist/qualification-record.js +85 -0
- package/dist/qualification-record.js.map +1 -0
- package/dist/qualify-cli.js +1 -1
- package/dist/qualify-cli.js.map +1 -1
- package/dist/qualify-declarations.d.ts +11 -2
- package/dist/qualify-declarations.js +14 -4
- package/dist/qualify-declarations.js.map +1 -1
- package/fixtures/clap-scan/fake.json +30 -6
- package/fixtures/probe-output/memory-limit-refused.json +190 -0
- package/fixtures/probe-output/plugin-crash.json +236 -0
- package/fixtures/probe-output/success-msi.json +363 -0
- package/package.json +5 -1
- package/src/clap-loader.ts +3 -2
- package/src/clap-qualify.ts +179 -138
- package/src/cost-fields.ts +39 -0
- package/src/hosting-codes.ts +1 -0
- package/src/hosting-suitability.ts +42 -7
- package/src/index.ts +5 -0
- package/src/judge-cli.ts +133 -0
- package/src/measurement/cli.ts +20 -0
- package/src/measurement/format.ts +80 -2
- package/src/measurement/probe-json.ts +4 -0
- package/src/measurement/sweep-jsonl.ts +2 -1
- package/src/measurement/vocabulary.ts +38 -0
- package/src/probe-judge.ts +272 -0
- package/src/probe-output-fixtures.ts +146 -0
- package/src/probe-output.ts +511 -0
- package/src/probe-runner.ts +244 -0
- package/src/qualification-record.ts +149 -0
- package/src/qualify-cli.ts +1 -1
- package/src/qualify-declarations.ts +16 -4
- package/tools/benchmark.py +116 -13
- package/tools/lv2-measure.mjs +2 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* Judging from a probe output. The probe output holds facts (`probe-output.ts`); this module turns
|
|
5
|
+
* them into the facts the one judge already reads and lets that judge speak. There is no second
|
|
6
|
+
* judge: a CLAP plugin's verdict is {@link rtSafetyDocument}'s fold of the same reasons it folds
|
|
7
|
+
* for a prober line, an LV2 plugin's is {@link rtSafetyReasons}, and cost is read by
|
|
8
|
+
* {@link hostingCostReasons} at the host's rate and quantum.
|
|
9
|
+
*
|
|
10
|
+
* What a probe output does not carry, this module does not invent:
|
|
11
|
+
*
|
|
12
|
+
* - `noteInputs` is the descriptor's fact. Without one the run's note sweep stands in: a plugin
|
|
13
|
+
* whose sweep was applicable has at least one note input; one whose sweep was not applicable is
|
|
14
|
+
* read as having none, so an instrument that could not be played reads as an effect. The caller
|
|
15
|
+
* that holds the descriptor passes the real count.
|
|
16
|
+
* - The note sweep's block count is the parameter sweep's: both run in one prober process at one
|
|
17
|
+
* block count, and the schema holds the note sweep's counts but not its blocks.
|
|
18
|
+
*/
|
|
19
|
+
import { DEFAULT_HOSTING_POLICY } from "./qualify-declarations.js";
|
|
20
|
+
import { rtSafetyDocument, } from "./clap-qualify.js";
|
|
21
|
+
import { gridCostReadings } from "./cost-fields.js";
|
|
22
|
+
import { hostingCostReasons, noteSweepReasons, rtSafetyReasons, contributedHostingRating, } from "./hosting-suitability.js";
|
|
23
|
+
import { PROBE_NOT_ATTEMPTED, PROBE_OK } from "./probe-output.js";
|
|
24
|
+
import { RATING_SEVERITY, worstRating } from "./rating.js";
|
|
25
|
+
/** A sum of one count over the points, or `undefined` when a point lacks it: a missing count is not zero. */
|
|
26
|
+
function total(points, count) {
|
|
27
|
+
let sum = 0;
|
|
28
|
+
for (const p of points) {
|
|
29
|
+
const n = count(p);
|
|
30
|
+
if (n === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
sum += n;
|
|
33
|
+
}
|
|
34
|
+
return sum;
|
|
35
|
+
}
|
|
36
|
+
/** The points whose run ended well: a point that crashed measured nothing. */
|
|
37
|
+
function okPoints(output) {
|
|
38
|
+
return output.grid.filter((p) => p.outcome === PROBE_OK);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The interposer's counts over every grid point that carries them. The interposer must have been
|
|
42
|
+
* loaded at every such point; the sweep counts as done when every point swept, and as applicable
|
|
43
|
+
* when any did. A count a point lacks leaves the total absent, and the judge reads that as
|
|
44
|
+
* unmeasured.
|
|
45
|
+
*/
|
|
46
|
+
export function rtSafetyOfProbeOutput(output) {
|
|
47
|
+
const points = okPoints(output).filter((p) => p.rtSafety !== undefined);
|
|
48
|
+
if (points.length === 0 || points.some((p) => p.rtSafety?.interposer !== true))
|
|
49
|
+
return { interposer: false };
|
|
50
|
+
const reading = (p) => p.rtSafety;
|
|
51
|
+
const allocations = total(points, (p) => reading(p)?.allocations);
|
|
52
|
+
const locks = total(points, (p) => reading(p)?.locks);
|
|
53
|
+
const syscalls = total(points, (p) => reading(p)?.syscalls);
|
|
54
|
+
return {
|
|
55
|
+
interposer: true,
|
|
56
|
+
swept: points.every((p) => reading(p)?.swept === true),
|
|
57
|
+
sweepApplicable: points.some((p) => reading(p)?.sweepApplicable === true),
|
|
58
|
+
blocks: total(points, (p) => reading(p)?.blocks ?? 0) ?? 0,
|
|
59
|
+
blockFrames: points[0]?.quantum ?? 0,
|
|
60
|
+
...(allocations === undefined ? {} : { allocationsInRun: allocations }),
|
|
61
|
+
...(locks === undefined ? {} : { locksInRun: locks }),
|
|
62
|
+
...(syscalls === undefined ? {} : { syscallsInRun: syscalls }),
|
|
63
|
+
events: points.flatMap((p) => reading(p)?.events ?? []),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function noteSweepOfProbeOutput(output, rt) {
|
|
67
|
+
const played = okPoints(output).find((p) => p.noteSweep?.applicable === true)?.noteSweep;
|
|
68
|
+
if (played === undefined)
|
|
69
|
+
return { applicable: false };
|
|
70
|
+
const dialect = {};
|
|
71
|
+
if (played.dialect === "clap" || played.dialect === "midi")
|
|
72
|
+
dialect.dialect = played.dialect;
|
|
73
|
+
const base = { applicable: true, ...dialect, blocks: rt.blocks ?? 0, blockFrames: rt.blockFrames ?? 0, noteEvents: 0, processErrors: 0, nonFinite: false };
|
|
74
|
+
if (!rt.interposer)
|
|
75
|
+
return { ...base, interposer: false };
|
|
76
|
+
return {
|
|
77
|
+
...base,
|
|
78
|
+
interposer: true,
|
|
79
|
+
...(played.allocations === undefined ? {} : { allocationsInRun: played.allocations }),
|
|
80
|
+
...(played.locks === undefined ? {} : { locksInRun: played.locks }),
|
|
81
|
+
...(played.syscalls === undefined ? {} : { syscallsInRun: played.syscalls }),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function integrityOfProbeOutput(output) {
|
|
85
|
+
const { files, layout, unpinnable } = output.binary;
|
|
86
|
+
if (layout === undefined || files.length === 0) {
|
|
87
|
+
return { unmeasuredReason: unpinnable === undefined ? "probe-error" : "unpinnable", unmeasuredDetail: unpinnable ?? "the probe output holds no layout pin" };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
...(output.plugin.version === undefined ? {} : { version: output.plugin.version }),
|
|
91
|
+
files: files.slice().sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
|
|
92
|
+
layout,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A CLAP probe output as the prober's line it stands for, so that {@link rtSafetyDocument} judges it.
|
|
97
|
+
* The facts the line holds and a probe output does not (the port layout, the features) are not read
|
|
98
|
+
* by the rtSafety fold and are left empty here.
|
|
99
|
+
*/
|
|
100
|
+
export function clapLineFromProbeOutput(output, facts = {}) {
|
|
101
|
+
const rtSafety = rtSafetyOfProbeOutput(output);
|
|
102
|
+
const noteSweep = noteSweepOfProbeOutput(output, rtSafety);
|
|
103
|
+
const points = okPoints(output);
|
|
104
|
+
const latency = {};
|
|
105
|
+
for (const p of points) {
|
|
106
|
+
if (p.latency !== undefined && latency[String(p.rate)] === undefined)
|
|
107
|
+
latency[String(p.rate)] = p.latency;
|
|
108
|
+
}
|
|
109
|
+
const withRt = points.filter((p) => p.rtSafety !== undefined);
|
|
110
|
+
return {
|
|
111
|
+
uri: `urn:clap:${output.plugin.id}`,
|
|
112
|
+
id: output.plugin.id,
|
|
113
|
+
binary: { path: output.binary.path, sha256: output.binary.sha256 },
|
|
114
|
+
hostExtensions: output.offer.clapExtensions ?? [],
|
|
115
|
+
clap: {
|
|
116
|
+
mainInputChannels: 0,
|
|
117
|
+
mainOutputChannels: 0,
|
|
118
|
+
sidechainInputs: 0,
|
|
119
|
+
features: [],
|
|
120
|
+
headlessOk: output.steps.some((s) => s.step === "instantiate" && s.outcome === PROBE_OK),
|
|
121
|
+
noteInputs: facts.noteInputs ?? (noteSweep.applicable ? 1 : 0),
|
|
122
|
+
latency,
|
|
123
|
+
threadViolations: total(withRt, (p) => p.rtSafety?.threadViolations ?? 0) ?? 0,
|
|
124
|
+
processErrors: total(withRt, (p) => p.rtSafety?.processErrors ?? 0) ?? 0,
|
|
125
|
+
// the sweep ran as many blocks as the points that counted say; a run with none measured nothing
|
|
126
|
+
processCalls: rtSafety.interposer ? (rtSafety.blocks ?? 0) : points.length,
|
|
127
|
+
nonFinite: output.steps.some((s) => s.outcome === "probe.non-finite-output"),
|
|
128
|
+
},
|
|
129
|
+
rtSafety,
|
|
130
|
+
noteSweep,
|
|
131
|
+
integrity: integrityOfProbeOutput(output),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const asRecordReason = (r) => ({ dimension: r.dimension, rating: contributedHostingRating(r), code: r.code, params: r.params });
|
|
135
|
+
function decidingOf(reasons, rating) {
|
|
136
|
+
if (rating === "suitable")
|
|
137
|
+
return undefined;
|
|
138
|
+
return [...reasons].sort((a, b) => RATING_SEVERITY[b.rating] - RATING_SEVERITY[a.rating]).find((r) => r.rating === rating);
|
|
139
|
+
}
|
|
140
|
+
function costOf(output, profile) {
|
|
141
|
+
const { rate, quantum } = profile.cost;
|
|
142
|
+
const reasons = hostingCostReasons({ cpuCost: { perRateQuantum: gridCostReadings(output.grid, PROBE_OK) } }, { rate, quantum, profile }, DEFAULT_HOSTING_POLICY);
|
|
143
|
+
const voices = output.grid.find((p) => p.outcome === PROBE_OK && p.rate === rate && p.quantum === quantum)?.cost?.voices;
|
|
144
|
+
return { rate, quantum, ...(voices === undefined ? {} : { voices }), reasons: reasons.map(asRecordReason) };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The outcome that ended the run badly, or `undefined` when it ended well. The run's own outcome is the
|
|
148
|
+
* first word; a grid point that failed under a run that says `probe.ok` is a document that contradicts
|
|
149
|
+
* itself, and is read as the failure it records rather than as a pass that skipped the point.
|
|
150
|
+
*/
|
|
151
|
+
function failedOutcome(output) {
|
|
152
|
+
if (output.run.outcome !== PROBE_OK)
|
|
153
|
+
return output.run.outcome;
|
|
154
|
+
return output.grid.find((p) => p.outcome !== PROBE_OK && p.outcome !== PROBE_NOT_ATTEMPTED)?.outcome;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Every profile's judgment of one probe output.
|
|
158
|
+
*
|
|
159
|
+
* A run that did not end `probe.ok` is `unknown` under every profile, with the run's outcome code as
|
|
160
|
+
* the reason: the measurement did not finish, so there is nothing to rate, and it is not a plugin
|
|
161
|
+
* `unsuitable` on evidence the run never gathered. A step that was not attempted is part of a run that
|
|
162
|
+
* ended well (a plugin with no note input has no note sweep).
|
|
163
|
+
*/
|
|
164
|
+
export function judgeProbeOutput(output, profiles, facts = {}) {
|
|
165
|
+
const uri = output.plugin.format === "clap" ? `urn:clap:${output.plugin.id}` : output.plugin.id;
|
|
166
|
+
const failure = failedOutcome(output);
|
|
167
|
+
if (failure !== undefined) {
|
|
168
|
+
const reason = { dimension: "rtSafety", rating: "unknown", code: failure, params: {} };
|
|
169
|
+
return {
|
|
170
|
+
output,
|
|
171
|
+
documents: [],
|
|
172
|
+
hosts: profiles.map((profile) => ({
|
|
173
|
+
verdict: { uri, host: profile.id, measured: false, rating: "unknown", qualified: false, deciding: failure },
|
|
174
|
+
hosting: "isolated",
|
|
175
|
+
reasons: [reason],
|
|
176
|
+
cost: costOf(output, profile),
|
|
177
|
+
})),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const line = output.plugin.format === "clap" ? clapLineFromProbeOutput(output, facts) : undefined;
|
|
181
|
+
const documents = [];
|
|
182
|
+
const hosts = profiles.map((profile) => {
|
|
183
|
+
let reasons;
|
|
184
|
+
if (line !== undefined) {
|
|
185
|
+
const doc = rtSafetyDocument(line, profile);
|
|
186
|
+
documents.push(doc);
|
|
187
|
+
reasons = doc.verdict.reasons.map(asRecordReason);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// an LV2 plugin: the control sweep's counts, and the note sweep's when it was played through a MIDI input
|
|
191
|
+
const rt = rtSafetyOfProbeOutput(output);
|
|
192
|
+
const notes = noteSweepOfProbeOutput(output, rt);
|
|
193
|
+
reasons = [...rtSafetyReasons(rt), ...noteSweepReasons(notes, facts.noteInputs ?? (notes.applicable ? 1 : 0))].map(asRecordReason);
|
|
194
|
+
}
|
|
195
|
+
const rating = worstRating(reasons.map((r) => r.rating));
|
|
196
|
+
const deciding = decidingOf(reasons, rating);
|
|
197
|
+
return {
|
|
198
|
+
verdict: {
|
|
199
|
+
uri,
|
|
200
|
+
host: profile.id,
|
|
201
|
+
measured: true,
|
|
202
|
+
rating,
|
|
203
|
+
qualified: rating === "suitable",
|
|
204
|
+
...(deciding === undefined ? {} : { deciding: deciding.code }),
|
|
205
|
+
},
|
|
206
|
+
hosting: rating === "suitable" && profile.isolation === "in-process" ? "in-process" : "isolated",
|
|
207
|
+
reasons,
|
|
208
|
+
cost: costOf(output, profile),
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
return { output, hosts, documents };
|
|
212
|
+
}
|
|
213
|
+
/** The verdict rows of a judgment, as the CLI prints them. */
|
|
214
|
+
export function judgmentVerdicts(judgment) {
|
|
215
|
+
return judgment.hosts.map((h) => h.verdict);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=probe-judge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe-judge.js","sourceRoot":"","sources":["../src/probe-judge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ClapQualifyLine } from "./clap-qualify.js";
|
|
2
|
+
import { type ProbeOutput } from "./probe-output.js";
|
|
3
|
+
export declare function fixtureText(name: string): string;
|
|
4
|
+
/** A fixture as a mutable JSON value, for the tests that break one field of it. */
|
|
5
|
+
export declare function fixtureJson(name: string): Record<string, any>;
|
|
6
|
+
/** A fixture through the reader; throws when the reader refuses it. */
|
|
7
|
+
export declare function readFixture(name: string): ProbeOutput;
|
|
8
|
+
/**
|
|
9
|
+
* The probe output that carries what a prober line carries, for the proofs that a verdict read from a
|
|
10
|
+
* probe output equals the verdict read from today's document. Built on the success fixture, so its machine,
|
|
11
|
+
* limits and run are a real document's.
|
|
12
|
+
*
|
|
13
|
+
* What the line holds and a probe output cannot is not encoded: the port layout and the features (no
|
|
14
|
+
* verdict reads them), the note sweep's process errors and non-finite flag, and a block count apart
|
|
15
|
+
* from the sweep's (the probe output has one, the blocks the sweep processed, which is `processCalls`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function probeOutputOfLine(line: ClapQualifyLine): Record<string, any>;
|
|
18
|
+
/** A prober line for a clean stereo effect, with `patch` merged over it. */
|
|
19
|
+
export declare function clapLineFixture(patch?: {
|
|
20
|
+
rtSafety?: object;
|
|
21
|
+
clap?: object;
|
|
22
|
+
hostExtensions?: string[];
|
|
23
|
+
noteSweep?: object;
|
|
24
|
+
integrity?: object;
|
|
25
|
+
}): ClapQualifyLine;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
|
+
/**
|
|
4
|
+
* The probe-output documents the tests build on, read from `fixtures/probe-output/`: plugin-hostd's
|
|
5
|
+
* three example documents (a success on the reference rig, a crash, a refusal for memory). Kept
|
|
6
|
+
* out of the test files so every test reads the same documents; a `.test.ts` imported for a helper
|
|
7
|
+
* runs its whole suite in each importer.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { OMX_CLAP_HOST_EXTENSIONS } from "./host-profiles.js";
|
|
13
|
+
import { readProbeOutput } from "./probe-output.js";
|
|
14
|
+
const FIXTURES = join(dirname(fileURLToPath(import.meta.url)), "..", "fixtures", "probe-output");
|
|
15
|
+
export function fixtureText(name) {
|
|
16
|
+
return readFileSync(join(FIXTURES, `${name}.json`), "utf8");
|
|
17
|
+
}
|
|
18
|
+
/** A fixture as a mutable JSON value, for the tests that break one field of it. */
|
|
19
|
+
export function fixtureJson(name) {
|
|
20
|
+
return JSON.parse(fixtureText(name));
|
|
21
|
+
}
|
|
22
|
+
/** A fixture through the reader; throws when the reader refuses it. */
|
|
23
|
+
export function readFixture(name) {
|
|
24
|
+
const r = readProbeOutput(fixtureText(name));
|
|
25
|
+
if (!r.ok)
|
|
26
|
+
throw new Error(`${name}: ${r.code}: ${r.problem}`);
|
|
27
|
+
return r.output;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The probe output that carries what a prober line carries, for the proofs that a verdict read from a
|
|
31
|
+
* probe output equals the verdict read from today's document. Built on the success fixture, so its machine,
|
|
32
|
+
* limits and run are a real document's.
|
|
33
|
+
*
|
|
34
|
+
* What the line holds and a probe output cannot is not encoded: the port layout and the features (no
|
|
35
|
+
* verdict reads them), the note sweep's process errors and non-finite flag, and a block count apart
|
|
36
|
+
* from the sweep's (the probe output has one, the blocks the sweep processed, which is `processCalls`).
|
|
37
|
+
*/
|
|
38
|
+
export function probeOutputOfLine(line) {
|
|
39
|
+
const doc = fixtureJson("success-msi");
|
|
40
|
+
const rt = line.rtSafety;
|
|
41
|
+
const note = line.noteSweep;
|
|
42
|
+
const pin = line.integrity;
|
|
43
|
+
const rates = Object.keys(line.clap.latency);
|
|
44
|
+
const quantum = rt.blockFrames ?? 512;
|
|
45
|
+
doc["plugin"] = { format: "clap", id: line.id, ...(pin.version === undefined ? {} : { version: pin.version }) };
|
|
46
|
+
doc["binary"] = {
|
|
47
|
+
path: line.binary.path,
|
|
48
|
+
sha256: line.binary.sha256,
|
|
49
|
+
files: pin.files ?? [],
|
|
50
|
+
...(pin.layout === undefined ? {} : { layout: pin.layout }),
|
|
51
|
+
...(pin.unmeasuredReason === undefined ? {} : { unpinnable: pin.unmeasuredDetail ?? pin.unmeasuredReason }),
|
|
52
|
+
};
|
|
53
|
+
delete doc["descriptor"];
|
|
54
|
+
doc["offer"] = { id: "default", clapExtensions: [...line.hostExtensions], realtime: "none" };
|
|
55
|
+
doc["steps"] = [{ step: "hash", outcome: "probe.ok", elapsedMs: 1 }, { step: "instantiate", outcome: "probe.ok", elapsedMs: 1 }];
|
|
56
|
+
const first = {};
|
|
57
|
+
if (rt.interposer) {
|
|
58
|
+
Object.assign(first, {
|
|
59
|
+
rtSafety: {
|
|
60
|
+
interposer: true,
|
|
61
|
+
swept: rt.swept,
|
|
62
|
+
sweepApplicable: rt.sweepApplicable,
|
|
63
|
+
blocks: line.clap.processCalls,
|
|
64
|
+
allocations: rt.allocationsInRun,
|
|
65
|
+
locks: rt.locksInRun,
|
|
66
|
+
syscalls: rt.syscallsInRun,
|
|
67
|
+
threadViolations: line.clap.threadViolations,
|
|
68
|
+
processErrors: line.clap.processErrors,
|
|
69
|
+
events: rt.events ?? [],
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
first["rtSafety"] = { interposer: false };
|
|
75
|
+
if (note.applicable) {
|
|
76
|
+
first["noteSweep"] = {
|
|
77
|
+
applicable: true,
|
|
78
|
+
...(note.dialect === undefined ? {} : { dialect: note.dialect }),
|
|
79
|
+
...(note.interposer === true ? { allocations: note.allocationsInRun, locks: note.locksInRun, syscalls: note.syscallsInRun } : {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const at = rates.length > 0 ? rates : ["48000"];
|
|
83
|
+
doc["grid"] = at.map((rate, i) => ({
|
|
84
|
+
rate: Number(rate),
|
|
85
|
+
quantum,
|
|
86
|
+
outcome: "probe.ok",
|
|
87
|
+
...(line.clap.latency[rate] === undefined ? {} : { latency: { ...line.clap.latency[rate], method: "impulse-onset" } }),
|
|
88
|
+
...(i === 0 ? first : {}),
|
|
89
|
+
}));
|
|
90
|
+
return doc;
|
|
91
|
+
}
|
|
92
|
+
const PIN = {
|
|
93
|
+
version: "1",
|
|
94
|
+
files: [{ path: "rt-safe.clap", sha256: "a".repeat(64) }],
|
|
95
|
+
layout: { scheme: "omx-layout/1", sha256: "b".repeat(64) },
|
|
96
|
+
};
|
|
97
|
+
/** A prober line for a clean stereo effect, with `patch` merged over it. */
|
|
98
|
+
export function clapLineFixture(patch = {}) {
|
|
99
|
+
return {
|
|
100
|
+
uri: "urn:clap:org.example.fx",
|
|
101
|
+
id: "org.example.fx",
|
|
102
|
+
binary: { path: "/x/rt-safe.clap", sha256: "a".repeat(64) },
|
|
103
|
+
hostExtensions: patch.hostExtensions ?? [...OMX_CLAP_HOST_EXTENSIONS],
|
|
104
|
+
clap: {
|
|
105
|
+
mainInputChannels: 2,
|
|
106
|
+
mainOutputChannels: 2,
|
|
107
|
+
sidechainInputs: 0,
|
|
108
|
+
features: ["audio-effect"],
|
|
109
|
+
headlessOk: true,
|
|
110
|
+
noteInputs: 0,
|
|
111
|
+
latency: { "48000": { declaredFrames: 0, measuredFrames: 0 }, "96000": { declaredFrames: 4, measuredFrames: 4 } },
|
|
112
|
+
threadViolations: 0,
|
|
113
|
+
processErrors: 0,
|
|
114
|
+
processCalls: 512,
|
|
115
|
+
nonFinite: false,
|
|
116
|
+
...patch.clap,
|
|
117
|
+
},
|
|
118
|
+
rtSafety: {
|
|
119
|
+
interposer: true,
|
|
120
|
+
swept: true,
|
|
121
|
+
sweepApplicable: true,
|
|
122
|
+
blocks: 512,
|
|
123
|
+
blockFrames: 512,
|
|
124
|
+
allocationsInRun: 0,
|
|
125
|
+
locksInRun: 0,
|
|
126
|
+
syscallsInRun: 0,
|
|
127
|
+
events: [],
|
|
128
|
+
...patch.rtSafety,
|
|
129
|
+
},
|
|
130
|
+
noteSweep: { applicable: false, ...patch.noteSweep },
|
|
131
|
+
integrity: { ...PIN, ...patch.integrity },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=probe-output-fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe-output-fixtures.js","sourceRoot":"","sources":["../src/probe-output-fixtures.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { type VoicesHeld } from "./measurement/format.js";
|
|
2
|
+
export declare const PROBE_OUTPUT_FORMAT = "plugin-hostd.probe-output";
|
|
3
|
+
/** The one major this reader knows. A minor of it only adds fields. */
|
|
4
|
+
export declare const PROBE_OUTPUT_MAJOR = 1;
|
|
5
|
+
export declare const PROBE_FORMAT_CODE: {
|
|
6
|
+
readonly majorUnknown: "probe.format.major-unknown";
|
|
7
|
+
readonly derivedMismatch: "probe.format.derived-mismatch";
|
|
8
|
+
readonly invalid: "probe.format.invalid";
|
|
9
|
+
};
|
|
10
|
+
export type ProbeFormatCode = (typeof PROBE_FORMAT_CODE)[keyof typeof PROBE_FORMAT_CODE];
|
|
11
|
+
/** The outcome that means a step ran to its end. */
|
|
12
|
+
export declare const PROBE_OK = "probe.ok";
|
|
13
|
+
export declare const PROBE_NOT_ATTEMPTED = "probe.not-attempted";
|
|
14
|
+
/**
|
|
15
|
+
* An exit-latency above this many microseconds makes an idle state deep. The runner writes the
|
|
16
|
+
* document by this rule, so the reader recomputes by it; the protocol document will state it
|
|
17
|
+
* (plugin-hostd#78) and this number follows that document.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEEP_IDLE_LATENCY_US = 20;
|
|
20
|
+
export interface ProbeFile {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
readonly sha256: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ProbeCost {
|
|
25
|
+
readonly median: number;
|
|
26
|
+
/** The percentile the figure is taken at, and its value, in nanoseconds per sample. */
|
|
27
|
+
readonly percentile: {
|
|
28
|
+
readonly p: number;
|
|
29
|
+
readonly value: number;
|
|
30
|
+
};
|
|
31
|
+
readonly blocks: number;
|
|
32
|
+
readonly warmupBlocks: number;
|
|
33
|
+
/** For an instrument: the notes it held while it was timed, how many and why that many. */
|
|
34
|
+
readonly voices?: VoicesHeld;
|
|
35
|
+
}
|
|
36
|
+
export interface ProbeRtSafety {
|
|
37
|
+
readonly interposer: boolean;
|
|
38
|
+
readonly swept?: boolean;
|
|
39
|
+
readonly sweepApplicable?: boolean;
|
|
40
|
+
readonly blocks?: number;
|
|
41
|
+
readonly allocations?: number;
|
|
42
|
+
readonly locks?: number;
|
|
43
|
+
readonly syscalls?: number;
|
|
44
|
+
readonly threadViolations?: number;
|
|
45
|
+
readonly processErrors?: number;
|
|
46
|
+
readonly events?: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
export interface ProbeNoteSweep {
|
|
49
|
+
readonly applicable: boolean;
|
|
50
|
+
readonly dialect?: string;
|
|
51
|
+
readonly allocations?: number;
|
|
52
|
+
readonly locks?: number;
|
|
53
|
+
readonly syscalls?: number;
|
|
54
|
+
}
|
|
55
|
+
/** One point of the protocol's grid: the figures at one rate and one quantum. */
|
|
56
|
+
export interface ProbeGridPoint {
|
|
57
|
+
readonly rate: number;
|
|
58
|
+
readonly quantum: number;
|
|
59
|
+
readonly outcome: string;
|
|
60
|
+
readonly latency?: {
|
|
61
|
+
readonly declaredFrames: number;
|
|
62
|
+
readonly measuredFrames: number;
|
|
63
|
+
};
|
|
64
|
+
readonly cost?: ProbeCost;
|
|
65
|
+
readonly rtSafety?: ProbeRtSafety;
|
|
66
|
+
readonly noteSweep?: ProbeNoteSweep;
|
|
67
|
+
}
|
|
68
|
+
export interface ProbeStep {
|
|
69
|
+
readonly step: string;
|
|
70
|
+
readonly outcome: string;
|
|
71
|
+
readonly rate?: number;
|
|
72
|
+
readonly quantum?: number;
|
|
73
|
+
readonly detail?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ProbeIdleState {
|
|
76
|
+
readonly cpu: number;
|
|
77
|
+
readonly state: string;
|
|
78
|
+
readonly latencyUs: number;
|
|
79
|
+
readonly disabled: boolean;
|
|
80
|
+
readonly usageDelta: number;
|
|
81
|
+
}
|
|
82
|
+
export interface ProbeOutput {
|
|
83
|
+
readonly formatVersion: string;
|
|
84
|
+
readonly run: {
|
|
85
|
+
readonly id: string;
|
|
86
|
+
readonly startedAt: string;
|
|
87
|
+
readonly elapsedMs: number;
|
|
88
|
+
readonly complete: boolean;
|
|
89
|
+
readonly outcome: string;
|
|
90
|
+
readonly reason?: string;
|
|
91
|
+
readonly protocol: {
|
|
92
|
+
readonly name: string;
|
|
93
|
+
readonly version: number;
|
|
94
|
+
};
|
|
95
|
+
readonly tools: Readonly<Record<string, string>>;
|
|
96
|
+
readonly via: string;
|
|
97
|
+
};
|
|
98
|
+
readonly plugin: {
|
|
99
|
+
readonly format: "clap" | "lv2";
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly name?: string;
|
|
102
|
+
readonly version?: string;
|
|
103
|
+
};
|
|
104
|
+
readonly binary: {
|
|
105
|
+
readonly path: string;
|
|
106
|
+
readonly sha256: string;
|
|
107
|
+
readonly files: readonly ProbeFile[];
|
|
108
|
+
readonly layout?: {
|
|
109
|
+
readonly scheme: string;
|
|
110
|
+
readonly sha256: string;
|
|
111
|
+
};
|
|
112
|
+
/** Why the files cannot be pinned, when they cannot. */
|
|
113
|
+
readonly unpinnable?: string;
|
|
114
|
+
};
|
|
115
|
+
readonly machine: {
|
|
116
|
+
readonly class: Readonly<Record<string, string | boolean>>;
|
|
117
|
+
readonly profile: {
|
|
118
|
+
readonly governor: string | null;
|
|
119
|
+
readonly cpuidle: readonly ProbeIdleState[];
|
|
120
|
+
readonly meetsProtocol: boolean;
|
|
121
|
+
readonly unmet: readonly string[];
|
|
122
|
+
};
|
|
123
|
+
readonly pinnedCpus: string;
|
|
124
|
+
};
|
|
125
|
+
readonly offer: {
|
|
126
|
+
readonly id: string;
|
|
127
|
+
readonly clapExtensions?: readonly string[];
|
|
128
|
+
};
|
|
129
|
+
readonly steps: readonly ProbeStep[];
|
|
130
|
+
readonly grid: readonly ProbeGridPoint[];
|
|
131
|
+
/** What the document says about how the plugin behaves, as it was written. */
|
|
132
|
+
readonly behaviour?: Readonly<Record<string, unknown>>;
|
|
133
|
+
}
|
|
134
|
+
export type ReadProbeOutputResult = {
|
|
135
|
+
readonly ok: true;
|
|
136
|
+
readonly output: ProbeOutput;
|
|
137
|
+
} | {
|
|
138
|
+
readonly ok: false;
|
|
139
|
+
readonly code: ProbeFormatCode;
|
|
140
|
+
readonly problem: string;
|
|
141
|
+
};
|
|
142
|
+
/** Whether any idle state deeper than {@link DEEP_IDLE_LATENCY_US} is enabled: then the machine does not limit its C-states. */
|
|
143
|
+
export declare function deepIdleEnabled(cpuidle: readonly ProbeIdleState[]): boolean;
|
|
144
|
+
/** Whether a deep idle state was entered while the run measured. */
|
|
145
|
+
export declare function deepIdleEntered(cpuidle: readonly ProbeIdleState[]): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* A probe output from its text, or the code that refuses it. The order of the checks is the order of
|
|
148
|
+
* what can be trusted: that it is JSON and the format, then the major (before any content is read),
|
|
149
|
+
* then that it holds no judgment, then the content, then the derived fields against it.
|
|
150
|
+
*/
|
|
151
|
+
export declare function readProbeOutput(text: string): ReadProbeOutputResult;
|
|
152
|
+
/** The SHA-256 of some bytes, as the record names a probe output's copy. */
|
|
153
|
+
export declare function sha256Hex(bytes: Uint8Array): string;
|