@openmixer/plugin-qualify 0.12.0 → 0.13.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 +1 -1
- package/dist/host-profiles.d.ts +1 -2
- package/dist/host-profiles.js +12 -2
- package/dist/host-profiles.js.map +1 -1
- package/dist/hosting-codes.d.ts +77 -57
- package/dist/hosting-codes.js +89 -77
- package/dist/hosting-codes.js.map +1 -1
- package/dist/hosting-suitability.d.ts +1 -2
- package/dist/hosting-suitability.js +4 -13
- package/dist/hosting-suitability.js.map +1 -1
- package/dist/measurement/cli.d.ts +1 -1
- package/dist/measurement/cli.js +1 -1
- package/dist/measurement/cli.js.map +1 -1
- package/dist/measurement/format.d.ts +1 -1
- package/dist/measurement/vocabulary.d.ts +30 -22
- package/dist/measurement/vocabulary.js +84 -163
- package/dist/measurement/vocabulary.js.map +1 -1
- package/fixtures/clap-scan/fake.json +109 -7
- package/fixtures/probe-output/success-msi.json +11 -0
- package/package.json +2 -2
- package/src/host-profiles.ts +12 -2
- package/src/hosting-codes.ts +182 -77
- package/src/hosting-suitability.ts +4 -14
- package/src/measurement/cli.ts +1 -1
- package/src/measurement/format.ts +1 -1
- package/src/measurement/vocabulary.ts +135 -167
|
@@ -109,6 +109,17 @@
|
|
|
109
109
|
"clap.params",
|
|
110
110
|
"clap.state",
|
|
111
111
|
"clap.thread-check",
|
|
112
|
+
"clap.note-ports",
|
|
113
|
+
"clap.note-name",
|
|
114
|
+
"clap.voice-info",
|
|
115
|
+
"clap.event-registry",
|
|
116
|
+
"clap.timer-support",
|
|
117
|
+
"clap.posix-fd-support",
|
|
118
|
+
"clap.thread-pool",
|
|
119
|
+
"clap.tail",
|
|
120
|
+
"clap.surround/4",
|
|
121
|
+
"clap.ambisonic/3",
|
|
122
|
+
"clap.audio-ports-config",
|
|
112
123
|
"clap.preset-load/2",
|
|
113
124
|
"clap.track-info/1",
|
|
114
125
|
"clap.remote-controls/2"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmixer/plugin-qualify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Qualify audio plugins for real-time hosting: scan, offline latency and cost measurement, a mod-host hosting sweep, and a fail-closed rating.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -96,6 +96,6 @@
|
|
|
96
96
|
"provenance": true
|
|
97
97
|
},
|
|
98
98
|
"dependencies": {
|
|
99
|
-
"@openmixer/omx-contract": "^
|
|
99
|
+
"@openmixer/omx-contract": "^3.0.0"
|
|
100
100
|
}
|
|
101
101
|
}
|
package/src/host-profiles.ts
CHANGED
|
@@ -42,8 +42,7 @@ export const OMX_INPROCESS_FEATURES: readonly string[] = [
|
|
|
42
42
|
* than on the desk. The list's home is the CLAP library — libomx-clap-core's own
|
|
43
43
|
* `clap_host_extensions.h`, what its host object offers — and this is its mirror, held equal to the
|
|
44
44
|
* header at the pinned omx-clap-host (by the console's conformance test), so the verdict never
|
|
45
|
-
* promises more or less than the host provides. Nothing else: no `gui
|
|
46
|
-
* `posix-fd-support`, no `thread-pool`.
|
|
45
|
+
* promises more or less than the host provides. Nothing else: no `gui`.
|
|
47
46
|
*/
|
|
48
47
|
export const OMX_CLAP_HOST_EXTENSIONS: readonly string[] = [
|
|
49
48
|
"clap.log",
|
|
@@ -52,6 +51,17 @@ export const OMX_CLAP_HOST_EXTENSIONS: readonly string[] = [
|
|
|
52
51
|
"clap.params",
|
|
53
52
|
"clap.audio-ports",
|
|
54
53
|
"clap.state",
|
|
54
|
+
"clap.note-ports",
|
|
55
|
+
"clap.note-name",
|
|
56
|
+
"clap.voice-info",
|
|
57
|
+
"clap.event-registry",
|
|
58
|
+
"clap.timer-support",
|
|
59
|
+
"clap.posix-fd-support",
|
|
60
|
+
"clap.thread-pool",
|
|
61
|
+
"clap.tail",
|
|
62
|
+
"clap.surround/4",
|
|
63
|
+
"clap.ambisonic/3",
|
|
64
|
+
"clap.audio-ports-config",
|
|
55
65
|
];
|
|
56
66
|
|
|
57
67
|
/**
|
package/src/hosting-codes.ts
CHANGED
|
@@ -1,82 +1,187 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
2
|
// Copyright (C) 2026 Pau Aliagas <linuxnow@gmail.com>
|
|
3
3
|
/**
|
|
4
|
-
* The hosting verdict's message codes. Codes, never prose: the
|
|
5
|
-
*
|
|
4
|
+
* The hosting verdict's message codes. Codes, never prose: the surface renders the operator's
|
|
5
|
+
* locale.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* omx-clap-core declares every hosting code now (the contract split moved `data/hosting/*.json`
|
|
8
|
+
* there, byte for byte): one `HOSTING_<DIMENSION>_CODES` table per dimension, rendered into the
|
|
9
|
+
* TypeScript modules its package installs under `pkg-config --variable=tsdir omx-clap-core`
|
|
10
|
+
* (BUILDING.md) — `omx-clap-core-vocabulary.js` for the dimensions carried from omx-contract,
|
|
11
|
+
* `omx-clap-core-hosting.js` for `hosting.idle.*`, its own (both with a `.d.ts`). {@link
|
|
12
|
+
* HOSTING_CODE} is those tables flattened into one `key: code` map, loaded at import: a code
|
|
13
|
+
* neither module declares cannot be named here, and a dimension either adds arrives without an
|
|
14
|
+
* edit.
|
|
11
15
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
16
|
+
import { execFileSync } from "node:child_process";
|
|
17
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
|
|
21
|
+
/** The two TypeScript modules omx-clap-core's `tsdir` carries, each a `HOSTING_<DIMENSION>_CODES` source. */
|
|
22
|
+
const CLAP_CORE_TS_MODULES = ["omx-clap-core-vocabulary.js", "omx-clap-core-hosting.js"] as const;
|
|
23
|
+
|
|
24
|
+
/** This package's own root, resolved from this module so it follows wherever it is installed. */
|
|
25
|
+
const PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
26
|
+
|
|
27
|
+
/** `native/fetch-deps.sh`'s own checkout of omx-clap-core, for a build with no omx-clap-core-devel installed. */
|
|
28
|
+
const DEPS_TS_DIR = join(PACKAGE_ROOT, "native/deps/omx-clap-core/ts");
|
|
29
|
+
|
|
30
|
+
/** Where `make install` of omx-clap-host puts them (BUILDING.md), for a run with no `pkg-config` binary at all. */
|
|
31
|
+
const DEFAULT_SYSTEM_TS_DIR = "/usr/share/omx-clap-core/ts";
|
|
32
|
+
|
|
33
|
+
/** `pkg-config --variable=tsdir omx-clap-core`, or `undefined` where pkg-config or the package is absent. */
|
|
34
|
+
function pkgConfigTsDir(env: Readonly<Record<string, string | undefined>>): string | undefined {
|
|
35
|
+
try {
|
|
36
|
+
const out = execFileSync(env.PKG_CONFIG ?? "pkg-config", ["--variable=tsdir", "omx-clap-core"], {
|
|
37
|
+
encoding: "utf8",
|
|
38
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
39
|
+
}).trim();
|
|
40
|
+
return out === "" ? undefined : out;
|
|
41
|
+
} catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Where omx-clap-core's TypeScript modules are looked for, in order: `OMX_CLAP_CORE_TSDIR` when
|
|
48
|
+
* set (and only that), else `pkg-config --variable=tsdir omx-clap-core`, else the checkout
|
|
49
|
+
* `native/fetch-deps.sh` stages, else the path `make install` of omx-clap-host uses by default —
|
|
50
|
+
* a packaged plugin-qualify's runtime has no `pkg-config` binary to ask.
|
|
51
|
+
*/
|
|
52
|
+
export function clapCoreTsDirCandidates(env: Readonly<Record<string, string | undefined>> = process.env): readonly string[] {
|
|
53
|
+
const set = env.OMX_CLAP_CORE_TSDIR;
|
|
54
|
+
if (set !== undefined && set !== "") return [set];
|
|
55
|
+
const fromPkgConfig = pkgConfigTsDir(env);
|
|
56
|
+
return [...(fromPkgConfig === undefined ? [] : [fromPkgConfig]), DEPS_TS_DIR, DEFAULT_SYSTEM_TS_DIR];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function locateClapCoreTsDir(): string {
|
|
60
|
+
const candidates = clapCoreTsDirCandidates();
|
|
61
|
+
const dir = candidates.find((d) => CLAP_CORE_TS_MODULES.every((m) => existsSync(join(d, m))));
|
|
62
|
+
if (dir === undefined) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`omx-clap-core's TypeScript modules (${CLAP_CORE_TS_MODULES.join(", ")}) were not found in any of: ` +
|
|
65
|
+
`${candidates.join(", ")}. Install omx-clap-core-devel (pkg-config omx-clap-core), set ` +
|
|
66
|
+
"OMX_CLAP_CORE_TSDIR to its tsdir, or run native/fetch-deps.sh.",
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return dir;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** True for an export name that is one of omx-clap-core's hosting tables. */
|
|
73
|
+
export function isHostingTableName(name: string): boolean {
|
|
74
|
+
return /^HOSTING_[A-Z0-9_]+_CODES$/.test(name);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type HostingEntries = Record<string, { readonly code: string }>;
|
|
78
|
+
|
|
79
|
+
async function loadHostingTables(): Promise<Record<string, HostingEntries>> {
|
|
80
|
+
const dir = locateClapCoreTsDir();
|
|
81
|
+
const tables: Record<string, HostingEntries> = {};
|
|
82
|
+
for (const name of CLAP_CORE_TS_MODULES) {
|
|
83
|
+
// The modules are self-contained ES modules in a directory with no package.json: Node 18 reads such a .js as
|
|
84
|
+
// CommonJS and refuses `export`, so the source is imported as a data: module, which is a module on every Node.
|
|
85
|
+
const source = readFileSync(join(dir, name), "utf8");
|
|
86
|
+
const mod: Record<string, unknown> = await import(`data:text/javascript;base64,${Buffer.from(source).toString("base64")}`);
|
|
87
|
+
for (const [exportName, table] of Object.entries(mod)) {
|
|
88
|
+
if (isHostingTableName(exportName)) tables[exportName] = table as HostingEntries;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return tables;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function flatten(tables: Record<string, HostingEntries>): HostingCodeTable {
|
|
95
|
+
const table: Record<string, string> = {};
|
|
96
|
+
for (const [name, entries] of Object.entries(tables)) {
|
|
97
|
+
for (const [key, entry] of Object.entries(entries)) {
|
|
98
|
+
if (key in table) throw new Error(`omx-clap-core declares the hosting key ${key} twice (${name})`);
|
|
99
|
+
table[key] = entry.code;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return Object.freeze(table) as unknown as HostingCodeTable;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* omx-clap-core's hosting codes, by key, across its two TypeScript modules — hand-kept here
|
|
107
|
+
* (not derived from a static import: the source is a runtime-resolved install directory, not an
|
|
108
|
+
* npm dependency) and held to the real modules by
|
|
109
|
+
* `src/contract-vocabulary-conformance.test.ts`, which turns red on any drift either way.
|
|
110
|
+
*/
|
|
111
|
+
export interface HostingCodeTable {
|
|
112
|
+
readonly clapExtensionsNotCovered: "hosting.clap.extensions-not-covered";
|
|
113
|
+
readonly clapFormatNotHosted: "hosting.clap.format-not-hosted";
|
|
114
|
+
readonly clapHeadlessFailed: "hosting.clap.headless-failed";
|
|
115
|
+
readonly clapLatencyMismatch: "hosting.clap.latency-mismatch";
|
|
116
|
+
readonly clapNoteInput: "hosting.clap.note-input";
|
|
117
|
+
readonly clapProcessError: "hosting.clap.process-error";
|
|
118
|
+
readonly clapThreadViolation: "hosting.clap.thread-violation";
|
|
119
|
+
readonly clapUnqualified: "hosting.clap.unqualified";
|
|
120
|
+
readonly costAboveCeiling: "hosting.cost.above-ceiling";
|
|
121
|
+
readonly costFieldsMissing: "hosting.cost.fields-missing";
|
|
122
|
+
readonly costSpiky: "hosting.cost.spiky-tail";
|
|
123
|
+
readonly costUnmeasured: "hosting.cost.unmeasured-at-rate-and-quantum";
|
|
124
|
+
readonly costWithinCeiling: "hosting.cost.within-ceiling";
|
|
125
|
+
readonly featuresAtomInUnfed: "hosting.features.atom-in-unfed";
|
|
126
|
+
readonly featuresDisqualifying: "hosting.features.host-not-provided";
|
|
127
|
+
readonly featuresMidiIn: "hosting.features.midi-in-fed-empty";
|
|
128
|
+
readonly featuresMissing: "hosting.features.missing";
|
|
129
|
+
readonly featuresPortsUnreadable: "hosting.features.ports-unreadable";
|
|
130
|
+
readonly featuresProvided: "hosting.features.all-provided";
|
|
131
|
+
readonly featuresUnscanned: "hosting.features.scan-predates-field";
|
|
132
|
+
readonly idleHoldRefused: "hosting.idle.hold-refused";
|
|
133
|
+
readonly latencyNonconforming: "hosting.latency.nonconforming";
|
|
134
|
+
readonly latencyParameterDependent: "hosting.latency.parameter-dependent";
|
|
135
|
+
readonly latencyResolved: "hosting.latency.resolved";
|
|
136
|
+
readonly latencyUnmeasured: "hosting.latency.unmeasured";
|
|
137
|
+
readonly outputNonFinite: "hosting.output.non-finite";
|
|
138
|
+
readonly overrideIsolated: "hosting.override.curator-isolated";
|
|
139
|
+
readonly patchBusy: "hosting.patch.busy";
|
|
140
|
+
readonly patchNotWritable: "hosting.patch.not-writable";
|
|
141
|
+
readonly patchTooLarge: "hosting.patch.too-large";
|
|
142
|
+
readonly presetNotFound: "hosting.preset.not-found";
|
|
143
|
+
readonly hostProvenanceDiffers: "hosting.provenance.host-differs";
|
|
144
|
+
readonly sweepControlDidNotFire: "hosting.provenance.sweep-control-did-not-fire";
|
|
145
|
+
readonly disabled: "hosting.disabled";
|
|
146
|
+
readonly linked: "hosting.linked";
|
|
147
|
+
readonly noRealisation: "hosting.no-realisation";
|
|
148
|
+
readonly realisedInProcess: "hosting.realised.in-process";
|
|
149
|
+
readonly unjudged: "hosting.unjudged";
|
|
150
|
+
readonly rtSafetyClean: "hosting.rt-safety.clean-under-sweep";
|
|
151
|
+
readonly rtSafetyNotReproducible: "hosting.rt-safety.not-reproducible";
|
|
152
|
+
readonly rtSafetyNotesClean: "hosting.rt-safety.clean-under-notes";
|
|
153
|
+
readonly rtSafetyNotesUnmeasured: "hosting.rt-safety.notes-unmeasured";
|
|
154
|
+
readonly rtSafetyNotesViolations: "hosting.rt-safety.violations-under-notes";
|
|
155
|
+
readonly rtSafetyUnmeasured: "hosting.rt-safety.unmeasured";
|
|
156
|
+
readonly rtSafetyViolations: "hosting.rt-safety.violations-in-run";
|
|
157
|
+
readonly stabilityBelowFloor: "hosting.stability.cycles-below-floor";
|
|
158
|
+
readonly stabilityCrashUnattributed: "hosting.stability.crash-unattributed";
|
|
159
|
+
readonly stabilityCrashedAttributed: "hosting.stability.crashed-attributed-plugin";
|
|
160
|
+
readonly stabilityCrashedLive: "hosting.stability.crashed-live-on-this-rig";
|
|
161
|
+
readonly stabilityLinksGuiToolkit: "hosting.stability.links-gui-toolkit";
|
|
162
|
+
readonly stabilitySoakFailedAtRate: "hosting.stability.soak-failed-at-rate";
|
|
163
|
+
readonly stabilitySoaked: "hosting.stability.soaked";
|
|
164
|
+
readonly stabilitySpawnsThreads: "hosting.stability.spawns-threads";
|
|
165
|
+
readonly stabilityUnmeasured: "hosting.stability.unmeasured";
|
|
166
|
+
readonly stabilityUnsoaked: "hosting.stability.unsoaked";
|
|
167
|
+
readonly stateNotACopy: "hosting.state.not-a-copy";
|
|
168
|
+
readonly statePathOnAudio: "hosting.state.path-on-audio";
|
|
169
|
+
readonly statePathOutside: "hosting.state.path-outside";
|
|
170
|
+
readonly statePathSymlink: "hosting.state.path-symlink";
|
|
171
|
+
readonly statePathTooLong: "hosting.state.path-too-long";
|
|
172
|
+
readonly statePathUnmakeable: "hosting.state.path-unmakeable";
|
|
173
|
+
readonly stateUnreadable: "hosting.state.unreadable";
|
|
174
|
+
readonly topologyAmbisonicConfig: "hosting.topology.ambisonic-config";
|
|
175
|
+
readonly topologyChannelMapUnknown: "hosting.topology.channel-map-unknown";
|
|
176
|
+
readonly topologyInstrument: "hosting.topology.instrument";
|
|
177
|
+
readonly topologyMatched: "hosting.topology.matched";
|
|
178
|
+
readonly topologyNoAudioInput: "hosting.topology.no-audio-input";
|
|
179
|
+
readonly topologyNoAudioOutput: "hosting.topology.no-audio-output";
|
|
180
|
+
readonly topologyPortTooWide: "hosting.topology.port-too-wide";
|
|
181
|
+
readonly topologyPortWithoutChannels: "hosting.topology.port-without-channels";
|
|
182
|
+
readonly topologyTooManyPorts: "hosting.topology.too-many-ports";
|
|
183
|
+
readonly topologyWiderThanStrip: "hosting.topology.wider-than-strip";
|
|
184
|
+
readonly workerNonconforming: "hosting.worker.nonconforming";
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const HOSTING_CODE: HostingCodeTable = flatten(await loadHostingTables());
|
|
@@ -148,12 +148,11 @@ export type HostingCode = (typeof HOSTING_CODE)[keyof typeof HOSTING_CODE];
|
|
|
148
148
|
*/
|
|
149
149
|
export const CLAP_CORE_REFUSALS = {
|
|
150
150
|
headlessFailed: "clapHeadlessFailed",
|
|
151
|
-
notAudioEffect: "clapNotAudioEffect",
|
|
152
151
|
noteInput: "clapNoteInput",
|
|
153
152
|
noAudioInput: "topologyNoAudioInput",
|
|
154
153
|
noAudioOutput: "topologyNoAudioOutput",
|
|
155
154
|
widerThanStrip: "topologyWiderThanStrip",
|
|
156
|
-
|
|
155
|
+
tooManyPorts: "topologyTooManyPorts",
|
|
157
156
|
crashedLive: "stabilityCrashedLive",
|
|
158
157
|
outputNonFinite: "outputNonFinite",
|
|
159
158
|
} as const satisfies Record<string, keyof typeof HOSTING_CODE>;
|
|
@@ -164,12 +163,11 @@ export const CLAP_CORE_REFUSALS = {
|
|
|
164
163
|
* refusal so the renderer holds no prose. A refusal without a line renders bare.
|
|
165
164
|
*/
|
|
166
165
|
export const CLAP_CORE_REFUSAL_DESCRIPTIONS: { readonly [K in keyof typeof CLAP_CORE_REFUSALS]?: string } = {
|
|
167
|
-
notAudioEffect: "the plugin is not an audio effect",
|
|
168
166
|
noteInput: "the plugin declares a note input the configuration refuses",
|
|
169
167
|
noAudioInput: "the plugin has no audio input",
|
|
170
168
|
noAudioOutput: "the plugin has no audio output",
|
|
171
169
|
widerThanStrip: "the plugin is wider than the strip",
|
|
172
|
-
|
|
170
|
+
tooManyPorts: "the plugin has more ports than the auxiliary limit allows",
|
|
173
171
|
crashedLive: "the plugin crashed live on this rig",
|
|
174
172
|
outputNonFinite: "the plugin produced non-finite output",
|
|
175
173
|
};
|
|
@@ -696,9 +694,6 @@ export function featureReasons(
|
|
|
696
694
|
}),
|
|
697
695
|
);
|
|
698
696
|
}
|
|
699
|
-
if ((features.cvPorts ?? 0) > 0) {
|
|
700
|
-
out.push(reason("features", "objective", "unsuitable", HOSTING_CODE.featuresCv));
|
|
701
|
-
}
|
|
702
697
|
}
|
|
703
698
|
if (descriptor.hasMidiIn && !instruments) {
|
|
704
699
|
out.push(reason("features", "objective", "conditional", HOSTING_CODE.featuresMidiIn));
|
|
@@ -821,7 +816,7 @@ export function hostingTopologyReasons(
|
|
|
821
816
|
];
|
|
822
817
|
}
|
|
823
818
|
return [
|
|
824
|
-
reason("topology", "objective", "conditional", HOSTING_CODE.
|
|
819
|
+
reason("topology", "objective", "conditional", HOSTING_CODE.topologyTooManyPorts, { ins, outs }),
|
|
825
820
|
];
|
|
826
821
|
}
|
|
827
822
|
|
|
@@ -845,7 +840,7 @@ export function clapTopologyReasons(clap: PluginClapMeasurement | undefined, ins
|
|
|
845
840
|
return [reason("topology", "objective", "unsuitable", HOSTING_CODE.topologyWiderThanStrip, { ins, outs })];
|
|
846
841
|
}
|
|
847
842
|
if (clap.sidechainInputs > 0) {
|
|
848
|
-
return [reason("topology", "objective", "unsuitable", HOSTING_CODE.
|
|
843
|
+
return [reason("topology", "objective", "unsuitable", HOSTING_CODE.topologyTooManyPorts, { ins, outs, sidechains: clap.sidechainInputs })];
|
|
849
844
|
}
|
|
850
845
|
return [reason("topology", "objective", "suitable", HOSTING_CODE.topologyMatched, { ins, outs })];
|
|
851
846
|
}
|
|
@@ -899,11 +894,6 @@ export function clapFeatureReasons(
|
|
|
899
894
|
}
|
|
900
895
|
const out: HostingReason[] = [];
|
|
901
896
|
const offered = profile.clapExtensions;
|
|
902
|
-
const kindHosted =
|
|
903
|
-
clap.features.includes(CLAP_FEATURE_AUDIO_EFFECT) || (profile.instruments && clap.features.includes(CLAP_FEATURE_INSTRUMENT));
|
|
904
|
-
if (!kindHosted) {
|
|
905
|
-
out.push(reason("features", "objective", "unsuitable", HOSTING_CODE.clapNotAudioEffect, { features: clap.features.join(" ") }));
|
|
906
|
-
}
|
|
907
897
|
if (!clap.headlessOk) {
|
|
908
898
|
out.push(reason("features", "objective", "unsuitable", HOSTING_CODE.clapHeadlessFailed));
|
|
909
899
|
} else {
|
package/src/measurement/cli.ts
CHANGED
|
@@ -99,7 +99,7 @@ export interface MeasureOptions {
|
|
|
99
99
|
* them: the provider's kinds (`--features`), its buf-size declarations (`--block-declares`) and its log
|
|
100
100
|
* modes (`--log`). A conformance test reads both.
|
|
101
101
|
*/
|
|
102
|
-
export const LV2_FEATURE_KINDS = ["map", "unmap", "options", "bounded", "worker", "default-state", "log"] as const;
|
|
102
|
+
export const LV2_FEATURE_KINDS = ["map", "unmap", "options", "bounded", "worker", "default-state", "log", "rtmempool"] as const;
|
|
103
103
|
export const LV2_BLOCK_DECLARATIONS = ["bounded", "fixed", "pow2"] as const;
|
|
104
104
|
export const LV2_LOG_MODES = ["silent", "route", "capture"] as const;
|
|
105
105
|
|
|
@@ -147,7 +147,7 @@ export interface MeasurementHost {
|
|
|
147
147
|
|
|
148
148
|
/** How the latency figures in this document were taken. */
|
|
149
149
|
export interface LatencyMethod {
|
|
150
|
-
/** A {@link ../vocabulary.METHOD_TERMS} code — `impulse-onset` or `
|
|
150
|
+
/** A {@link ../vocabulary.METHOD_TERMS} code — `impulse-onset`, `declared-port` or `note-onset`. */
|
|
151
151
|
readonly method: string;
|
|
152
152
|
readonly blockFrames: number;
|
|
153
153
|
/** What was fed in, in words. An onset measured through an opened gate is not the same
|