@vestra-player/sdk 1.5.18 → 1.5.20
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/dist/capabilities.js +1 -0
- package/dist/commands.js +0 -1
- package/dist/player-runtime.d.ts +1 -1
- package/dist/player-runtime.js +1 -1
- package/dist/plugin/markdown.d.ts +7 -0
- package/dist/plugin/markdown.js +62 -22
- package/dist/plugin/packages.js +5 -0
- package/dist/plugin/player.d.ts +2 -0
- package/dist/plugin/player.js +11 -6
- package/dist/plugin/services.js +10 -3
- package/dist/plugin/testing.d.ts +47 -8
- package/dist/plugin/testing.js +114 -19
- package/dist/plugin/types.d.ts +173 -21
- package/dist/plugin/ui.d.ts +4 -2
- package/dist/plugin/ui.js +31 -13
- package/dist/plugin/values.d.ts +15 -0
- package/dist/plugin/values.js +18 -0
- package/dist/wire.d.ts +3 -2
- package/dist/wire.js +3 -2
- package/llms-full.txt +154 -18
- package/llms.txt +23 -23
- package/package.json +1 -1
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @vestra-player/sdk 1.5.
|
|
1
|
+
# @vestra-player/sdk 1.5.20: 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
|
|
|
@@ -583,6 +583,23 @@ Play/pause, stop, previous/next, frame steps, relative seeks, speed, volume and
|
|
|
583
583
|
|
|
584
584
|
The difference from the `Player` methods: a `Player` control is a precise operation the plugin is responsible for (conditional, silent, its own error handling); a core action is the user's action, performed on the plugin's behalf. The action ids, menu places and default keys are in Reference: commands; how keys reach them is in Commands, menus and key bindings.
|
|
585
585
|
|
|
586
|
+
##### Step seeks: exact or keyframe
|
|
587
|
+
|
|
588
|
+
← / → (`seek-backward` / `seek-forward`) seek by the step that player.setStepSeek sets (5 s by default). By default they land on the exact time, which on a file with keyframes far apart means decoding from the previous keyframe first: a visible stall on 4K video. `setStepSeek({ seconds, keyframes: true })` (player 0.5.1, SDK 1.5.19) makes them land on a keyframe instead: forward on the first keyframe at or after position + step, backward on the last at or before position − step, and every press moves. Presses during a seek add up and continue from where it landed, and the on-screen text shows the landed time. Sources without moving video still seek exactly. The seek bar, `player.seek`, scrubs, chapters, loops and `player.step` are never affected.
|
|
589
|
+
|
|
590
|
+
For more steps of your own (Ctrl+→ and the like), call `plugin.host.run("seek-forward", { seconds: 30 })`: the same checks, mode, accumulation and text as →. In keyframe mode it resolves once the seek has landed, so `player.state.position` is current afterwards; do not show your own text for it. Set `"minPlayerVersion": "0.5.1"` when you rely on either option: older players ignore them.
|
|
591
|
+
|
|
592
|
+
```ts
|
|
593
|
+
const keyframes = true; // the plugin's own setting
|
|
594
|
+
await plugin.player.setStepSeek({ seconds: 5, keyframes });
|
|
595
|
+
const seek = (delta: number) =>
|
|
596
|
+
plugin.host.run(delta < 0 ? "seek-backward" : "seek-forward", {
|
|
597
|
+
seconds: Math.abs(delta),
|
|
598
|
+
});
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
In tests, `TestHost.keyframes` models the source's keyframes, and `host.coreSeeks` records each step seek with where it landed.
|
|
602
|
+
|
|
586
603
|
## Concept: Video and audio processing
|
|
587
604
|
|
|
588
605
|
A plugin can change what the user sees and hears in three different places. They look alike in the API (each is a handle with `set`, a `status` and `onStatus`), but they act at different stages and have different owners, so choosing the right one matters:
|
|
@@ -856,7 +873,8 @@ export component ListPanel inherits Rectangle {
|
|
|
856
873
|
##### Names and values
|
|
857
874
|
|
|
858
875
|
- Write names in camelCase or kebab-case in TypeScript: the SDK turns every capital letter into `-` plus the lower-case letter (`canMark` → `can-mark`, `strengthChanged` → `strength-changed`). Fields inside struct values are **not** converted, so spell struct fields exactly as the Slint struct does (and without `_`, which Slint treats as `-`).
|
|
859
|
-
- Values must be JSON: booleans, numbers, strings, arrays (Slint models) and objects (Slint structs). Two exceptions: an image from ui.image
|
|
876
|
+
- Values must be JSON: booleans, numbers, strings, arrays (Slint models) and objects (Slint structs). Two exceptions: an image from ui.image or ui.remoteImage wherever the Slint type is `image`: the whole value, or (SDK 1.5.19, player 0.5.1) a field at any depth, such as the logo of each row of a list; and a document from ui.markdown wherever the Slint type is `[MarkdownBlock]`: the whole value, or (SDK 1.5.4, the player after 0.4.0) a field at any depth, such as the `body` of each message in a chat list.
|
|
877
|
+
- Images in rows: give small pictures `maxSide` (about twice the drawn size, `64` for a 32 px logo), so that the player decodes them small. The images nested in one view's values may show at most 32 MB of decoded pixels together; a write past that is refused with `limit`. A nested image whose file fails the player's checks is drawn empty, and the rest of the row is shown. Rows with images update in place, so a `ListView` keeps its scroll position when the list is written again.
|
|
860
878
|
- Every name must exist in the Slint file. Writing a property the file does not declare makes a tool window's `show()` or a panel's `ready` fail, and in a settings page it keeps the Options window from opening; for a tool window, so does a callback bound with `on()` that the file does not declare. Once the view is open, such writes are reported to onError.
|
|
861
879
|
|
|
862
880
|
##### set, bind and the update pass
|
|
@@ -2157,7 +2175,7 @@ The table lists the API whose documentation names a player version, newest last:
|
|
|
2157
2175
|
| 0.4.1 | PluginError, FileResolverOptions, PackageCandidate.install, PluginWarning.code, Packages.validate |
|
|
2158
2176
|
| 0.4.2 | Resolvers.fileTypes, Resolvers.onFileTypesChange |
|
|
2159
2177
|
| 0.4.3 | CommandOptions.path, PropValue, View.set, Appearance.setLanguage, TemplateArgs, Text, ConfirmOptions.args, OsdPanel.set, OsdPanelOptions.maxColumns, Osd.show |
|
|
2160
|
-
| 0.5.1 | SlotState.reason, Panel.setInteraction, PlaybackStats.presentedFps |
|
|
2178
|
+
| 0.5.1 | ImageRef, ImageOptions.maxSide, PropValue, Ui.image, Ui.remoteImage, SlotState.reason, Panel.setInteraction, PlaybackStats.presentedFps, Player.setStepSeek, Host.run, Packages.reload |
|
|
2161
2179
|
|
|
2162
2180
|
The Slint library carries no version tags: `Theme.danger` needs player 0.3.0; `@vestra/icons.slint` and the palette `vestra-light` need 0.4.0 (Theme).
|
|
2163
2181
|
|
|
@@ -2178,7 +2196,7 @@ A plugin lists what it may do in the manifest's `capabilities` (Manifest). A cal
|
|
|
2178
2196
|
| `ui.window` | Windows.create | — | Open tool windows | |
|
|
2179
2197
|
| `ui.mount` | Panels.mount, Panels.bottom, Panels.sidebar, Panels.backdrop, PanelSlot.onChange, Panel.onChange, BackdropSlot.onChange | — | Show panels in the bottom bar, the sidebar or behind the video | |
|
|
2180
2198
|
| `ui.dialog` | Dialogs.confirm, Dialogs.openFile, Dialogs.openFiles, Dialogs.openDirectory, Dialogs.saveFile | — | Show file pickers and confirmations | |
|
|
2181
|
-
| `plugins.manage` | Packages.validate, Packages.validateArchive, Packages.setEnabled, Packages.uninstall | — | Install, uninstall and disable other plugins | yes |
|
|
2199
|
+
| `plugins.manage` | Packages.validate, Packages.validateArchive, Packages.setEnabled, Packages.reload, Packages.uninstall | — | Install, uninstall and disable other plugins | yes |
|
|
2182
2200
|
| `processing.video` | Plugin.video.filter, Plugin.video.view, Plugin.video.render | `playback.read` | Process the picture (filters, shaders) | |
|
|
2183
2201
|
| `processing.audio` | Plugin.audio.filter | `playback.read`, `events` | Process the sound | |
|
|
2184
2202
|
| `subtitles.read` | Subtitles.state, Subtitles.onChange, Subtitles.refresh | — | Read subtitles | |
|
|
@@ -2651,7 +2669,6 @@ Every command the player (`host`) and its built-in plugins register when the pla
|
|
|
2651
2669
|
| Settings ▸ Keyboard Shortcuts… | | `vestra.hotkeys/keys` |
|
|
2652
2670
|
| Settings ▸ Mouse… | | `vestra.hotkeys/mouse` |
|
|
2653
2671
|
| Settings ▸ Ignore Default Shortcuts | | `vestra.hotkeys/ignore-defaults` |
|
|
2654
|
-
| Settings ▸ Plugin Manager… | | `vestra.plugins/manage` |
|
|
2655
2672
|
| Settings ▸ Appearance ▸ Vestra Dark | | `vestra.preferences/theme.vestra` |
|
|
2656
2673
|
| Settings ▸ Appearance ▸ Vestra Light | | `vestra.preferences/theme.vestra-light` |
|
|
2657
2674
|
| Settings ▸ Appearance ▸ Show Logo When Idle | | `vestra.visualizer/idle-logo` |
|
|
@@ -3537,6 +3554,20 @@ interface ImageRef {
|
|
|
3537
3554
|
}
|
|
3538
3555
|
```
|
|
3539
3556
|
|
|
3557
|
+
### ImageOptions
|
|
3558
|
+
|
|
3559
|
+
Options of Ui.image and Ui.remoteImage.
|
|
3560
|
+
|
|
3561
|
+
```ts
|
|
3562
|
+
interface ImageOptions {
|
|
3563
|
+
/**
|
|
3564
|
+
* Decode the image scaled down, aspect kept, so that neither side is over this many pixels (an integer 1–4096); smaller images stay as they are. Use about twice the drawn size (64 for a 32 px logo) so that it stays sharp on high-density screens. It keeps the decoded memory small: a 1024×1024 icon is 4 MB decoded, 16 KB at `maxSide: 64`.
|
|
3565
|
+
* @player 0.5.1; older players refuse the reference (`invalid`).
|
|
3566
|
+
*/
|
|
3567
|
+
maxSide?: number;
|
|
3568
|
+
}
|
|
3569
|
+
```
|
|
3570
|
+
|
|
3540
3571
|
### MarkdownRef
|
|
3541
3572
|
|
|
3542
3573
|
A Markdown document for `MarkdownView` or `MarkdownBlocks`, made by
|
|
@@ -3571,9 +3602,8 @@ interface MarkdownOptions {
|
|
|
3571
3602
|
|
|
3572
3603
|
### PropValue
|
|
3573
3604
|
|
|
3574
|
-
The value of one Slint property: JSON with Markdown documents
|
|
3575
|
-
depth (PropData)
|
|
3576
|
-
property.
|
|
3605
|
+
The value of one Slint property: JSON with Markdown documents and images
|
|
3606
|
+
at any depth (PropData).
|
|
3577
3607
|
|
|
3578
3608
|
```ts
|
|
3579
3609
|
type PropValue = PropData | ImageRef;
|
|
@@ -3581,11 +3611,11 @@ type PropValue = PropData | ImageRef;
|
|
|
3581
3611
|
|
|
3582
3612
|
### PropData
|
|
3583
3613
|
|
|
3584
|
-
JSON whose values may also be Markdown documents
|
|
3585
|
-
of PropValue that nests.
|
|
3614
|
+
JSON whose values may also be Markdown documents and (SDK 1.5.19) images,
|
|
3615
|
+
at any depth: the part of PropValue that nests.
|
|
3586
3616
|
|
|
3587
3617
|
```ts
|
|
3588
|
-
type PropData = null | boolean | number | string | MarkdownRef | Text | TextList | PropData[] | {
|
|
3618
|
+
type PropData = null | boolean | number | string | MarkdownRef | ImageRef | Text | TextList | PropData[] | {
|
|
3589
3619
|
[key: string]: PropData;
|
|
3590
3620
|
};
|
|
3591
3621
|
```
|
|
@@ -3611,10 +3641,22 @@ interface Ui {
|
|
|
3611
3641
|
* Reference a PNG or JPEG file for an `image` property.
|
|
3612
3642
|
* @capability None.
|
|
3613
3643
|
* @param path - Absolute path of the image file, inside the package directory or the data directory.
|
|
3644
|
+
* @param options - `maxSide` (SDK 1.5.19, player 0.5.1): decode the image scaled down, aspect kept, so that neither side is over it.
|
|
3614
3645
|
* @returns A new ImageRef, owned by this scope.
|
|
3615
|
-
* @throws invalid (throws) `path` is not a non-empty string.
|
|
3646
|
+
* @throws invalid (throws) `path` is not a non-empty string, or `maxSide` is not an integer 1–4096.
|
|
3616
3647
|
*/
|
|
3617
|
-
image(path: string): ImageRef;
|
|
3648
|
+
image(path: string, options?: ImageOptions): ImageRef;
|
|
3649
|
+
/**
|
|
3650
|
+
* Download an `https:` PNG or JPEG image (a thumbnail, a repository's plugin icon) and reference the local copy, as Ui.image does.
|
|
3651
|
+
* @capability None (the plugin process has network access).
|
|
3652
|
+
* @player Any (the reference is an ordinary ImageRef); nested in a value, player 0.5.1.
|
|
3653
|
+
* @param url - The image's `https:` address.
|
|
3654
|
+
* @param options - As for Ui.image.
|
|
3655
|
+
* @returns The reference, owned by this scope, once the file is in the cache.
|
|
3656
|
+
* @throws invalid (rejects) `url` is not an `https:` address, or `maxSide` is not an integer 1–4096.
|
|
3657
|
+
* @throws unavailable (rejects) the download failed, timed out, was too large, or is not a PNG or JPEG image; or the plugin has no data directory.
|
|
3658
|
+
*/
|
|
3659
|
+
remoteImage(url: string, options?: ImageOptions): Promise<ImageRef>;
|
|
3618
3660
|
/**
|
|
3619
3661
|
* Prepare a Markdown document for `MarkdownView` (`@vestra/markdown.slint`).
|
|
3620
3662
|
* @capability None.
|
|
@@ -5181,10 +5223,28 @@ interface Player {
|
|
|
5181
5223
|
*/
|
|
5182
5224
|
step(unit: "frame" | "keyframe", direction: "backward" | "forward", options?: Conditional): Promise<void>;
|
|
5183
5225
|
/**
|
|
5184
|
-
* The core's first-tier relative seek (`seek-backward` / `seek-forward`,
|
|
5226
|
+
* The core's first-tier relative seek (`seek-backward` / `seek-forward`,
|
|
5227
|
+
* ← / →): 0.1–3600 seconds in tenths, default 5. The newest call of any
|
|
5228
|
+
* plugin wins; it reverts when that plugin stops.
|
|
5229
|
+
*
|
|
5230
|
+
* `keyframes: true` (player 0.5.1, SDK 1.5.19): the step seeks
|
|
5231
|
+
* (`seek-backward` / `seek-forward`, including Host.run with
|
|
5232
|
+
* `seconds` and the picture-in-picture skips) land on a keyframe instead
|
|
5233
|
+
* of the exact time: forward on the first keyframe at or after position +
|
|
5234
|
+
* step, backward on the last at or before position − step, and they
|
|
5235
|
+
* always move. Presses during a seek add up and continue from where it
|
|
5236
|
+
* landed; the on-screen text shows the landed time. Sources without moving
|
|
5237
|
+
* video seek exactly. The seek bar, Player.seek, scrubs, chapters,
|
|
5238
|
+
* loops and Player.step are unaffected. Omitted or `false`: exact
|
|
5239
|
+
* seeks, as before. `seconds` and `keyframes` are written as a pair: the
|
|
5240
|
+
* newest call sets both.
|
|
5241
|
+
*
|
|
5242
|
+
* Older players ignore `keyframes`: set `"minPlayerVersion": "0.5.1"` in
|
|
5243
|
+
* the manifest when you rely on it.
|
|
5185
5244
|
*/
|
|
5186
5245
|
setStepSeek(options: {
|
|
5187
5246
|
seconds: number;
|
|
5247
|
+
keyframes?: boolean;
|
|
5188
5248
|
}): Promise<void>;
|
|
5189
5249
|
/** The chapters of the current media (empty without media or chapters), read on demand; `sourceId` tells which source they belong to. `playback.read`. */
|
|
5190
5250
|
chapters(): Promise<{
|
|
@@ -5226,7 +5286,7 @@ The core's basic playback actions (menu commands owned by the player).
|
|
|
5226
5286
|
| `play-pause` | Space | pause / resume, replay after the end |
|
|
5227
5287
|
| `previous` / `next` | PageUp, Mouse:X1 / PageDown, Mouse:X2 | ask the sequence provider |
|
|
5228
5288
|
| `frame-back` / `frame-forward` | D / F | `player.step("frame", …)` |
|
|
5229
|
-
| `seek-backward` / `seek-forward` | ← / → | relative seek by `setStepSeek` seconds |
|
|
5289
|
+
| `seek-backward` / `seek-forward` | ← / → | relative seek by `setStepSeek` seconds (or `host.run`'s `seconds`), exact or to keyframes as `setStepSeek` says |
|
|
5230
5290
|
| `rate-normal`, `rate-down`, `rate-up` | Z, X, C | 1×, ±0.1 within 0.25–4 |
|
|
5231
5291
|
| `volume-up` / `volume-down` | ↑ / ↓, wheel | ±5 (`volume-up` stops at 100) |
|
|
5232
5292
|
| `mute` | M | toggle mute |
|
|
@@ -5252,6 +5312,23 @@ interface Host {
|
|
|
5252
5312
|
* Prefer this over reimplementing playback buttons.
|
|
5253
5313
|
*/
|
|
5254
5314
|
run(action: HostAction): Promise<void>;
|
|
5315
|
+
/**
|
|
5316
|
+
* One step seek of `seconds` (0.1–3600 in tenths) instead of the
|
|
5317
|
+
* Player.setStepSeek step: the same checks, mode (exact or
|
|
5318
|
+
* keyframes), accumulation and on-screen text as ← / →. Use it for more
|
|
5319
|
+
* seek steps of your own (Ctrl+→ and the like) so that they add up with
|
|
5320
|
+
* the core's and land the same way.
|
|
5321
|
+
*
|
|
5322
|
+
* In keyframe mode it resolves once the seek has landed (so
|
|
5323
|
+
* `player.state.position` is current after the `await`); presses that add
|
|
5324
|
+
* up resolve together, the last with the text. In exact mode it resolves
|
|
5325
|
+
* once the seek is submitted, as before. `invalid` for `seconds` out of
|
|
5326
|
+
* range.
|
|
5327
|
+
* @player 0.5.1 (set `"minPlayerVersion": "0.5.1"`: older players ignore `seconds` and seek by the `setStepSeek` step)
|
|
5328
|
+
*/
|
|
5329
|
+
run(action: "seek-backward" | "seek-forward", options: {
|
|
5330
|
+
seconds: number;
|
|
5331
|
+
}): Promise<void>;
|
|
5255
5332
|
}
|
|
5256
5333
|
```
|
|
5257
5334
|
|
|
@@ -6092,6 +6169,23 @@ interface Packages {
|
|
|
6092
6169
|
* 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. `unsupported` to disable a built-in (PluginInfo.builtin): users manage third-party plugins only (players released with SDK 1.5.18 on; older ones disabled built-ins too).
|
|
6093
6170
|
*/
|
|
6094
6171
|
setEnabled(id: string, enabled: boolean): Promise<void>;
|
|
6172
|
+
/**
|
|
6173
|
+
* Restart a plugin (`plugins.manage`): stop it and start it again from the
|
|
6174
|
+
* same package with the same data directory, for example to recover one
|
|
6175
|
+
* that misbehaves. Built-ins included. A stopped or failed plugin is just
|
|
6176
|
+
* started. The disabled flag is never written, so a reload never leaves
|
|
6177
|
+
* a plugin disabled.
|
|
6178
|
+
*
|
|
6179
|
+
* Resolves once the plugin is stopped and its start is scheduled; the
|
|
6180
|
+
* player starts it as soon as the old process is gone (at most 20 s).
|
|
6181
|
+
* Follow it with Packages.onChange: `starting`, then `running`,
|
|
6182
|
+
* or `failed` with the reason.
|
|
6183
|
+
*
|
|
6184
|
+
* `invalid` for oneself or a disabled plugin (enable it instead),
|
|
6185
|
+
* `missing` unknown, `busy` while it is being installed or reloaded.
|
|
6186
|
+
* @player 0.5.1; older players reject it as an unknown request (`unsupported`).
|
|
6187
|
+
*/
|
|
6188
|
+
reload(id: string): Promise<void>;
|
|
6095
6189
|
/**
|
|
6096
6190
|
* 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.
|
|
6097
6191
|
*/
|
|
@@ -6991,12 +7085,16 @@ class TestHost implements Transport {
|
|
|
6991
7085
|
kind: string;
|
|
6992
7086
|
title?: string | null;
|
|
6993
7087
|
}[]): void;
|
|
6994
|
-
/**
|
|
7088
|
+
/**
|
|
7089
|
+
* Runtime images written to views (`plugin.ui.image`, `plugin.ui.remoteImage`), whole values and (SDK 1.5.19) images nested in rows, newest last. The SDK refuses images of released scopes before anything is sent. The test host does not read the files, so it does not check the player's per-view budget (`IMAGE_LIMITS.viewBytes`).
|
|
7090
|
+
*/
|
|
6995
7091
|
readonly images: {
|
|
6996
7092
|
/** The image file's path, as given to `ui.image`. */
|
|
6997
7093
|
path: string;
|
|
6998
7094
|
/** The SDK's reference number for that `ImageRef`. */
|
|
6999
7095
|
ref: number;
|
|
7096
|
+
/** Its `maxSide` option, when given. */
|
|
7097
|
+
maxSide?: number;
|
|
7000
7098
|
}[];
|
|
7001
7099
|
/**
|
|
7002
7100
|
* The file an image property shows, or `null` when the value is not a runtime image. View properties hold images in their wire form; this reads the path back.
|
|
@@ -7317,6 +7415,25 @@ class TestHost implements Transport {
|
|
|
7317
7415
|
constructor();
|
|
7318
7416
|
/** The `player.setStepSeek` value in effect (default 5). */
|
|
7319
7417
|
stepSeek: number;
|
|
7418
|
+
/** The `player.setStepSeek` `keyframes` in effect (default `false`, SDK 1.5.19). */
|
|
7419
|
+
stepSeekKeyframes: boolean;
|
|
7420
|
+
/**
|
|
7421
|
+
* Test data: the keyframe times (seconds, ascending) of the current source, for keyframe step seeks. `null` (the default): none modelled, and step seeks are exact even with `stepSeekKeyframes`.
|
|
7422
|
+
*/
|
|
7423
|
+
keyframes: number[] | null;
|
|
7424
|
+
/**
|
|
7425
|
+
* Every step seek the core ran (`seek-backward` / `seek-forward`, from a key, the menu or `host.run`), newest last: the step, whether it went to a keyframe, and where it landed.
|
|
7426
|
+
*/
|
|
7427
|
+
readonly coreSeeks: {
|
|
7428
|
+
/** `seek-backward` or `seek-forward`. */
|
|
7429
|
+
action: string;
|
|
7430
|
+
/** The step: `host.run`'s `seconds`, else `setStepSeek`'s. */
|
|
7431
|
+
seconds: number;
|
|
7432
|
+
/** It landed on a keyframe (`stepSeekKeyframes` and keyframes modelled). */
|
|
7433
|
+
keyframes: boolean;
|
|
7434
|
+
/** The new position. */
|
|
7435
|
+
landed: number;
|
|
7436
|
+
}[];
|
|
7320
7437
|
/** Every `player.step`, newest last. */
|
|
7321
7438
|
readonly steps: {
|
|
7322
7439
|
/** `"frame"` or `"keyframe"`. */
|
|
@@ -7430,7 +7547,7 @@ class TestHost implements Transport {
|
|
|
7430
7547
|
/** Every `packages.setEnabled` / `uninstall` / `install`, newest last. */
|
|
7431
7548
|
readonly packageCalls: {
|
|
7432
7549
|
/** Which call. */
|
|
7433
|
-
method: "setEnabled" | "uninstall" | "install";
|
|
7550
|
+
method: "setEnabled" | "reload" | "uninstall" | "install";
|
|
7434
7551
|
/** The target plugin id. */
|
|
7435
7552
|
id: string;
|
|
7436
7553
|
/** `setEnabled`'s value. */
|
|
@@ -7447,7 +7564,7 @@ class TestHost implements Transport {
|
|
|
7447
7564
|
*/
|
|
7448
7565
|
readonly candidates: Map<string, PackageManifest>;
|
|
7449
7566
|
/**
|
|
7450
|
-
* Remote
|
|
7567
|
+
* Remote images (`plugin.ui.markdown`, `plugin.ui.remoteImage`): address → a local PNG or JPEG file served for it, or `null` for a failing download. Nothing is fetched from the network in tests; unknown addresses fail.
|
|
7451
7568
|
*/
|
|
7452
7569
|
readonly remoteImages: Map<string, string | null>;
|
|
7453
7570
|
/**
|
|
@@ -7876,6 +7993,25 @@ const UI_VALUE_LIMITS: {
|
|
|
7876
7993
|
};
|
|
7877
7994
|
```
|
|
7878
7995
|
|
|
7996
|
+
### IMAGE_LIMITS
|
|
7997
|
+
|
|
7998
|
+
The player's runtime image limits (`host/src/ui_image.rs`): a file's
|
|
7999
|
+
bytes and sides, the decoded pixels each plugin caches, and (SDK 1.5.19,
|
|
8000
|
+
player 0.5.1) the decoded pixels the nested images of one view may show.
|
|
8001
|
+
|
|
8002
|
+
```ts
|
|
8003
|
+
const IMAGE_LIMITS: Readonly<{
|
|
8004
|
+
/** The largest image file the player reads, in bytes. */
|
|
8005
|
+
fileBytes: number;
|
|
8006
|
+
/** The longest side, in pixels, the player accepts for an image file. */
|
|
8007
|
+
side: 4096;
|
|
8008
|
+
/** The decoded pixel bytes the player caches for each plugin's images. */
|
|
8009
|
+
pluginBytes: number;
|
|
8010
|
+
/** The decoded pixel bytes the nested images of one view may show (player 0.5.1). */
|
|
8011
|
+
viewBytes: number;
|
|
8012
|
+
}>;
|
|
8013
|
+
```
|
|
8014
|
+
|
|
7879
8015
|
### HostError
|
|
7880
8016
|
|
|
7881
8017
|
A definite refusal from the player (or the plugin runner), with a stable
|
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.20: 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. Everything a plugin creates (commands, windows, panels, filters, listeners…) is a handle that is released automatically when the plugin stops. L<n> are line numbers in llms-full.txt, next to this file: every page, declaration and example.
|
|
4
4
|
|
|
5
5
|
**Rules**
|
|
6
6
|
|
|
@@ -33,7 +33,7 @@ my-plugin/
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
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:
|
|
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: L2120–2183.
|
|
37
37
|
|
|
38
38
|
**main.ts**
|
|
39
39
|
|
|
@@ -60,7 +60,7 @@ export default async function activate(plugin: Plugin) {
|
|
|
60
60
|
- `ui.window`: Windows.create
|
|
61
61
|
- `ui.mount`: Panels.mount/bottom/sidebar/backdrop, PanelSlot/Panel/BackdropSlot.onChange
|
|
62
62
|
- `ui.dialog`: Dialogs.confirm/openFile/openFiles/openDirectory/saveFile
|
|
63
|
-
- `plugins.manage`: Packages.validate/validateArchive/setEnabled/uninstall
|
|
63
|
+
- `plugins.manage`: Packages.validate/validateArchive/setEnabled/reload/uninstall
|
|
64
64
|
- `processing.video`: Plugin.video.filter/video.view/video.render (also `playback.read`)
|
|
65
65
|
- `processing.audio`: Plugin.audio.filter (also `playback.read`, `events`)
|
|
66
66
|
- `subtitles.read`: Subtitles.state/onChange/refresh
|
|
@@ -76,9 +76,9 @@ export default async function activate(plugin: Plugin) {
|
|
|
76
76
|
- `ui.settings`: Settings.page/show
|
|
77
77
|
- `ui.theme`: Appearance.set/setLanguage
|
|
78
78
|
- `secrets`: Secrets.get/set/delete
|
|
79
|
-
- No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme and packages.list. Details:
|
|
79
|
+
- No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme and packages.list. Details: L2184–2226.
|
|
80
80
|
|
|
81
|
-
**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` is a TestHost (an in-memory player): `host.setSource(…)`, `host.command(id).run()`, `host.press(key)`, `await host.settle()`, then assert on `host.osd`, `host.window(id).props`… Guide:
|
|
81
|
+
**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` is a TestHost (an in-memory player): `host.setSource(…)`, `host.command(id).run()`, `host.press(key)`, `await host.settle()`, then assert on `host.osd`, `host.window(id).props`… Guide: L1606–1771; TestHost: L6845.
|
|
82
82
|
|
|
83
83
|
**Command line**
|
|
84
84
|
|
|
@@ -106,39 +106,39 @@ export default async function activate(plugin: Plugin) {
|
|
|
106
106
|
- `limit`: A player-wide limit was reached, a property value is over the limits of PropValue
|
|
107
107
|
- `reserved`: The id is `vestra` or starts with `vestra.`
|
|
108
108
|
- `versionMismatch`: The package needs a newer player or another `apiVersion`
|
|
109
|
-
- Others: PluginError, llms-full.txt
|
|
109
|
+
- Others: PluginError, llms-full.txt L3122.
|
|
110
110
|
|
|
111
111
|
## Reference
|
|
112
112
|
|
|
113
113
|
- [llms-full.txt](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt), also node_modules/@vestra-player/sdk/llms-full.txt; the pages are on the [site](https://vestrasys.github.io/vestra-player-sdk/).
|
|
114
114
|
- Tutorials: Getting started L9–214
|
|
115
|
-
- Concepts: How a plugin runs L215–364; Commands, menus and key bindings L365–462; Playback state, controls and sources L463–
|
|
116
|
-
- How-to: Keep a slider responsive while dragging
|
|
117
|
-
- Guidelines: Interface guidelines
|
|
118
|
-
- Reference: Manifest
|
|
119
|
-
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html):
|
|
120
|
-
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html):
|
|
115
|
+
- Concepts: How a plugin runs L215–364; Commands, menus and key bindings L365–462; Playback state, controls and sources L463–602; Video and audio processing L603–680; Windows, panels, settings pages, dialogs and the OSD L681–968
|
|
116
|
+
- How-to: Keep a slider responsive while dragging L969–1143; Remember a window's state between runs L1144–1273; Translate a plugin L1274–1457; Migrate a plugin to English source text L1458–1605; Test a plugin L1606–1771; Publish a plugin L1772–1860; Migrating off package rollback (1.5.16, removed in 1.5.17) L1861–1936
|
|
117
|
+
- Guidelines: Interface guidelines L1937–2021; Menu guidelines L2022–2119
|
|
118
|
+
- Reference: Manifest L2120–2183; Capabilities L2184–2226; Limits L2227–2321; Commands, menus and bindings L2322–2789; Platforms L2790–2818; Theme L2819–3023; Command line L3024–3079
|
|
119
|
+
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L3080–6680
|
|
120
|
+
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L6681–8045
|
|
121
121
|
|
|
122
122
|
## API
|
|
123
123
|
|
|
124
124
|
Where each module of `plugin` (`plugin.<module>`) is declared:
|
|
125
125
|
|
|
126
|
-
- Plugin
|
|
127
|
-
- Commands
|
|
126
|
+
- Plugin L3314, Scope L3183, PluginError L3122, Disposable L3095
|
|
127
|
+
- Commands L3526; Windows L3756; Panels L4399; Dialogs L4685; Player L5133; video: VideoFilter L5433, VideoView L5496, RenderOptions L5538; audio: AudioFilter L5457; Subtitles L5636; media: MediaCapture L5796; Resolvers L5901; Packages L6143; Osd L5369; Host L5300; Clipboard L6275; Power L6295; Tools L6328; Storage L6371; System L6394; Secrets L6412; window: MainWindow L4522; App L4603; Bindings L6245; Ui L3631; Timeline L4479; Drops L4055; Appearance L4084; I18n L4226; Settings L4332.
|
|
128
128
|
|
|
129
129
|
## Examples
|
|
130
130
|
|
|
131
131
|
Tested plugins in [examples/](https://github.com/vestrasys/vestra-player-sdk/tree/main/examples):
|
|
132
132
|
|
|
133
|
-
- hello: The README Quick start: one menu command and an on-screen message.
|
|
134
|
-
- blur: A tool window with one slider that blurs the playing video.
|
|
135
|
-
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone.
|
|
136
|
-
- bookmark: A tool window bound to the playback state: remember the position and jump back to it.
|
|
137
|
-
- panel-menu: A sidebar panel with its own right-click menu.
|
|
138
|
-
- menus: Radio menu items, separator groups and a menu item whose title changes.
|
|
139
|
-
- theme-widgets: A tool window drawn with the player's theme and widgets.
|
|
140
|
-
- markdown: A window that shows a Markdown document.
|
|
141
|
-
- i18n: A plugin in the player's language: English source text, a Chinese translation.
|
|
133
|
+
- hello: The README Quick start: one menu command and an on-screen message. L8469–8558
|
|
134
|
+
- blur: A tool window with one slider that blurs the playing video. L8559–8820
|
|
135
|
+
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L8821–9153
|
|
136
|
+
- bookmark: A tool window bound to the playback state: remember the position and jump back to it. L9154–9338
|
|
137
|
+
- panel-menu: A sidebar panel with its own right-click menu. L9339–9544
|
|
138
|
+
- menus: Radio menu items, separator groups and a menu item whose title changes. L9545–9704
|
|
139
|
+
- theme-widgets: A tool window drawn with the player's theme and widgets. L9705–9868
|
|
140
|
+
- markdown: A window that shows a Markdown document. L9869–10063
|
|
141
|
+
- i18n: A plugin in the player's language: English source text, a Chinese translation. L10064–10231
|
|
142
142
|
|
|
143
143
|
## Optional
|
|
144
144
|
|