@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/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # Vestra Player SDK
2
2
 
3
- > @vestra-player/sdk 1.5.28: 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.
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: L2194–2260.
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 without one fails with `capability`)
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: L2261–2319.
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: L1658–1846; TestHost: L7056.
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 L3226.
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; the pages are on the [site](https://vestrasys.github.io/vestra-player-sdk/).
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–506; Playback state, controls and sources L507–652; Video and audio processing L653–731; Windows, panels, settings pages, dialogs and the OSD L732–1020
116
- - How-to: Keep a slider responsive while dragging L1021–1195; Remember a window's state between runs L1196–1325; Translate a plugin L1326–1509; Migrate a plugin to English source text L1510–1657; Test a plugin L1658–1846; Publish a plugin L1847–1935; Migrating off package rollback (1.5.16, removed in 1.5.17) L1936–2011
117
- - Guidelines: Interface guidelines L2012–2096; Menu guidelines L2097–2193
118
- - Reference: Manifest L2194–2260; Capabilities L2261–2319; Limits L2320–2424; Commands, menus and bindings L2425–2889; Platforms L2890–2918; Theme L2919–3125; Command line L3126–3183
119
- - [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L3184–6891
120
- - [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L6892–8297
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 module of `plugin` (`plugin.<module>`) is declared:
124
+ Where each `plugin.<module>` is declared:
125
125
 
126
- - Plugin L3418, Scope L3287, PluginError L3226, Disposable L3199
127
- - Commands L3630; Windows L3860; Panels L4503; Dialogs L4789; Player L5256; video: VideoFilter L5563, VideoView L5626, RenderOptions L5668; audio: AudioFilter L5587; Subtitles L5766; media: MediaCapture L5927; Resolvers L6032; Packages L6274; Osd L5499; Host L5430; Clipboard L6406; Power L6426; Tools L6459; Storage L6502; System L6589; Secrets L6607; window: MainWindow L4626; App L4707; Bindings L6376; Ui L3735; Timeline L4583; Drops L4159; Appearance L4188; I18n L4330; Settings L4436.
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. L8721–8810
134
- - blur: A tool window with one slider that blurs the playing video. L8811–9072
135
- - signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L9073–9405
136
- - bookmark: A tool window bound to the playback state: remember the position and jump back to it. L9406–9590
137
- - panel-menu: A sidebar panel with its own right-click menu. L9591–9796
138
- - menus: Radio menu items, separator groups and a menu item whose title changes. L9797–9956
139
- - theme-widgets: A tool window drawn with the player's theme and widgets. L9957–10120
140
- - markdown: A window that shows a Markdown document. L10121–10315
141
- - i18n: A plugin in the player's language: English source text, a Chinese translation. L10316–10483
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 in node_modules/@vestra-player/sdk/dist/plugin/types.d.ts (the API) and dist/plugin/testing.d.ts (TestHost); Slint library in slint/vestra/.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.5.28",
3
+ "version": "1.5.30",
4
4
  "description": "Plugin API types, test host and plugin CLI for Vestra Player (apiVersion vestra/1)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -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
+ }
@@ -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.