@vestra-player/sdk 1.6.0 → 1.6.2

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 CHANGED
@@ -1,20 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.2
4
+
5
+ **Who must change: nobody, but check `TestHost` tests of a full sidebar or of `keepsRunning` with a background tab.** No change to the TypeScript API or the wire, `apiVersion` stays `vestra/1`, no new capability, no player version needed. `TestHost` follows player 0.7.3: it no longer refuses a ninth sidebar tab, and `keepsRunning` lists a sidebar panel only while its tab is the current tab, as `"its sidebar tab is the current tab"`. A test that expected `conflict` for a ninth tab, or `"a mounted panel"` for a sidebar panel, now fails.
6
+
7
+ - **Sidebar tabs without a limit** (player 0.7.3; the player's [sidebar tabs design](https://github.com/vestrasys/vestra-player/blob/main/doc/architecture/sidebar-tabs.md)). The sidebar takes any number of tabs: the strip shows the tabs that fit and a `»` menu at its end lists all of them, the current one checked. Players 0.4.x to 0.7.2 refused a ninth tab with `conflict` (「侧栏最多 8 个页签」); player 0.7.3 never refuses a sidebar mount for that. `Panel.ready`, [Windows, panels, settings pages, dialogs and the OSD](docs/explanation/ui.md#shared-space) and `TestHost` say so. The SDK's copy of the player's Chinese texts (`HOST_ZH_HANS`) drops "The sidebar holds at most {} tabs", which the player no longer has.
8
+ - **A background tab does not keep its plugin running** (player 0.7.3). The current tab keeps its plugin running as busy work; a sidebar panel never makes a plugin resident. A plugin whose sidebar panel is in a background tab, and that holds nothing else that keeps it running, goes to standby after the idle time like any idle plugin (stop reason `idle`); the player keeps its tab, with its title, in the strip and the `»` menu. Showing the tab starts the plugin again: `activate` runs and mounts the same panel (same file and component), which takes the tab over, and `Panel.ready` resolves again. The new process mounts with the properties its `activate` passes, so keep what the panel shows in session storage, the only state that survives standby, and restore it in `activate`. `Panel.state`, [Windows, panels…](docs/explanation/ui.md#panel), [How a plugin runs › Idle plugins are stopped](docs/explanation/plugins.md#idle-plugins-are-stopped) and [How the player runs and talks to plugins](docs/explanation/host-and-node.md) (the recorded `ui.mount`, the `panel_shown` wake) describe it. `TestHost.keepsRunning` lists `"its sidebar tab is the current tab"` while it is, and nothing for a background tab; `"a mounted panel"` is now for the bottom bar and the backdrop only.
9
+
10
+ ## 1.6.1
11
+
12
+ **Who must change: nobody.** Docs only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability.
13
+
14
+ - **Player versions corrected to 0.7.1.** Players 0.6.6 to 0.6.8 and 0.7.0 were internal builds that were never published; 0.7.1 is the first published player with the plugin supervisor, on-demand start for everyone and selectable Markdown. Every "player 0.6.6", "0.6.7", "0.6.8" and "planned for player 0.6.x" label now reads player 0.7.1, and `"minPlayerVersion": "0.6.8"` for selectable Markdown is now `"0.7.1"`. A plugin that set `"0.6.8"` keeps loading on 0.7.1 and later. The tables of [How the player runs and talks to plugins](docs/explanation/host-and-node.md), [How a plugin runs](docs/explanation/plugins.md#idle-plugins-are-stopped) and [Reference: limits › Plugin processes](docs/reference/limits.md#plugin-processes) show the 0.7.1 values in one column (start timeout 60 s and no start retry after it, 5 s stop grace, idle time 30 s, process budget, memory pressure). The entries of 1.5.58 and 1.6.0 are aligned the same way. Behaviour that player 0.6.4 already shipped (stop reasons, `InstallOptions.enabled`) is no longer called planned.
15
+ - **Player release version** ([Reference: manifest › Player versions](docs/reference/manifest.md#player-versions), `AppInfo.version`, `minPlayerVersion`). From player 0.7.1, `plugin.app.version` and the version `minPlayerVersion` is compared with are the player release version, which can differ from the host binary version. Plugins compare against the release version.
16
+ - **Windows GPU rendering** ([Reference: platforms](docs/reference/platforms.md), [Offer a GPU rendering switch](docs/how-to/gpu-rendering.md)). Windows has a GPU renderer since player 0.5.14 (Direct3D 12), experimental and off by default: **Video ▸ GPU Rendering (Experimental)** or `VESTRA_RENDER=gpu` turns it on. Software (CPU) mode, the default there, cannot run render options or plugin shaders (`unsupported`); platforms lists plugin shaders in their own row.
17
+ - **The `lut3d` `.cube` format** (`VideoNode`, [Video and audio processing](docs/explanation/processing.md)). FFmpeg's `.cube` reader (`parse_cube` in `libavfilter/vf_lut3d.c`) reads the table: `LUT_3D_SIZE N`, optional `TITLE` and `DOMAIN_MIN`/`DOMAIN_MAX`, then N³ lines `r g b`, red changing fastest. Lines before `LUT_3D_SIZE` are skipped. Any other keyword after it, such as `MIN` or `MAX`, makes FFmpeg refuse the file, and the chain fails with "error running command (-12)". The player checks only the header.
18
+
3
19
  ## 1.6.0
4
20
 
5
- **Who must change: nobody.** No change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability. New since 1.5.58 for plugin authors: Markdown the user can select and copy (`selectable` on `MarkdownView` and `MarkdownBlocks`, `plain` and `links` on `MarkdownBlock`, in the SDK's copy of the player's `@vestra/markdown.slint`; a plugin that uses them sets `"minPlayerVersion": "0.6.8"`), and, from player 0.6.7, plugins started on demand by default: a plugin starts on its first use and is stopped when idle, so `activate` can run many times and must never wait for its own commands or views (see 1.5.58). This is a minor release because it adds backward-compatible API and marks that milestone; nothing is removed or changed, and a plugin built with 1.5.x keeps working as it is.
21
+ **Who must change: nobody.** No change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability. New since 1.5.58 for plugin authors: Markdown the user can select and copy (`selectable` on `MarkdownView` and `MarkdownBlocks`, `plain` and `links` on `MarkdownBlock`, in the SDK's copy of the player's `@vestra/markdown.slint`; a plugin that uses them sets `"minPlayerVersion": "0.7.1"`), and, from player 0.7.1, plugins started on demand by default: a plugin starts on its first use and is stopped when idle, so `activate` can run many times and must never wait for its own commands or views (see 1.5.58). This is a minor release because it adds backward-compatible API and marks that milestone; nothing is removed or changed, and a plugin built with 1.5.x keeps working as it is.
6
22
 
7
- - **Selectable Markdown** (player 0.6.8; the SDK's `slint/vestra/markdown.slint` is synced with the player's). `MarkdownView` and `MarkdownBlocks` take `in property <bool> selectable: false`. With `true`, a paragraph, heading, list item or quote without links is shown as its plain text in a read-only selectable text field (right-click Copy / Select All, where Copy with nothing selected copies the whole block; Ctrl+C / Ctrl+A; each field is a Tab stop); a block with links keeps its clickable links, and its right-click menu copies it as plain text with each address after its link text, `text (url)`, plus Copy Link when it has one link. Code blocks are always selectable, whatever `selectable` says (in player 0.6.8 this applies to every plugin's Markdown). A selection stays inside one block and is lost when its row scrolls out of a `MarkdownView`. `MarkdownBlock` gains `plain: string` (the block as plain text) and `links: [string]` (its link addresses). Older players do not have the property: set `"minPlayerVersion": "0.6.8"` before using it. See [Reference: theme › Markdown](docs/reference/theme.md#markdown).
8
- - **Start retries corrected** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md#the-start-deadline), [Reference: limits](docs/reference/limits.md#plugin-processes), [How a plugin runs](docs/explanation/plugins.md#restarts-activate-can-run-more-than-once)). 1.5.58 said a start that is not ready within the start timeout is tried up to three more times. That was player 0.6.6; from player 0.6.7 a timed-out start gets one try (60 s) and is not retried, and only a process that cannot be created is tried again (about 250 ms, 500 ms and 1 s apart).
23
+ _Player versions aligned in 1.6.1: players 0.6.6 to 0.6.8 and 0.7.0 were internal builds, never published; 0.7.1 is the first published player with these features._
24
+
25
+ - **Selectable Markdown** (player 0.7.1; the SDK's `slint/vestra/markdown.slint` is synced with the player's). `MarkdownView` and `MarkdownBlocks` take `in property <bool> selectable: false`. With `true`, a paragraph, heading, list item or quote without links is shown as its plain text in a read-only selectable text field (right-click Copy / Select All, where Copy with nothing selected copies the whole block; Ctrl+C / Ctrl+A; each field is a Tab stop); a block with links keeps its clickable links, and its right-click menu copies it as plain text with each address after its link text, `text (url)`, plus Copy Link when it has one link. Code blocks are always selectable, whatever `selectable` says (in player 0.7.1 this applies to every plugin's Markdown). A selection stays inside one block and is lost when its row scrolls out of a `MarkdownView`. `MarkdownBlock` gains `plain: string` (the block as plain text) and `links: [string]` (its link addresses). Older players do not have the property: set `"minPlayerVersion": "0.7.1"` before using it. See [Reference: theme › Markdown](docs/reference/theme.md#markdown).
26
+ - **Start retries corrected** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md#the-start-deadline), [Reference: limits](docs/reference/limits.md#plugin-processes), [How a plugin runs](docs/explanation/plugins.md#restarts-activate-can-run-more-than-once)). 1.5.58 said a start that is not ready within the start timeout is tried up to three more times. That was the internal build 0.6.6; from player 0.7.1 a timed-out start gets one try (60 s) and is not retried, and only a process that cannot be created is tried again (about 250 ms, 500 ms and 1 s apart).
9
27
 
10
28
  ## 1.5.58
11
29
 
12
- **Who must change: nobody.** Documentation only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability, no player version needed. Plugin authors should read what the player's new plugin supervisor does with their plugin (player 0.6.6, and the defaults planned for 0.6.7), and check that `activate` never waits for its own commands or views.
30
+ **Who must change: nobody.** Documentation only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability, no player version needed. Plugin authors should read what the player's new plugin supervisor does with their plugin (written for the internal build 0.6.6 and the defaults planned for 0.6.7; player 0.7.1 is the first published player with it, with the 0.6.7 defaults), and check that `activate` never waits for its own commands or views.
31
+
32
+ _Player versions aligned in 1.6.1: players 0.6.6 to 0.6.8 and 0.7.0 were internal builds, never published; 0.7.1 is the first published player with these features._
13
33
 
14
- - **The plugin supervisor, as a plugin sees it** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md), [How a plugin runs](docs/explanation/plugins.md)). Player 0.6.6: a failed start is tried up to three more times; a built-in that crashes starts again by itself after 3 s, 6 s…; the fifth crash within 10 minutes stops a plugin until it is reloaded; an own process's JavaScript heap is capped at 512 MB (V8's heap only, not `Buffer` contents or addons), and passing it ends the process with "<name> ran out of memory"; a process that ended by itself gets no `runtime.stop`; without on-demand start a third-party plugin is listed as failed on its first crash, as before; at quit every plugin is stopped at once with 1 s in all; and two processes of one plugin never use its data directory at the same time. With on-demand start (lazy activation, `VESTRA_LAZY=1` in 0.6.6): a crashed plugin keeps its entries, shown disabled with the reason during a pause of 1 s, 2 s, 4 s…, and starts again on its next use (a resident plugin by itself); third-party plugins start a few at a time, clicks first; every start holds its clicks, resolutions, drops and view callbacks until `runtime.ready` (so an `activate` that awaits its own command or view callback waits until the start timeout); at most 64 are held per plugin, and one that cannot be taken is answered ("<name> is busy", "… could not start", "… is disabled") instead of dropped; busy work (a `busy` command, a dialog, a settings page shown, a resolution) keeps a plugin running with no time limit, and its idle time counts from when the work ends. Planned for player 0.6.7: on-demand start for everyone; a process budget for the machine's memory and the system's memory pressure put idle plugins in standby early, with the stop reason `idle`; idle time 30 s, start timeout 60 s, 5 s grace for a disable, uninstall, reload, upgrade or standby, a 5-minute cap on a player request awaiting the plugin's reply (a resolution; declared busy work stays uncapped), and a resident plugin never goes to standby. The source excerpts of host code that no longer exists (the lazy-activation trigger list, the 15-second activation record, the 250 ms idle poll, the stop's 5 ms poll) are replaced by descriptions of the current behaviour.
15
- - **[Reference: limits › Plugin processes](docs/reference/limits.md#plugin-processes)**: heap cap, start timeout, retries, start limit, restart pauses, stop graces, quit, idle time, request timeout, start slots (`min(4, max(2, cores / 2))` plus a reserve for clicks), held triggers (64), waiting starts (256), the process budget (`clamp(physical MiB / 2 × 0.30 / 85, 3, 16)`) and the memory pressure thresholds (both planned for 0.6.7), for player 0.6.6 and as planned for 0.6.7.
16
- - **`StopReason`** lists when each reason comes with the supervisor: `quit` also after a lost GPU device, `disable` clears session storage, `idle` also for the process budget and memory pressure (planned for 0.6.7; never for a busy plugin), `failed` also for a start timeout (possibly while `activate` runs) and, planned for 0.6.7, an unanswered request; a crash or running out of memory is no stop at all. The stop reasons are no longer described as planned: they shipped in player 0.6.4. **`PluginInfo.process`** `"idle"` also covers the pause after a crash before a plugin starts again. `Plugin`, `DisposeInfo` and [Store a plugin's data](docs/how-to/store-data.md) give the new stop graces.
17
- - **`appearance.changed` says what changed** (player 0.6.6): `"changed": ["theme"]` or `["language"]` beside `theme` and `language`. This SDK does not read it yet; a later release uses it so that a plugin woken by a language change no longer hears its unchanged theme once.
34
+ - **The plugin supervisor, as a plugin sees it** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md), [How a plugin runs](docs/explanation/plugins.md)). The internal build 0.6.6: a failed start is tried up to three more times; a built-in that crashes starts again by itself after 3 s, 6 s…; the fifth crash within 10 minutes stops a plugin until it is reloaded; an own process's JavaScript heap is capped at 512 MB (V8's heap only, not `Buffer` contents or addons), and passing it ends the process with "<name> ran out of memory"; a process that ended by itself gets no `runtime.stop`; without on-demand start a third-party plugin is listed as failed on its first crash, as before; at quit every plugin is stopped at once with 1 s in all; and two processes of one plugin never use its data directory at the same time. With on-demand start (lazy activation, `VESTRA_LAZY=1` in 0.6.6): a crashed plugin keeps its entries, shown disabled with the reason during a pause of 1 s, 2 s, 4 s…, and starts again on its next use (a resident plugin by itself); third-party plugins start a few at a time, clicks first; every start holds its clicks, resolutions, drops and view callbacks until `runtime.ready` (so an `activate` that awaits its own command or view callback waits until the start timeout); at most 64 are held per plugin, and one that cannot be taken is answered ("<name> is busy", "… could not start", "… is disabled") instead of dropped; busy work (a `busy` command, a dialog, a settings page shown, a resolution) keeps a plugin running with no time limit, and its idle time counts from when the work ends. Player 0.7.1 (planned as 0.6.7): on-demand start for everyone; a process budget for the machine's memory and the system's memory pressure put idle plugins in standby early, with the stop reason `idle`; idle time 30 s, start timeout 60 s, 5 s grace for a disable, uninstall, reload, upgrade or standby, a 5-minute cap on a player request awaiting the plugin's reply (a resolution; declared busy work stays uncapped), and a resident plugin never goes to standby. The source excerpts of host code that no longer exists (the lazy-activation trigger list, the 15-second activation record, the 250 ms idle poll, the stop's 5 ms poll) are replaced by descriptions of the current behaviour.
35
+ - **[Reference: limits › Plugin processes](docs/reference/limits.md#plugin-processes)**: heap cap, start timeout, retries, start limit, restart pauses, stop graces, quit, idle time, request timeout, start slots (`min(4, max(2, cores / 2))` plus a reserve for clicks), held triggers (64), waiting starts (256), the process budget (`clamp(physical MiB / 2 × 0.30 / 85, 3, 16)`) and the memory pressure thresholds (both from player 0.7.1), for the internal build 0.6.6 and for 0.7.1 (planned as 0.6.7).
36
+ - **`StopReason`** lists when each reason comes with the supervisor: `quit` also after a lost GPU device, `disable` clears session storage, `idle` also for the process budget and memory pressure (player 0.7.1; never for a busy plugin), `failed` also for a start timeout (possibly while `activate` runs) and, from player 0.7.1, an unanswered request; a crash or running out of memory is no stop at all. The stop reasons are no longer described as planned: they shipped in player 0.6.4. **`PluginInfo.process`** `"idle"` also covers the pause after a crash before a plugin starts again. `Plugin`, `DisposeInfo` and [Store a plugin's data](docs/how-to/store-data.md) give the new stop graces.
37
+ - **`appearance.changed` says what changed** (player 0.7.1): `"changed": ["theme"]` or `["language"]` beside `theme` and `language`. This SDK does not read it yet; a later release uses it so that a plugin woken by a language change no longer hears its unchanged theme once.
18
38
 
19
39
  ## 1.5.57
20
40
 
Binary file
package/dist/i18n.js CHANGED
@@ -943,7 +943,6 @@ export const HOST_ZH_HANS = {
943
943
  sidebar: "侧栏",
944
944
  "video backdrop": "视频背景",
945
945
  "The {} is used by {}": "{}已被 {} 使用",
946
- "The sidebar holds at most {} tabs": "侧栏最多 {} 个页签",
947
946
  "{} is resolved by {}": "{} 已由 {} 解析",
948
947
  "File type .{}": "文件类型 .{}",
949
948
  "Not available in fullscreen": "全屏时不可用",
@@ -22,7 +22,7 @@ export interface PluginInstance {
22
22
  /**
23
23
  * Stop the plugin: dispose the root scope, then stop the runtime.
24
24
  * `info.reason` (SDK 1.5.54) is why: the runner passes `runtime.stop`'s
25
- * `data.reason` (planned for player 0.6.4), or `"host-lost"` when its input closed
25
+ * `data.reason` (player 0.6.4), or `"host-lost"` when its input closed
26
26
  * without a `runtime.stop`. It reaches `plugin.stopReason` and every
27
27
  * `onDispose` cleanup; a reason the SDK does not know reads as
28
28
  * `undefined`. A second call runs no cleanup again and keeps the first reason.
@@ -2451,7 +2451,7 @@ export declare class TestHost implements Transport {
2451
2451
  * adds or upgrades the entry in {@link TestHost.packages} following the
2452
2452
  * player's source rules: the same source upgrades, another source needs
2453
2453
  * `replace` (`conflict` otherwise), a built-in id is `unsupported`. As
2454
- * player 0.6.4 (planned), the installed entry's `state` follows
2454
+ * player 0.6.4 and later, the installed entry's `state` follows
2455
2455
  * {@link "@vestra-player/sdk"!InstallOptions.enabled}: a first install
2456
2456
  * runs, an update of a `disabled` entry stays `disabled` unless `enabled`
2457
2457
  * is `true`, and `enabled: false` installs it `disabled`. Set
@@ -2475,7 +2475,7 @@ export declare class TestHost implements Transport {
2475
2475
  readonly candidates: Map<string, PackageManifest>;
2476
2476
  /**
2477
2477
  * Which player's install rule `packages.install` plays. `true` (default,
2478
- * SDK 1.5.55): player 0.6.4 (planned), where an update or reinstall
2478
+ * SDK 1.5.55): player 0.6.4 and later, where an update or reinstall
2479
2479
  * keeps a `disabled` plugin disabled unless the plugin passes
2480
2480
  * {@link "@vestra-player/sdk"!InstallOptions.enabled}. `false`: players
2481
2481
  * up to 0.6.3, where every install runs the plugin and `enabled` is
@@ -2782,12 +2782,18 @@ export declare class TestHost implements Transport {
2782
2782
  close(): void;
2783
2783
  /**
2784
2784
  * Why the player would keep this plugin running while nothing uses it
2785
- * (lazy activation, player 0.5.21), one line per reason, as the player's
2786
- * log says it: an event it listens to that is not one the player wakes
2787
- * it for (with what listens and where it was added), its mounted panel,
2788
- * its open windows. Empty: the player may stop it while idle and start
2789
- * it again on its next use. Filter chains, streams, jobs and the like
2790
- * (which also keep a plugin running) are not listed.
2785
+ * (lazy activation, player 0.5.21), one line per reason: an event it
2786
+ * listens to that is not one the player wakes it for (with what listens
2787
+ * and where it was added), its panel in the bottom bar or the backdrop,
2788
+ * its open windows (these as the player's log says them), and, from
2789
+ * player 0.7.3, its sidebar tab while that is the current tab. The
2790
+ * player counts the current tab as busy work, not as something live: it
2791
+ * keeps the plugin running only while the tab is shown, and a sidebar
2792
+ * panel in a background tab is no reason at all (the plugin may go to
2793
+ * standby; showing the tab starts it again). Empty: the player may stop
2794
+ * it while idle and start it again on its next use. Filter chains,
2795
+ * streams, jobs and the like (which also keep a plugin running) are not
2796
+ * listed.
2791
2797
  *
2792
2798
  * @capability None.
2793
2799
  * @since 1.5.40
@@ -314,8 +314,6 @@ const TEST_ZH_HANS = {
314
314
  "External SRT": "外部 SRT",
315
315
  "External ASS": "外部 ASS",
316
316
  };
317
- /** The player's limit of sidebar tabs. */
318
- const MAX_SIDEBAR_TABS = 8;
319
317
  /**
320
318
  * The player's refusal of a declaration (commands.rs `CommandError`): code
321
319
  * `invalid`, `conflict` or `limit`, its message prefixed as the player's.
@@ -3100,7 +3098,7 @@ export class TestHost {
3100
3098
  * adds or upgrades the entry in {@link TestHost.packages} following the
3101
3099
  * player's source rules: the same source upgrades, another source needs
3102
3100
  * `replace` (`conflict` otherwise), a built-in id is `unsupported`. As
3103
- * player 0.6.4 (planned), the installed entry's `state` follows
3101
+ * player 0.6.4 and later, the installed entry's `state` follows
3104
3102
  * {@link "@vestra-player/sdk"!InstallOptions.enabled}: a first install
3105
3103
  * runs, an update of a `disabled` entry stays `disabled` unless `enabled`
3106
3104
  * is `true`, and `enabled: false` installs it `disabled`. Set
@@ -3124,7 +3122,7 @@ export class TestHost {
3124
3122
  candidates = new Map();
3125
3123
  /**
3126
3124
  * Which player's install rule `packages.install` plays. `true` (default,
3127
- * SDK 1.5.55): player 0.6.4 (planned), where an update or reinstall
3125
+ * SDK 1.5.55): player 0.6.4 and later, where an update or reinstall
3128
3126
  * keeps a `disabled` plugin disabled unless the plugin passes
3129
3127
  * {@link "@vestra-player/sdk"!InstallOptions.enabled}. `false`: players
3130
3128
  * up to 0.6.3, where every install runs the plugin and `enabled` is
@@ -3983,12 +3981,18 @@ export class TestHost {
3983
3981
  }
3984
3982
  /**
3985
3983
  * Why the player would keep this plugin running while nothing uses it
3986
- * (lazy activation, player 0.5.21), one line per reason, as the player's
3987
- * log says it: an event it listens to that is not one the player wakes
3988
- * it for (with what listens and where it was added), its mounted panel,
3989
- * its open windows. Empty: the player may stop it while idle and start
3990
- * it again on its next use. Filter chains, streams, jobs and the like
3991
- * (which also keep a plugin running) are not listed.
3984
+ * (lazy activation, player 0.5.21), one line per reason: an event it
3985
+ * listens to that is not one the player wakes it for (with what listens
3986
+ * and where it was added), its panel in the bottom bar or the backdrop,
3987
+ * its open windows (these as the player's log says them), and, from
3988
+ * player 0.7.3, its sidebar tab while that is the current tab. The
3989
+ * player counts the current tab as busy work, not as something live: it
3990
+ * keeps the plugin running only while the tab is shown, and a sidebar
3991
+ * panel in a background tab is no reason at all (the plugin may go to
3992
+ * standby; showing the tab starts it again). Empty: the player may stop
3993
+ * it while idle and start it again on its next use. Filter chains,
3994
+ * streams, jobs and the like (which also keep a plugin running) are not
3995
+ * listed.
3992
3996
  *
3993
3997
  * @capability None.
3994
3998
  * @since 1.5.40
@@ -4012,7 +4016,13 @@ export class TestHost {
4012
4016
  if (!WAKE_EVENTS.includes(event))
4013
4017
  for (const why of this.listeningWhy.get(event) ?? ["a listener"])
4014
4018
  reasons.push(`listens to ${event}: ${why}`);
4015
- if (this.panel)
4019
+ // A sidebar panel is never live (player 0.7.3): the current tab keeps
4020
+ // the plugin running as busy work, a background tab not at all.
4021
+ if (this.panel?.slot === "sidebar") {
4022
+ if (this.layout.sidebar?.owner === 1)
4023
+ reasons.push("its sidebar tab is the current tab");
4024
+ }
4025
+ else if (this.panel)
4016
4026
  reasons.push("a mounted panel");
4017
4027
  for (const [id, window] of this.windows)
4018
4028
  if (window.visible)
@@ -4234,8 +4244,8 @@ export class TestHost {
4234
4244
  "ui.mount": (p) => {
4235
4245
  if (this.panel)
4236
4246
  throw new HostError("conflict", "owner already mounted");
4237
- // Like the player: one panel in the bottom bar and the backdrop, tabs
4238
- // in the sidebar (up to 8).
4247
+ // Like the player: one panel in the bottom bar and the backdrop, any
4248
+ // number of tabs in the sidebar (player 0.7.3; 0.4.x to 0.7.2 took 8).
4239
4249
  const holder = p.slot === "backdrop"
4240
4250
  ? this.backdrop?.owner
4241
4251
  : p.slot === "bottom"
@@ -4246,11 +4256,6 @@ export class TestHost {
4246
4256
  this.#hostText(SLOT_LABELS[String(p.slot)]),
4247
4257
  String(holder),
4248
4258
  ]));
4249
- if (p.slot === "sidebar" &&
4250
- (this.layout.sidebar?.panels?.length ?? 0) >= MAX_SIDEBAR_TABS)
4251
- throw taken(this.#hostText("The sidebar holds at most {} tabs", [
4252
- MAX_SIDEBAR_TABS,
4253
- ]));
4254
4259
  const properties = this.#initialValues(this.#shownValues(p.properties));
4255
4260
  this.#seeImages(properties);
4256
4261
  this.#resetWrites("$mount");
@@ -421,7 +421,7 @@ export interface Scope extends Disposable {
421
421
  * The plugin writes its cache file at once when the player crashed or
422
422
  * was killed, instead of waiting for the next periodic save. The cleanup
423
423
  * may get a {@link DisposeInfo}: `stopping` says the plugin itself stops
424
- * (not a child scope), `reason` why (planned for player 0.6.4). Players
424
+ * (not a child scope), `reason` why (player 0.6.4). Players
425
425
  * whose SDK is older than 1.5.54 call the cleanup without an argument,
426
426
  * so read it with `?.`.
427
427
  * ```ts
@@ -524,9 +524,9 @@ export interface Scope extends Disposable {
524
524
  * (menus, windows, panels, filters, subtitle layers, snapshots, jobs,
525
525
  * resolvers, streams); pending requests then fail with `disabled` and the
526
526
  * root scope is disposed for local cleanup (timers, signals, sockets). A
527
- * process that has not exited after its grace is killed: 300 ms in player
528
- * 0.6.6 (2 s when it goes to standby), planned to be 5 s from player 0.6.7
529
- * (300 ms after a fault); at quit all plugins together get 1 s. Media the
527
+ * process that has not exited after its grace is killed: 5 s from player
528
+ * 0.7.1 (before it 300 ms; 300 ms after a fault); at quit all plugins
529
+ * together get 1 s. Media the
530
530
  * plugin opened with {@link Player.open} keeps playing.
531
531
  *
532
532
  * @example Write a minimal plugin with one menu item
@@ -591,7 +591,7 @@ export interface Plugin extends Scope {
591
591
  *
592
592
  * - `quit`: the player quits (or restarts after a lost GPU device). Every
593
593
  * plugin is stopped at the same time, with 1 s in all (300 ms after a
594
- * lost device; player 0.6.6).
594
+ * lost device; player 0.7.1).
595
595
  * - `disable`: the user, or a plugin with `plugins.manage`, switched the
596
596
  * plugin off. Its session storage is cleared.
597
597
  * - `uninstall`: the user uninstalls it.
@@ -604,25 +604,23 @@ export interface Plugin extends Scope {
604
604
  * its menu items, keys, settings pages, resolvers and drop targets stay,
605
605
  * and so does its session storage
606
606
  * ([Idle plugins](../../docs/explanation/plugins.md#idle-plugins-are-stopped)).
607
- * Only with on-demand start (lazy activation), off by default up to
608
- * player 0.6.6 (`VESTRA_LAZY=1` turns it on) and planned for everyone in
609
- * player 0.6.7. It comes after the idle time without use (60 s; 30 s
610
- * planned for 0.6.7), right after a first run that holds nothing live,
611
- * and when the player's limit on third-party processes or low system
612
- * memory puts an idle plugin in standby early (planned for 0.6.7). A busy
613
- * plugin never gets it; a resident one (it held something live when it
614
- * became ready) only after the idle time, and from player 0.6.7 (planned)
615
- * never.
607
+ * Only with on-demand start (lazy activation): on for everyone from
608
+ * player 0.7.1, off by default before it (`VESTRA_LAZY=1` turns it on).
609
+ * It comes after the idle time without use (30 s; 60 s before 0.7.1),
610
+ * right after a first run that holds nothing live, and, from player
611
+ * 0.7.1, when the player's limit on third-party processes or low system
612
+ * memory puts an idle plugin in standby early. A busy plugin never gets
613
+ * it; a resident one (it held something live when it became ready) never
614
+ * from player 0.7.1 (before it, after the idle time).
616
615
  * - `failed`: the player stops it for a fault it can still tell the plugin
617
616
  * about: a malformed request, an unreadable or oversized line, a start
618
- * that is not ready within the start timeout (15 s; 60 s planned for
619
- * player 0.6.7; the stop may come while `activate` still runs), an
620
- * uncaught exception the shared process attributes to this plugin, and,
621
- * planned for player 0.6.7, a request from the player (a resolution) it
622
- * leaves unanswered for 5 minutes. From player 0.6.6 the player may
623
- * start it again afterwards (a built-in or resident plugin by itself, a
624
- * plugin with on-demand start on its next use), until the fifth fault
625
- * within 10 minutes.
617
+ * that is not ready within the start timeout (60 s from player 0.7.1;
618
+ * the stop may come while `activate` still runs), an uncaught exception
619
+ * the shared process attributes to this plugin, and, from player 0.7.1,
620
+ * a request from the player (a resolution) it leaves unanswered for 5
621
+ * minutes. From player 0.7.1 the player may start it again afterwards (a
622
+ * built-in or resident plugin by itself, a plugin that has run before on
623
+ * its next use), until the fifth fault within 10 minutes.
626
624
  * - `host-lost`: the plugin's runner saw its pipe to the player close
627
625
  * without a stop: the player crashed or was killed. Requests are refused
628
626
  * with `disabled`; clean up locally only. Player 0.6.4 sends `quit` on a
@@ -634,7 +632,7 @@ export interface Plugin extends Scope {
634
632
  * own process is killed because its input queue is full or a write to it
635
633
  * failed, when its own process fails to activate (the runner exits without
636
634
  * cleaning up), when the process ended by itself (it crashed, or its
637
- * JavaScript heap passed the 512 MB cap of player 0.6.6 and V8 ended it:
635
+ * JavaScript heap passed the 512 MB cap of player 0.7.1 and V8 ended it:
638
636
  * "ran out of memory"), and when the shared runner is restarted as a whole
639
637
  * (a hang, a fault it cannot attribute, an unreadable line of its own, a
640
638
  * member's full input queue, the runner exiting): every member is killed
@@ -1773,7 +1771,7 @@ export interface Ui {
1773
1771
  * the list on every streamed chunk keeps the scroll position and costs
1774
1772
  * little.
1775
1773
  *
1776
- * From player 0.6.8 both views take `selectable: true` (default `false`):
1774
+ * From player 0.7.1 both views take `selectable: true` (default `false`):
1777
1775
  * the user can select and copy the text, one block at a time; blocks with
1778
1776
  * links keep their clickable links and copy as `text (url)`. Code blocks
1779
1777
  * are always selectable. `MarkdownBlock.plain` (the block as plain text)
@@ -2734,15 +2732,22 @@ export interface Panel extends View, Disposable {
2734
2732
  * A second sidebar panel is not refused: it resolves as another tab
2735
2733
  * (see {@link Panel.state}). Built-in plugins mount first at start-up,
2736
2734
  * so the playlist's tab is first and a built-in panel keeps its position.
2735
+ * Behaviour from player 0.7.3: the sidebar takes any number of tabs; the
2736
+ * strip shows the tabs that fit and a `»` menu lists all of them.
2737
+ * Players 0.4.x to 0.7.2 refused a ninth tab with `conflict`. A plugin
2738
+ * whose sidebar tab is in the background, and that holds nothing else
2739
+ * that keeps it running, goes to standby when idle; showing the tab
2740
+ * starts it again (see {@link Panel.state}).
2737
2741
  *
2738
2742
  * @throws `ui-prepare` (rejects) The Slint file does not compile, or a
2739
2743
  * bound property is not declared on the bridge global; `message` has the
2740
2744
  * diagnostics. (Players 0.4.0 and older also answer a taken bottom bar
2741
2745
  * or sidebar with it.)
2742
2746
  * @throws `conflict` (rejects) Another plugin's panel holds the bottom bar
2743
- * or the backdrop (shown, or being mounted), or the sidebar has all the
2744
- * tabs it takes (8); `message` names the position and the holder
2745
- * (「侧栏已被 vestra.playlist 使用」). Not an activation failure.
2747
+ * or the backdrop (shown, or being mounted); `message` names the
2748
+ * position and the holder (「底栏已被 vestra.playback 使用」). Not an
2749
+ * activation failure. Never for the sidebar (behaviour from player
2750
+ * 0.7.3); players 0.4.x to 0.7.2 also refused a ninth sidebar tab.
2746
2751
  * @throws `busy` (rejects) The player is still preparing this plugin's
2747
2752
  * previous mount, or its queue of mounts is full.
2748
2753
  * @throws `invalid` (rejects) `title` is longer than 128 bytes or has
@@ -2763,6 +2768,19 @@ export interface Panel extends View, Disposable {
2763
2768
  * only this plugin's own changes. A sidebar panel in a background tab
2764
2769
  * has `active: false`, `effective: false` and `reason: "otherTab"`.
2765
2770
  *
2771
+ * Behaviour from player 0.7.3: a background tab does not keep the plugin
2772
+ * running.
2773
+ * If the panel is all that keeps it running, the plugin goes to standby
2774
+ * after the idle time (stop reason `idle`): the player keeps its tab, with
2775
+ * its title, in the strip and the `»` menu. When the user shows the tab,
2776
+ * the player starts the plugin again; `activate` runs and mounts the same
2777
+ * panel (same file and component), which takes the tab over, and
2778
+ * {@link Panel.ready} resolves again. Anything the plugin kept only in
2779
+ * memory is gone: restore the view from storage (session storage
2780
+ * survives standby). While it is in the background, the player may also
2781
+ * drop the panel's component and build it again from the bridge
2782
+ * properties last written, as it does on any rebuild.
2783
+ *
2766
2784
  * @throws Never; `null` stands for "not mounted".
2767
2785
  *
2768
2786
  * @since 1.5.2
@@ -4405,7 +4423,13 @@ export interface MainWindow {
4405
4423
  * @category Plugin
4406
4424
  */
4407
4425
  export interface AppInfo {
4408
- /** The player's version, e.g. `"1.0.0"`. */
4426
+ /**
4427
+ * The player's version, e.g. `"0.7.1"`. From player 0.7.1 this is the
4428
+ * player's release version (the version of the published release), which
4429
+ * can differ from the version of the host binary inside it. The player
4430
+ * compares `minPlayerVersion` with this value, and plugins compare with
4431
+ * it too.
4432
+ */
4409
4433
  readonly version: string;
4410
4434
  /** Short git hash of the build, `null` when unknown. */
4411
4435
  readonly build: string | null;
@@ -8586,11 +8610,11 @@ export interface InstallOptions {
8586
8610
  * Built-in plugins always run (and cannot be installed over). A value
8587
8611
  * that is not a boolean is `invalid`.
8588
8612
  *
8589
- * Planned for player 0.6.4: older players ignore it and an install there
8613
+ * Player 0.6.4 and later: older players ignore it and an install there
8590
8614
  * always runs the plugin, so after a committed install call
8591
8615
  * {@link Packages.setEnabled} when the state matters.
8592
8616
  *
8593
- * @player 0.6.4 (planned); older players ignore it (an install always
8617
+ * @player 0.6.4; older players ignore it (an install always
8594
8618
  * enables the plugin).
8595
8619
  */
8596
8620
  enabled?: boolean;
@@ -8639,8 +8663,8 @@ export interface PackageCandidate {
8639
8663
  * player). A reserved id (`vestra` or `vestra.*`, which every built-in
8640
8664
  * uses) fails with `reserved` (player 0.4.1; already when validated), as
8641
8665
  * only the player installs built-in plugins. An update keeps a disabled
8642
- * plugin disabled unless `enabled` says otherwise (planned for player
8643
- * 0.6.4; see {@link InstallOptions.enabled}).
8666
+ * plugin disabled unless `enabled` says otherwise (player 0.6.4; see
8667
+ * {@link InstallOptions.enabled}).
8644
8668
  *
8645
8669
  * @capability plugins.manage
8646
8670
  * @throws `invalid` (rejects) An option is malformed: a `source` the
@@ -8845,11 +8869,11 @@ export interface PluginInfo {
8845
8869
  * while the plugin is switched on but has no process. That is standby
8846
8870
  * with on-demand start (lazy activation): nothing used it for the idle
8847
8871
  * time, or the player's limit on third-party processes or low system
8848
- * memory stopped it early (planned for player 0.6.7); it starts again on its next
8872
+ * memory stopped it early (player 0.7.1); it starts again on its next
8849
8873
  * use, and its menu items, keys, settings pages, resolvers and drop
8850
- * targets stay. From player 0.6.6 it is also the pause after a crash: a
8874
+ * targets stay. From player 0.7.1 it is also the pause after a crash: a
8851
8875
  * built-in or resident plugin waiting to start again by itself, or a
8852
- * plugin with on-demand start whose commands are shown disabled with the
8876
+ * plugin that has run before whose commands are shown disabled with the
8853
8877
  * reason until the pause ends. Absent in other states and from players
8854
8878
  * before 0.5.18. A change between the two alone does not fire
8855
8879
  * {@link Packages.onChange}; a plugin stopped by the start limit (five
@@ -194,6 +194,39 @@ export type VideoNode =
194
194
  * 16 MiB) inside the plugin's package directory or data directory
195
195
  * after following links; a path with `[` or `]` is refused. Outside
196
196
  * those: `invalid`; a file that does not exist: `missing`.
197
+ *
198
+ * The player checks only that header; the table itself is read by
199
+ * FFmpeg's `.cube` reader (`parse_cube` in FFmpeg's
200
+ * [`libavfilter/vf_lut3d.c`](https://github.com/FFmpeg/FFmpeg/blob/master/libavfilter/vf_lut3d.c)),
201
+ * which takes a subset of the
202
+ * Adobe/Resolve format:
203
+ *
204
+ * - Every line before `LUT_3D_SIZE N` is skipped (a `TITLE`, comments,
205
+ * and also a `DOMAIN_MIN` or `DOMAIN_MAX` there, which then has no
206
+ * effect).
207
+ * - After it, optional `TITLE`, `DOMAIN_MIN r g b` and
208
+ * `DOMAIN_MAX r g b` lines (default `0 0 0` and `1 1 1`), blank
209
+ * lines and `#` comments, then N³ data lines of three numbers
210
+ * `r g b`, red changing fastest, then green, then blue.
211
+ * - Any other keyword after `LUT_3D_SIZE`, such as `MIN` or `MAX`, is
212
+ * read as a data line, and FFmpeg refuses the file, as it does one
213
+ * with fewer than N³ data lines. The chain then fails and the
214
+ * player reports mpv's "error running command (-12)".
215
+ *
216
+ * ```text
217
+ * TITLE "Identity"
218
+ * LUT_3D_SIZE 2
219
+ * DOMAIN_MIN 0 0 0
220
+ * DOMAIN_MAX 1 1 1
221
+ * 0 0 0
222
+ * 1 0 0
223
+ * 0 1 0
224
+ * 1 1 0
225
+ * 0 0 1
226
+ * 1 0 1
227
+ * 0 1 1
228
+ * 1 1 1
229
+ * ```
197
230
  */
198
231
  file: string;
199
232
  /** How colours between the table's points are computed; `tetrahedral` is FFmpeg's default. */
package/dist/wire.d.ts CHANGED
@@ -733,7 +733,7 @@ export declare function createWire(transport: Transport): {
733
733
  installed: (id: string) => Promise<InstalledPackage>;
734
734
  /**
735
735
  * `source` and `replace` are sent only when given (player 0.2.0);
736
- * `enabled` only when given (planned for player 0.6.4, older players
736
+ * `enabled` only when given (player 0.6.4; older players
737
737
  * ignore it).
738
738
  */
739
739
  install: (token: string, expectedRevision: number, requestId: string, options?: {
package/dist/wire.js CHANGED
@@ -343,7 +343,7 @@ export function createWire(transport) {
343
343
  installed: (id) => transport.request("packages.installed", { id }),
344
344
  /**
345
345
  * `source` and `replace` are sent only when given (player 0.2.0);
346
- * `enabled` only when given (planned for player 0.6.4, older players
346
+ * `enabled` only when given (player 0.6.4; older players
347
347
  * ignore it).
348
348
  */
349
349
  install: (token, expectedRevision, requestId, options = {}) => transport.request("packages.install", {
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # Vestra Player SDK
2
2
 
3
- > @vestra-player/sdk 1.6.0: 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. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
3
+ > @vestra-player/sdk 1.6.2: 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. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
4
4
 
5
5
  ## Read the documentation
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
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": {