@vestra-player/sdk 1.5.9 → 1.5.11

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.9: full reference
1
+ # @vestra-player/sdk 1.5.11: 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
 
@@ -998,11 +998,11 @@ change).
998
998
  | `timeout` | A time limit ran out (`openStream` start-up, `tools.run`, `system.*` after 10 s). |
999
999
  | `stream`, `device` | `openStream`: the producer failed / the audio device is not ready. |
1000
1000
  | `backend-uncertain` | The player's backend blocked a filter stage; call `retry()`. |
1001
- | `limit` | A player-wide limit was reached (for example the number of commands). |
1001
+ | `limit` | A player-wide limit was reached (for example the number of commands), a property value is over the limits of PropValue, or a request is longer than the player's 1 MiB message. |
1002
1002
  | `reserved` | Packages.validate, PackageCandidate.install: the id is `vestra` or starts with `vestra.` (any case), which only the player's built-in plugins use (player 0.4.1). |
1003
1003
  | `versionMismatch` | The package needs a newer player (`minPlayerVersion`) or another `apiVersion`. |
1004
1004
  | `ui-prepare` | The player could not prepare a mounted panel or a settings page (its Slint file does not compile, a bound property is not declared, or another plugin's panel holds the slot); `message` has the diagnostics. |
1005
- | `ui` | The player could not apply a property to a tool window or a settings page, or could not build the Options window (a property the Slint file does not declare, a value of the wrong type); `message` has Slint's reason. |
1005
+ | `ui` | The player could not apply a property to a tool window or a settings page, or could not build the Options window (a property the Slint file does not declare, a value of the wrong type); `message` has Slint's reason. Also reported to Scope.onError without a request: a callback whose arguments the player could not convert, a property it could not show again when it rebuilt a view (an image file removed since). |
1006
1006
  | `host` | Any other failure inside the player; `message` is the player's reason. |
1007
1007
  | `disabled` | The plugin is being stopped; pending requests fail with it. |
1008
1008
  | `unknown`, `rejected`, `expired` | After a transport problem the SDK could not confirm the outcome (does not happen in normal operation). |
@@ -1201,8 +1201,8 @@ interface CommandState {
1201
1201
  checked: boolean | null;
1202
1202
  /** Shown as busy; like `enabled: false`, the player does not call `run`. Default false. */
1203
1203
  busy: boolean;
1204
- /** Shown when the command is disabled or busy. */
1205
- reason: string | null;
1204
+ /** Shown when the command is disabled or busy: English source text the player translates, or a Text (SDK 1.5.11). */
1205
+ reason: TextValue | null;
1206
1206
  }
1207
1207
  ```
1208
1208
 
@@ -1279,10 +1279,15 @@ interface CommandOptions {
1279
1279
  * titled their menus in Chinese (视频…): there `["Video", "Blur"]` is a
1280
1280
  * menu of its own, so plugins for those players write `@video`; player
1281
1281
  * 0.4.3 still accepts the old Chinese titles of its own menus.
1282
+ *
1283
+ * A segment that mixes words with data (a track number, a count) is a
1284
+ * Text (SDK 1.5.11, player 0.4.3): `plugin.i18n.text("Track {}
1285
+ * ({})", [n, codec])`. The menu shows it translated and filled in; it
1286
+ * merges by its English rendering ("Track 2 (opus)").
1282
1287
  */
1283
- path?: string[];
1284
- /** Menu label (English source text, shown translated); defaults to the last path segment. */
1285
- title?: string;
1288
+ path?: (string | Text)[];
1289
+ /** Menu label (English source text, shown translated, or a Text); defaults to the last path segment. */
1290
+ title?: string | Text;
1286
1291
  /**
1287
1292
  * Sibling order in the menu, ascending (integer, default 0). A submenu sits where its first command sits, except a built-in menu, which keeps its fixed place. Directly inside a built-in menu, 0 (the default) sorts last. Equal orders: plugin id, then declaration order. Range ±1,000,000. See CommandOptions for the menu order rules.
1288
1293
  */
@@ -1324,8 +1329,8 @@ interface CommandOptions {
1324
1329
  checked?: Bindable<boolean | null>;
1325
1330
  /** Busy state (default false); the player does not call `run` while busy. */
1326
1331
  busy?: Bindable<boolean>;
1327
- /** Why the command is disabled or busy (shown to the user). */
1328
- reason?: Bindable<string | null>;
1332
+ /** Why the command is disabled or busy (shown to the user): English source text, or a Text for one with data in it (SDK 1.5.11). */
1333
+ reason?: Bindable<TextValue | null>;
1329
1334
  /**
1330
1335
  * Run the command (menu item, binding, panel menu or `host.command(id).run()` in tests). It may return a promise; errors and rejections go to Scope.onError, and bound values are re-evaluated when it returns and when its promise settles.
1331
1336
  */
@@ -1432,7 +1437,7 @@ JSON whose values may also be Markdown documents, at any depth: the part
1432
1437
  of PropValue that nests.
1433
1438
 
1434
1439
  ```ts
1435
- type PropData = null | boolean | number | string | MarkdownRef | PropData[] | {
1440
+ type PropData = null | boolean | number | string | MarkdownRef | Text | TextList | PropData[] | {
1436
1441
  [key: string]: PropData;
1437
1442
  };
1438
1443
  ```
@@ -1948,12 +1953,82 @@ type LanguagePreference = "system" | Locale;
1948
1953
  ### TemplateArgs
1949
1954
 
1950
1955
  Arguments of a template sentence (Osd.show,
1951
- OsdPanel.set, ConfirmOptions.args): an array for `{}` and
1952
- `{0}`, `{1}` placeholders, or an object for `{name}` placeholders. At most
1953
- 16 strings and finite numbers; whole numbers print without a fraction.
1956
+ OsdPanel.set, ConfirmOptions.args, I18n.text): an
1957
+ array for `{}` and `{0}`, `{1}` placeholders, or an object for `{name}`
1958
+ placeholders. At most 16. Strings and finite numbers are data, shown as
1959
+ they are (whole numbers without a fraction); a Text or
1960
+ TextList argument (SDK 1.5.11, player 0.4.3) is translated too,
1961
+ so a sentence can be built from translated parts.
1954
1962
 
1955
1963
  ```ts
1956
- type TemplateArgs = readonly (string | number)[] | Readonly<Record<string, string | number>>;
1964
+ type TemplateArgs = readonly TextArg[] | Readonly<Record<string, TextArg>>;
1965
+ ```
1966
+
1967
+ ### Text
1968
+
1969
+ A text the player translates with the plugin's catalog and fills in:
1970
+ English source text with its arguments. Made by I18n.text; plain
1971
+ data, not a translation (the plugin never sees the translated string).
1972
+
1973
+ ```ts
1974
+ interface Text {
1975
+ /** The English source text: a template with `{}`, `{0}` or `{name}`. */
1976
+ readonly $vestraText: string;
1977
+ /** Values for its placeholders. */
1978
+ readonly args?: TemplateArgs;
1979
+ }
1980
+ ```
1981
+
1982
+ ### TextList
1983
+
1984
+ Values joined the way the interface language joins them ("a, b" in
1985
+ English, "a、b" in Chinese). Made by I18n.list; accepted where a
1986
+ Text is.
1987
+
1988
+ ```ts
1989
+ interface TextList {
1990
+ /** The items: data, or texts the player translates. */
1991
+ readonly $vestraList: readonly TextArg[];
1992
+ /** How they are joined; `"list"` by default. */
1993
+ readonly style?: ListStyle;
1994
+ }
1995
+ ```
1996
+
1997
+ ### ListStyle
1998
+
1999
+ How a TextList is joined, per interface language:
2000
+
2001
+ | style | English | 简体中文 | 日本語 |
2002
+ | --- | --- | --- | --- |
2003
+ | `list` (enumeration) | `, ` | `、` | `、` |
2004
+ | `clauses` (parts of one sentence) | `, ` | `,` | `、` |
2005
+ | `semicolons` | `; ` | `;` | `;` |
2006
+ | `sentences` (no final full stop) | `. ` | `。` | `。` |
2007
+ | `lines` | line break | line break | line break |
2008
+
2009
+ Korean, German and Spanish join as English; French puts a narrow space
2010
+ before `;`.
2011
+
2012
+ ```ts
2013
+ type ListStyle = "list" | "clauses" | "semicolons" | "sentences" | "lines";
2014
+ ```
2015
+
2016
+ ### TextArg
2017
+
2018
+ An argument of a template: data (a string or a finite number, shown as it
2019
+ is) or a Text or TextList (translated).
2020
+
2021
+ ```ts
2022
+ type TextArg = string | number | Text | TextList;
2023
+ ```
2024
+
2025
+ ### TextValue
2026
+
2027
+ A text the player shows: English source text (translated as a whole), a
2028
+ Text or a TextList.
2029
+
2030
+ ```ts
2031
+ type TextValue = string | Text | TextList;
1957
2032
  ```
1958
2033
 
1959
2034
  ### I18n
@@ -1968,6 +2043,68 @@ interface I18n {
1968
2043
  * The interface language of this run, chosen at start-up from the saved Appearance.language or the system's languages; English when neither names a Locale. Players before 0.4.3 report `"en"`.
1969
2044
  */
1970
2045
  readonly locale: Locale;
2046
+ /**
2047
+ * A text that mixes words with data, for the player to translate: the
2048
+ * English source text (a template) and its arguments. It returns a plain
2049
+ * Text value, not a translation; pass it where the player shows
2050
+ * text (see Text) and the player shows it translated with this
2051
+ * plugin's catalog. `vestra-plugin i18n extract` collects `source` from
2052
+ * every call, so write it as a literal (or a conditional of literals, or
2053
+ * an `as const` table entry).
2054
+ *
2055
+ * Arguments are data unless they are texts themselves, so a sentence can
2056
+ * be built from translated parts without composing it in TypeScript.
2057
+ * `text` does not use `this`: `const { text, list } = plugin.i18n` works.
2058
+ * @param source - English source text; `{}`, `{0}` or `{name}` for the arguments, `{{` and `}}` for braces.
2059
+ * @param args - Values for its placeholders.
2060
+ * @throws invalid A malformed or over-limit value (`TEXT_LIMITS`).
2061
+ * @capability None.
2062
+ */
2063
+ text(source: string, args?: TemplateArgs): Text;
2064
+ /**
2065
+ * Items joined the way the interface language joins them (see ListStyle): `list(["a.glsl", "b.glsl"])` shows "a.glsl, b.glsl" in English and "a.glsl、b.glsl" in Chinese. Items are data, or texts the player translates. Accepted where a Text is.
2066
+ * @param items - At most 256.
2067
+ * @param style - `"list"` by default.
2068
+ * @throws invalid A malformed or over-limit value.
2069
+ * @capability None.
2070
+ */
2071
+ list(items: readonly TextArg[], style?: ListStyle): TextList;
2072
+ /**
2073
+ * An `Error` whose words the player shows translated: throw it where the player shows a plugin's failure to the user, such as from a file or web resolver's `resolve` (FileResolverOptions, WebResolverOptions) (also when a stream fails while it starts). The player shows `text` translated with this plugin's catalog (as `player.state.error` and the failure message); `message` is the English rendering, for logs and older players. Elsewhere it is an ordinary `Error`.
2074
+ * @param source - English source text, as I18n.text's.
2075
+ * @param args - Values for its placeholders.
2076
+ * @throws invalid A malformed or over-limit value.
2077
+ * @capability None.
2078
+ */
2079
+ error(source: string, args?: TemplateArgs): TextError;
2080
+ /**
2081
+ * The string a text shows in this run's language, for text that leaves
2082
+ * the player: what the plugin copies to the clipboard or writes to a file
2083
+ * ("Copy info", "Save as…"). Translated with this plugin's catalog (a
2084
+ * string as a whole, a Text or TextList with its
2085
+ * arguments), the way the player would show it.
2086
+ *
2087
+ * Only for text leaving the player. Never use it for the interface (a
2088
+ * window, the menu, the OSD, a dialog): pass the value itself there, so
2089
+ * the player translates it and `vestra-plugin i18n check` can see the
2090
+ * sentence is whole.
2091
+ * @param value - Source text, or a text value.
2092
+ * @returns The translated string.
2093
+ * @throws invalid A malformed value.
2094
+ * @capability None.
2095
+ */
2096
+ resolve(value: TextValue): string;
2097
+ }
2098
+ ```
2099
+
2100
+ ### TextError
2101
+
2102
+ An `Error` the player shows translated (I18n.error).
2103
+
2104
+ ```ts
2105
+ interface TextError extends Error {
2106
+ /** What the player shows. */
2107
+ readonly text: Text;
1971
2108
  }
1972
2109
  ```
1973
2110
 
@@ -2135,12 +2272,12 @@ This plugin's own marks; disposing it removes them.
2135
2272
  ```ts
2136
2273
  interface TimelineLayer extends Disposable {
2137
2274
  /**
2138
- * Replace the layer (last write wins; `[]` clears it). At most 1000 marks, titles ≤ 100 characters, times within the media. Failures go to `onError`; with `ifCurrent`, a write for another source is dropped silently.
2275
+ * Replace the layer (last write wins; `[]` clears it). At most 1000 marks, titles ≤ 100 characters, times within the media. Failures go to `onError`; with `ifCurrent`, a write for another source is dropped silently. A title is data (a chapter's or bookmark's own name), or a Text the player translates (`text("Chapter {}", [n])`, SDK 1.5.11); other plugins read the shown string.
2139
2276
  */
2140
2277
  set(marks: {
2141
2278
  time: number;
2142
2279
  kind: MarkKind;
2143
- title?: string;
2280
+ title?: string | Text;
2144
2281
  }[], options?: {
2145
2282
  ifCurrent?: PlayerState;
2146
2283
  }): void;
@@ -2335,19 +2472,19 @@ Chinese character is one character).
2335
2472
  ```ts
2336
2473
  interface ConfirmOptions {
2337
2474
  /** The question, shown in bold; 1–200 characters. */
2338
- message: string;
2475
+ message: TextValue;
2339
2476
  /** More text under the message; at most 2000 characters. */
2340
- detail?: string;
2477
+ detail?: TextValue;
2341
2478
  /** The confirm button's text (the default button: Enter picks it); 1–40 characters. */
2342
- confirm: string;
2479
+ confirm: TextValue;
2343
2480
  /** The cancel button's text (Escape picks it); 1–40 characters. */
2344
- cancel?: string;
2481
+ cancel?: TextValue;
2345
2482
  /** Mark the confirm button as destructive: red text on macOS, a warning icon on Windows. */
2346
2483
  destructive?: boolean;
2347
2484
  /** A checkbox under the text, such as "Don't ask again"; 1–40 characters. */
2348
- checkbox?: string;
2485
+ checkbox?: TextValue;
2349
2486
  /**
2350
- * Values for the placeholders of `message` and `detail` (player 0.4.3). Every text of the dialog is English source text that the player shows translated from the plugin's catalog; `message` and `detail` are templates like Osd.show's. The length limits apply to the shown text.
2487
+ * Values for the placeholders of `message` and `detail` (player 0.4.3). Any of the texts may instead be a Text (SDK 1.5.11), which carries its own arguments; `args` only fills the string ones. Every text of the dialog is English source text that the player shows translated from the plugin's catalog; `message` and `detail` are templates like Osd.show's. The length limits apply to the shown text.
2351
2488
  */
2352
2489
  args?: TemplateArgs;
2353
2490
  }
@@ -2390,8 +2527,8 @@ interface Dialogs {
2390
2527
  * @throws capability (rejects) The manifest does not declare `ui.dialog`.
2391
2528
  */
2392
2529
  openFile(options?: {
2393
- /** The dialog's title, at most 256 bytes. */
2394
- title?: string;
2530
+ /** The dialog's title (English source text or a Text), at most 256 bytes. */
2531
+ title?: TextValue;
2395
2532
  }): Promise<string | null>;
2396
2533
  /**
2397
2534
  * Ask the user for one or more files to open.
@@ -2404,8 +2541,8 @@ interface Dialogs {
2404
2541
  * @throws capability (rejects) The manifest does not declare `ui.dialog`.
2405
2542
  */
2406
2543
  openFiles(options?: {
2407
- /** The dialog's title, at most 256 bytes. */
2408
- title?: string;
2544
+ /** The dialog's title (English source text or a Text), at most 256 bytes. */
2545
+ title?: TextValue;
2409
2546
  }): Promise<string[]>;
2410
2547
  /**
2411
2548
  * Ask the user for a folder.
@@ -2418,8 +2555,8 @@ interface Dialogs {
2418
2555
  * @throws capability (rejects) The manifest does not declare `ui.dialog`.
2419
2556
  */
2420
2557
  openDirectory(options?: {
2421
- /** The dialog's title, at most 256 bytes. */
2422
- title?: string;
2558
+ /** The dialog's title (English source text or a Text), at most 256 bytes. */
2559
+ title?: TextValue;
2423
2560
  }): Promise<string | null>;
2424
2561
  /**
2425
2562
  * Ask the user where to save a file.
@@ -2432,10 +2569,12 @@ interface Dialogs {
2432
2569
  * @throws capability (rejects) The manifest does not declare `ui.dialog`.
2433
2570
  */
2434
2571
  saveFile(options?: {
2435
- /** The dialog's title, at most 256 bytes. */
2436
- title?: string;
2437
- /** The proposed file name: a plain name, at most 256 bytes. */
2438
- fileName?: string;
2572
+ /** The dialog's title (English source text or a Text), at most 256 bytes. */
2573
+ title?: TextValue;
2574
+ /**
2575
+ * The proposed file name: a plain name, at most 256 bytes. A string is data (not translated); a Text (SDK 1.5.11) is shown translated, `text("Playlist.m3u8")` (a `/` or `\\` in a translation becomes `-`).
2576
+ */
2577
+ fileName?: TextValue;
2439
2578
  }): Promise<string | null>;
2440
2579
  }
2441
2580
  ```
@@ -2973,9 +3112,23 @@ interface OsdPanel extends Disposable {
2973
3112
  * Show the block with this text, change it, or hide it.
2974
3113
  * @capability ui.osd
2975
3114
  * @param text - The text, with `\n` between lines: at most 32 lines and 4096 bytes once translated and formatted. `null` hides the block. A template, like Osd.show's.
2976
- * @param args - Values for its placeholders (player 0.4.3).
3115
+ * @param args - Values for its placeholders (player 0.4.3); `null` or omitted for none.
3116
+ * @param options - `maxColumns`: cut long lines (SDK 1.5.11).
3117
+ */
3118
+ set(text: TextValue | null, args?: TemplateArgs | null, options?: OsdPanelOptions): void;
3119
+ }
3120
+ ```
3121
+
3122
+ ### OsdPanelOptions
3123
+
3124
+ Options of OsdPanel.set.
3125
+
3126
+ ```ts
3127
+ interface OsdPanelOptions {
3128
+ /**
3129
+ * Cut every line longer than this many columns, after translation and formatting, ending it with `…`: a wide character (Chinese, Japanese, Korean, full-width forms) is two columns, a combining mark none, any other one. An integer from 8 to 1000 (player 0.4.3; older players show whole lines). Measure the video area to choose it.
2977
3130
  */
2978
- set(text: string | null, args?: TemplateArgs): void;
3131
+ maxColumns?: number;
2979
3132
  }
2980
3133
  ```
2981
3134
 
@@ -2998,7 +3151,7 @@ interface Osd {
2998
3151
  * @throws unavailable (rejects) The player runs without a user interface.
2999
3152
  * @throws capability (rejects) The manifest does not declare `ui.osd`.
3000
3153
  */
3001
- show(text: string, args?: TemplateArgs): Promise<void>;
3154
+ show(text: TextValue, args?: TemplateArgs): Promise<void>;
3002
3155
  /**
3003
3156
  * Create this plugin's information block.
3004
3157
  * @capability ui.osd
@@ -3268,7 +3421,9 @@ interface Subtitles {
3268
3421
  /**
3269
3422
  * Upload a subtitle file's bytes (UTF-8 SRT, or ASS/SSA with
3270
3423
  * `format: "ass"`) for the current source; select it unless
3271
- * `select: "none"`. `title` (1–200 characters) names the track. Aborting
3424
+ * `select: "none"`. `title` (1–200 characters) names the track: data, or
3425
+ * a Text the player translates (`text("{} · {}", [text("Simplified
3426
+ * Chinese"), file])`, SDK 1.5.11). Aborting
3272
3427
  * `signal` before the commit discards the upload (rejects with AbortError);
3273
3428
  * once the commit was sent it completes.
3274
3429
  *
@@ -3278,7 +3433,7 @@ interface Subtitles {
3278
3433
  */
3279
3434
  load(bytes: Uint8Array, options?: SubtitleConditional & {
3280
3435
  format?: "srt" | "ass";
3281
- title?: string;
3436
+ title?: string | Text;
3282
3437
  select?: "primary" | "secondary" | "none";
3283
3438
  signal?: AbortSignal;
3284
3439
  }): Promise<SubtitleTrack>;
@@ -3810,8 +3965,12 @@ One command's bindings, from Bindings.list.
3810
3965
  interface BindingInfo extends BindingRef {
3811
3966
  /** Menu title. */
3812
3967
  title: string;
3813
- /** Menu path; `null` for a command outside the menu. */
3968
+ /** Menu path as shown; `null` for a command outside the menu. */
3814
3969
  path: string[] | null;
3970
+ /**
3971
+ * The menu path's keys: the English text menus merge by, the same in every interface language (`["Playback", "Seek", "Back 5 s"]`; a built-in menu by its key, `"Video"`, also when declared as `@video`). `null` for a command outside the menu, and from players before 0.4.3. Find a command by where it is in the menu with this, not with `path`. Always set by `list()`; optional so that test fakes written for older SDKs still type-check.
3972
+ */
3973
+ key?: string[] | null;
3815
3974
  /** Global, or only while the plugin's panel has focus. */
3816
3975
  scope: "global" | "panel";
3817
3976
  /** The command's own bindings. */
@@ -4287,8 +4446,9 @@ and its semantics are simplified:
4287
4446
  value ranges (an out-of-range `filter.set` ends in `failed` with
4288
4447
  `invalid`), an empty chain removes the plugin's chain, a chain on a
4289
4448
  generated stream fails `unsupported` (the player's own conformance
4290
- cases check all three), and the command limits (COMMAND_LIMITS)
4291
- and menu ids (MENU_IDS) are enforced.
4449
+ cases check all three), and the command limits (COMMAND_LIMITS),
4450
+ property value limits (UI_VALUE_LIMITS) and menu ids
4451
+ (MENU_IDS) are enforced.
4292
4452
 
4293
4453
  Typical workflow: start the plugin with startPlugin (it reads the
4294
4454
  plugin's `manifest.json`), drive it the way the user or another plugin
@@ -4329,6 +4489,21 @@ interface FakeWindow {
4329
4489
  }
4330
4490
  ```
4331
4491
 
4492
+ ### FileDialogText
4493
+
4494
+ A file dialog as the player shows it (TestHost.fileDialogs).
4495
+
4496
+ ```ts
4497
+ interface FileDialogText {
4498
+ /** Which dialog. */
4499
+ kind: "openFile" | "openFiles" | "openDirectory" | "saveFile";
4500
+ /** Its title as shown, if the plugin gave one. */
4501
+ title?: string;
4502
+ /** The proposed file name as shown, if the plugin gave one. */
4503
+ fileName?: string;
4504
+ }
4505
+ ```
4506
+
4332
4507
  ### FakeCommand
4333
4508
 
4334
4509
  A command the plugin registered with `plugin.commands.add`, as the test
@@ -4347,6 +4522,10 @@ interface FakeCommand {
4347
4522
  title: string;
4348
4523
  /** Each segment of the path as shown; empty without a path. */
4349
4524
  path: string[];
4525
+ /**
4526
+ * The disabled or busy reason as shown, `null` without one (a plugin command's; not enumerable, so comparing `display` with `{ title, path }` still works).
4527
+ */
4528
+ reason?: string | null;
4350
4529
  };
4351
4530
  /** The command state the player last received (after the update pass). */
4352
4531
  state: {
@@ -4356,8 +4535,8 @@ interface FakeCommand {
4356
4535
  checked: boolean | null;
4357
4536
  /** `true` while the plugin reports the command as busy. */
4358
4537
  busy: boolean;
4359
- /** The reason shown when the command is disabled or busy. */
4360
- reason: string | null;
4538
+ /** The reason the plugin sent (source text or a text value; see `display.reason`). */
4539
+ reason: TextValue | null;
4361
4540
  };
4362
4541
  /** The state revision the player holds; increases with every state update the SDK sends. */
4363
4542
  revision: number;
@@ -4518,7 +4697,7 @@ class TestHost implements Transport {
4518
4697
  * @param args - Values for its placeholders.
4519
4698
  * @returns The shown text.
4520
4699
  */
4521
- translate(text: string, args?: TemplateArgs): string;
4700
+ translate(text: TextValue, args?: TemplateArgs): string;
4522
4701
  /** The saved interface language (`plugin.appearance.language`), changed by `appearance.setLanguage` or TestHost.setLanguage. */
4523
4702
  language: LanguagePreference;
4524
4703
  /**
@@ -4541,6 +4720,10 @@ class TestHost implements Transport {
4541
4720
  /** The checkbox, if any. */
4542
4721
  checkbox?: string;
4543
4722
  }[];
4723
+ /**
4724
+ * Every file dialog (`openFile`, `openFiles`, `openDirectory`, `saveFile`) as the player shows it: the title translated, a text file name translated, newest last. The options the plugin sent are in `host.sent("dialogs.open")`.
4725
+ */
4726
+ readonly fileDialogs: FileDialogText[];
4544
4727
  /** The sequence provider's flags, `null` without a provider. */
4545
4728
  sequence: {
4546
4729
  /** The provider's `canNext`, as last evaluated. */
@@ -5257,6 +5440,70 @@ they agree).
5257
5440
  const LOCALES: readonly ["en", "zh-Hans", "ja", "ko", "de", "fr", "es"];
5258
5441
  ```
5259
5442
 
5443
+ ### LIST_SEPARATORS
5444
+
5445
+ The separator of each list style per interface language, as the player's
5446
+ table (`i18n::text::SEPARATORS`; its tests check that they agree).
5447
+
5448
+ ```ts
5449
+ const LIST_SEPARATORS: Readonly<Record<Locale, Readonly<Record<ListStyle, string>>>>;
5450
+ ```
5451
+
5452
+ ### TEXT_LIMITS
5453
+
5454
+ The player's limits on one text value (a
5455
+ Text or
5456
+ TextList with everything nested in it), as the player's
5457
+ `i18n::text` (its tests check that they agree).
5458
+
5459
+ ```ts
5460
+ const TEXT_LIMITS: {
5461
+ /** Nesting depth of texts and lists; the value itself is depth 0 (8). */
5462
+ readonly depth: 8;
5463
+ /** Texts, lists and arguments in all, the value itself included (1024). */
5464
+ readonly nodes: 1024;
5465
+ /** Arguments of one text (16). */
5466
+ readonly args: 16;
5467
+ /** Items of one list (256). */
5468
+ readonly items: 256;
5469
+ /** UTF-8 bytes of a source text or a string argument (4096). */
5470
+ readonly stringBytes: 4096;
5471
+ };
5472
+ ```
5473
+
5474
+ ### UI_VALUE_LIMITS
5475
+
5476
+ The player's limits on one property value (a `PropValue` as written
5477
+ by `View.set` or `View.bind`, or an initial property of a
5478
+ window, panel or settings page). The player's tests check that these
5479
+ agree with the player; TestHost enforces them the same way.
5480
+
5481
+ A value over a limit is refused whole with code `limit` (the property
5482
+ keeps what it showed) and reported to `Scope.onError`: a write by
5483
+ `View.set` or `View.bind` as described there. As an initial property it
5484
+ makes `Window.show` reject; a panel or settings page opens without it and
5485
+ the failure goes to the plugin's `onError`.
5486
+
5487
+ They bound the work one write costs the player's interface thread; they
5488
+ are not meant as list sizes to aim for. A list that can grow without
5489
+ bound (a playlist, a history) should send the rows near the view and say
5490
+ how many there are, not the whole list.
5491
+
5492
+ ```ts
5493
+ const UI_VALUE_LIMITS: {
5494
+ /** Nesting depth; the value itself is depth 0 (8). */
5495
+ readonly depth: 8;
5496
+ /** Values in all, counting every array, object, string, number, boolean and null, the value itself included; a Markdown document is one (16384). */
5497
+ readonly values: 16384;
5498
+ /** Rows of one array (4096). */
5499
+ readonly arrayRows: 4096;
5500
+ /** UTF-8 bytes of one string or object field name (64 KiB). */
5501
+ readonly stringBytes: number;
5502
+ /** UTF-8 bytes of all strings and field names together, the text of the value's Markdown documents included (1 MiB). */
5503
+ readonly textBytes: number;
5504
+ };
5505
+ ```
5506
+
5260
5507
  ### HostError
5261
5508
 
5262
5509
  A definite refusal from the player (or the plugin runner), with a stable
@@ -5653,9 +5900,10 @@ interface WireSystemInfo {
5653
5900
 
5654
5901
  ```ts
5655
5902
  type CommandDeclaration = {
5656
- title: string;
5657
- /** Complete primary menu path INCLUDING its leaf; empty = not in the main menu. */
5658
- path: string[];
5903
+ /** Source text, or a text value (player 0.4.3). */
5904
+ title: string | TextJson;
5905
+ /** Complete primary menu path INCLUDING its leaf; empty = not in the main menu. Segments may be text values (player 0.4.3). */
5906
+ path: (string | TextJson)[];
5659
5907
  /** Sibling order, ascending; a submenu takes its first command's order (a built-in menu keeps a fixed one). */
5660
5908
  order: number;
5661
5909
  /** Separator label: adjacent siblings of different groups get a line. */
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # Vestra Player SDK
2
2
 
3
- > @vestra-player/sdk 1.5.9: 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. llms-full.txt, next to this file, has every declaration, the guides and the examples; L<n> below are its line numbers.
3
+ > @vestra-player/sdk 1.5.11: 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. llms-full.txt, next to this file, has every declaration, the guides and the examples; L<n> below are its line numbers.
4
4
 
5
5
  **How plugins run**
6
6
 
@@ -137,7 +137,7 @@ test("shows the position", async () => {
137
137
  - `failed`: The operation ran and failed
138
138
  - `aborted`: An `AbortSignal` fired
139
139
  - `timeout`: A time limit ran out
140
- - `limit`: A player-wide limit was reached
140
+ - `limit`: A player-wide limit was reached, a property value is over the limits of PropValue, or a request is longer than the player's 1 MiB message
141
141
  - `reserved`: Packages.validate, PackageCandidate.install: the id is `vestra` or starts with `vestra.`, which only the player's built-in plugins use
142
142
  - `versionMismatch`: The package needs a newer player or another `apiVersion`
143
143
  - `ui-prepare`: The player could not prepare a mounted panel or a settings page
@@ -152,56 +152,56 @@ test("shows the position", async () => {
152
152
  - [Concept: Windows, panels, settings pages, dialogs and the OSD](https://vestrasys.github.io/vestra-player-sdk/documents/Windows__panels__settings_pages__dialogs_and_the_OSD.html): L281–626
153
153
  - [How-to: Keep a slider responsive while dragging](https://vestrasys.github.io/vestra-player-sdk/documents/Keep_a_slider_responsive_while_dragging.html): L627–801
154
154
  - [How-to: Remember a window's state between runs](https://vestrasys.github.io/vestra-player-sdk/documents/Remember_a_window_s_state_between_runs.html): L802–931
155
- - [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L932–4268
156
- - [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html) (TestHost, startPlugin): L4269–5290
155
+ - [API: @vestra-player/sdk](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk.html): L932–4427
156
+ - [API: @vestra-player/sdk/testing](https://vestrasys.github.io/vestra-player-sdk/modules/_vestra-player_sdk_testing.html) (TestHost, startPlugin): L4428–5537
157
157
 
158
158
  ## API
159
159
 
160
160
  Where each module of `plugin` is declared:
161
161
 
162
162
  - Plugin L1153, Scope L1022, PluginError L974, Disposable L947
163
- - plugin.commands: Commands L1356
164
- - plugin.windows: Windows L1561
165
- - plugin.panels: Panels L2070
166
- - plugin.dialogs: Dialogs L2356
167
- - plugin.player: Player L2795
168
- - plugin.video: VideoFilter L3046, VideoView L3109, RenderOptions L3151
169
- - plugin.audio: AudioFilter L3070
170
- - plugin.subtitles: Subtitles L3249
171
- - plugin.media: MediaCapture L3407
172
- - plugin.resolvers: Resolvers L3512
173
- - plugin.packages: Packages L3752
174
- - plugin.osd: Osd L2982
175
- - plugin.host: Host L2944
176
- - plugin.clipboard: Clipboard L3865
177
- - plugin.power: Power L3885
178
- - plugin.tools: Tools L3918
179
- - plugin.storage: Storage L3961
180
- - plugin.system: System L3984
181
- - plugin.secrets: Secrets L4002
182
- - plugin.window: MainWindow L2193
183
- - plugin.app: App L2274
184
- - plugin.bindings: Bindings L3835
185
- - plugin.ui: Ui L1448
186
- - plugin.timeline: Timeline L2150
187
- - plugin.drops: Drops L1858
188
- - plugin.appearance: Appearance L1887
189
- - plugin.i18n: I18n L1959
190
- - plugin.settings: Settings L2003
163
+ - plugin.commands: Commands L1361
164
+ - plugin.windows: Windows L1566
165
+ - plugin.panels: Panels L2207
166
+ - plugin.dialogs: Dialogs L2493
167
+ - plugin.player: Player L2934
168
+ - plugin.video: VideoFilter L3199, VideoView L3262, RenderOptions L3304
169
+ - plugin.audio: AudioFilter L3223
170
+ - plugin.subtitles: Subtitles L3402
171
+ - plugin.media: MediaCapture L3562
172
+ - plugin.resolvers: Resolvers L3667
173
+ - plugin.packages: Packages L3907
174
+ - plugin.osd: Osd L3135
175
+ - plugin.host: Host L3083
176
+ - plugin.clipboard: Clipboard L4024
177
+ - plugin.power: Power L4044
178
+ - plugin.tools: Tools L4077
179
+ - plugin.storage: Storage L4120
180
+ - plugin.system: System L4143
181
+ - plugin.secrets: Secrets L4161
182
+ - plugin.window: MainWindow L2330
183
+ - plugin.app: App L2411
184
+ - plugin.bindings: Bindings L3994
185
+ - plugin.ui: Ui L1453
186
+ - plugin.timeline: Timeline L2287
187
+ - plugin.drops: Drops L1863
188
+ - plugin.appearance: Appearance L1892
189
+ - plugin.i18n: I18n L2034
190
+ - plugin.settings: Settings L2140
191
191
 
192
192
  ## Examples
193
193
 
194
194
  Complete plugins with tests, in [examples/](https://github.com/vestrasys/vestra-player-sdk/tree/main/examples) and in llms-full.txt:
195
195
 
196
- - hello: The README Quick start: one menu command and an on-screen message. L5706–5795
197
- - blur: A tool window with one slider that blurs the playing video. L5796–6057
198
- - signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L6058–6390
199
- - bookmark: A tool window bound to the playback state: remember the position and jump back to it. L6391–6575
200
- - panel-menu: A sidebar panel with its own right-click menu. L6576–6781
201
- - menus: Radio menu items, separator groups and a menu item whose title changes. L6782–6941
202
- - theme-widgets: A tool window drawn with the player's theme and widgets. L6942–7105
203
- - markdown: A window that shows a Markdown document. L7106–7299
204
- - i18n: A plugin in the player's language: English source text, a Chinese translation. L7300–7467
196
+ - hello: The README Quick start: one menu command and an on-screen message. L5954–6043
197
+ - blur: A tool window with one slider that blurs the playing video. L6044–6305
198
+ - signal-generator: Generates its own video and audio: colour bars and a 1 kHz tone. L6306–6638
199
+ - bookmark: A tool window bound to the playback state: remember the position and jump back to it. L6639–6823
200
+ - panel-menu: A sidebar panel with its own right-click menu. L6824–7029
201
+ - menus: Radio menu items, separator groups and a menu item whose title changes. L7030–7189
202
+ - theme-widgets: A tool window drawn with the player's theme and widgets. L7190–7353
203
+ - markdown: A window that shows a Markdown document. L7354–7547
204
+ - i18n: A plugin in the player's language: English source text, a Chinese translation. L7548–7715
205
205
 
206
206
  ## Optional
207
207
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.5.9",
3
+ "version": "1.5.11",
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": {