@vestra-player/sdk 1.5.45 → 1.5.47

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-full.txt CHANGED
@@ -1,4 +1,4 @@
1
- # @vestra-player/sdk 1.5.45: full reference
1
+ # @vestra-player/sdk 1.5.47: 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
 
@@ -2284,6 +2284,7 @@ The table lists the API whose documentation names a player version, newest last:
2284
2284
  | 0.5.20 | VideoShaders |
2285
2285
  | 0.5.21 | Scope.when, When, Bindings.onChange |
2286
2286
  | 0.5.25 | UpscalingReason.cause, UpscalingReason.plugins, UpscalingDecodingCause, UpscalingPlugin, UpscalingVideoSize, UpscalingState.video, UpscalingState.area, UpscalingState.gpu, UpscalingState.hwdecCurrent, UpscalingState.inChain, VideoUpscaling.onChange |
2287
+ | 0.6.0 | PropValue |
2287
2288
 
2288
2289
  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).
2289
2290
 
@@ -2352,7 +2353,7 @@ The check follows types, not names: `plugin.player.seek`, `const { player } = pl
2352
2353
 
2353
2354
  ## Reference: Limits
2354
2355
 
2355
- The player bounds what one request may cost it. The limits are guards against runaway plugins, not sizes to aim for: a plugin that needs to come close to one usually needs a different design (send the rows near the view, not the whole list). The SDK checks the same limits before it sends a request, so a plugin's own tests hit them too (TestHost enforces them). A name in code style is a constant you can import from `@vestra-player/sdk/testing`.
2356
+ The player bounds what one request may cost it. The limits are guards against runaway plugins, not sizes to aim for. Since player 0.6.0 a whole list fits (50,000 playlist rows): bind it and draw it with a Slint `ListView` (a long list should use one: a `for` builds every row). The SDK sends row patches, and an array property larger than one request in parts (SDK 1.5.46); only a property's top-level array without Markdown documents is split, so any other value, and each row, must fit in one request (a row of more than 512 KiB is refused with `limit`). The SDK checks the same limits before it sends a request, so a plugin's own tests hit them too (TestHost enforces them). A name in code style is a constant you can import from `@vestra-player/sdk/testing`.
2356
2357
 
2357
2358
  #### Commands
2358
2359
 
@@ -2380,10 +2381,10 @@ One value written to a window, panel or settings page property (View.set, View.b
2380
2381
  | Limit | Value | Meaning |
2381
2382
  | --- | --- | --- |
2382
2383
  | `UI_VALUE_LIMITS.depth` | 8 | Nesting depth; the value itself is depth 0. |
2383
- | `UI_VALUE_LIMITS.values` | 16384 | Values in all, counting every array, object, string, number, boolean and null, the value itself included; a Markdown document is one. |
2384
- | `UI_VALUE_LIMITS.arrayRows` | 4096 | Rows of one array. |
2384
+ | `UI_VALUE_LIMITS.values` | 1048576 | Values in all, counting every array, object, string, number, boolean and null, the value itself included; a Markdown document is one. |
2385
+ | `UI_VALUE_LIMITS.arrayRows` | 100000 | Rows of one array. |
2385
2386
  | `UI_VALUE_LIMITS.stringBytes` | 65536 (64 KiB) | UTF-8 bytes of one string or object field name. |
2386
- | `UI_VALUE_LIMITS.textBytes` | 1048576 (1 MiB) | UTF-8 bytes of all strings and field names together, the text of the value's Markdown documents included. |
2387
+ | `UI_VALUE_LIMITS.textBytes` | 33554432 (32 MiB) | UTF-8 bytes of all strings and field names together, the text of the value's Markdown documents included. |
2387
2388
 
2388
2389
  #### Text values
2389
2390
 
@@ -2629,8 +2630,8 @@ Every command the player (`host`) and its built-in plugins register when the pla
2629
2630
  | Copy to Clipboard ▸ Folder Path | | `vestra.playback/copy-folder` |
2630
2631
  | Copy to Clipboard ▸ Full Path | | `vestra.playback/copy-path` |
2631
2632
  | Playback ▸ Play/Pause | `Space`, `Mouse:LeftClick` | `host/play-pause` |
2632
- | Playback ▸ Previous | `PageUp`, `Mouse:X1` | `host/previous` |
2633
- | Playback ▸ Next | `PageDown`, `Mouse:X2` | `host/next` |
2633
+ | Playback ▸ Previous | `PageUp`, `Mouse:X2` | `host/previous` |
2634
+ | Playback ▸ Next | `PageDown`, `Mouse:X1` | `host/next` |
2634
2635
  | Playback ▸ Seek ▸ Previous Frame | `D` | `host/frame-back` |
2635
2636
  | Playback ▸ Seek ▸ Next Frame | `F` | `host/frame-forward` |
2636
2637
  | Playback ▸ Seek ▸ Previous Keyframe | `Ctrl+Shift+ArrowLeft` | `vestra.playback/keyframe-back` |
@@ -2856,7 +2857,7 @@ Every command the player (`host`) and its built-in plugins register when the pla
2856
2857
  | Audio ▸ Processing ▸ Crystalizer | `Shift+C` | `vestra.audio/audio.clarity` |
2857
2858
  | Audio ▸ Reset | | `vestra.audio/audio.reset` |
2858
2859
  | Audio ▸ Show Album Cover for Audio Only | | `vestra.visualizer/audio-cover` |
2859
- | Toggle Fullscreen | `Enter`, `Alt+Enter`, `F11` | `host/fullscreen` |
2860
+ | Toggle Fullscreen | `Escape` | `host/fullscreen` |
2860
2861
  | Screen ▸ Picture-in-Picture | | `vestra.window/pip` |
2861
2862
  | Screen ▸ Mini Size | ``` | `vestra.window/mini` |
