@vestra-player/sdk 1.5.6 → 1.5.8
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 +18 -0
- package/bin/vestra-plugin.mjs +24 -10
- package/dist/commands.d.ts +1 -2
- package/dist/commands.js +1 -2
- package/dist/plugin/packages.js +1 -65
- package/dist/plugin/resolvers.js +64 -0
- package/dist/plugin/stream.js +62 -4
- package/dist/plugin/testing.d.ts +45 -1
- package/dist/plugin/testing.js +87 -4
- package/dist/plugin/types.d.ts +72 -30
- package/dist/plugin/window.d.ts +2 -0
- package/dist/plugin/window.js +4 -0
- package/dist/wire.d.ts +3 -12
- package/dist/wire.js +0 -10
- package/llms-full.txt +70 -34
- package/llms.txt +40 -40
- package/package.json +1 -1
package/dist/plugin/types.d.ts
CHANGED
|
@@ -73,9 +73,8 @@ export interface Disposable {
|
|
|
73
73
|
* | `timeout` | A time limit ran out (`openStream` start-up, `tools.run`, `system.*` after 10 s). |
|
|
74
74
|
* | `stream`, `device` | `openStream`: the producer failed / the audio device is not ready. |
|
|
75
75
|
* | `backend-uncertain` | The player's backend blocked a filter stage; call `retry()`. |
|
|
76
|
-
* | `cleanup` | {@link PackageTrial.stop} could not confirm cleanup; call it again. |
|
|
77
76
|
* | `limit` | A player-wide limit was reached (for example the number of commands). |
|
|
78
|
-
* | `reserved` | {@link Packages.validate}, {@link PackageCandidate.
|
|
77
|
+
* | `reserved` | {@link Packages.validate}, {@link PackageCandidate.install}: the id is `vestra` or starts with `vestra.` (any case), which only the player's built-in plugins use (player 0.4.1). |
|
|
79
78
|
* | `versionMismatch` | The package needs a newer player (`minPlayerVersion`) or another `apiVersion`. |
|
|
80
79
|
* | `ui-prepare` | The player could not prepare a mounted panel or a settings page (its Slint file does not compile, a bound property is not declared, or another plugin's panel holds the slot); `message` has the diagnostics. |
|
|
81
80
|
* | `ui` | The player could not apply a property to a tool window or a settings page, or could not build the Options window (a property the Slint file does not declare, a value of the wrong type); `message` has Slint's reason. |
|
|
@@ -195,7 +194,7 @@ export interface Scope extends Disposable {
|
|
|
195
194
|
readonly media: MediaCapture;
|
|
196
195
|
/** Page-URL to stream-URL resolvers (`source.resolve`). */
|
|
197
196
|
readonly resolvers: Resolvers;
|
|
198
|
-
/** The installed plugins; validation,
|
|
197
|
+
/** The installed plugins; validation, installs (`plugins.manage` for changes). */
|
|
199
198
|
readonly packages: Packages;
|
|
200
199
|
/** On-screen messages over the video (`ui.osd`). */
|
|
201
200
|
readonly osd: Osd;
|
|
@@ -320,8 +319,7 @@ export interface Plugin extends Scope {
|
|
|
320
319
|
readonly id: string;
|
|
321
320
|
/**
|
|
322
321
|
* A writable directory for this plugin's own files (settings, remembered
|
|
323
|
-
* folders). Kept across restarts, disabling and upgrades
|
|
324
|
-
* temporary one. Write files atomically: to a temporary name, then rename.
|
|
322
|
+
* folders). Kept across restarts, disabling and upgrades. Write files atomically: to a temporary name, then rename.
|
|
325
323
|
* Throws `unavailable` when the player provided none.
|
|
326
324
|
*
|
|
327
325
|
* Location: `~/Library/Application Support/Vestra/plugin-data/<id>/` on
|
|
@@ -3002,9 +3000,15 @@ export interface Stream extends Disposable {
|
|
|
3002
3000
|
/**
|
|
3003
3001
|
* The stream stopped for a reason outside this plugin: `error` is null when
|
|
3004
3002
|
* another source replaced it or the user closed it, otherwise the failure
|
|
3005
|
-
* (`stream
|
|
3006
|
-
* itself stops it (`stop()`, `dispose()`,
|
|
3007
|
-
* `stop()` is that notification.
|
|
3003
|
+
* (`stream` with the player's text, `invalid` for a bad frame, …). Not
|
|
3004
|
+
* called when the plugin itself stops it (`stop()`, `dispose()`,
|
|
3005
|
+
* deactivation): the promise of `stop()` is that notification.
|
|
3006
|
+
*
|
|
3007
|
+
* The player retires a stream's producer as soon as it is replaced or
|
|
3008
|
+
* closed; the SDK reads the player's state to tell that from a failure
|
|
3009
|
+
* (before 1.5.7 a replaced or closed stream could get `unavailable`
|
|
3010
|
+
* "producer absent"). Without `playback.read` a failure the SDK has not
|
|
3011
|
+
* seen yet is reported as null.
|
|
3008
3012
|
*/
|
|
3009
3013
|
onStop(listener: (error: PluginError | null) => void): Disposable;
|
|
3010
3014
|
/**
|
|
@@ -3147,7 +3151,8 @@ export interface Player {
|
|
|
3147
3151
|
* activation, pausing and acknowledgement. Frames travel over a local
|
|
3148
3152
|
* connection the SDK sets up: a Unix socket on macOS and Linux, loopback
|
|
3149
3153
|
* TCP with a token on Windows. Rejects with a {@link StreamStartError}
|
|
3150
|
-
* (`timeout`), `stream` or `
|
|
3154
|
+
* (`timeout`), `stream`, `device`, or `replaced` when another source
|
|
3155
|
+
* replaced it (or it was closed) before it ran.
|
|
3151
3156
|
*
|
|
3152
3157
|
* @example
|
|
3153
3158
|
* ```ts
|
|
@@ -3937,6 +3942,14 @@ export interface FileResolverOptions {
|
|
|
3937
3942
|
/**
|
|
3938
3943
|
* What a file resolver returns: a stream, with the same frame contract as
|
|
3939
3944
|
* {@link StreamOptions} (size limits, `frame()` on the audio clock).
|
|
3945
|
+
*
|
|
3946
|
+
* After `resolve` returns, the SDK starts the stream while the open waits.
|
|
3947
|
+
* If that fails, the open fails with the player's words instead of the
|
|
3948
|
+
* SDK's (the detail goes to the log): `device` "音频输出设备不可用",
|
|
3949
|
+
* `timeout` "启动超时", `busy` "播放器正忙,请稍后重试", other start-up
|
|
3950
|
+
* failures "无法启动播放". An error thrown by `frame()` keeps its message.
|
|
3951
|
+
* To give your own text for a file you can tell is unusable (a bad header),
|
|
3952
|
+
* check it in `resolve` and throw there.
|
|
3940
3953
|
*/
|
|
3941
3954
|
export interface ResolvedStream {
|
|
3942
3955
|
/** Always `"stream"`. */
|
|
@@ -3993,6 +4006,47 @@ export interface Resolvers {
|
|
|
3993
4006
|
* error's message.
|
|
3994
4007
|
*/
|
|
3995
4008
|
add(options: ResolverOptions): Resolver;
|
|
4009
|
+
/**
|
|
4010
|
+
* The extensions some plugin's file resolver handles (SDK 1.5.8, player
|
|
4011
|
+
* 0.4.2): lower case, without the dot, sorted, each once; not who
|
|
4012
|
+
* registered them. Reading needs no capability; `[]` from older players.
|
|
4013
|
+
* Without `events` it is the list from when the plugin first read it.
|
|
4014
|
+
* Use it to accept such files beside the player's own media types, for
|
|
4015
|
+
* example in a playlist's drop or folder scan.
|
|
4016
|
+
*
|
|
4017
|
+
* @example
|
|
4018
|
+
* ```ts
|
|
4019
|
+
* const MEDIA = ["mp4", "mkv", "mp3"];
|
|
4020
|
+
* const accepted = (path: string) => {
|
|
4021
|
+
* const extension = path.split(".").pop()?.toLowerCase() ?? "";
|
|
4022
|
+
* return MEDIA.includes(extension) || plugin.resolvers.fileTypes.includes(extension);
|
|
4023
|
+
* };
|
|
4024
|
+
* ```
|
|
4025
|
+
*
|
|
4026
|
+
* @capability None.
|
|
4027
|
+
* @player 0.4.2
|
|
4028
|
+
* @since 1.5.8
|
|
4029
|
+
*/
|
|
4030
|
+
readonly fileTypes: readonly string[];
|
|
4031
|
+
/**
|
|
4032
|
+
* {@link Resolvers.fileTypes} changed: a file resolver was added, or its
|
|
4033
|
+
* plugin stopped. Needs `events`; without it the listener never fires.
|
|
4034
|
+
*
|
|
4035
|
+
* @param listener - Receives the new list.
|
|
4036
|
+
* @returns A handle that removes the listener.
|
|
4037
|
+
*
|
|
4038
|
+
* @example
|
|
4039
|
+
* ```ts
|
|
4040
|
+
* plugin.resolvers.onFileTypesChange((types) => {
|
|
4041
|
+
* void plugin.osd.show(`Also accepted: ${types.join(", ")}`);
|
|
4042
|
+
* });
|
|
4043
|
+
* ```
|
|
4044
|
+
*
|
|
4045
|
+
* @capability `events`
|
|
4046
|
+
* @player 0.4.2
|
|
4047
|
+
* @since 1.5.8
|
|
4048
|
+
*/
|
|
4049
|
+
onFileTypesChange(listener: (types: string[]) => void): Disposable;
|
|
3996
4050
|
}
|
|
3997
4051
|
/**
|
|
3998
4052
|
* The manifest of a package, as validated. The display fields and
|
|
@@ -4084,11 +4138,6 @@ export interface PackageCandidate {
|
|
|
4084
4138
|
readonly manifest: PackageManifest;
|
|
4085
4139
|
/** The checks the player ran. */
|
|
4086
4140
|
readonly checks: string[];
|
|
4087
|
-
/**
|
|
4088
|
-
* Load it temporarily alongside the installed plugins. A reserved id
|
|
4089
|
-
* (`vestra.*`) fails with `reserved`.
|
|
4090
|
-
*/
|
|
4091
|
-
trial(): Promise<PackageTrial>;
|
|
4092
4141
|
/**
|
|
4093
4142
|
* Install it. The same source upgrades the installed plugin (its data
|
|
4094
4143
|
* stays); another source fails with `conflict` unless `replace` is set;
|
|
@@ -4099,17 +4148,6 @@ export interface PackageCandidate {
|
|
|
4099
4148
|
*/
|
|
4100
4149
|
install(options?: InstallOptions): Promise<PackageChange>;
|
|
4101
4150
|
}
|
|
4102
|
-
/** A trial load of a package. Disposing it stops the trial and waits for cleanup. */
|
|
4103
|
-
export interface PackageTrial extends Disposable {
|
|
4104
|
-
/** The trial's status as the player reports it. */
|
|
4105
|
-
readonly status: string;
|
|
4106
|
-
/**
|
|
4107
|
-
* Stop and wait until the host confirmed cleanup. Rejects with code
|
|
4108
|
-
* `cleanup` when the host stopped the trial without confirming cleanup;
|
|
4109
|
-
* calling `stop()` again then asks the host again.
|
|
4110
|
-
*/
|
|
4111
|
-
stop(): Promise<void>;
|
|
4112
|
-
}
|
|
4113
4151
|
/** The progress of an install, rollback or uninstall. */
|
|
4114
4152
|
export type PackageChangeStatus = "preparing" | "activating" | "restoring" | "committed" | "cancelled" | "failed" | "failedDegraded" | "tooLate";
|
|
4115
4153
|
/**
|
|
@@ -4134,8 +4172,8 @@ export interface PluginInfo {
|
|
|
4134
4172
|
id: string;
|
|
4135
4173
|
/** Version, `null` when unknown. */
|
|
4136
4174
|
version: string | null;
|
|
4137
|
-
/** From the install library, a `--plugin` development load
|
|
4138
|
-
origin: "installed" | "development"
|
|
4175
|
+
/** From the install library, or a `--plugin` development load. */
|
|
4176
|
+
origin: "installed" | "development";
|
|
4139
4177
|
/** Run state. */
|
|
4140
4178
|
state: "starting" | "running" | "disabled" | "failed" | "stopped";
|
|
4141
4179
|
/** Why it failed (`state: "failed"`). */
|
|
@@ -4151,7 +4189,7 @@ export interface PluginInfo {
|
|
|
4151
4189
|
* replaced. `false` from players before 0.2.0.
|
|
4152
4190
|
*/
|
|
4153
4191
|
builtin: boolean;
|
|
4154
|
-
/** Where an installed plugin came from; `null` for development loads
|
|
4192
|
+
/** Where an installed plugin came from; `null` for development loads. */
|
|
4155
4193
|
source: PackageSource | null;
|
|
4156
4194
|
/**
|
|
4157
4195
|
* Its data directory (`plugin.dataDirectory` of that plugin); `null` when
|
|
@@ -4207,6 +4245,10 @@ export interface Packages {
|
|
|
4207
4245
|
* Validate a package directory (`plugins.manage`). A package whose id is
|
|
4208
4246
|
* reserved for the built-in plugins (`vestra` or `vestra.*`) fails with
|
|
4209
4247
|
* `reserved` (player 0.4.1).
|
|
4248
|
+
*
|
|
4249
|
+
* The player keeps the 32 most recent candidates of all plugins; an
|
|
4250
|
+
* older one's `install` fails with `stale` (validate again). Before
|
|
4251
|
+
* player 0.4.2 the 33rd validation of a run failed with `busy` instead.
|
|
4210
4252
|
*/
|
|
4211
4253
|
validate(directory: string): Promise<PackageCandidate>;
|
|
4212
4254
|
/**
|
|
@@ -4225,7 +4267,7 @@ export interface Packages {
|
|
|
4225
4267
|
/**
|
|
4226
4268
|
* Stop or start a plugin (`plugins.manage`). An installed plugin stays
|
|
4227
4269
|
* disabled across launches; a development load only for this run.
|
|
4228
|
-
* `invalid` to disable oneself, `
|
|
4270
|
+
* `invalid` to disable oneself, `missing` unknown.
|
|
4229
4271
|
* `busy` while it is being installed.
|
|
4230
4272
|
*/
|
|
4231
4273
|
setEnabled(id: string, enabled: boolean): Promise<void>;
|
|
@@ -4233,7 +4275,7 @@ export interface Packages {
|
|
|
4233
4275
|
* Remove an installed plugin (`plugins.manage`); `removeData` also deletes
|
|
4234
4276
|
* its data directory, otherwise reinstalling it from the same source
|
|
4235
4277
|
* reconnects to its data. Its user bindings stay (as orphans).
|
|
4236
|
-
* `unsupported` for built-ins
|
|
4278
|
+
* `unsupported` for built-ins and development loads, `missing`
|
|
4237
4279
|
* unknown, `invalid` for oneself.
|
|
4238
4280
|
*/
|
|
4239
4281
|
uninstall(id: string, options?: {
|
package/dist/plugin/window.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export declare class WindowService {
|
|
|
19
19
|
start(): void;
|
|
20
20
|
/** The palette, as the `window.state` reply carried it (`plugin.appearance`). */
|
|
21
21
|
appearance: string | undefined;
|
|
22
|
+
/** The file resolvers' extensions, as the reply carried them (`plugin.resolvers.fileTypes`). */
|
|
23
|
+
fileTypes: string[] | undefined;
|
|
22
24
|
accept(facts: WindowFacts): void;
|
|
23
25
|
read(): Promise<void>;
|
|
24
26
|
watch(listener: (state: WindowState) => void): {
|
package/dist/plugin/window.js
CHANGED
|
@@ -52,9 +52,13 @@ export class WindowService {
|
|
|
52
52
|
}
|
|
53
53
|
/** The palette, as the `window.state` reply carried it (`plugin.appearance`). */
|
|
54
54
|
appearance;
|
|
55
|
+
/** The file resolvers' extensions, as the reply carried them (`plugin.resolvers.fileTypes`). */
|
|
56
|
+
fileTypes;
|
|
55
57
|
accept(facts) {
|
|
56
58
|
if (facts.appearance)
|
|
57
59
|
this.appearance = facts.appearance;
|
|
60
|
+
if (Array.isArray(facts.fileTypes))
|
|
61
|
+
this.fileTypes = [...facts.fileTypes];
|
|
58
62
|
const next = view(facts);
|
|
59
63
|
if (JSON.stringify(next) === JSON.stringify(this.state))
|
|
60
64
|
return;
|
package/dist/wire.d.ts
CHANGED
|
@@ -25,12 +25,6 @@ export interface PackageValidation {
|
|
|
25
25
|
checks: string[];
|
|
26
26
|
trustedExecution: true;
|
|
27
27
|
}
|
|
28
|
-
export interface PackageTrial {
|
|
29
|
-
trialId: number;
|
|
30
|
-
activationOwner?: number;
|
|
31
|
-
status: string;
|
|
32
|
-
cleanupConfirmed?: boolean;
|
|
33
|
-
}
|
|
34
28
|
export interface InstalledPackage {
|
|
35
29
|
revision: number;
|
|
36
30
|
current: null | {
|
|
@@ -102,7 +96,7 @@ export declare class HostError extends Error {
|
|
|
102
96
|
export interface PackageInfo {
|
|
103
97
|
id: string;
|
|
104
98
|
version: string | null;
|
|
105
|
-
origin: "installed" | "development"
|
|
99
|
+
origin: "installed" | "development";
|
|
106
100
|
state: "starting" | "running" | "disabled" | "failed" | "stopped";
|
|
107
101
|
error: string | null;
|
|
108
102
|
capabilities: string[];
|
|
@@ -175,6 +169,8 @@ export interface WindowFacts {
|
|
|
175
169
|
};
|
|
176
170
|
/** The palette (`plugin.appearance`), with the `window.state` reply; a newer player may name a palette this SDK does not list. */
|
|
177
171
|
appearance?: string;
|
|
172
|
+
/** The file resolvers' extensions (`plugin.resolvers.fileTypes`; player 0.4.2). */
|
|
173
|
+
fileTypes?: string[];
|
|
178
174
|
}
|
|
179
175
|
/** One timeline mark as the player merges them (`timeline.marks`). */
|
|
180
176
|
export interface WireMark {
|
|
@@ -530,11 +526,6 @@ export declare function createWire(transport: Transport): {
|
|
|
530
526
|
validate: (directory: string, apiVersion?: string) => Promise<PackageValidation>;
|
|
531
527
|
/** Player 0.2.0: a `.vxp` file. */
|
|
532
528
|
validateArchive: (file: string) => Promise<PackageValidation>;
|
|
533
|
-
/** `requestId` recovers a lost first reply in this owner session. */
|
|
534
|
-
trial: (token: string, requestId: string) => Promise<PackageTrial>;
|
|
535
|
-
trialStateByRequest: (requestId: string) => Promise<PackageTrial>;
|
|
536
|
-
trialState: (trialId: number) => Promise<PackageTrial>;
|
|
537
|
-
stopTrial: (trialId: number) => Promise<PackageTrial>;
|
|
538
529
|
installed: (id: string) => Promise<InstalledPackage>;
|
|
539
530
|
/** `source` and `replace` are sent only when given (player 0.2.0). */
|
|
540
531
|
install: (token: string, expectedRevision: number, requestId: string, options?: {
|
package/dist/wire.js
CHANGED
|
@@ -258,16 +258,6 @@ export function createWire(transport) {
|
|
|
258
258
|
validateArchive: (file) => transport.request("packages.validateArchive", {
|
|
259
259
|
file,
|
|
260
260
|
}),
|
|
261
|
-
/** `requestId` recovers a lost first reply in this owner session. */
|
|
262
|
-
trial: (token, requestId) => transport.request("packages.trial", {
|
|
263
|
-
token,
|
|
264
|
-
requestId,
|
|
265
|
-
}),
|
|
266
|
-
trialStateByRequest: (requestId) => transport.request("packages.trialStateByRequest", {
|
|
267
|
-
requestId,
|
|
268
|
-
}),
|
|
269
|
-
trialState: (trialId) => transport.request("packages.trialState", { trialId }),
|
|
270
|
-
stopTrial: (trialId) => transport.request("packages.stopTrial", { trialId }),
|
|
271
261
|
installed: (id) => transport.request("packages.installed", { id }),
|
|
272
262
|
/** `source` and `replace` are sent only when given (player 0.2.0). */
|
|
273
263
|
install: (token, expectedRevision, requestId, options = {}) => transport.request("packages.install", {
|
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @vestra-player/sdk 1.5.
|
|
1
|
+
# @vestra-player/sdk 1.5.8: full reference
|
|
2
2
|
|
|
3
3
|
> Everything needed to write a Vestra Player plugin (plugin API `vestra/1`): the guides, every public declaration of `@vestra-player/sdk` and `@vestra-player/sdk/testing` with its documentation, and the complete source of the example plugins. Generated from the SDK's sources by scripts/llms.mjs; the short index is llms.txt.
|
|
4
4
|
|
|
@@ -124,7 +124,7 @@ A manifest with every field. `id`, `apiVersion`, `entry` and `capabilities` are
|
|
|
124
124
|
}
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
Unknown fields, unknown capabilities and paths that leave the package directory (including through symbolic links) are rejected. The id's characters are ASCII letters, digits, `.`, `-` and `_`; the official plugin repository additionally requires `<GitHub user or organization>.<plugin name>`. The `vestra.` prefix (and the id `vestra`, in any case) is reserved for the plugins built into the player: from player 0.4.1 the player refuses to install
|
|
127
|
+
Unknown fields, unknown capabilities and paths that leave the package directory (including through symbolic links) are rejected. The id's characters are ASCII letters, digits, `.`, `-` and `_`; the official plugin repository additionally requires `<GitHub user or organization>.<plugin name>`. The `vestra.` prefix (and the id `vestra`, in any case) is reserved for the plugins built into the player: from player 0.4.1 the player refuses to install such a package (`reserved`). Every other plugin is a third-party plugin, including those hosted in the official repository.
|
|
128
128
|
|
|
129
129
|
| Capability | Opens |
|
|
130
130
|
| -------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
@@ -998,9 +998,8 @@ change).
|
|
|
998
998
|
| `timeout` | A time limit ran out (`openStream` start-up, `tools.run`, `system.*` after 10 s). |
|
|
999
999
|
| `stream`, `device` | `openStream`: the producer failed / the audio device is not ready. |
|
|
1000
1000
|
| `backend-uncertain` | The player's backend blocked a filter stage; call `retry()`. |
|
|
1001
|
-
| `cleanup` | PackageTrial.stop could not confirm cleanup; call it again. |
|
|
1002
1001
|
| `limit` | A player-wide limit was reached (for example the number of commands). |
|
|
1003
|
-
| `reserved` | Packages.validate, PackageCandidate.
|
|
1002
|
+
| `reserved` | Packages.validate, PackageCandidate.install: the id is `vestra` or starts with `vestra.` (any case), which only the player's built-in plugins use (player 0.4.1). |
|
|
1004
1003
|
| `versionMismatch` | The package needs a newer player (`minPlayerVersion`) or another `apiVersion`. |
|
|
1005
1004
|
| `ui-prepare` | The player could not prepare a mounted panel or a settings page (its Slint file does not compile, a bound property is not declared, or another plugin's panel holds the slot); `message` has the diagnostics. |
|
|
1006
1005
|
| `ui` | The player could not apply a property to a tool window or a settings page, or could not build the Options window (a property the Slint file does not declare, a value of the wrong type); `message` has Slint's reason. |
|
|
@@ -1080,7 +1079,7 @@ interface Scope extends Disposable {
|
|
|
1080
1079
|
readonly media: MediaCapture;
|
|
1081
1080
|
/** Page-URL to stream-URL resolvers (`source.resolve`). */
|
|
1082
1081
|
readonly resolvers: Resolvers;
|
|
1083
|
-
/** The installed plugins; validation,
|
|
1082
|
+
/** The installed plugins; validation, installs (`plugins.manage` for changes). */
|
|
1084
1083
|
readonly packages: Packages;
|
|
1085
1084
|
/** On-screen messages over the video (`ui.osd`). */
|
|
1086
1085
|
readonly osd: Osd;
|
|
@@ -1174,8 +1173,7 @@ interface Plugin extends Scope {
|
|
|
1174
1173
|
readonly id: string;
|
|
1175
1174
|
/**
|
|
1176
1175
|
* A writable directory for this plugin's own files (settings, remembered
|
|
1177
|
-
* folders). Kept across restarts, disabling and upgrades
|
|
1178
|
-
* temporary one. Write files atomically: to a temporary name, then rename.
|
|
1176
|
+
* folders). Kept across restarts, disabling and upgrades. Write files atomically: to a temporary name, then rename.
|
|
1179
1177
|
* Throws `unavailable` when the player provided none.
|
|
1180
1178
|
*
|
|
1181
1179
|
* Location: `~/Library/Application Support/Vestra/plugin-data/<id>/` on
|
|
@@ -2616,7 +2614,17 @@ interface Stream extends Disposable {
|
|
|
2616
2614
|
/** The stream is producing frames. */
|
|
2617
2615
|
readonly running: boolean;
|
|
2618
2616
|
/**
|
|
2619
|
-
* The stream stopped for a reason outside this plugin: `error` is null when
|
|
2617
|
+
* The stream stopped for a reason outside this plugin: `error` is null when
|
|
2618
|
+
* another source replaced it or the user closed it, otherwise the failure
|
|
2619
|
+
* (`stream` with the player's text, `invalid` for a bad frame, …). Not
|
|
2620
|
+
* called when the plugin itself stops it (`stop()`, `dispose()`,
|
|
2621
|
+
* deactivation): the promise of `stop()` is that notification.
|
|
2622
|
+
*
|
|
2623
|
+
* The player retires a stream's producer as soon as it is replaced or
|
|
2624
|
+
* closed; the SDK reads the player's state to tell that from a failure
|
|
2625
|
+
* (before 1.5.7 a replaced or closed stream could get `unavailable`
|
|
2626
|
+
* "producer absent"). Without `playback.read` a failure the SDK has not
|
|
2627
|
+
* seen yet is reported as null.
|
|
2620
2628
|
*/
|
|
2621
2629
|
onStop(listener: (error: PluginError | null) => void): Disposable;
|
|
2622
2630
|
/**
|
|
@@ -2758,7 +2766,8 @@ interface Player {
|
|
|
2758
2766
|
* activation, pausing and acknowledgement. Frames travel over a local
|
|
2759
2767
|
* connection the SDK sets up: a Unix socket on macOS and Linux, loopback
|
|
2760
2768
|
* TCP with a token on Windows. Rejects with a StreamStartError
|
|
2761
|
-
* (`timeout`), `stream` or `
|
|
2769
|
+
* (`timeout`), `stream`, `device`, or `replaced` when another source
|
|
2770
|
+
* replaced it (or it was closed) before it ran.
|
|
2762
2771
|
*/
|
|
2763
2772
|
openStream(options: StreamOptions): Promise<Stream>;
|
|
2764
2773
|
/** Pause or resume. */
|
|
@@ -3389,6 +3398,14 @@ interface FileResolverOptions {
|
|
|
3389
3398
|
What a file resolver returns: a stream, with the same frame contract as
|
|
3390
3399
|
StreamOptions (size limits, `frame()` on the audio clock).
|
|
3391
3400
|
|
|
3401
|
+
After `resolve` returns, the SDK starts the stream while the open waits.
|
|
3402
|
+
If that fails, the open fails with the player's words instead of the
|
|
3403
|
+
SDK's (the detail goes to the log): `device` "音频输出设备不可用",
|
|
3404
|
+
`timeout` "启动超时", `busy` "播放器正忙,请稍后重试", other start-up
|
|
3405
|
+
failures "无法启动播放". An error thrown by `frame()` keeps its message.
|
|
3406
|
+
To give your own text for a file you can tell is unusable (a bad header),
|
|
3407
|
+
check it in `resolve` and throw there.
|
|
3408
|
+
|
|
3392
3409
|
```ts
|
|
3393
3410
|
interface ResolvedStream {
|
|
3394
3411
|
/** Always `"stream"`. */
|
|
@@ -3431,6 +3448,20 @@ interface Resolvers {
|
|
|
3431
3448
|
* Register a resolver. When anyone opens a matching URL or file the player calls `resolve`; `signal` aborts when the open is cancelled or replaced. One scheme + host pair, and one extension, has one resolver (`conflict` otherwise). A rejected `resolve` fails the open with the error's message.
|
|
3432
3449
|
*/
|
|
3433
3450
|
add(options: ResolverOptions): Resolver;
|
|
3451
|
+
/**
|
|
3452
|
+
* The extensions some plugin's file resolver handles (SDK 1.5.8, player 0.4.2): lower case, without the dot, sorted, each once; not who registered them. Reading needs no capability; `[]` from older players. Without `events` it is the list from when the plugin first read it. Use it to accept such files beside the player's own media types, for example in a playlist's drop or folder scan.
|
|
3453
|
+
* @capability None.
|
|
3454
|
+
* @player 0.4.2
|
|
3455
|
+
*/
|
|
3456
|
+
readonly fileTypes: readonly string[];
|
|
3457
|
+
/**
|
|
3458
|
+
* Resolvers.fileTypes changed: a file resolver was added, or its plugin stopped. Needs `events`; without it the listener never fires.
|
|
3459
|
+
* @param listener - Receives the new list.
|
|
3460
|
+
* @returns A handle that removes the listener.
|
|
3461
|
+
* @capability `events`
|
|
3462
|
+
* @player 0.4.2
|
|
3463
|
+
*/
|
|
3464
|
+
onFileTypesChange(listener: (types: string[]) => void): Disposable;
|
|
3434
3465
|
}
|
|
3435
3466
|
```
|
|
3436
3467
|
|
|
@@ -3536,8 +3567,6 @@ interface PackageCandidate {
|
|
|
3536
3567
|
readonly manifest: PackageManifest;
|
|
3537
3568
|
/** The checks the player ran. */
|
|
3538
3569
|
readonly checks: string[];
|
|
3539
|
-
/** Load it temporarily alongside the installed plugins. A reserved id (`vestra.*`) fails with `reserved`. */
|
|
3540
|
-
trial(): Promise<PackageTrial>;
|
|
3541
3570
|
/**
|
|
3542
3571
|
* Install it. The same source upgrades the installed plugin (its data stays); another source fails with `conflict` unless `replace` is set; a built-in id fails with `unsupported` (built-ins update with the player). A reserved id (`vestra` or `vestra.*`, which every built-in uses) fails with `reserved` (player 0.4.1; already when validated), as only the player installs built-in plugins.
|
|
3543
3572
|
*/
|
|
@@ -3545,21 +3574,6 @@ interface PackageCandidate {
|
|
|
3545
3574
|
}
|
|
3546
3575
|
```
|
|
3547
3576
|
|
|
3548
|
-
### PackageTrial
|
|
3549
|
-
|
|
3550
|
-
A trial load of a package. Disposing it stops the trial and waits for cleanup.
|
|
3551
|
-
|
|
3552
|
-
```ts
|
|
3553
|
-
interface PackageTrial extends Disposable {
|
|
3554
|
-
/** The trial's status as the player reports it. */
|
|
3555
|
-
readonly status: string;
|
|
3556
|
-
/**
|
|
3557
|
-
* Stop and wait until the host confirmed cleanup. Rejects with code `cleanup` when the host stopped the trial without confirming cleanup; calling `stop()` again then asks the host again.
|
|
3558
|
-
*/
|
|
3559
|
-
stop(): Promise<void>;
|
|
3560
|
-
}
|
|
3561
|
-
```
|
|
3562
|
-
|
|
3563
3577
|
### PackageChangeStatus
|
|
3564
3578
|
|
|
3565
3579
|
The progress of an install, rollback or uninstall.
|
|
@@ -3598,8 +3612,8 @@ interface PluginInfo {
|
|
|
3598
3612
|
id: string;
|
|
3599
3613
|
/** Version, `null` when unknown. */
|
|
3600
3614
|
version: string | null;
|
|
3601
|
-
/** From the install library, a `--plugin` development load
|
|
3602
|
-
origin: "installed" | "development"
|
|
3615
|
+
/** From the install library, or a `--plugin` development load. */
|
|
3616
|
+
origin: "installed" | "development";
|
|
3603
3617
|
/** Run state. */
|
|
3604
3618
|
state: "starting" | "running" | "disabled" | "failed" | "stopped";
|
|
3605
3619
|
/** Why it failed (`state: "failed"`). */
|
|
@@ -3612,7 +3626,7 @@ interface PluginInfo {
|
|
|
3612
3626
|
previousVersion: string | null;
|
|
3613
3627
|
/** Shipped with the player: it can be disabled, not uninstalled or replaced. `false` from players before 0.2.0. */
|
|
3614
3628
|
builtin: boolean;
|
|
3615
|
-
/** Where an installed plugin came from; `null` for development loads
|
|
3629
|
+
/** Where an installed plugin came from; `null` for development loads. */
|
|
3616
3630
|
source: PackageSource | null;
|
|
3617
3631
|
/** Its data directory (`plugin.dataDirectory` of that plugin); `null` when the player has none. The path's layout is not part of the API. */
|
|
3618
3632
|
dataDirectory: string | null;
|
|
@@ -3648,7 +3662,13 @@ need no capability; everything else needs `plugins.manage`.
|
|
|
3648
3662
|
```ts
|
|
3649
3663
|
interface Packages {
|
|
3650
3664
|
/**
|
|
3651
|
-
* Validate a package directory (`plugins.manage`). A package whose id is
|
|
3665
|
+
* Validate a package directory (`plugins.manage`). A package whose id is
|
|
3666
|
+
* reserved for the built-in plugins (`vestra` or `vestra.*`) fails with
|
|
3667
|
+
* `reserved` (player 0.4.1).
|
|
3668
|
+
*
|
|
3669
|
+
* The player keeps the 32 most recent candidates of all plugins; an
|
|
3670
|
+
* older one's `install` fails with `stale` (validate again). Before
|
|
3671
|
+
* player 0.4.2 the 33rd validation of a run failed with `busy` instead.
|
|
3652
3672
|
*/
|
|
3653
3673
|
validate(directory: string): Promise<PackageCandidate>;
|
|
3654
3674
|
/**
|
|
@@ -3662,11 +3682,11 @@ interface Packages {
|
|
|
3662
3682
|
/** The new list after any start, stop, failure, install or uninstall. No capability. */
|
|
3663
3683
|
onChange(listener: (plugins: PluginInfo[]) => void): Disposable;
|
|
3664
3684
|
/**
|
|
3665
|
-
* Stop or start a plugin (`plugins.manage`). An installed plugin stays disabled across launches; a development load only for this run. `invalid` to disable oneself, `
|
|
3685
|
+
* Stop or start a plugin (`plugins.manage`). An installed plugin stays disabled across launches; a development load only for this run. `invalid` to disable oneself, `missing` unknown. `busy` while it is being installed.
|
|
3666
3686
|
*/
|
|
3667
3687
|
setEnabled(id: string, enabled: boolean): Promise<void>;
|
|
3668
3688
|
/**
|
|
3669
|
-
* Remove an installed plugin (`plugins.manage`); `removeData` also deletes its data directory, otherwise reinstalling it from the same source reconnects to its data. Its user bindings stay (as orphans). `unsupported` for built-ins
|
|
3689
|
+
* Remove an installed plugin (`plugins.manage`); `removeData` also deletes its data directory, otherwise reinstalling it from the same source reconnects to its data. Its user bindings stay (as orphans). `unsupported` for built-ins and development loads, `missing` unknown, `invalid` for oneself.
|
|
3670
3690
|
*/
|
|
3671
3691
|
uninstall(id: string, options?: {
|
|
3672
3692
|
removeData?: boolean;
|
|
@@ -4260,6 +4280,10 @@ interface FakeProducer {
|
|
|
4260
4280
|
videoFrames: number;
|
|
4261
4281
|
/** `true` once the plugin released the producer (stream stopped or disposed). */
|
|
4262
4282
|
released: boolean;
|
|
4283
|
+
/**
|
|
4284
|
+
* `true` once the player retired the producer, as the real player does at once: another source replaced it (`open`, another stream, a resolved file), the source was closed, or TestHost.failStream failed it. A retired producer's `producer.state` answers `unavailable`.
|
|
4285
|
+
*/
|
|
4286
|
+
retired: boolean;
|
|
4263
4287
|
/**
|
|
4264
4288
|
* `true` if the frame connection closed while this stream was still the player's source: the player reports that as a playback failure ("producer transport closed"). `stop()` closes the source first.
|
|
4265
4289
|
*/
|
|
@@ -4698,6 +4722,12 @@ class TestHost implements Transport {
|
|
|
4698
4722
|
/** Exact host names it resolves (a web resolver), with `schemes`. */
|
|
4699
4723
|
hosts?: string[];
|
|
4700
4724
|
}[];
|
|
4725
|
+
/** What `plugin.resolvers.fileTypes` reports: the extensions of this plugin's file resolvers and of TestHost.otherResolvers, sorted, each once. */
|
|
4726
|
+
fileTypes(): string[];
|
|
4727
|
+
/**
|
|
4728
|
+
* Push `resolvers.fileTypes` when TestHost.fileTypes changed: called after this plugin's resolvers come and go; call it yourself after changing TestHost.otherResolvers (another plugin started or stopped).
|
|
4729
|
+
*/
|
|
4730
|
+
updateFileTypes(): void;
|
|
4701
4731
|
/**
|
|
4702
4732
|
* File opens waiting for this plugin's file resolver (`extensions`), by request id: the path and how it was opened. Opening a matching path (`player.open`, TestHost.openElsewhere) sends `source.resolveRequest`; the answer selects the stream, fails the open or, once the source changed, is `stale`. Any later source change cancels it (`source.resolveCancel`). Web resolvers are not simulated: emit `source.resolveRequest` yourself.
|
|
4703
4733
|
*/
|
|
@@ -4854,6 +4884,12 @@ class TestHost implements Transport {
|
|
|
4854
4884
|
* @param phase - The phase to end in (default `"ready"`).
|
|
4855
4885
|
*/
|
|
4856
4886
|
openElsewhere(source: string, phase?: SourceState["phase"]): void;
|
|
4887
|
+
/**
|
|
4888
|
+
* Simulate a generated stream failing in the player (its audio device lost, its frame connection broken), like the player: the source fails with `message` (`phase: "error"`) and the producer is retired at once. The stream's `onStop` listeners get a `stream` error with `message`.
|
|
4889
|
+
* @param producerId - The producer, from TestHost.producers.
|
|
4890
|
+
* @param message - The player's failure text.
|
|
4891
|
+
*/
|
|
4892
|
+
failStream(producerId: number, message: string): void;
|
|
4857
4893
|
/**
|
|
4858
4894
|
* Press a binding like the host's table would: panel-focus bindings first when `panel` is true, then global ones; the earliest registration wins a conflict. Resolves after the command ran; rejects when nothing is bound or the command is disabled or busy. Bindings use the reference syntax (`"Space"`, `"Ctrl+O"`, `"Mouse:WheelUp"`); the player's core actions match first, and user overrides in `bindings.overlay` apply.
|
|
4859
4895
|
*/
|
|
@@ -4876,7 +4912,7 @@ class TestHost implements Transport {
|
|
|
4876
4912
|
/** Its version, `null` when unknown. */
|
|
4877
4913
|
version: string | null;
|
|
4878
4914
|
/** Where it was loaded from. */
|
|
4879
|
-
origin: "installed" | "development"
|
|
4915
|
+
origin: "installed" | "development";
|
|
4880
4916
|
/** Its run state. */
|
|
4881
4917
|
state: "starting" | "running" | "disabled" | "failed" | "stopped";
|
|
4882
4918
|
/** Why it failed (`state: "failed"`). */
|
|
@@ -5030,7 +5066,7 @@ own sensible display cap well below `perPlugin`.
|
|
|
5030
5066
|
|
|
5031
5067
|
```ts
|
|
5032
5068
|
const COMMAND_LIMITS: {
|
|
5033
|
-
/** Commands one plugin instance may have at the same time (160).
|
|
5069
|
+
/** Commands one plugin instance may have at the same time (160). */
|
|
5034
5070
|
readonly perPlugin: 160;
|
|
5035
5071
|
/** Commands of every plugin plus the player's own, together (1024). */
|
|
5036
5072
|
readonly total: 1024;
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vestra Player SDK
|
|
2
2
|
|
|
3
|
-
> @vestra-player/sdk 1.5.
|
|
3
|
+
> @vestra-player/sdk 1.5.8: 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; it runs in its own Node.js process. llms-full.txt, next to this file, has every declaration, the guides and the examples; L<n> below are its line numbers.
|
|
4
4
|
|
|
5
5
|
**How plugins run**
|
|
6
6
|
|
|
@@ -136,7 +136,7 @@ test("shows the position", async () => {
|
|
|
136
136
|
- `aborted`: An `AbortSignal` fired
|
|
137
137
|
- `timeout`: A time limit ran out
|
|
138
138
|
- `limit`: A player-wide limit was reached
|
|
139
|
-
- `reserved`: Packages.validate, PackageCandidate.
|
|
139
|
+
- `reserved`: Packages.validate, PackageCandidate.install: the id is `vestra` or starts with `vestra.`, which only the player's built-in plugins use
|
|
140
140
|
- `versionMismatch`: The package needs a newer player or another `apiVersion`
|
|
141
141
|
- `ui-prepare`: The player could not prepare a mounted panel or a settings page
|
|
142
142
|
- `ui`: The player could not apply a property to a tool window or a settings page, or could not build the Options window
|
|
@@ -150,54 +150,54 @@ test("shows the position", async () => {
|
|
|
150
150
|
- [Concept: Windows, panels, settings pages, dialogs and the OSD](https://vestrasys.github.io/vestra-player-sdk/documents/Windows__panels__settings_pages__dialogs_and_the_OSD.html): L281–626
|
|
151
151
|
- [How-to: Keep a slider responsive while dragging](https://vestrasys.github.io/vestra-player-sdk/documents/Keep_a_slider_responsive_while_dragging.html): L627–801
|
|
152
152
|
- [How-to: Remember a window's state between runs](https://vestrasys.github.io/vestra-player-sdk/documents/Remember_a_window_s_state_between_runs.html): L802–931
|
|
153
|
-
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L932–
|
|
154
|
-
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html) (TestHost, startPlugin):
|
|
153
|
+
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L932–4173
|
|
154
|
+
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html) (TestHost, startPlugin): L4174–5120
|
|
155
155
|
|
|
156
156
|
## API
|
|
157
157
|
|
|
158
158
|
Where each module of `plugin` is declared:
|
|
159
159
|
|
|
160
|
-
- Plugin
|
|
161
|
-
- plugin.commands: Commands
|
|
162
|
-
- plugin.windows: Windows
|
|
163
|
-
- plugin.panels: Panels
|
|
164
|
-
- plugin.dialogs: Dialogs
|
|
165
|
-
- plugin.player: Player
|
|
166
|
-
- plugin.video: VideoFilter
|
|
167
|
-
- plugin.audio: AudioFilter
|
|
168
|
-
- plugin.subtitles: Subtitles
|
|
169
|
-
- plugin.media: MediaCapture
|
|
170
|
-
- plugin.resolvers: Resolvers
|
|
171
|
-
- plugin.packages: Packages
|
|
172
|
-
- plugin.osd: Osd
|
|
173
|
-
- plugin.host: Host
|
|
174
|
-
- plugin.clipboard: Clipboard
|
|
175
|
-
- plugin.power: Power
|
|
176
|
-
- plugin.tools: Tools
|
|
177
|
-
- plugin.storage: Storage
|
|
178
|
-
- plugin.system: System
|
|
179
|
-
- plugin.secrets: Secrets
|
|
180
|
-
- plugin.window: MainWindow
|
|
181
|
-
- plugin.app: App
|
|
182
|
-
- plugin.bindings: Bindings
|
|
183
|
-
- plugin.ui: Ui
|
|
184
|
-
- plugin.timeline: Timeline
|
|
185
|
-
- plugin.drops: Drops
|
|
186
|
-
- plugin.appearance: Appearance
|
|
187
|
-
- plugin.settings: Settings
|
|
160
|
+
- Plugin L1151, Scope L1022, PluginError L974, Disposable L947
|
|
161
|
+
- plugin.commands: Commands L1347
|
|
162
|
+
- plugin.windows: Windows L1552
|
|
163
|
+
- plugin.panels: Panels L2003
|
|
164
|
+
- plugin.dialogs: Dialogs L2285
|
|
165
|
+
- plugin.player: Player L2724
|
|
166
|
+
- plugin.video: VideoFilter L2973, VideoView L3036, RenderOptions L3078
|
|
167
|
+
- plugin.audio: AudioFilter L2997
|
|
168
|
+
- plugin.subtitles: Subtitles L3176
|
|
169
|
+
- plugin.media: MediaCapture L3334
|
|
170
|
+
- plugin.resolvers: Resolvers L3439
|
|
171
|
+
- plugin.packages: Packages L3657
|
|
172
|
+
- plugin.osd: Osd L2910
|
|
173
|
+
- plugin.host: Host L2873
|
|
174
|
+
- plugin.clipboard: Clipboard L3770
|
|
175
|
+
- plugin.power: Power L3790
|
|
176
|
+
- plugin.tools: Tools L3823
|
|
177
|
+
- plugin.storage: Storage L3866
|
|
178
|
+
- plugin.system: System L3889
|
|
179
|
+
- plugin.secrets: Secrets L3907
|
|
180
|
+
- plugin.window: MainWindow L2126
|
|
181
|
+
- plugin.app: App L2207
|
|
182
|
+
- plugin.bindings: Bindings L3740
|
|
183
|
+
- plugin.ui: Ui L1439
|
|
184
|
+
- plugin.timeline: Timeline L2083
|
|
185
|
+
- plugin.drops: Drops L1849
|
|
186
|
+
- plugin.appearance: Appearance L1878
|
|
187
|
+
- plugin.settings: Settings L1936
|
|
188
188
|
|
|
189
189
|
## Examples
|
|
190
190
|
|
|
191
191
|
Complete plugins with tests, in [examples/](https://github.com/vestrasys/vestra-player-sdk/tree/main/examples) and in llms-full.txt:
|
|
192
192
|
|
|
193
|
-
- hello: The README Quick start: one menu command and an on-screen message.
|
|
194
|
-
- blur: A tool window with one slider that blurs the playing video.
|
|
195
|
-
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone.
|
|
196
|
-
- bookmark: A tool window bound to the playback state: remember the position and jump back to it.
|
|
197
|
-
- panel-menu: A sidebar panel with its own right-click menu.
|
|
198
|
-
- menus: Radio menu items, separator groups and a menu item whose title changes.
|
|
199
|
-
- theme-widgets: A tool window drawn with the player's theme and widgets.
|
|
200
|
-
- markdown: A window that shows a Markdown document.
|
|
193
|
+
- hello: The README Quick start: one menu command and an on-screen message. L5534–5623
|
|
194
|
+
- blur: A tool window with one slider that blurs the playing video. L5624–5885
|
|
195
|
+
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L5886–6218
|
|
196
|
+
- bookmark: A tool window bound to the playback state: remember the position and jump back to it. L6219–6403
|
|
197
|
+
- panel-menu: A sidebar panel with its own right-click menu. L6404–6609
|
|
198
|
+
- menus: Radio menu items, separator groups and a menu item whose title changes. L6610–6769
|
|
199
|
+
- theme-widgets: A tool window drawn with the player's theme and widgets. L6770–6933
|
|
200
|
+
- markdown: A window that shows a Markdown document. L6934–7127
|
|
201
201
|
|
|
202
202
|
## Optional
|
|
203
203
|
|