@vestra-player/sdk 1.5.58 → 1.6.1
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 +25 -5
- package/dist/docs-tree.json.gz +0 -0
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/testing.d.ts +2 -2
- package/dist/plugin/testing.js +2 -2
- package/dist/plugin/types.d.ts +42 -31
- package/dist/processing.d.ts +33 -0
- package/dist/wire.d.ts +1 -1
- package/dist/wire.js +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/slint/vestra/markdown.slint +172 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.6.1
|
|
4
|
+
|
|
5
|
+
**Who must change: nobody.** Docs only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability.
|
|
6
|
+
|
|
7
|
+
- **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.
|
|
8
|
+
- **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.
|
|
9
|
+
- **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.
|
|
10
|
+
- **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.
|
|
11
|
+
|
|
12
|
+
## 1.6.0
|
|
13
|
+
|
|
14
|
+
**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.
|
|
15
|
+
|
|
16
|
+
_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._
|
|
17
|
+
|
|
18
|
+
- **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).
|
|
19
|
+
- **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).
|
|
20
|
+
|
|
3
21
|
## 1.5.58
|
|
4
22
|
|
|
5
|
-
**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 (
|
|
23
|
+
**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.
|
|
24
|
+
|
|
25
|
+
_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._
|
|
6
26
|
|
|
7
|
-
- **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)).
|
|
8
|
-
- **[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
|
|
9
|
-
- **`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 (
|
|
10
|
-
- **`appearance.changed` says what changed** (player 0.
|
|
27
|
+
- **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.
|
|
28
|
+
- **[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).
|
|
29
|
+
- **`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.
|
|
30
|
+
- **`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.
|
|
11
31
|
|
|
12
32
|
## 1.5.57
|
|
13
33
|
|
package/dist/docs-tree.json.gz
CHANGED
|
Binary file
|
package/dist/plugin/index.d.ts
CHANGED
|
@@ -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` (
|
|
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.
|
package/dist/plugin/testing.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
package/dist/plugin/testing.js
CHANGED
|
@@ -3100,7 +3100,7 @@ export class TestHost {
|
|
|
3100
3100
|
* adds or upgrades the entry in {@link TestHost.packages} following the
|
|
3101
3101
|
* player's source rules: the same source upgrades, another source needs
|
|
3102
3102
|
* `replace` (`conflict` otherwise), a built-in id is `unsupported`. As
|
|
3103
|
-
* player 0.6.4
|
|
3103
|
+
* player 0.6.4 and later, the installed entry's `state` follows
|
|
3104
3104
|
* {@link "@vestra-player/sdk"!InstallOptions.enabled}: a first install
|
|
3105
3105
|
* runs, an update of a `disabled` entry stays `disabled` unless `enabled`
|
|
3106
3106
|
* is `true`, and `enabled: false` installs it `disabled`. Set
|
|
@@ -3124,7 +3124,7 @@ export class TestHost {
|
|
|
3124
3124
|
candidates = new Map();
|
|
3125
3125
|
/**
|
|
3126
3126
|
* Which player's install rule `packages.install` plays. `true` (default,
|
|
3127
|
-
* SDK 1.5.55): player 0.6.4
|
|
3127
|
+
* SDK 1.5.55): player 0.6.4 and later, where an update or reinstall
|
|
3128
3128
|
* keeps a `disabled` plugin disabled unless the plugin passes
|
|
3129
3129
|
* {@link "@vestra-player/sdk"!InstallOptions.enabled}. `false`: players
|
|
3130
3130
|
* up to 0.6.3, where every install runs the plugin and `enabled` is
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -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 (
|
|
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:
|
|
528
|
-
* 0.
|
|
529
|
-
*
|
|
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.
|
|
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)
|
|
608
|
-
* player 0.
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
* memory puts an idle plugin in standby early
|
|
613
|
-
*
|
|
614
|
-
*
|
|
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 (
|
|
619
|
-
*
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
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.
|
|
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,6 +1771,13 @@ export interface Ui {
|
|
|
1773
1771
|
* the list on every streamed chunk keeps the scroll position and costs
|
|
1774
1772
|
* little.
|
|
1775
1773
|
*
|
|
1774
|
+
* From player 0.7.1 both views take `selectable: true` (default `false`):
|
|
1775
|
+
* the user can select and copy the text, one block at a time; blocks with
|
|
1776
|
+
* links keep their clickable links and copy as `text (url)`. Code blocks
|
|
1777
|
+
* are always selectable. `MarkdownBlock.plain` (the block as plain text)
|
|
1778
|
+
* and `MarkdownBlock.links` (its link addresses) are readable in Slint.
|
|
1779
|
+
* See [Reference: theme › Markdown](../../docs/reference/theme.md#markdown).
|
|
1780
|
+
*
|
|
1776
1781
|
* @capability None.
|
|
1777
1782
|
* @player 0.2.0 (set `"minPlayerVersion": "0.2.0"` in the manifest)
|
|
1778
1783
|
*
|
|
@@ -4398,7 +4403,13 @@ export interface MainWindow {
|
|
|
4398
4403
|
* @category Plugin
|
|
4399
4404
|
*/
|
|
4400
4405
|
export interface AppInfo {
|
|
4401
|
-
/**
|
|
4406
|
+
/**
|
|
4407
|
+
* The player's version, e.g. `"0.7.1"`. From player 0.7.1 this is the
|
|
4408
|
+
* player's release version (the version of the published release), which
|
|
4409
|
+
* can differ from the version of the host binary inside it. The player
|
|
4410
|
+
* compares `minPlayerVersion` with this value, and plugins compare with
|
|
4411
|
+
* it too.
|
|
4412
|
+
*/
|
|
4402
4413
|
readonly version: string;
|
|
4403
4414
|
/** Short git hash of the build, `null` when unknown. */
|
|
4404
4415
|
readonly build: string | null;
|
|
@@ -8579,11 +8590,11 @@ export interface InstallOptions {
|
|
|
8579
8590
|
* Built-in plugins always run (and cannot be installed over). A value
|
|
8580
8591
|
* that is not a boolean is `invalid`.
|
|
8581
8592
|
*
|
|
8582
|
-
*
|
|
8593
|
+
* Player 0.6.4 and later: older players ignore it and an install there
|
|
8583
8594
|
* always runs the plugin, so after a committed install call
|
|
8584
8595
|
* {@link Packages.setEnabled} when the state matters.
|
|
8585
8596
|
*
|
|
8586
|
-
* @player 0.6.4
|
|
8597
|
+
* @player 0.6.4; older players ignore it (an install always
|
|
8587
8598
|
* enables the plugin).
|
|
8588
8599
|
*/
|
|
8589
8600
|
enabled?: boolean;
|
|
@@ -8632,8 +8643,8 @@ export interface PackageCandidate {
|
|
|
8632
8643
|
* player). A reserved id (`vestra` or `vestra.*`, which every built-in
|
|
8633
8644
|
* uses) fails with `reserved` (player 0.4.1; already when validated), as
|
|
8634
8645
|
* only the player installs built-in plugins. An update keeps a disabled
|
|
8635
|
-
* plugin disabled unless `enabled` says otherwise (
|
|
8636
|
-
*
|
|
8646
|
+
* plugin disabled unless `enabled` says otherwise (player 0.6.4; see
|
|
8647
|
+
* {@link InstallOptions.enabled}).
|
|
8637
8648
|
*
|
|
8638
8649
|
* @capability plugins.manage
|
|
8639
8650
|
* @throws `invalid` (rejects) An option is malformed: a `source` the
|
|
@@ -8838,11 +8849,11 @@ export interface PluginInfo {
|
|
|
8838
8849
|
* while the plugin is switched on but has no process. That is standby
|
|
8839
8850
|
* with on-demand start (lazy activation): nothing used it for the idle
|
|
8840
8851
|
* time, or the player's limit on third-party processes or low system
|
|
8841
|
-
* memory stopped it early (
|
|
8852
|
+
* memory stopped it early (player 0.7.1); it starts again on its next
|
|
8842
8853
|
* use, and its menu items, keys, settings pages, resolvers and drop
|
|
8843
|
-
* targets stay. From player 0.
|
|
8854
|
+
* targets stay. From player 0.7.1 it is also the pause after a crash: a
|
|
8844
8855
|
* built-in or resident plugin waiting to start again by itself, or a
|
|
8845
|
-
* plugin
|
|
8856
|
+
* plugin that has run before whose commands are shown disabled with the
|
|
8846
8857
|
* reason until the pause ends. Absent in other states and from players
|
|
8847
8858
|
* before 0.5.18. A change between the two alone does not fire
|
|
8848
8859
|
* {@link Packages.onChange}; a plugin stopped by the start limit (five
|
package/dist/processing.d.ts
CHANGED
|
@@ -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 (
|
|
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 (
|
|
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.
|
|
3
|
+
> @vestra-player/sdk 1.6.1: 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
|
@@ -9,7 +9,15 @@
|
|
|
9
9
|
// row (a chat message: a `[MarkdownBlock]` field of the row's struct).
|
|
10
10
|
// `code-copy: true` adds a Copy button to code blocks that reports
|
|
11
11
|
// `copy-code(code)`; the plugin copies it (`plugin.clipboard`).
|
|
12
|
-
|
|
12
|
+
// `selectable: true` lets the user select and copy text with the mouse:
|
|
13
|
+
// paragraphs, headings, list items and quotes without links then show their
|
|
14
|
+
// plain text (`MarkdownBlock.plain`, no inline styles) in a read-only text
|
|
15
|
+
// field, one field per block, with a Copy / Select All menu. A block with
|
|
16
|
+
// links keeps its styled text (links stay clickable); its right-click menu
|
|
17
|
+
// copies the block as plain text with each address after its link text,
|
|
18
|
+
// `text (url)`, and offers Copy Link when the block has one link. Code
|
|
19
|
+
// blocks are always selectable.
|
|
20
|
+
import { ListView, Palette } from "std-widgets.slint";
|
|
13
21
|
import { Theme } from "theme.slint";
|
|
14
22
|
import { Icon } from "icons.slint";
|
|
15
23
|
|
|
@@ -36,21 +44,130 @@ export struct MarkdownBlock {
|
|
|
36
44
|
// Task list item: 0 none, 1 open, 2 done (a drawn box, no font glyph).
|
|
37
45
|
task: int,
|
|
38
46
|
text: styled-text,
|
|
47
|
+
// The block's text without styles, what `selectable` shows: a code
|
|
48
|
+
// block's code, a table's cells (tab-separated lines), an image's alt.
|
|
49
|
+
plain: string,
|
|
39
50
|
code: string,
|
|
40
51
|
image: image,
|
|
41
52
|
has-image: bool,
|
|
42
53
|
image-width: int,
|
|
43
54
|
image-height: int,
|
|
44
55
|
alt: string,
|
|
56
|
+
// The addresses of the block's links, in order.
|
|
57
|
+
links: [string],
|
|
45
58
|
rows: [MarkdownRow],
|
|
46
59
|
// Table column alignment: "left", "center", "right" or "" (left).
|
|
47
60
|
aligns: [string],
|
|
48
61
|
}
|
|
49
62
|
|
|
63
|
+
// Read-only text the user can select: a right-click menu with Copy and
|
|
64
|
+
// Select All (as Slint's own text fields; Copy without a selection copies
|
|
65
|
+
// the whole block), and Ctrl+C / Ctrl+A (⌘C / ⌘A) while it has focus. No
|
|
66
|
+
// caret, as selectable text on a web page. Each one is a Tab stop, and
|
|
67
|
+
// while one has focus the arrow keys move in it (Slint 1.18's read-only
|
|
68
|
+
// TextInput).
|
|
69
|
+
component SelectableText {
|
|
70
|
+
in property <string> text;
|
|
71
|
+
in property <brush> color: Theme.text;
|
|
72
|
+
in property <length> font-size: Theme.font-tab;
|
|
73
|
+
in property <int> font-weight: 400;
|
|
74
|
+
in property <string> font-family;
|
|
75
|
+
min-height: input.min-height;
|
|
76
|
+
preferred-height: input.preferred-height;
|
|
77
|
+
ContextMenuArea {
|
|
78
|
+
Menu {
|
|
79
|
+
MenuItem {
|
|
80
|
+
title: @tr("Copy");
|
|
81
|
+
enabled: root.text != "";
|
|
82
|
+
activated => {
|
|
83
|
+
if input.anchor-position-byte-offset == input.cursor-position-byte-offset {
|
|
84
|
+
input.select-all();
|
|
85
|
+
input.copy();
|
|
86
|
+
input.clear-selection();
|
|
87
|
+
} else {
|
|
88
|
+
input.copy();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
MenuItem {
|
|
93
|
+
title: @tr("Select All");
|
|
94
|
+
enabled: root.text != "";
|
|
95
|
+
activated => { input.select-all(); }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
input := TextInput {
|
|
99
|
+
width: root.width;
|
|
100
|
+
height: root.height;
|
|
101
|
+
text: root.text;
|
|
102
|
+
read-only: true;
|
|
103
|
+
single-line: false;
|
|
104
|
+
wrap: word-wrap;
|
|
105
|
+
color: root.color;
|
|
106
|
+
font-size: root.font-size;
|
|
107
|
+
font-weight: root.font-weight;
|
|
108
|
+
font-family: root.font-family;
|
|
109
|
+
text-cursor-width: 0px;
|
|
110
|
+
// The std-widgets LineEdit's selection colours, legible in both
|
|
111
|
+
// palettes (as the info plugin's properties).
|
|
112
|
+
selection-background-color: Palette.selection-background;
|
|
113
|
+
selection-foreground-color: Palette.selection-foreground;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// A block with links in a selectable view: its styled text (links stay
|
|
119
|
+
// clickable) under a right-click menu that copies `plain` (with the
|
|
120
|
+
// addresses) and, for one link, the link. The menu lies above the text: a
|
|
121
|
+
// left click passes through it to the links.
|
|
122
|
+
component LinkText {
|
|
123
|
+
in property <styled-text> text;
|
|
124
|
+
in property <string> plain;
|
|
125
|
+
in property <[string]> links;
|
|
126
|
+
in property <brush> color: Theme.text;
|
|
127
|
+
in property <length> font-size: Theme.font-tab;
|
|
128
|
+
callback link-clicked(string);
|
|
129
|
+
min-height: styled.min-height;
|
|
130
|
+
preferred-height: styled.preferred-height;
|
|
131
|
+
function put(text: string) {
|
|
132
|
+
clip.text = text;
|
|
133
|
+
clip.select-all();
|
|
134
|
+
clip.copy();
|
|
135
|
+
}
|
|
136
|
+
styled := StyledText {
|
|
137
|
+
width: root.width;
|
|
138
|
+
height: root.height;
|
|
139
|
+
text: root.text;
|
|
140
|
+
default-color: root.color;
|
|
141
|
+
default-font-size: root.font-size;
|
|
142
|
+
link-color: Theme.accent;
|
|
143
|
+
link-clicked(url) => { root.link-clicked(url); }
|
|
144
|
+
}
|
|
145
|
+
ContextMenuArea {
|
|
146
|
+
Menu {
|
|
147
|
+
MenuItem {
|
|
148
|
+
title: @tr("Copy");
|
|
149
|
+
activated => { root.put(root.plain); }
|
|
150
|
+
}
|
|
151
|
+
if root.links.length == 1: MenuItem {
|
|
152
|
+
title: @tr("Copy Link");
|
|
153
|
+
activated => { root.put(root.links[0]); }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Puts text on the clipboard (Slint has no clipboard function).
|
|
158
|
+
clip := TextInput {
|
|
159
|
+
visible: false;
|
|
160
|
+
width: 0px;
|
|
161
|
+
height: 0px;
|
|
162
|
+
read-only: true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
50
166
|
component MarkdownBlockView {
|
|
51
167
|
in property <MarkdownBlock> block;
|
|
52
168
|
in property <length> available;
|
|
53
169
|
in property <bool> code-copy;
|
|
170
|
+
in property <bool> selectable;
|
|
54
171
|
callback link-clicked(string);
|
|
55
172
|
callback copy-code(string);
|
|
56
173
|
private property <length> quote-indent: block.quote * 12px;
|
|
@@ -61,7 +178,21 @@ component MarkdownBlockView {
|
|
|
61
178
|
HorizontalLayout {
|
|
62
179
|
padding-left: root.quote-indent + root.list-indent;
|
|
63
180
|
VerticalLayout {
|
|
64
|
-
if block.kind == "heading":
|
|
181
|
+
if block.kind == "heading" && root.selectable && block.links.length > 0: LinkText {
|
|
182
|
+
width: root.inner;
|
|
183
|
+
text: block.text;
|
|
184
|
+
plain: block.plain;
|
|
185
|
+
links: block.links;
|
|
186
|
+
font-size: root.heading-size;
|
|
187
|
+
link-clicked(url) => { root.link-clicked(url); }
|
|
188
|
+
}
|
|
189
|
+
if block.kind == "heading" && root.selectable && block.links.length == 0: SelectableText {
|
|
190
|
+
width: root.inner;
|
|
191
|
+
text: block.plain;
|
|
192
|
+
font-size: root.heading-size;
|
|
193
|
+
font-weight: 700;
|
|
194
|
+
}
|
|
195
|
+
if block.kind == "heading" && !root.selectable: StyledText {
|
|
65
196
|
width: root.inner;
|
|
66
197
|
text: block.text;
|
|
67
198
|
default-color: Theme.text;
|
|
@@ -69,7 +200,20 @@ component MarkdownBlockView {
|
|
|
69
200
|
link-color: Theme.accent;
|
|
70
201
|
link-clicked(url) => { root.link-clicked(url); }
|
|
71
202
|
}
|
|
72
|
-
if block.kind == "paragraph":
|
|
203
|
+
if block.kind == "paragraph" && root.selectable && block.links.length > 0: LinkText {
|
|
204
|
+
width: root.inner;
|
|
205
|
+
text: block.text;
|
|
206
|
+
plain: block.plain;
|
|
207
|
+
links: block.links;
|
|
208
|
+
color: block.quote > 0 ? Theme.text-dim : Theme.text;
|
|
209
|
+
link-clicked(url) => { root.link-clicked(url); }
|
|
210
|
+
}
|
|
211
|
+
if block.kind == "paragraph" && root.selectable && block.links.length == 0: SelectableText {
|
|
212
|
+
width: root.inner;
|
|
213
|
+
text: block.plain;
|
|
214
|
+
color: block.quote > 0 ? Theme.text-dim : Theme.text;
|
|
215
|
+
}
|
|
216
|
+
if block.kind == "paragraph" && !root.selectable: StyledText {
|
|
73
217
|
width: root.inner;
|
|
74
218
|
text: block.text;
|
|
75
219
|
default-color: block.quote > 0 ? Theme.text-dim : Theme.text;
|
|
@@ -106,7 +250,18 @@ component MarkdownBlockView {
|
|
|
106
250
|
}
|
|
107
251
|
}
|
|
108
252
|
}
|
|
109
|
-
|
|
253
|
+
if root.selectable && block.links.length > 0: LinkText {
|
|
254
|
+
width: root.inner - 20px;
|
|
255
|
+
text: block.text;
|
|
256
|
+
plain: block.plain;
|
|
257
|
+
links: block.links;
|
|
258
|
+
link-clicked(url) => { root.link-clicked(url); }
|
|
259
|
+
}
|
|
260
|
+
if root.selectable && block.links.length == 0: SelectableText {
|
|
261
|
+
width: root.inner - 20px;
|
|
262
|
+
text: block.plain;
|
|
263
|
+
}
|
|
264
|
+
if !root.selectable: StyledText {
|
|
110
265
|
width: root.inner - 20px;
|
|
111
266
|
text: block.text;
|
|
112
267
|
default-color: Theme.text;
|
|
@@ -123,12 +278,12 @@ component MarkdownBlockView {
|
|
|
123
278
|
VerticalLayout {
|
|
124
279
|
padding: 6px;
|
|
125
280
|
// Plain lines in the monospace font; CJK falls back.
|
|
126
|
-
|
|
281
|
+
// Always selectable: code is there to be copied.
|
|
282
|
+
SelectableText {
|
|
127
283
|
width: root.inner - 12px;
|
|
128
|
-
text: block.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
default-font-size: Theme.font-body;
|
|
284
|
+
text: block.code;
|
|
285
|
+
font-family: Theme.font-mono;
|
|
286
|
+
font-size: Theme.font-body;
|
|
132
287
|
}
|
|
133
288
|
}
|
|
134
289
|
if root.code-copy: Rectangle {
|
|
@@ -216,6 +371,8 @@ export component MarkdownBlocks inherits Rectangle {
|
|
|
216
371
|
in property <[MarkdownBlock]> blocks;
|
|
217
372
|
// A Copy button on code blocks, reporting `copy-code(code)`.
|
|
218
373
|
in property <bool> code-copy: false;
|
|
374
|
+
// Text the user can select and copy (see the top of this file).
|
|
375
|
+
in property <bool> selectable: false;
|
|
219
376
|
callback link-clicked(string);
|
|
220
377
|
callback copy-code(string);
|
|
221
378
|
min-height: column.min-height;
|
|
@@ -228,6 +385,7 @@ export component MarkdownBlocks inherits Rectangle {
|
|
|
228
385
|
block: block;
|
|
229
386
|
available: root.width;
|
|
230
387
|
code-copy: root.code-copy;
|
|
388
|
+
selectable: root.selectable;
|
|
231
389
|
link-clicked(url) => { root.link-clicked(url); }
|
|
232
390
|
copy-code(code) => { root.copy-code(code); }
|
|
233
391
|
}
|
|
@@ -244,6 +402,10 @@ export component MarkdownView inherits Rectangle {
|
|
|
244
402
|
in property <length> inset: 10px;
|
|
245
403
|
// A Copy button on code blocks, reporting `copy-code(code)`.
|
|
246
404
|
in property <bool> code-copy: false;
|
|
405
|
+
// Text the user can select and copy (see the top of this file). A
|
|
406
|
+
// selection is lost when its block scrolls out of view (the `ListView`
|
|
407
|
+
// drops the row).
|
|
408
|
+
in property <bool> selectable: false;
|
|
247
409
|
callback link-clicked(string);
|
|
248
410
|
callback copy-code(string);
|
|
249
411
|
list := ListView {
|
|
@@ -261,6 +423,7 @@ export component MarkdownView inherits Rectangle {
|
|
|
261
423
|
block: block;
|
|
262
424
|
available: self.width;
|
|
263
425
|
code-copy: root.code-copy;
|
|
426
|
+
selectable: root.selectable;
|
|
264
427
|
link-clicked(url) => { root.link-clicked(url); }
|
|
265
428
|
copy-code(code) => { root.copy-code(code); }
|
|
266
429
|
}
|