2862
2863
  | Screen ▸ 0.5× | `1` | `vestra.window/size.0.5` |
@@ -2900,7 +2901,8 @@ Every command the player (`host`) and its built-in plugins register when the pla
2900
2901
  | Settings ▸ Language ▸ Español | | `vestra.preferences/language.es` |
2901
2902
  | About Vestra Player… | `F1` | `vestra.info/info.about` |
2902
2903
  | Quit | `Cmd+Q` | `host/quit` |
2903
- | Leave Fullscreen (not in the menu) | `Escape` | `host/exit-fullscreen` |
2904
+ | Enter Fullscreen (not in the menu) | | `host/enter-fullscreen` |
2905
+ | Leave Fullscreen (not in the menu) | | `host/exit-fullscreen` |
2904
2906
  | Toggle Sidebar (not in the menu) | | `host/sidebar` |
2905
2907
  | Brief Info (not in the menu) | `Shift+Tab` | `vestra.info/info.brief` |
2906
2908
  | Play (not in the menu) | `Enter`, `P` (panel focus) | `vestra.playlist/playlist.play` |
@@ -2978,7 +2980,7 @@ A menu item shows the first of its keyboard bindings that is in effect.
2978
2980
  | `digits` | `0`–`9` | Digit keys of the main keyboard: `0` to `9`. |
2979
2981
  | `functionKeys` | `F1`–`F24` | Function keys: `F1` to `F24`. |
2980
2982
  | `named` | `Space`, `Enter`, `Tab`, `Escape`, `Backspace`, `Delete`, `Insert`, `Home`, `End`, `PageUp`, `PageDown`, `ArrowLeft`, `ArrowRight`, `ArrowUp`, `ArrowDown`, `Plus`, `Numpad0`, `Numpad1`, `Numpad2`, `Numpad3`, `Numpad4`, `Numpad5`, `Numpad6`, `Numpad7`, `Numpad8`, `Numpad9`, `NumpadPlus`, `NumpadMinus`, `NumpadMultiply`, `NumpadDivide`, `NumpadEnter`, `NumpadDecimal` | Other named keys, matched by the physical key. `Plus` is the `+` key however it is typed; the `Numpad…` names are the numeric keypad only, never the main keyboard. |
2981
- | `mouse` | `Mouse:LeftClick`, `Mouse:LeftDoubleClick`, `Mouse:LeftDoubleClick:LeftHalf`, `Mouse:LeftDoubleClick:RightHalf`, `Mouse:MiddleClick`, `Mouse:X1`, `Mouse:X2`, `Mouse:WheelUp`, `Mouse:WheelDown`, `Mouse:WheelLeft`, `Mouse:WheelRight` | Mouse inputs on the video area. `:LeftHalf` and `:RightHalf` tell the halves of the video apart for a double click. |
2983
+ | `mouse` | `Mouse:LeftClick`, `Mouse:LeftDoubleClick`, `Mouse:LeftDoubleClick:LeftHalf`, `Mouse:LeftDoubleClick:RightHalf`, `Mouse:MiddleClick`, `Mouse:X1`, `Mouse:X2`, `Mouse:WheelUp`, `Mouse:WheelDown`, `Mouse:WheelLeft`, `Mouse:WheelRight` | Mouse inputs on the video area; the side buttons `Mouse:X1` (back) and `Mouse:X2` (forward) anywhere in the main window or the floating sidebar window, except while a menu is open (player 0.6.0). `:LeftHalf` and `:RightHalf` tell the halves of the video apart for a double click. |
2982
2984
 
2983
2985
  #### Core actions
2984
2986
 
@@ -2988,8 +2990,8 @@ The player's own playback commands, which plugin.host.run runs by id (capability
2988
2990
  | --- | --- | --- |
2989
2991
  | `stop` | Close | `F4` |
2990
2992
  | `play-pause` | Playback ▸ Play/Pause | `Space`, `Mouse:LeftClick` |
2991
- | `previous` | Playback ▸ Previous | `PageUp`, `Mouse:X1` |
2992
- | `next` | Playback ▸ Next | `PageDown`, `Mouse:X2` |
2993
+ | `previous` | Playback ▸ Previous | `PageUp`, `Mouse:X2` |
2994
+ | `next` | Playback ▸ Next | `PageDown`, `Mouse:X1` |
2993
2995
  | `frame-back` | Playback ▸ Seek ▸ Previous Frame | `D` |
2994
2996
  | `frame-forward` | Playback ▸ Seek ▸ Next Frame | `F` |
2995
2997
  | `seek-backward` | Playback ▸ Seek ▸ Back 5 s | `ArrowLeft` |
