@vestra-player/sdk 1.5.28 → 1.5.30
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 +23 -0
- package/bin/vestra-plugin.mjs +103 -0
- package/dist/capabilities.d.ts +13 -3
- package/dist/capabilities.js +13 -3
- package/dist/commands.d.ts +94 -8
- package/dist/commands.js +124 -7
- package/dist/index.d.ts +6 -1
- package/dist/palettes.d.ts +16 -2
- package/dist/palettes.js +16 -2
- package/dist/player-runtime.d.ts +1 -1
- package/dist/player-runtime.js +1 -1
- package/dist/plugin/bindings.d.ts +27 -3
- package/dist/plugin/bindings.js +27 -3
- package/dist/plugin/commands.js +29 -2
- package/dist/plugin/osd.d.ts +13 -1
- package/dist/plugin/osd.js +13 -1
- package/dist/plugin/services.d.ts +46 -6
- package/dist/plugin/services.js +46 -6
- package/dist/plugin/testing.d.ts +403 -61
- package/dist/plugin/testing.js +408 -60
- package/dist/plugin/types.d.ts +860 -162
- package/dist/plugin/values.d.ts +27 -3
- package/dist/plugin/values.js +27 -3
- package/dist/processing.d.ts +16 -4
- package/dist/source-resolvers.d.ts +33 -8
- package/dist/subtitles.d.ts +19 -9
- package/dist/wire.d.ts +12 -3
- package/dist/wire.js +12 -3
- package/llms-full.txt +3503 -25
- package/llms.txt +26 -26
- package/package.json +1 -1
- package/slint/vestra/bar-buttons.slint +138 -0
- package/slint/vestra/icons.slint +4 -0
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.30: 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>: a line of llms-full.txt (next to this file), which has 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: L2231–2298.
|
|
37
37
|
|
|
38
38
|
**main.ts**
|
|
39
39
|
|
|
@@ -49,7 +49,7 @@ export default async function activate(plugin: Plugin) {
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
**Capabilities** (a call
|
|
52
|
+
**Capabilities** (without one a call fails: `capability`)
|
|
53
53
|
|
|
54
54
|
- `producer.av`: Player.openStream (also `playback.control`)
|
|
55
55
|
- `playback.read`: Player.state/refresh/stats/chapters/audioDevices, Timeline.marks
|
|
@@ -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: L2299–2357.
|
|
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: L1672–1860; TestHost: L9776.
|
|
82
82
|
|
|
83
83
|
**Command line**
|
|
84
84
|
|
|
@@ -106,40 +106,40 @@ 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 L3319.
|
|
110
110
|
|
|
111
111
|
## Reference
|
|
112
112
|
|
|
113
|
-
- [llms-full.txt](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt), also node_modules/@vestra-player/sdk/llms-full.txt;
|
|
113
|
+
- [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/).
|
|
114
114
|
- Tutorials: Getting started L9–237
|
|
115
|
-
- Concepts: How a plugin runs L238–408; Commands, menus and key bindings L409–
|
|
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 L238–408; Commands, menus and key bindings L409–520; Playback state, controls and sources L521–666; Video and audio processing L667–745; Windows, panels, settings pages, dialogs and the OSD L746–1034
|
|
116
|
+
- How-to: Keep a slider responsive while dragging L1035–1209; Remember a window's state between runs L1210–1339; Translate a plugin L1340–1523; Migrate a plugin to English source text L1524–1671; Test a plugin L1672–1860; Publish a plugin L1861–1949; Migrating off package rollback (1.5.16, removed in 1.5.17) L1950–2025
|
|
117
|
+
- Guidelines: Interface guidelines L2026–2133; Menu guidelines L2134–2230
|
|
118
|
+
- Reference: Manifest L2231–2298; Capabilities L2299–2357; Limits L2358–2472; Commands, menus and bindings L2473–2955; Platforms L2956–2984; Theme L2985–3206; Command line L3207–3264
|
|
119
|
+
- [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L3265–9552
|
|
120
|
+
- [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L9553–11761
|
|
121
121
|
|
|
122
122
|
## API
|
|
123
123
|
|
|
124
|
-
Where each
|
|
124
|
+
Where each `plugin.<module>` is declared:
|
|
125
125
|
|
|
126
|
-
- Plugin
|
|
127
|
-
- Commands
|
|
126
|
+
- Plugin L3568, Scope L3395, PluginError L3319, Disposable L3280
|
|
127
|
+
- Commands L3928; Windows L4838; Panels L6257; Dialogs L6718; Player L7328; video: VideoFilter L7818, VideoView L7904, RenderOptions L7958; audio: AudioFilter L7855; Subtitles L8071; media: MediaCapture L8257; Resolvers L8428; Packages L8711; Osd L7683; Host L7557; Clipboard L8870; Power L8905; Tools L8938; Storage L9000; System L9117; Secrets L9151; window: MainWindow L6512; App L6624; Bindings L8828; Ui L4190; Timeline L6469; Drops L5531; Appearance L5585; I18n L5818; Settings L6101.
|
|
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. L12192–12281
|
|
134
|
+
- blur: A tool window with one slider that blurs the playing video. L12282–12543
|
|
135
|
+
- signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L12544–12876
|
|
136
|
+
- bookmark: A tool window bound to the playback state: remember the position and jump back to it. L12877–13063
|
|
137
|
+
- panel-menu: A sidebar panel with its own right-click menu. L13064–13272
|
|
138
|
+
- menus: Radio menu items, separator groups and a menu item whose title changes. L13273–13432
|
|
139
|
+
- theme-widgets: A tool window drawn with the player's theme and widgets. L13433–13596
|
|
140
|
+
- markdown: A window that shows a Markdown document. L13597–13793
|
|
141
|
+
- i18n: A plugin in the player's language: English source text, a Chinese translation. L13794–13961
|
|
142
142
|
|
|
143
143
|
## Optional
|
|
144
144
|
|
|
145
|
-
- [Changelog](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md); full doc comments
|
|
145
|
+
- [Changelog](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md); full doc comments: node_modules/@vestra-player/sdk/dist/plugin/{types,testing}.d.ts; Slint library: slint/vestra/.
|
package/package.json
CHANGED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Command buttons of a bottom bar (player 0.5.10, SDK 1.5.29): the buttons
|
|
2
|
+
// that plugins' commands contribute (`commands.add({ button })`) and the
|
|
3
|
+
// player's sidebar toggle, rightmost. The player fills `BarButtonsHost` in
|
|
4
|
+
// every window it composes and runs the clicks; a bottom bar places one
|
|
5
|
+
// `BarButtons` in its own layout and gives it the width it can spare:
|
|
6
|
+
// import { BarButtons } from "@vestra/bar-buttons.slint";
|
|
7
|
+
// strip := BarButtons { x: parent.width - self.width - 4px; room: ...; }
|
|
8
|
+
// It shows as many 41×40 cells as fit in `room`, the strip as wide as the
|
|
9
|
+
// cells shown (`width`). Cells go from the strip's outer (left) end inward:
|
|
10
|
+
// of the plugins' buttons (ascending `order`, left to right) the lowest
|
|
11
|
+
// order goes first, and the sidebar toggle goes last. A bar without a `BarButtons` shows none of them (their menu
|
|
12
|
+
// entries stay; the player logs which buttons are hidden).
|
|
13
|
+
//
|
|
14
|
+
// The cells look like the bar's own icon buttons: a 32×32 plate on hover
|
|
15
|
+
// and press, the V-Line icon in the text colour (accent while a toggle is
|
|
16
|
+
// on), the bar's tooltip (ToolTipArea). They are persistent elements shown with
|
|
17
|
+
// `visible:`; nothing is created on hover or resize.
|
|
18
|
+
import { Theme } from "theme.slint";
|
|
19
|
+
import { Icon } from "icons.slint";
|
|
20
|
+
import { ToolTipArea } from "widgets.slint";
|
|
21
|
+
|
|
22
|
+
// One button as the player shows it.
|
|
23
|
+
export struct BarButtonItem {
|
|
24
|
+
// What a click runs (the player's own token; "" for no button).
|
|
25
|
+
token: string,
|
|
26
|
+
// A name of @vestra/icons.slint, or "" for `image`.
|
|
27
|
+
icon: string,
|
|
28
|
+
// The plugin's image (`plugin.ui.image`), drawn in the icon colour.
|
|
29
|
+
image: image,
|
|
30
|
+
// The command's title (the accessibility label).
|
|
31
|
+
label: string,
|
|
32
|
+
// The tooltip: the title and its key, the reason it is unavailable.
|
|
33
|
+
tip: string,
|
|
34
|
+
enabled: bool,
|
|
35
|
+
// The command has a checked state; `checked` draws the icon in the accent.
|
|
36
|
+
checkable: bool,
|
|
37
|
+
checked: bool,
|
|
38
|
+
// At half opacity: on, but not shown for want of room (the sidebar).
|
|
39
|
+
dimmed: bool,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Filled by the player; a bar reads it only through `BarButtons`.
|
|
43
|
+
export global BarButtonsHost {
|
|
44
|
+
// The plugins' buttons, left to right, at most 8.
|
|
45
|
+
in property <[BarButtonItem]> buttons;
|
|
46
|
+
// The sidebar toggle (`token` "" while there is none).
|
|
47
|
+
in property <BarButtonItem> toggle;
|
|
48
|
+
// Set when a `BarButtons` exists in this window.
|
|
49
|
+
in-out property <bool> placed;
|
|
50
|
+
// A click on the cell with this token.
|
|
51
|
+
callback clicked(string);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// One 41×40 cell (the bar's BarButton). `shown`: on screen; a hidden cell
|
|
55
|
+
// is not actionable from the accessibility tree either.
|
|
56
|
+
component Cell inherits Rectangle {
|
|
57
|
+
in property <BarButtonItem> item;
|
|
58
|
+
in property <bool> shown;
|
|
59
|
+
private property <bool> live: root.shown && root.item.enabled;
|
|
60
|
+
private property <brush> tint: !root.item.enabled ? Theme.icon-disabled
|
|
61
|
+
: root.item.checked ? (touch.pressed ? Theme.accent-press : Theme.accent)
|
|
62
|
+
: Theme.text;
|
|
63
|
+
width: 41px;
|
|
64
|
+
height: 40px;
|
|
65
|
+
visible: root.shown;
|
|
66
|
+
opacity: root.item.dimmed ? 0.5 : 1;
|
|
67
|
+
accessible-role: button;
|
|
68
|
+
accessible-label: root.item.label;
|
|
69
|
+
accessible-description: root.item.tip;
|
|
70
|
+
accessible-enabled: root.live;
|
|
71
|
+
accessible-checkable: root.item.checkable;
|
|
72
|
+
accessible-checked: root.item.checked;
|
|
73
|
+
accessible-action-default => { if root.live { BarButtonsHost.clicked(root.item.token); } }
|
|
74
|
+
Rectangle {
|
|
75
|
+
x: 4px;
|
|
76
|
+
y: 4px;
|
|
77
|
+
width: parent.width - 9px;
|
|
78
|
+
height: parent.height - 8px;
|
|
79
|
+
border-radius: Theme.radius-panel;
|
|
80
|
+
background: !root.live ? transparent
|
|
81
|
+
: touch.pressed ? Theme.press-bg
|
|
82
|
+
: touch.has-hover ? Theme.hover-bg : transparent;
|
|
83
|
+
}
|
|
84
|
+
Icon {
|
|
85
|
+
visible: root.item.icon != "";
|
|
86
|
+
x: (root.width - 1px - self.width) / 2;
|
|
87
|
+
y: (root.height - self.height) / 2;
|
|
88
|
+
name: root.item.icon;
|
|
89
|
+
color: root.tint;
|
|
90
|
+
}
|
|
91
|
+
// A plugin's image in the icon box (14×12), aspect kept, coloured like the icons.
|
|
92
|
+
Image {
|
|
93
|
+
visible: root.item.icon == "";
|
|
94
|
+
x: (root.width - 1px - self.width) / 2;
|
|
95
|
+
y: (root.height - self.height) / 2;
|
|
96
|
+
width: 14px;
|
|
97
|
+
height: 12px;
|
|
98
|
+
source: root.item.image;
|
|
99
|
+
image-fit: contain;
|
|
100
|
+
colorize: root.tint;
|
|
101
|
+
}
|
|
102
|
+
ToolTipArea {
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
text: root.shown ? root.item.tip : "";
|
|
106
|
+
touch := TouchArea {
|
|
107
|
+
enabled: root.live;
|
|
108
|
+
clicked => { BarButtonsHost.clicked(root.item.token); }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// The strip: place it at the bar's right end and give it the width you can
|
|
114
|
+
// spare; it is as wide as the cells it shows (read `width` to lay out the rest).
|
|
115
|
+
export component BarButtons {
|
|
116
|
+
// The width the bar can give the strip; the cells that fit show.
|
|
117
|
+
in property <length> room;
|
|
118
|
+
// The index (in the player's list, ascending order) of the leftmost
|
|
119
|
+
// plugin button shown; the ones before it are hidden for want of room.
|
|
120
|
+
out property <int> first-shown: BarButtonsHost.buttons.length - root.count;
|
|
121
|
+
// The cells that fit in `room`.
|
|
122
|
+
private property <int> fit: Math.max(0, Math.floor(root.room / 41px));
|
|
123
|
+
private property <bool> toggle: BarButtonsHost.toggle.token != "" && root.fit >= 1;
|
|
124
|
+
// The plugins' buttons shown: the highest orders, left of the toggle's cell.
|
|
125
|
+
private property <int> count: Math.max(0, Math.min(BarButtonsHost.buttons.length, root.fit - (root.toggle ? 1 : 0)));
|
|
126
|
+
width: (root.count + (root.toggle ? 1 : 0)) * 41px;
|
|
127
|
+
height: 40px;
|
|
128
|
+
init => { BarButtonsHost.placed = true; }
|
|
129
|
+
Cell { x: (0 - root.first-shown) * 41px; shown: 0 >= root.first-shown && 0 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[0]; }
|
|
130
|
+
Cell { x: (1 - root.first-shown) * 41px; shown: 1 >= root.first-shown && 1 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[1]; }
|
|
131
|
+
Cell { x: (2 - root.first-shown) * 41px; shown: 2 >= root.first-shown && 2 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[2]; }
|
|
132
|
+
Cell { x: (3 - root.first-shown) * 41px; shown: 3 >= root.first-shown && 3 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[3]; }
|
|
133
|
+
Cell { x: (4 - root.first-shown) * 41px; shown: 4 >= root.first-shown && 4 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[4]; }
|
|
134
|
+
Cell { x: (5 - root.first-shown) * 41px; shown: 5 >= root.first-shown && 5 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[5]; }
|
|
135
|
+
Cell { x: (6 - root.first-shown) * 41px; shown: 6 >= root.first-shown && 6 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[6]; }
|
|
136
|
+
Cell { x: (7 - root.first-shown) * 41px; shown: 7 >= root.first-shown && 7 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[7]; }
|
|
137
|
+
Cell { x: root.count * 41px; shown: root.toggle; item: BarButtonsHost.toggle; }
|
|
138
|
+
}
|
package/slint/vestra/icons.slint
CHANGED
|
@@ -48,6 +48,10 @@ export global Icons {
|
|
|
48
48
|
// Four corners pointing out (enter) or in (leave), the default 14 × 12 box.
|
|
49
49
|
if name == "fullscreen" { return "M 1.5 4.5 V 1.5 H 4.5 M 9.5 1.5 H 12.5 V 4.5 M 12.5 7.5 V 10.5 H 9.5 M 4.5 10.5 H 1.5 V 7.5"; }
|
|
50
50
|
if name == "exit-fullscreen" { return "M 4.5 1.5 V 4.5 H 1.5 M 9.5 1.5 V 4.5 H 12.5 M 12.5 7.5 H 9.5 V 10.5 M 1.5 7.5 H 4.5 V 10.5"; }
|
|
51
|
+
// A shopping bag (the plugin store) and a four-point sparkle with a
|
|
52
|
+
// small cross (AI), the default 14 × 12 box; bar buttons use them.
|
|
53
|
+
if name == "store" { return "M 2.5 4 H 11.5 L 10.9 9.6 Q 10.8 10.5 9.9 10.5 H 4.1 Q 3.2 10.5 3.1 9.6 Z M 5.2 4 V 3.3 A 1.8 1.8 0 0 1 8.8 3.3 V 4"; }
|
|
54
|
+
if name == "ai" { return "M 6 1.5 Q 6.6 5.4 10.5 6 Q 6.6 6.6 6 10.5 Q 5.4 6.6 1.5 6 Q 5.4 5.4 6 1.5 Z M 11.5 1.2 V 3.8 M 10.2 2.5 H 12.8"; }
|
|
51
55
|
return "";
|
|
52
56
|
}
|
|
53
57
|
// Line width.
|