@vestra-player/sdk 1.5.48 → 1.5.50
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/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/bin/vestra-plugin.mjs +46 -0
- package/dist/docs-tree.json.gz +0 -0
- package/dist/docs.d.ts +53 -0
- package/dist/docs.js +544 -0
- package/dist/player-runtime.d.ts +1 -1
- package/dist/plugin/commands.js +23 -7
- package/dist/plugin/index.d.ts +11 -4
- package/dist/plugin/index.js +4 -2
- package/dist/plugin/runtime.d.ts +20 -1
- package/dist/plugin/runtime.js +44 -1
- package/dist/plugin/testing.d.ts +5 -2
- package/dist/plugin/testing.js +20 -12
- package/dist/plugin/types.d.ts +23 -5
- package/llms.txt +31 -137
- package/package.json +6 -4
- package/llms-full.txt +0 -20316
package/dist/plugin/runtime.d.ts
CHANGED
|
@@ -37,6 +37,15 @@ export type Change = ReadonlyMap<string, ReadonlySet<string>>;
|
|
|
37
37
|
* without `update()`) still shows within about this long.
|
|
38
38
|
*/
|
|
39
39
|
export declare const SAFETY_PASS_MS = 1000;
|
|
40
|
+
/** How the plugin is run: the player's runner, or `TestHost`. */
|
|
41
|
+
export interface RuntimeOptions {
|
|
42
|
+
/**
|
|
43
|
+
* A declaration the player refuses during activation fails activation
|
|
44
|
+
* (`startPlugin`, so a plugin's tests show it) instead of being logged,
|
|
45
|
+
* reported to `onError` and skipped (the player's runner).
|
|
46
|
+
*/
|
|
47
|
+
strictDeclarations?: boolean;
|
|
48
|
+
}
|
|
40
49
|
export declare const same: (a: Json | undefined, b: Json | undefined) => boolean;
|
|
41
50
|
/** One value in flight, only the newest waiting. Each push learns its fate. */
|
|
42
51
|
export declare class Latest<T> {
|
|
@@ -74,7 +83,7 @@ export declare class Runtime {
|
|
|
74
83
|
* property writes). Not part of the plugin API; empty for older players.
|
|
75
84
|
*/
|
|
76
85
|
readonly features: ReadonlySet<string>;
|
|
77
|
-
constructor(transport: Transport, manifest: PluginManifest, directory: string, dataDirectory?: string, app?: unknown);
|
|
86
|
+
constructor(transport: Transport, manifest: PluginManifest, directory: string, dataDirectory?: string, app?: unknown, options?: RuntimeOptions);
|
|
78
87
|
can(capability: string): boolean;
|
|
79
88
|
/** Lazily created singletons shared by every scope of this plugin. */
|
|
80
89
|
service<T>(name: string, create: () => T): T;
|
|
@@ -83,6 +92,16 @@ export declare class Runtime {
|
|
|
83
92
|
* plugin reports ready; later ones report failures to their scope.
|
|
84
93
|
*/
|
|
85
94
|
starting<T>(work: Promise<T>, report: (error: unknown) => void): Promise<T>;
|
|
95
|
+
/**
|
|
96
|
+
* A declaration the player checks on its own (`what`: "command x"),
|
|
97
|
+
* started like `starting`. In the player's runner a refusal of it during
|
|
98
|
+
* activation (`invalid`, `conflict`, `limit`) does not fail the plugin:
|
|
99
|
+
* it is logged, skipped and reported to the scope once activation
|
|
100
|
+
* completes, so an `onError` added anywhere in `activate` hears it (SDK
|
|
101
|
+
* 1.5.49; VS Code logs a bad contribution and activates the extension).
|
|
102
|
+
* Under `strictDeclarations` (TestHost) it fails activation as before.
|
|
103
|
+
*/
|
|
104
|
+
declaring<T>(work: Promise<T>, what: string, report: (error: unknown) => void): Promise<T>;
|
|
86
105
|
activated(): Promise<void>;
|
|
87
106
|
bind(evaluate: () => void): Disposable;
|
|
88
107
|
/**
|
package/dist/plugin/runtime.js
CHANGED
|
@@ -86,6 +86,16 @@ function merge(into, from) {
|
|
|
86
86
|
* without `update()`) still shows within about this long.
|
|
87
87
|
*/
|
|
88
88
|
export const SAFETY_PASS_MS = 1000;
|
|
89
|
+
/**
|
|
90
|
+
* The player's answers to a declaration that refuse that one declaration
|
|
91
|
+
* (a command's path, texts or count): during activation they skip it
|
|
92
|
+
* instead of failing the plugin (`Runtime.declaring`, SDK 1.5.49).
|
|
93
|
+
*/
|
|
94
|
+
const DECLARATION_REFUSALS = new Set([
|
|
95
|
+
"invalid",
|
|
96
|
+
"conflict",
|
|
97
|
+
"limit",
|
|
98
|
+
]);
|
|
89
99
|
export const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
90
100
|
/** One value in flight, only the newest waiting. Each push learns its fate. */
|
|
91
101
|
export class Latest {
|
|
@@ -149,6 +159,10 @@ export class Runtime {
|
|
|
149
159
|
/** Registrations that activation must wait for before reporting ready. */
|
|
150
160
|
startup = new Set();
|
|
151
161
|
#activating = true;
|
|
162
|
+
/** `RuntimeOptions.strictDeclarations`. */
|
|
163
|
+
#strict;
|
|
164
|
+
/** Declarations skipped during activation: reported once it completes. */
|
|
165
|
+
#refusals = [];
|
|
152
166
|
#transport;
|
|
153
167
|
/** Each binding with the events whose state it read last time (held). */
|
|
154
168
|
#bindings = new Map();
|
|
@@ -187,8 +201,9 @@ export class Runtime {
|
|
|
187
201
|
* property writes). Not part of the plugin API; empty for older players.
|
|
188
202
|
*/
|
|
189
203
|
features;
|
|
190
|
-
constructor(transport, manifest, directory, dataDirectory, app) {
|
|
204
|
+
constructor(transport, manifest, directory, dataDirectory, app, options = {}) {
|
|
191
205
|
this.#transport = transport;
|
|
206
|
+
this.#strict = options.strictDeclarations ?? false;
|
|
192
207
|
this.dataDirectory = dataDirectory;
|
|
193
208
|
this.local = transport.local;
|
|
194
209
|
this.host = createWire(transport);
|
|
@@ -233,6 +248,32 @@ export class Runtime {
|
|
|
233
248
|
work.catch(() => { });
|
|
234
249
|
return work;
|
|
235
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* A declaration the player checks on its own (`what`: "command x"),
|
|
253
|
+
* started like `starting`. In the player's runner a refusal of it during
|
|
254
|
+
* activation (`invalid`, `conflict`, `limit`) does not fail the plugin:
|
|
255
|
+
* it is logged, skipped and reported to the scope once activation
|
|
256
|
+
* completes, so an `onError` added anywhere in `activate` hears it (SDK
|
|
257
|
+
* 1.5.49; VS Code logs a bad contribution and activates the extension).
|
|
258
|
+
* Under `strictDeclarations` (TestHost) it fails activation as before.
|
|
259
|
+
*/
|
|
260
|
+
declaring(work, what, report) {
|
|
261
|
+
if (!this.#activating || this.#strict)
|
|
262
|
+
return this.starting(work, report);
|
|
263
|
+
const settled = work.then(() => { }, (error) => {
|
|
264
|
+
if (!(error instanceof HostError) ||
|
|
265
|
+
!DECLARATION_REFUSALS.has(error.code))
|
|
266
|
+
throw error;
|
|
267
|
+
console.error(`[${this.manifest.id}] ${what} skipped, the player refused it (${error.code}): ${error.message}`);
|
|
268
|
+
this.#refusals.push(() => report(error));
|
|
269
|
+
});
|
|
270
|
+
// Observed now: `activated()` may come after `activate` awaits, and
|
|
271
|
+
// its `allSettled` still sees the rejection.
|
|
272
|
+
settled.catch(() => { });
|
|
273
|
+
this.startup.add(settled);
|
|
274
|
+
work.catch(() => { });
|
|
275
|
+
return work;
|
|
276
|
+
}
|
|
236
277
|
async activated() {
|
|
237
278
|
while (this.startup.size) {
|
|
238
279
|
const pending = [...this.startup];
|
|
@@ -242,6 +283,8 @@ export class Runtime {
|
|
|
242
283
|
throw result.reason;
|
|
243
284
|
}
|
|
244
285
|
this.#activating = false;
|
|
286
|
+
for (const report of this.#refusals.splice(0))
|
|
287
|
+
report();
|
|
245
288
|
}
|
|
246
289
|
bind(evaluate) {
|
|
247
290
|
const held = new Map();
|
package/dist/plugin/testing.d.ts
CHANGED
|
@@ -2728,8 +2728,11 @@ export declare class TestHost implements Transport {
|
|
|
2728
2728
|
*
|
|
2729
2729
|
* Rejects when `manifest.json` cannot be read or parsed, when `activate`
|
|
2730
2730
|
* throws, or when a registration made during activation fails (for example
|
|
2731
|
-
* `limit`, `conflict`, `invalid`)
|
|
2732
|
-
*
|
|
2731
|
+
* `limit`, `conflict`, `invalid`). Stricter than the player's runner for
|
|
2732
|
+
* commands (SDK 1.5.49): there the SDK logs a command declaration the
|
|
2733
|
+
* player refuses during activation, skips it and activates the rest of the
|
|
2734
|
+
* plugin (`onError` hears it); `startPlugin` fails, so a test shows the
|
|
2735
|
+
* bad declaration.
|
|
2733
2736
|
*
|
|
2734
2737
|
* @param activate - The plugin's default-exported `activate` function.
|
|
2735
2738
|
* @param options - Where the plugin lives and how to start it.
|
package/dist/plugin/testing.js
CHANGED
|
@@ -3956,14 +3956,23 @@ export class TestHost {
|
|
|
3956
3956
|
!BAR_BUTTON_ICONS.includes(icon))
|
|
3957
3957
|
throw commandInvalid(`unknown button icon ${JSON.stringify(icon)}: a name of @vestra/icons.slint (${BAR_BUTTON_ICONS.join(", ")}) or an image from plugin.ui.image`);
|
|
3958
3958
|
}
|
|
3959
|
+
// The binding table's `Table::canonical` (player 0.6.1): each binding
|
|
3960
|
+
// parsed, and each input once, compared parsed, before the reason,
|
|
3961
|
+
// conflicts and limits.
|
|
3959
3962
|
const bindings = (declaration.bindings ?? []);
|
|
3960
|
-
|
|
3963
|
+
const seen = new Set();
|
|
3964
|
+
for (const binding of bindings.map(String)) {
|
|
3965
|
+
let input;
|
|
3961
3966
|
try {
|
|
3962
|
-
canonical(
|
|
3967
|
+
input = canonical(binding);
|
|
3963
3968
|
}
|
|
3964
3969
|
catch (error) {
|
|
3965
3970
|
throw commandInvalid(error.message);
|
|
3966
3971
|
}
|
|
3972
|
+
if (seen.has(input))
|
|
3973
|
+
throw commandInvalid(`binding ${binding} is listed twice`);
|
|
3974
|
+
seen.add(input);
|
|
3975
|
+
}
|
|
3967
3976
|
if (reason !== null)
|
|
3968
3977
|
commandText(reason, "reason", COMMAND_LIMITS.reasonBytes);
|
|
3969
3978
|
if (this.commands.has(id))
|
|
@@ -3991,13 +4000,6 @@ export class TestHost {
|
|
|
3991
4000
|
this.commands.size + this.coreCommands.size + hostOnly.length >=
|
|
3992
4001
|
COMMAND_LIMITS.total)
|
|
3993
4002
|
throw new HostError("limit", "command registry limit reached");
|
|
3994
|
-
// The binding table: each input once per command.
|
|
3995
|
-
const seen = new Set();
|
|
3996
|
-
for (const binding of bindings.map(String)) {
|
|
3997
|
-
if (seen.has(binding))
|
|
3998
|
-
throw new HostError("invalid", `binding ${binding} is listed twice`);
|
|
3999
|
-
seen.add(binding);
|
|
4000
|
-
}
|
|
4001
4003
|
const host = this;
|
|
4002
4004
|
let sent = p.state;
|
|
4003
4005
|
this.commands.set(id, {
|
|
@@ -5426,8 +5428,11 @@ function tellResidency(host) {
|
|
|
5426
5428
|
*
|
|
5427
5429
|
* Rejects when `manifest.json` cannot be read or parsed, when `activate`
|
|
5428
5430
|
* throws, or when a registration made during activation fails (for example
|
|
5429
|
-
* `limit`, `conflict`, `invalid`)
|
|
5430
|
-
*
|
|
5431
|
+
* `limit`, `conflict`, `invalid`). Stricter than the player's runner for
|
|
5432
|
+
* commands (SDK 1.5.49): there the SDK logs a command declaration the
|
|
5433
|
+
* player refuses during activation, skips it and activates the rest of the
|
|
5434
|
+
* plugin (`onError` hears it); `startPlugin` fails, so a test shows the
|
|
5435
|
+
* bad declaration.
|
|
5431
5436
|
*
|
|
5432
5437
|
* @param activate - The plugin's default-exported `activate` function.
|
|
5433
5438
|
* @param options - Where the plugin lives and how to start it.
|
|
@@ -5512,7 +5517,10 @@ export async function startPlugin(activate, options = {}) {
|
|
|
5512
5517
|
const instance = await createPlugin(host, manifest, directory, data,
|
|
5513
5518
|
// Like the player: protocol additions it takes (`app.features` set on
|
|
5514
5519
|
// the host replaces them, e.g. `[]` for an older player's behaviour).
|
|
5515
|
-
{ features: [PATCH_FEATURE], ...host.app }
|
|
5520
|
+
{ features: [PATCH_FEATURE], ...host.app },
|
|
5521
|
+
// Unlike the player's runner, which logs a refused command declaration
|
|
5522
|
+
// and activates the rest: a plugin's tests show the refusal.
|
|
5523
|
+
{ strictDeclarations: true });
|
|
5516
5524
|
await activate(instance.plugin);
|
|
5517
5525
|
// Like the player: a position or resolver another plugin holds is not an
|
|
5518
5526
|
// activation failure.
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -487,7 +487,11 @@ export interface Scope extends Disposable {
|
|
|
487
487
|
* Registrations started during activation (commands, panels, resolvers,
|
|
488
488
|
* subscriptions) do not need to be awaited: the plugin is reported ready
|
|
489
489
|
* once they all succeed, and activation fails if `activate` throws or any
|
|
490
|
-
* of them fails.
|
|
490
|
+
* of them fails. A command declaration the player refuses is the exception
|
|
491
|
+
* (SDK 1.5.49): the SDK logs and skips it, its `ready` rejects and
|
|
492
|
+
* {@link Scope.onError} hears it, the rest of the plugin activates
|
|
493
|
+
* (`startPlugin` still fails on it). The entry module must
|
|
494
|
+
* **default-export** `activate`.
|
|
491
495
|
*
|
|
492
496
|
* Stopping: the player first revokes everything the plugin owns on its side
|
|
493
497
|
* (menus, windows, panels, filters, subtitle layers, snapshots, jobs,
|
|
@@ -1138,8 +1142,21 @@ export interface Command extends Disposable {
|
|
|
1138
1142
|
* Resolves when the host has registered the command. Rejects with
|
|
1139
1143
|
* `conflict` (path already taken), `invalid` or `limit` (more than 160
|
|
1140
1144
|
* commands in this plugin, or 1024 in the whole player). You rarely need
|
|
1141
|
-
* to await it:
|
|
1142
|
-
*
|
|
1145
|
+
* to await it: the refusal goes to {@link Scope.onError}. During
|
|
1146
|
+
* activation the SDK, in the plugin's process, logs the refusal with the
|
|
1147
|
+
* command id and the player's message, skips the command and lets the
|
|
1148
|
+
* rest of the plugin activate (SDK 1.5.49; before, the refusal failed
|
|
1149
|
+
* activation); the error reaches `onError` once activation completes,
|
|
1150
|
+
* so a listener added anywhere in `activate` hears it. `startPlugin`
|
|
1151
|
+
* stays strict: there a refusal during activation fails it, so tests
|
|
1152
|
+
* show the bad declaration. Any other failure during activation
|
|
1153
|
+
* (`capability`, no answer) fails activation.
|
|
1154
|
+
*
|
|
1155
|
+
* Only the player's answer is skipped. What {@link Commands.add} checks
|
|
1156
|
+
* itself still throws from `add` (an unknown `@` menu id, more than 8
|
|
1157
|
+
* path segments, an `order` out of range, a malformed binding or one
|
|
1158
|
+
* listed twice, a bad `button`, a reason text of the wrong shape, an id
|
|
1159
|
+
* already declared), and fails activation unless the plugin catches it.
|
|
1143
1160
|
*
|
|
1144
1161
|
* @throws `conflict` (rejects) Another command already has this menu path,
|
|
1145
1162
|
* or the path would be both a menu item and a submenu.
|
|
@@ -1161,8 +1178,9 @@ export interface Command extends Disposable {
|
|
|
1161
1178
|
* when the user picks the item, presses a key or clicks the button.
|
|
1162
1179
|
* Commands of all plugins merge into the player's menus by their English
|
|
1163
1180
|
* path keys. Registration is asynchronous: `add` returns at once, and
|
|
1164
|
-
* {@link Command.ready} reports the player's answer (during activation
|
|
1165
|
-
* refusal
|
|
1181
|
+
* {@link Command.ready} reports the player's answer (during activation
|
|
1182
|
+
* the SDK logs a refusal and skips that command, SDK 1.5.49;
|
|
1183
|
+
* `startPlugin` fails on it). What `add` checks itself throws from `add`.
|
|
1166
1184
|
*
|
|
1167
1185
|
* @capability commands
|
|
1168
1186
|
*
|
package/llms.txt
CHANGED
|
@@ -1,148 +1,42 @@
|
|
|
1
1
|
# Vestra Player SDK
|
|
2
2
|
|
|
3
|
-
> @vestra-player/sdk 1.5.
|
|
3
|
+
> @vestra-player/sdk 1.5.50: write plugins for Vestra Player in TypeScript (plugin API `vestra/1`). A plugin is a folder with `manifest.json` and an entry module whose default export `activate(plugin)` the player calls. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Read the documentation
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
7
|
+
- **Command line** (any coding agent): `npx -p @vestra-player/sdk vestra-plugin docs [path] [--page N]` prints one node of the tree; `npx -p @vestra-player/sdk vestra-plugin docs --search <words>` lists the matching paths. In a project that depends on the SDK, `npx vestra-plugin docs` is enough.
|
|
8
|
+
- **In a Node.js program**: `import { docs, searchDocs } from "@vestra-player/sdk/docs"`; `docs(path, { page })` and `searchDocs(query, { page })` return the same text.
|
|
9
|
+
- **Paths**: `/` lists the top level; every answer lists the paths one level down with a one-line summary. `/API/<category>/<symbol>/<member>` is one declaration with its signature, parameters, return value, errors, capability, player version and examples, for example `/API/Media/Snapshot/dispose`. `/Guides/<group>/<page>` is a page of the site, for example `/Guides/How-to/Test a plugin` (the file name works too: `/Guides/How-to/testing`). Case, spaces and punctuation do not matter, the leading `/` is optional, `.` works like `/`, a name alone finds its declaration (`TestHost`, `Snapshot.export`, `plugin.player`), and `#heading` opens the page of a long answer that has that section.
|
|
10
|
+
- **Size**: every answer is at most 8 KB; a longer one ends with the number of its next page (`--page 2`).
|
|
11
|
+
- **Before writing code**, read `/Guides/Tutorials/Getting started` and `/Guides/Guidelines`, then the API of what you use. Test with `/Guides/How-to/Test a plugin`.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Top level
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
main.ts the entry module
|
|
19
|
-
ui/hello.slint optional: user interface
|
|
20
|
-
tests/main.test.ts tests (node:test)
|
|
21
|
-
package.json dev dependency and scripts
|
|
22
|
-
```
|
|
15
|
+
- `/Overview`: The package's README: what the SDK is, installing it and where to start.
|
|
16
|
+
- `/Guides`: The documentation pages, by group: tutorials, how-to guides, reference, explanation, guidelines, examples, upgrading.
|
|
17
|
+
- `/API`: Every type and value of @vestra-player/sdk (the plugin API), @vestra-player/sdk/testing (the test host) and @vestra-player/sdk/docs (this tree), by category.
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
## Guides
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Fields: `id`, `version`, `apiVersion`, `entry`, `capabilities`, `name`, `author`, `punchline`, `description`, `tags`, `icon`, `readme`, `changelog`, `sourceUrl`, `license`, `minPlayerVersion`; unknown fields and capabilities are rejected. Rules and limits: L2218–2292.
|
|
37
|
-
|
|
38
|
-
**main.ts**
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
import type { Plugin } from "@vestra-player/sdk";
|
|
42
|
-
|
|
43
|
-
export default async function activate(plugin: Plugin) {
|
|
44
|
-
plugin.commands.add({
|
|
45
|
-
id: "hello",
|
|
46
|
-
path: ["Tools", "Hello"],
|
|
47
|
-
run: () => plugin.osd.show("Hello"),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
**Capabilities** (without one a call fails: `capability`)
|
|
53
|
-
|
|
54
|
-
- `producer.av`: Player.openStream (also `playback.control`)
|
|
55
|
-
- `playback.read`: Player.state/refresh/stats/chapters/audioDevices, Timeline.marks
|
|
56
|
-
- `playback.control`: Player.open/setPaused/seek/setRate/restart/close/scrub/setOutput/provideSequence/next/previous/addAudioTrack/selectAudioTrack/step/setStepSeek/setLoop/setAudioDevice, Power.preventSleep
|
|
57
|
-
- `source.resolve`: Resolvers.add
|
|
58
|
-
- `events`: Player/Subtitles/Timeline/MainWindow/Appearance/PanelSlot/Panel/BackdropSlot.onChange, Resolvers.onFileTypesChange
|
|
59
|
-
- `commands`: Commands.add, Host.run
|
|
60
|
-
- `ui.window`: Windows.create
|
|
61
|
-
- `ui.mount`: Panels.mount/bottom/sidebar/backdrop, PanelSlot/Panel/BackdropSlot.onChange
|
|
62
|
-
- `ui.dialog`: Dialogs.confirm/openFile/openFiles/openDirectory/saveFile
|
|
63
|
-
- `plugins.manage`: Packages.validate/validateArchive/setEnabled/reload/uninstall
|
|
64
|
-
- `processing.video`: Plugin.video.filter/video.view/video.render/video.shaders (also `playback.read`)
|
|
65
|
-
- `processing.audio`: Plugin.audio.filter (also `playback.read`, `events`)
|
|
66
|
-
- `subtitles.read`: Subtitles.state/onChange/refresh
|
|
67
|
-
- `subtitles.control`: Subtitles.select/load/remove/setStyle
|
|
68
|
-
- `media.read`: MediaCapture.capture, Snapshot.export (also `media.control`)
|
|
69
|
-
- `media.control`: MediaCapture.capture, Snapshot.export (also `media.read`)
|
|
70
|
-
- `ui.osd`: Osd.show/panel
|
|
71
|
-
- `clipboard`: Clipboard.readText/writeText/writeImage
|
|
72
|
-
- `window.control`: MainWindow.setVideoArea/setAlwaysOnTop/setCursorAutoHide/setPictureInPicture
|
|
73
|
-
- `bindings.manage`: Bindings.list/set/reset/onChange
|
|
74
|
-
- `timeline.marks`: Timeline.layer
|
|
75
|
-
- `ui.drop`: Drops.provide, Panel.onDrop
|
|
76
|
-
- `ui.settings`: Settings.page/show
|
|
77
|
-
- `ui.theme`: Appearance.set/setLanguage
|
|
78
|
-
- `secrets`: Secrets.get/set/delete
|
|
79
|
-
- `rendering.manage`: Rendering.setPreference/restartPlayer
|
|
80
|
-
- `video.upscaling`: VideoUpscaling.state/set/onChange
|
|
81
|
-
- No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme, packages.list and rendering.state. Details: L2293–2353.
|
|
82
|
-
|
|
83
|
-
**Test**: `tests/*.test.ts` with `node:test`, run by `vestra-plugin test`. `startPlugin(activate, { directory: new URL("..", import.meta.url) })` from `@vestra-player/sdk/testing` returns `{ host, stop }`, `host` an in-memory player (TestHost): act (`host.command(id).run()`, `host.press(key)`), `await host.settle()`, assert on `host.osd`, `host.window(id).props`… Guide: L1861–2021; TestHost: L15502.
|
|
84
|
-
|
|
85
|
-
**Command line**
|
|
86
|
-
|
|
87
|
-
- `vestra-plugin check`: strict type check of the plugin's .ts files and tests/*.ts
|
|
88
|
-
- `vestra-plugin build`: check, then write dist/
|
|
89
|
-
- `vestra-plugin test`: node --test on tests/*.test.{ts,mjs}
|
|
90
|
-
- `vestra-plugin pack`: build, then dist/ → <out>/<id>-<version>.vxp
|
|
91
|
-
- `vestra-plugin i18n extract`: find the texts to translate, write locales/messages.pot and merge it into every locales/<lang>.po
|
|
92
|
-
- `vestra-plugin i18n check`: coverage per language, placeholder and plural problems, a stale messages.pot
|
|
93
|
-
- `vestra-player --plugin <dir>` runs a plugin from source, no build needed.
|
|
94
|
-
|
|
95
|
-
**Error codes** (`error.code`; branch on it, never on `message`)
|
|
96
|
-
|
|
97
|
-
- `stale`: A condition no longer held
|
|
98
|
-
- `capability`: The manifest does not declare the capability the call needs
|
|
99
|
-
- `invalid`: A bad argument
|
|
100
|
-
- `missing`: The target does not exist
|
|
101
|
-
- `busy`: The player is still doing a previous call of the same kind
|
|
102
|
-
- `conflict`: Another plugin owns the resource
|
|
103
|
-
- `unavailable`: Not possible right now
|
|
104
|
-
- `unsupported`: Not possible on this system, build or source
|
|
105
|
-
- `failed`: The operation ran and failed
|
|
106
|
-
- `aborted`: An `AbortSignal` fired
|
|
107
|
-
- `timeout`: A time limit ran out
|
|
108
|
-
- `limit`: A player-wide limit was reached, a property value is over the limits of PropValue
|
|
109
|
-
- `reserved`: The id is `vestra` or starts with `vestra.`
|
|
110
|
-
- `versionMismatch`: The package needs a newer player
|
|
111
|
-
- Others: PluginError, llms-full.txt L5966.
|
|
112
|
-
|
|
113
|
-
## Reference
|
|
114
|
-
|
|
115
|
-
- [llms-full.txt](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt), also node_modules/@vestra-player/sdk/llms-full.txt; pages: [site](https://vestrasys.github.io/vestra-player-sdk/).
|
|
116
|
-
- Tutorials: Getting started L9–134; Add a window L135–213; Add settings and translations L214–367; Test, check, pack and publish L368–424; Write your own blur kernel L425–685
|
|
117
|
-
- How-to: Control playback L686–854; Store a plugin's data L855–961; Load subtitles from a plugin L962–1074; Keep a slider responsive while dragging L1075–1262; Remember a window's state between runs L1263–1414; Offer a GPU rendering switch L1415–1540; Keep a command's state without keeping the plugin running L1541–1697; Translate a plugin L1698–1860; Test a plugin L1861–2021; Publish a plugin L2022–2123; Troubleshooting L2124–2217
|
|
118
|
-
- Reference: Manifest L2218–2292; Capabilities L2293–2353; Limits L2354–2506; Commands, menus and bindings L2507–3033; Platforms L3034–3064; Theme L3065–3414; Command line L3415–3472; Error codes L3473–3520; Translations L3521–3613; Test host L3614–3800
|
|
119
|
-
- Explanation: How a plugin runs L3801–4003; Commands, menus and key bindings L4004–4158; Playback state, controls and sources L4159–4318; Video and audio processing L4319–4439; Windows, panels, settings pages, dialogs and the OSD L4440–4704; GPU and software rendering L4705–4721; The player's Rust core L4722–5063; How the player runs and talks to plugins L5064–5403
|
|
120
|
-
- Guidelines: Plugin rules L5404–5415; Interface guidelines L5416–5532; Menu guidelines L5533–5591
|
|
121
|
-
- Upgrading: Migrate a plugin to English source text L5592–5741; Migrating off package rollback (1.5.16, removed in 1.5.17) L5742–5819; Who must change, release by release L5820–5888
|
|
122
|
-
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L5889–15175
|
|
123
|
-
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L15176–18059
|
|
21
|
+
- `/Guides/Tutorials`: Step-by-step lessons; the first four build one plugin, from an empty folder to a tested package in the plugin store.
|
|
22
|
+
- `/Guides/How-to`: Short guides that each answer one practical question about writing, translating, testing or publishing a plugin.
|
|
23
|
+
- `/Guides/Reference`: Lookup tables that span many symbols (capabilities, manifest fields and player versions, limits, menu and binding names, platform differences, theme, command line), generated from the SDK's code.
|
|
24
|
+
- `/Guides/Explanation`: What each part of the player and its plugins is, why it works the way it does and how the parts fit together.
|
|
25
|
+
- `/Guides/Guidelines`: The rules a plugin follows so that its windows, panels, messages and menu items look and behave like the rest of Vestra Player.
|
|
26
|
+
- `/Guides/Examples`: Complete, tested example plugins with a screenshot each and a step-by-step walkthrough of their code.
|
|
27
|
+
- `/Guides/Upgrading`: What to change in a plugin when an SDK or player release deprecates, removes or changes something it uses.
|
|
124
28
|
|
|
125
29
|
## API
|
|
126
30
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
- bookmark: A tool window bound to the playback state: remember the position and jump back to it. L19197–19389
|
|
140
|
-
- panel-menu: A sidebar panel with its own right-click menu. L19390–19604
|
|
141
|
-
- menus: Radio menu items, separator groups and a menu item whose title changes. L19605–19770
|
|
142
|
-
- theme-widgets: A tool window drawn with the player's theme and widgets. L19771–19940
|
|
143
|
-
- markdown: A window that shows a Markdown document. L19941–20143
|
|
144
|
-
- i18n: A plugin in the player's language: English source text, a Chinese translation. L20144–20317
|
|
145
|
-
|
|
146
|
-
## Optional
|
|
147
|
-
|
|
148
|
-
- [Changelog](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md); full doc comments in the package's dist/plugin/*.d.ts; Slint library in slint/vestra/.
|
|
31
|
+
- `/API/Commands`: 15 entries: CommandState, Bindable, Condition, When, MenuId, BarButtonIcon, CommandButton, CommandOptions, Command, Commands, HostAction, Host, BindingRef, BindingInfo, Bindings
|
|
32
|
+
- `/API/Media`: 6 entries: CaptureOptions, Snapshot, ExportOptions, JobState, ExportJob, MediaCapture
|
|
33
|
+
- `/API/Packages`: 10 entries: PackageManifest, PackageSource, InstallOptions, PackageCandidate, PackageChangeStatus, PackageChange, PluginInfo, PluginDisplay, PluginWarning, Packages
|
|
34
|
+
- `/API/Playback`: 18 entries: MarkKind, TimelineMark, TimelineLayer, Timeline, AudioTrack, PlayerState, AudioDevice, Chapter, Conditional, Media, Scrub, StreamFrame, StreamOptions, StreamStartError, Stream,…
|
|
35
|
+
- `/API/Plugin`: 11 entries: Disposable, PluginError, Scope, Plugin, WindowState, MainWindow, AppInfo, App, SystemInfo, DisplayInfo, Json
|
|
36
|
+
- `/API/Processing`: 18 entries: FilterStatus, VideoFilter, AudioFilter, ViewSettings, VideoView, RenderSettings, RenderOptions, VideoShaders, UpscalingReasonCode, UpscalingReason, UpscalingDecodingCause,…
|
|
37
|
+
- `/API/Services`: 15 entries: Clipboard, Power, ToolResult, Tools, JsonStore, Storage, SessionStorage, System, Secrets, RenderingMode, RenderingPreference, RenderingReasonCode, RenderingReason, RenderingState,…
|
|
38
|
+
- `/API/Sources`: 7 entries: ResolverOptions, WebResolverOptions, FileResolverOptions, ResolvedStream, Resolver, Resolvers, ResolvedMedia
|
|
39
|
+
- `/API/Subtitles`: 5 entries: SubtitleTrack, SubtitlesState, SubtitleConditional, Subtitles, SubtitleStyle
|
|
40
|
+
- `/API/UI`: 42 entries: ImageRef, ImageOptions, MarkdownRef, MarkdownOptions, PropValue, PropData, Props, Ui, View, Window, Windows, SlotState, SlotPanel, PanelState, PanelSlot, SidebarSlot, Panel,…
|
|
41
|
+
- `/API/Testing`: 32 entries: CapabilityInfo, CAPABILITY_INFO, MESSAGE_LIMIT, COMMAND_LIMITS, MENU_IDS, BAR_BUTTON_ICONS, BAR_BUTTON_LIMITS, BuiltinSubmenu, BUILTIN_SUBMENUS, BuiltinCommand, BUILTIN_COMMANDS, LOCALES,…
|
|
42
|
+
- `/API/Docs`: 4 entries: DOCS_PAGE_BYTES, DocsOptions, docs, searchDocs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vestra-player/sdk",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.50",
|
|
4
4
|
"description": "Plugin API types, test host and plugin CLI for Vestra Player (apiVersion vestra/1)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -24,12 +24,15 @@
|
|
|
24
24
|
"types": "./dist/player-runtime.d.ts",
|
|
25
25
|
"default": "./dist/player-runtime.js"
|
|
26
26
|
},
|
|
27
|
+
"./docs": {
|
|
28
|
+
"types": "./dist/docs.d.ts",
|
|
29
|
+
"default": "./dist/docs.js"
|
|
30
|
+
},
|
|
27
31
|
"./ts-plugin": {
|
|
28
32
|
"types": "./ts-plugin/index.d.ts",
|
|
29
33
|
"default": "./ts-plugin/index.js"
|
|
30
34
|
},
|
|
31
35
|
"./llms.txt": "./llms.txt",
|
|
32
|
-
"./llms-full.txt": "./llms-full.txt",
|
|
33
36
|
"./package.json": "./package.json"
|
|
34
37
|
},
|
|
35
38
|
"bin": {
|
|
@@ -43,8 +46,7 @@
|
|
|
43
46
|
"README.md",
|
|
44
47
|
"CHANGELOG.md",
|
|
45
48
|
"LICENSE",
|
|
46
|
-
"llms.txt"
|
|
47
|
-
"llms-full.txt"
|
|
49
|
+
"llms.txt"
|
|
48
50
|
],
|
|
49
51
|
"scripts": {
|
|
50
52
|
"build": "node scripts/build.mjs",
|