@@ -3000,9 +3002,9 @@ The player's own playback commands, which plugin.host.run runs by id (capability
3000
3002
  | `volume-up` | Audio ▸ Volume + | `ArrowUp`, `Mouse:WheelUp` |
3001
3003
  | `volume-down` | Audio ▸ Volume − | `ArrowDown`, `Mouse:WheelDown` |
3002
3004
  | `mute` | Audio ▸ Mute | `M` |
3003
- | `fullscreen` | Toggle Fullscreen | `Enter`, `Alt+Enter`, `F11` |
3005
+ | `fullscreen` | Toggle Fullscreen | `Escape` |
3004
3006
 
3005
- The player also owns **Toggle Fullscreen** (`host/fullscreen`), **Leave Fullscreen** (`host/exit-fullscreen`, `Escape`, only in fullscreen) and **Quit** (`host/quit`), and **Toggle Sidebar** (`host/sidebar`, player 0.5.10: the bottom bar's sidebar button, outside the menu, no default key); their keys are in Built-in commands.
3007
+ The player also owns **Toggle Fullscreen** (`host/fullscreen`, `Escape` from player 0.6.0; up to 0.5.x `Enter`, `Alt+Enter` and `F11`), **Enter Fullscreen** (`host/enter-fullscreen`, player 0.6.0: no default key, outside the menu, enabled only when windowed), **Leave Fullscreen** (`host/exit-fullscreen`: no default key from player 0.6.0, up to 0.5.x `Escape`; outside the menu, enabled only in fullscreen) and **Quit** (`host/quit`), and **Toggle Sidebar** (`host/sidebar`, player 0.5.10: the bottom bar's sidebar button, outside the menu, no default key); their keys are in Built-in commands.
3006
3008
 
3007
3009
  #### Keys the system takes first
3008
3010
 
@@ -4105,7 +4107,7 @@ flowchart TB
4105
4107
 
4106
4108
  - **Where bindings apply.** Bindings belong to the main window: they fire while it or the floating sidebar window has focus. They do **not** fire in tool windows or the Options window; keys there are the Slint file's own business (a `FocusScope`, a default button). While a menu or a system dialog is open, bindings pause.
4107
4109
  - **Conflicts are not errors.** A binding that loses is written to the player's log and takes effect by itself when the winner goes away (its plugin stops, the user rebinds it). Tests can check `host.conflicts` (TestHost.conflicts).
4108
- - **A disabled command lets its key go.** This is what makes context-dependent keys work: `Escape` bound to "Leave Fullscreen" does nothing outside fullscreen, so `Escape` reaches the focused control. Give `reason` to a command whose key should still be taken and explained while it is disabled.
4110
+ - **A disabled command lets its key go.** This is what makes context-dependent keys work: a command bound to `Delete` that is disabled while nothing is selected does nothing then, so `Delete` reaches the focused control (a text field deletes a character). Give `reason` to a command whose key should still be taken and explained while it is disabled.
4109
4111
  - **`repeat: true`** fires again on the keyboard's auto-repeat while the key is held; without it a binding fires once per press.
4110
4112
  - **Some keys never reach a binding.** The system takes some keys first, and the standard close keys close a tool window, the floating sidebar or the Options window before any binding sees them (in the main window they are ordinary keys). Keys the system takes first lists them; default bindings avoid them.
4111
4113
 
@@ -4118,7 +4120,7 @@ Key names describe keys, not characters, with two deliberate exceptions:
4118
4120
  - **Option combinations match the physical key**, so `Alt+O` fires for ⌥O although that key types `ø`, and dead keys (⌥E, ⌥N…) fire too. On layouts that need Option to type a symbol (German ⌥5 = ``, ⌥L = `@`), a binding for the typed symbol (`"["`, `"@"`) wins over one for the physical key (`Alt+5`).
4119
4121
  - **`Ctrl` is portable, `Cmd` is not.** On macOS `Ctrl+X` fires for both ⌃X and ⌘X, `Cmd+X` only for ⌘X. On Windows `Cmd` is the Windows logo key, which the system mostly keeps, so write `Ctrl+…` for a binding that works on both systems.
4120
4122
 
4121
- Mouse bindings apply only over the video area. `Mouse:LeftDoubleClick:LeftHalf` and `:RightHalf` win over the plain double click; wheel bindings count accumulated scroll steps. The right button is reserved for the context menu, and a left drag in window mode moves the window instead of clicking. A `Mouse:LeftClick` fires on release, except when the same modifiers also have a double-click binding and the click's command is not checkable: then the player waits the system's double-click interval to tell a click from a double click. (A checkable command such as play/pause runs at once; a double click runs it twice, which restores its state, and the double-click binding still fires.) The player's defaults (player 0.5.2): a left click on the video is Play/Pause and nothing is bound to a double click (up to 0.5.1 a double click was Toggle Fullscreen); a click whose command is disabled does nothing.
4123
+ Mouse bindings apply only over the video area, except the side buttons `Mouse:X1` (back) and `Mouse:X2` (forward), which fire anywhere in the main window or the floating sidebar window, except while a menu is open, as in browsers (player 0.6.0; before, only over the video area). `Mouse:LeftDoubleClick:LeftHalf` and `:RightHalf` win over the plain double click; wheel bindings count accumulated scroll steps. The right button is reserved for the context menu, and a left drag in window mode moves the window instead of clicking. A `Mouse:LeftClick` fires on release, except when the same modifiers also have a double-click binding and the click's command is not checkable: then the player waits the system's double-click interval to tell a click from a double click. (A checkable command such as play/pause runs at once; a double click runs it twice, which restores its state, and the double-click binding still fires.) The player's defaults (player 0.5.2): a left click on the video is Play/Pause and nothing is bound to a double click (up to 0.5.1 a double click was Toggle Fullscreen); a click whose command is disabled does nothing.
4122
4124
 
4123
4125
  ##### The user's bindings
4124
4126
 
@@ -4143,7 +4145,7 @@ plugin.commands.add({
4143
4145
 
4144
4146
  #### The player's own commands
4145
4147
 
4146
- The player registers some commands itself, with the owner `host`: **Toggle Fullscreen**, **Leave Fullscreen**, **Quit**, **Toggle Sidebar** (the bottom bar's sidebar button, player 0.5.10) and the core playback actions (play/pause, stop, previous/next, frame step, relative seek, speed, volume, mute). They exist whether or not any plugin runs, and the user rebinds them like any other command.
4148
+ The player registers some commands itself, with the owner `host`: **Toggle Fullscreen** (`Escape` from player 0.6.0), **Enter Fullscreen** and **Leave Fullscreen** (player 0.6.0: no default key, each enabled only where it acts), **Quit**, **Toggle Sidebar** (the bottom bar's sidebar button, player 0.5.10) and the core playback actions (play/pause, stop, previous/next, frame step, relative seek, speed, volume, mute). They exist whether or not any plugin runs, and the user rebinds them like any other command.
4147
4149
 
4148
4150
  A plugin button that does what a core action does should run that action with plugin.host.run (capability `commands`): it applies the same checks and shows the same on-screen text as the menu item and the key, so a bottom bar's play button and the Space key behave identically. The action ids, their menu places and default keys are in Reference: commands; what they do to playback is in Playback.
4149
4151
 
@@ -4649,6 +4651,8 @@ From player 0.6.0 and SDK 1.5.44, a changed array (a list's rows) is sent as the
4649
4651
  - **Your Slint code must not write into the rows of an array property** (`rows[i].selected = true` in a handler). A whole write used to overwrite such a change on the next update; a row patch touches only the rows whose value changed in your plugin, so the edited row keeps the Slint-side value until your value for that row changes. Send the event to the plugin with a callback and change the row there.
4650
4652
  - **`set()` with an unchanged array sends the whole array**, as `set()` always sends: use it to pull a list back to your rows. A bound array whose rows did not change sends nothing.
4651
4653
 
4654
+ To find the changed rows the SDK encodes every row of a bound array on each update pass, which in a list of tens of thousands of rows is most of a pass. From SDK 1.5.47 it skips that for rows it can prove unchanged: a **deep-frozen** row object (`Object.freeze` on the row and on every object and array inside it, plain objects and arrays only, no getters or own `toJSON`; image and document handles may sit inside: they are immutable, so they need no freezing) that the bind function returns again is encoded once and then taken from a cache kept by the row object. To use it in a long list, keep each row as the same frozen object while it does not change and make a new one when it does (memoize by the row's id and the fields it shows). Nothing else changes: rows that are not frozen, or that hold a mutable part, are encoded on every pass as before, so a plugin that changes its rows in place keeps working.
4655
+
4652
4656
  ##### Two-way controls
4653
4657
 
4654
4658
  A control whose value both the user and the plugin change (a slider, a switch, a text field, a combo box) needs a **two-way binding to an `in-out` property**:
@@ -5816,6 +5820,8 @@ Every SDK release's CHANGELOG entry opens with who must change and what happens
5816
5820
 
5817
5821
  | Release | Who must change | Guide |
5818
5822
  | --- | --- | --- |
5823
+ | [1.5.47](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md#1547) | **Nobody.** No changes to the TypeScript API, `apiVersion` stays `vestra/1`, no new capability, no player version needed. | — |
5824
+ | [1.5.46](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md#1546) | **Nobody.** No changes to the TypeScript API, `apiVersion` stays `vestra/1`, no new capability. | — |
5819
5825
  | [1.5.45](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md#1545) | **Nobody.** No changes to the TypeScript API, `apiVersion` stays `vestra/1`, no new capability, no player version needed. | — |
5820
5826
  | [1.5.44](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md#1544) | **Nobody.** No changes to the TypeScript API, `apiVersion` stays `vestra/1`, no new capability. | — |
5821
5827
  | [1.5.43](https://github.com/vestrasys/vestra-player-sdk/blob/main/CHANGELOG.md#1543) | **Nobody.** Additions only, `apiVersion` stays `vestra/1`, no new capability. | — |
@@ -6763,9 +6769,12 @@ interface CommandOptions {
6763
6769
  * `Home`, `End`, `PageUp`, `PageDown`, `ArrowLeft`/`Right`/`Up`/`Down`,
6764
6770
  * `Plus`, any other single symbol as typed (`">"`, not `"Shift+."`),
6765
6771
  * `Numpad0`–`Numpad9`, `NumpadPlus`, `NumpadMinus`, `NumpadMultiply`,
6766
- * `NumpadDivide`, `NumpadEnter`, `NumpadDecimal`, and the video-area mouse
6772
+ * `NumpadDivide`, `NumpadEnter`, `NumpadDecimal`, the video-area mouse
6767
6773
  * inputs `Mouse:LeftClick`, `Mouse:LeftDoubleClick[:LeftHalf|:RightHalf]`,
6768
- * `Mouse:MiddleClick`, `Mouse:X1`, `Mouse:X2`, `Mouse:WheelUp`/`Down`/`Left`/`Right`.
6774
+ * `Mouse:MiddleClick`, `Mouse:WheelUp`/`Down`/`Left`/`Right`, and the side
6775
+ * buttons `Mouse:X1` (back), `Mouse:X2` (forward), from 0.6.0 on anywhere
6776
+ * in the main window or the floating sidebar window, except while a menu
6777
+ * is open.
6769
6778
  *
6770
6779
  * Platforms: on macOS `Ctrl+X` fires for both ⌃X and ⌘X while `Cmd+X`
6771
6780
  * means ⌘X only; on Windows `Cmd` is the Windows logo key, so write
@@ -7102,20 +7111,23 @@ ImageOptions.maxSide for small pictures such as logos and
7102
7111
  thumbnails.
7103
7112
 
7104
7113
  Limits per value (`UI_VALUE_LIMITS` in `@vestra-player/sdk/testing`,
7105
- player 0.4.3; older players: 4096 values and 1024 rows): nesting depth 8,
7106
- 16384 values in total (every array, object, string, number, boolean and
7107
- null counts, the value itself included; a document or an image is one), 4096 rows
7108
- per array, 64 KiB per string or field name and 1 MiB of text in total,
7109
- field names and the text of its Markdown documents included (256 KB per
7110
- document). A list of rows with 8 fields is 9 values per row, so about
7111
- 1800 rows fit. The whole request must also fit the player's 1 MiB
7112
- message. A value over a limit is refused with code `limit` and the
7113
- property keeps what it showed (see View.set); `TestHost` refuses
7114
- it the same way.
7115
-
7116
- The limits bound the work of one write, not the size of your data: for
7117
- a list that can grow without bound, send the rows near the view and the
7118
- row count, and move that window as the user scrolls.
7114
+ player 0.6.0; players 0.4.3 to 0.5: 16384 values, 4096 rows, 1 MiB of
7115
+ text): nesting depth 8, 1,048,576 values in total (every array, object,
7116
+ string, number, boolean and null counts, the value itself included; a
7117
+ document or an image is one), 100,000 rows per array, 64 KiB per string
7118
+ or field name and 32 MiB of text in total, field names and the text of
7119
+ its Markdown documents included (256 KB per document). A list of rows
7120
+ with 13 fields is 14 values per row, so 50,000 such rows fit. An array
7121
+ property larger than one 1 MiB request is sent in parts (SDK 1.5.46, a
7122
+ player that takes row patches); only the top-level array is split, so
7123
+ any other value, and each row, must fit in one request (a row of more
7124
+ than 512 KiB is refused with `limit`). A value over a limit is refused
7125
+ with code
7126
+ `limit` and the property keeps what it showed (see View.set);
7127
+ `TestHost` refuses it the same way.
7128
+
7129
+ Bind a whole list and draw it with a Slint `ListView`, which builds only
7130
+ the rows on screen; the SDK sends what changed (row patches).
7119
7131
 
7120
7132
  ```ts
7121
7133
  type PropValue = PropData | ImageRef;
@@ -11247,13 +11259,13 @@ and the main window's fullscreen toggle.
11247
11259
  | --- | --- | --- |
11248
11260
  | `stop` | F4 | close the source |
11249
11261
  | `play-pause` | Space, a left click on the video (player 0.5.2) | pause / resume, replay after the end |
11250
- | `previous` / `next` | PageUp, Mouse:X1 / PageDown, Mouse:X2 | ask the sequence provider |
11262
+ | `previous` / `next` | PageUp, Mouse:X2 / PageDown, Mouse:X1 (from 0.6.0; up to 0.5.x X1 was previous and X2 next) | ask the sequence provider |
11251
11263
  | `frame-back` / `frame-forward` | D / F | `player.step("frame", …)` |
11252
11264
  | `seek-backward` / `seek-forward` | ← / → | relative seek by `setStepSeek` seconds (or `host.run`'s `seconds`), exact or to keyframes as `setStepSeek` says |
11253
11265
  | `rate-normal`, `rate-down`, `rate-up` | Z, X, C | 1×, ±0.1 within 0.25–4 |
11254
11266
  | `volume-up` / `volume-down` | ↑ / ↓, wheel | ±5 (`volume-up` stops at 100) |
11255
11267
  | `mute` | M | toggle mute |
11256
- | `fullscreen` | Enter, Alt+Enter, F11 | toggle the main window's fullscreen: enter it when windowed, leave it when fullscreen, as the Toggle Fullscreen command does (SDK 1.5.21, player 0.5.2; `unavailable` when the player has no window) |
11268
+ | `fullscreen` | Escape (from 0.6.0; up to 0.5.x Enter, Alt+Enter, F11) | toggle the main window's fullscreen: enter it when windowed, leave it when fullscreen, as the Toggle Fullscreen command does (SDK 1.5.21, player 0.5.2; `unavailable` when the player has no window) |
11257
11269
 
11258
11270
  In the binding overlay their keys are `host/<action>`. `fullscreen`
11259
11271
  changes no playback state: read the result from `window.state.fullscreen`
@@ -17620,7 +17632,9 @@ const BINDING_INPUTS: Readonly<{
17620
17632
  * Other named keys, matched by the physical key. `Plus` is the `+` key however it is typed; the `Numpad…` names are the numeric keypad only, never the main keyboard.
17621
17633
  */
17622
17634
  readonly named: readonly ["Space", "Enter", "Tab", "Escape", "Backspace", "Delete", "Insert", "Home", "End", "PageUp", "PageDown", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Plus", ...string[], "NumpadPlus", "NumpadMinus", "NumpadMultiply", "NumpadDivide", "NumpadEnter", "NumpadDecimal"];
17623
- /** Mouse inputs on the video area. `:LeftHalf` and `:RightHalf` tell the halves of the video apart for a double click. */
17635
+ /**
17636
+ * Mouse inputs on the video area; the side buttons `Mouse:X1` (back) and `Mouse:X2` (forward) anywhere in the main window or the floating sidebar window, except while a menu is open (player 0.6.0). `:LeftHalf` and `:RightHalf` tell the halves of the video apart for a double click.
17637
+ */
17624
17638
  readonly mouse: readonly ["Mouse:LeftClick", "Mouse:LeftDoubleClick", "Mouse:LeftDoubleClick:LeftHalf", "Mouse:LeftDoubleClick:RightHalf", "Mouse:MiddleClick", "Mouse:X1", "Mouse:X2", "Mouse:WheelUp", "Mouse:WheelDown", "Mouse:WheelLeft", "Mouse:WheelRight"];
17625
17639
  }>;
17626
17640
  ```
@@ -17854,53 +17868,41 @@ keeps what it showed) and reported to `Scope.onError`: a write by
17854
17868
  makes `Window.show` reject; a panel or settings page opens without it and
17855
17869
  the failure goes to the plugin's `onError`.
17856
17870
 
17857
- They bound the work one write costs the player's interface thread; they
17858
- are not meant as list sizes to aim for. A list that can grow without
17859
- bound (a playlist, a history) should send the rows near the view and say
17860
- how many there are, not the whole list.
17871
+ Since player 0.6.0 (SDK 1.5.46) they allow a whole list: a plugin binds
17872
+ all of its rows (a playlist of 50,000 entries fits) and the view draws
17873
+ them with a Slint `ListView`, which builds only the rows on screen. The
17874
+ SDK sends a changed array as row patches, and an array larger than one
17875
+ request (about 512 KiB of rows) as its first rows followed by `insert`
17876
+ patches of the rest; the player converts large writes off its interface
17877
+ thread. Before player 0.6.0 the limits were 4,096 rows, 16,384 values and
17878
+ 1 MiB of text, so a long list had to be sent as a window of rows.
17879
+
17880
+ In a row, `null` where the view declares an `image` shows no picture
17881
+ (player 0.6.0): rows without a thumbnail need no placeholder image.
17861
17882
 
17862
17883
  ```ts
17863
17884
  const UI_VALUE_LIMITS: {
17864
17885
  /** Nesting depth; the value itself is depth 0 (8). */
17865
17886
  readonly depth: 8;
17866
- /** Values in all, counting every array, object, string, number, boolean and null, the value itself included; a Markdown document is one (16384). */
17867
- readonly values: 16384;
17868
- /** Rows of one array (4096). */
17869
- readonly arrayRows: 4096;
17887
+ /**
17888
+ * Values in all, counting every array, object, string, number, boolean and null, the value itself included; a Markdown document is one (1,048,576; 16,384 before player 0.6.0).
17889
+ */
17890
+ readonly values: number;
17891
+ /** Rows of one array (100,000; 4,096 before player 0.6.0). */
17892
+ readonly arrayRows: 100000;
17870
17893
  /** UTF-8 bytes of one string or object field name (64 KiB). */
17871
17894
  readonly stringBytes: number;
17872
- /** UTF-8 bytes of all strings and field names together, the text of the value's Markdown documents included (1 MiB). */
17895
+ /** UTF-8 bytes of all strings and field names together, the text of the value's Markdown documents included (32 MiB; 1 MiB before player 0.6.0). */
17873
17896
  readonly textBytes: number;
17874
17897
  };
17875
17898
  ```
17876
17899
 
17877
- Example: Send a long playlist as a window of rows
17900
+ Example: Bind a whole list
17878
17901
 
17879
- A list view shows any number of entries while each write stays small:
17880
- the plugin sends only the rows around the scroll position plus the total,
17881
- and the view reports where it scrolled to. After the `scrolled` handler
17882
- returns, the SDK evaluates the `bind` function again and sends the new
17883
- window. Each row object and each of its fields count as one value toward
17884
- `values`, and so does the array holding them.
17885
- ```ts
17886
- import { UI_VALUE_LIMITS } from "@vestra-player/sdk/testing";
17902
+ The view draws every row with a `ListView`; the SDK sends what changed.
17887
17903
 
17888
- // 200 rows, or fewer if the limits were smaller: 2 fields per row make
17889
- // 3 values (the row and its fields), plus 1 for the array.
17890
- const size = Math.min(
17891
- 200,
17892
- UI_VALUE_LIMITS.arrayRows,
17893
- Math.floor((UI_VALUE_LIMITS.values - 1) / 3),
17894
- );
17895
- let first = 0;
17896
- list.bind(() => ({
17897
- total: entries.length,
17898
- rows: entries.slice(first, first + size),
17899
- }));
17900
- // The Slint view reports its first visible row; the window follows it.
17901
- list.on("scrolled", (row: number) => {
17902
- first = Math.max(0, row - Math.floor(size / 2));
17903
- });
17904
+ ```ts
17905
+ list.bind(() => ({ rows: entries.map((e) => ({ ...e, selected: false })) }));
17904
17906
  ```
17905
17907
 
17906
17908
  ### IMAGE_LIMITS
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # Vestra Player SDK
2
2
 
3
- > @vestra-player/sdk 1.5.45: 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 (the player's built-in plugins share one). 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.
3
+ > @vestra-player/sdk 1.5.47: 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 (the player's built-in plugins share one). 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: L2218–2291.
36
+ Fields: `id`, `version`, `apiVersion`, `entry`, `capabilities`, `name`, `author`, `punchline`, `description`, `tags`, `icon`, `readme`, `changelog`, `sourceUrl`, `license`, `minPlayerVersion`; unknown fields and capabilities are rejected. Rules and limits: L2218–2292.
37
37
 
38
38
  **main.ts**
39
39
 
@@ -78,9 +78,9 @@ export default async function activate(plugin: Plugin) {
78
78
  - `secrets`: Secrets.get/set/delete
79
79
  - `rendering.manage`: Rendering.setPreference/restartPlayer
80
80
  - `video.upscaling`: VideoUpscaling.state/set/onChange
81
- - No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme, packages.list and rendering.state. Details: L2292–2352.
81
+ - No capability: `tools`, `storage`, `system`, `app`, `ui` (images and Markdown), `i18n`, reading window.state, appearance.theme, packages.list and rendering.state. Details: L2293–2353.
82
82
 
83
- **Test**: `tests/*.test.ts` with `node:test`, run by `vestra-plugin test`. `startPlugin(activate, { directory: new URL("..", import.meta.url) })` from `@vestra-player/sdk/testing` returns `{ host, stop }`, `host` an in-memory player (TestHost): act (`host.command(id).run()`, `host.press(key)`), `await host.settle()`, assert on `host.osd`, `host.window(id).props`… Guide: L1861–2021; TestHost: L15479.
83
+ **Test**: `tests/*.test.ts` with `node:test`, run by `vestra-plugin test`. `startPlugin(activate, { directory: new URL("..", import.meta.url) })` from `@vestra-player/sdk/testing` returns `{ host, stop }`, `host` an in-memory player (TestHost): act (`host.command(id).run()`, `host.press(key)`), `await host.settle()`, assert on `host.osd`, `host.window(id).props`… Guide: L1861–2021; TestHost: L15491.
84
84
 
85
85
  **Command line**
86
86
 
@@ -108,40 +108,40 @@ export default async function activate(plugin: Plugin) {
108
108
  - `limit`: A player-wide limit was reached, a property value is over the limits of PropValue
109
109
  - `reserved`: The id is `vestra` or starts with `vestra.`
110
110
  - `versionMismatch`: The package needs a newer player
111
- - Others: PluginError, llms-full.txt L5952.
111
+ - Others: PluginError, llms-full.txt L5958.
112
112
 
113
113
  ## Reference
114
114
 
115
115
  - [llms-full.txt](https://vestrasys.github.io/vestra-player-sdk/llms-full.txt), also node_modules/@vestra-player/sdk/llms-full.txt; pages: [site](https://vestrasys.github.io/vestra-player-sdk/).
116
116
  - Tutorials: Getting started L9–134; Add a window L135–213; Add settings and translations L214–367; Test, check, pack and publish L368–424; Write your own blur kernel L425–685
117
117
  - How-to: Control playback L686–854; Store a plugin's data L855–961; Load subtitles from a plugin L962–1074; Keep a slider responsive while dragging L1075–1262; Remember a window's state between runs L1263–1414; Offer a GPU rendering switch L1415–1540; Keep a command's state without keeping the plugin running L1541–1697; Translate a plugin L1698–1860; Test a plugin L1861–2021; Publish a plugin L2022–2123; Troubleshooting L2124–2217
118
- - Reference: Manifest L2218–2291; Capabilities L2292–2352; Limits L2353–2498; Commands, menus and bindings L2499–3024; Platforms L3025–3055; Theme L3056–3405; Command line L3406–3463; Error codes L3464–3511; Translations L3512–3604; Test host L3605–3791
119
- - Explanation: How a plugin runs L3792–3994; Commands, menus and key bindings L3995–4149; Playback state, controls and sources L4150–4309; Video and audio processing L4310–4430; Windows, panels, settings pages, dialogs and the OSD L4431–4693; GPU and software rendering L4694–4710; The player's Rust core L4711–5052; How the player runs and talks to plugins L5053–5392
120
- - Guidelines: Plugin rules L5393–5404; Interface guidelines L5405–5521; Menu guidelines L5522–5580
121
- - Upgrading: Migrate a plugin to English source text L5581–5730; Migrating off package rollback (1.5.16, removed in 1.5.17) L5731–5808; Who must change, release by release L5809–5874
122
- - [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L5875–15152
123
- - [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L15153–18027
118
+ - Reference: Manifest L2218–2292; Capabilities L2293–2353; Limits L2354–2499; Commands, menus and bindings L2500–3026; Platforms L3027–3057; Theme L3058–3407; Command line L3408–3465; Error codes L3466–3513; Translations L3514–3606; Test host L3607–3793
119
+ - Explanation: How a plugin runs L3794–3996; Commands, menus and key bindings L3997–4151; Playback state, controls and sources L4152–4311; Video and audio processing L4312–4432; Windows, panels, settings pages, dialogs and the OSD L4433–4697; GPU and software rendering L4698–4714; The player's Rust core L4715–5056; How the player runs and talks to plugins L5057–5396
120
+ - Guidelines: Plugin rules L5397–5408; Interface guidelines L5409–5525; Menu guidelines L5526–5584
121
+ - Upgrading: Migrate a plugin to English source text L5585–5734; Migrating off package rollback (1.5.16, removed in 1.5.17) L5735–5812; Who must change, release by release L5813–5880
122
+ - [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L5881–15164
123
+ - [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html): L15165–18029
124
124
 
125
125
  ## API
126
126
 
127
127
  Where each `plugin.<module>` is declared:
128
128
 
129
- - Plugin L6291, Scope L6027, PluginError L5952, Disposable L5890
130
- - Commands L6881; When L6478; Windows L7824; Panels L9270; Dialogs L9940; Player L10681; video: VideoFilter L11561, VideoView L11661, RenderOptions L11748, VideoShaders L11826, VideoUpscaling L12184; audio: AudioFilter L11606; Subtitles L12420; media: MediaCapture L12824; Resolvers L13054; Packages L13456; Osd L11426; Host L11268; Clipboard L13785; Power L13872; Tools L13931; Storage L14083; System L14282; Secrets L14362; window: MainWindow L9587; App L9767; Rendering L14625; Bindings L13684; Ui L7170; Timeline L9499; Drops L8517; Appearance L8598; I18n L8831; Settings L9114.
129
+ - Plugin L6297, Scope L6033, PluginError L5958, Disposable L5896
130
+ - Commands L6890; When L6484; Windows L7836; Panels L9282; Dialogs L9952; Player L10693; video: VideoFilter L11573, VideoView L11673, RenderOptions L11760, VideoShaders L11838, VideoUpscaling L12196; audio: AudioFilter L11618; Subtitles L12432; media: MediaCapture L12836; Resolvers L13066; Packages L13468; Osd L11438; Host L11280; Clipboard L13797; Power L13884; Tools L13943; Storage L14095; System L14294; Secrets L14374; window: MainWindow L9599; App L9779; Rendering L14637; Bindings L13696; Ui L7182; Timeline L9511; Drops L8529; Appearance L8610; I18n L8843; Settings L9126.
131
131
 
132
132
  ## Examples
133
133
 
134
134
  Tested plugins in [examples/](https://github.com/vestrasys/vestra-player-sdk/tree/main/examples):
135
135
 
136
- - hello: The README Quick start: one menu command and an on-screen message. L18462–18557
137
- - blur: A tool window with one slider that blurs the playing video. L18558–18825
138
- - signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L18826–19164
139
- - bookmark: A tool window bound to the playback state: remember the position and jump back to it. L19165–19357
140
- - panel-menu: A sidebar panel with its own right-click menu. L19358–19572
141
- - menus: Radio menu items, separator groups and a menu item whose title changes. L19573–19738
142
- - theme-widgets: A tool window drawn with the player's theme and widgets. L19739–19908
143
- - markdown: A window that shows a Markdown document. L19909–20111
144
- - i18n: A plugin in the player's language: English source text, a Chinese translation. L20112–20285
136
+ - hello: The README Quick start: one menu command and an on-screen message. L18464–18559
137
+ - blur: A tool window with one slider that blurs the playing video. L18560–18827
138
+ - signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L18828–19166
139
+ - bookmark: A tool window bound to the playback state: remember the position and jump back to it. L19167–19359
140
+ - panel-menu: A sidebar panel with its own right-click menu. L19360–19574
141
+ - menus: Radio menu items, separator groups and a menu item whose title changes. L19575–19740
142
+ - theme-widgets: A tool window drawn with the player's theme and widgets. L19741–19910
143
+ - markdown: A window that shows a Markdown document. L19911–20113
144
+ - i18n: A plugin in the player's language: English source text, a Chinese translation. L20114–20287
145
145
 
146
146
  ## Optional
147
147
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.5.45",
3
+ "version": "1.5.47",
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": {