@vestra-player/sdk 1.6.7 → 1.6.9
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 +18 -0
- package/bin/vestra-plugin.mjs +1 -84
- package/dist/api-requests.js +5 -1
- package/dist/commands.d.ts +6 -7
- package/dist/commands.js +6 -7
- package/dist/docs-tree.json.gz +0 -0
- package/dist/host-capabilities.js +4 -1
- package/dist/player-runtime.d.ts +1 -0
- package/dist/player-runtime.js +1 -0
- package/dist/plugin/osd.d.ts +4 -0
- package/dist/plugin/osd.js +26 -1
- package/dist/plugin/testing.d.ts +100 -2
- package/dist/plugin/testing.js +160 -5
- package/dist/plugin/timeline.d.ts +40 -3
- package/dist/plugin/timeline.js +102 -10
- package/dist/plugin/types.d.ts +204 -21
- package/dist/wire.d.ts +27 -4
- package/dist/wire.js +8 -1
- package/llms.txt +4 -4
- package/package.json +1 -1
- package/slint/vestra/bar-buttons.slint +72 -16
package/dist/plugin/types.d.ts
CHANGED
|
@@ -954,17 +954,17 @@ export type BarButtonIcon = "play" | "pause" | "stop" | "back" | "forward" | "op
|
|
|
954
954
|
* A command's button on the bottom bar: {@link CommandOptions.button}.
|
|
955
955
|
*
|
|
956
956
|
* @remarks
|
|
957
|
-
* **Where it shows.** The
|
|
958
|
-
*
|
|
959
|
-
*
|
|
960
|
-
* `order`,
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
*
|
|
965
|
-
*
|
|
966
|
-
*
|
|
967
|
-
* [
|
|
957
|
+
* **Where it shows.** The player draws the bottom bar's button strip and
|
|
958
|
+
* decides where it goes: today at the right end of the bottom bar; this may
|
|
959
|
+
* change (older players let the bar place `BarButtons` itself). Buttons
|
|
960
|
+
* are ordered by `order`, then by plugin id; lower `order` comes first and
|
|
961
|
+
* stays visible longest. When the strip runs out of room, or more than 8
|
|
962
|
+
* plugin buttons are declared, the remaining buttons move to the strip's »
|
|
963
|
+
* menu, in the same order. A button is never dropped: it is either in the
|
|
964
|
+
* strip or in the » menu, and its command keeps its menu entry, its key and
|
|
965
|
+
* its place in the command palette. Users may pin and unpin buttons later;
|
|
966
|
+
* do not rely on a position. See
|
|
967
|
+
* [Bottom-bar buttons](../../docs/explanation/commands.md#bottom-bar-buttons).
|
|
968
968
|
*
|
|
969
969
|
* **What it shows.** The icon, the command's title (translated, a trailing
|
|
970
970
|
* "…" removed) and its first key as the tooltip ("Plugin Store (F9)"),
|
|
@@ -974,9 +974,9 @@ export type BarButtonIcon = "play" | "pause" | "stop" | "back" | "forward" | "op
|
|
|
974
974
|
* a command with `checked` shows a small dot under its icon while checked.
|
|
975
975
|
* A click runs the command exactly like a click on its menu item.
|
|
976
976
|
*
|
|
977
|
-
* **Limits.** One button per plugin
|
|
978
|
-
*
|
|
979
|
-
*
|
|
977
|
+
* **Limits.** One button per plugin, the first it declares (a later one
|
|
978
|
+
* stays a menu item only), and eight in the strip (`BAR_BUTTON_LIMITS`); the
|
|
979
|
+
* rest are in the » menu. The button goes
|
|
980
980
|
* with its command: disposing the command, or disabling, stopping or
|
|
981
981
|
* uninstalling the plugin, removes it.
|
|
982
982
|
*
|
|
@@ -984,8 +984,7 @@ export type BarButtonIcon = "play" | "pause" | "stop" | "back" | "forward" | "op
|
|
|
984
984
|
* A Store icon appears in the bottom bar's button strip; a click opens
|
|
985
985
|
* the store window, exactly like the menu item. The player draws the
|
|
986
986
|
* button from the command's title, keys and state, and places it by
|
|
987
|
-
* `order` (200 is where the player's own Plugin Store button sits)
|
|
988
|
-
* bar that does not place `BarButtons` shows only the menu item.
|
|
987
|
+
* `order` (200 is where the player's own Plugin Store button sits).
|
|
989
988
|
* ```ts
|
|
990
989
|
* const store = plugin.windows.create("ui/store.slint");
|
|
991
990
|
* plugin.commands.add({
|
|
@@ -1238,8 +1237,8 @@ export interface CommandOptions {
|
|
|
1238
1237
|
/**
|
|
1239
1238
|
* A button for this command on the bottom bar (SDK 1.5.29, player 0.5.10):
|
|
1240
1239
|
* an icon and a place, `{ icon: "store", order: 200 }`. Needs a `path`: the
|
|
1241
|
-
* menu entry is where the command stays reachable
|
|
1242
|
-
*
|
|
1240
|
+
* menu entry is where the command stays reachable wherever the button
|
|
1241
|
+
* is (the strip or its » menu). See
|
|
1243
1242
|
* {@link CommandButton} for where it shows, what it shows and the limits.
|
|
1244
1243
|
* Fails with `invalid` for an unknown icon name, an order outside 0–999 or
|
|
1245
1244
|
* a button without a path.
|
|
@@ -4217,6 +4216,36 @@ export interface TimelineMark {
|
|
|
4217
4216
|
/** The manifest id of the plugin that published it. */
|
|
4218
4217
|
readonly plugin: string;
|
|
4219
4218
|
}
|
|
4219
|
+
/**
|
|
4220
|
+
* How a timeline range is drawn; readers choose colours by it.
|
|
4221
|
+
*
|
|
4222
|
+
* - `"selection"`: a span the user picked to act on, such as a clip to
|
|
4223
|
+
* export. The player's seek bar draws it in the accent colour.
|
|
4224
|
+
* - `"region"`: a part of the media the plugin describes, such as an intro
|
|
4225
|
+
* or a chapter's span. Drawn dimmer, under selections.
|
|
4226
|
+
*
|
|
4227
|
+
* @since 1.6.9
|
|
4228
|
+
* @category Playback
|
|
4229
|
+
*/
|
|
4230
|
+
export type RangeStyle = "selection" | "region";
|
|
4231
|
+
/**
|
|
4232
|
+
* One range on the seek bar (player 0.7.6).
|
|
4233
|
+
*
|
|
4234
|
+
* @since 1.6.9
|
|
4235
|
+
* @category Playback
|
|
4236
|
+
*/
|
|
4237
|
+
export interface TimelineRange {
|
|
4238
|
+
/** Seconds from the start. */
|
|
4239
|
+
readonly start: number;
|
|
4240
|
+
/** Seconds from the start, after `start`. */
|
|
4241
|
+
readonly end: number;
|
|
4242
|
+
/** How it is drawn. */
|
|
4243
|
+
readonly style: RangeStyle;
|
|
4244
|
+
/** Label, `null` without one. */
|
|
4245
|
+
readonly title: string | null;
|
|
4246
|
+
/** The manifest id of the plugin that published it. */
|
|
4247
|
+
readonly plugin: string;
|
|
4248
|
+
}
|
|
4220
4249
|
/**
|
|
4221
4250
|
* This plugin's own marks; disposing it removes them.
|
|
4222
4251
|
*
|
|
@@ -4274,6 +4303,54 @@ export interface TimelineLayer extends Disposable {
|
|
|
4274
4303
|
}[], options?: {
|
|
4275
4304
|
ifCurrent?: PlayerState;
|
|
4276
4305
|
}): void;
|
|
4306
|
+
/**
|
|
4307
|
+
* Replace the layer's ranges (last write wins; `[]` clears them), spans of
|
|
4308
|
+
* the media drawn on the seek bar (player 0.7.6). The marks and the ranges
|
|
4309
|
+
* of a layer are replaced on their own: `set` keeps the ranges and
|
|
4310
|
+
* `setRanges` keeps the marks. Disposing the layer, its scope or stopping
|
|
4311
|
+
* the plugin removes both, and a new source clears every layer.
|
|
4312
|
+
*
|
|
4313
|
+
* At most 100 ranges (`TIMELINE_LIMITS.ranges`), `0 ≤ start < end`, `end`
|
|
4314
|
+
* within the media while its duration is known, titles ≤ 100 characters.
|
|
4315
|
+
* Ranges may overlap. Failures go to `onError`; with `ifCurrent`, a
|
|
4316
|
+
* write for another source is dropped silently. A title is data or a
|
|
4317
|
+
* {@link Text} the player translates, as in `set`.
|
|
4318
|
+
*
|
|
4319
|
+
* Players before 0.7.6 build `plugin` from an SDK without `setRanges`, so
|
|
4320
|
+
* the call throws a `TypeError` there: declare
|
|
4321
|
+
* `"minPlayerVersion": "0.7.6"`.
|
|
4322
|
+
*
|
|
4323
|
+
* @example Show the clip range on the seek bar while a panel is open
|
|
4324
|
+
* The span the user picked shows on the seek bar in the accent colour
|
|
4325
|
+
* while the plugin's tab is showing, and goes when it is not. Two point
|
|
4326
|
+
* marks would show the ends but not the span between them.
|
|
4327
|
+
* ```ts
|
|
4328
|
+
* declare const panel: Panel;
|
|
4329
|
+
* declare const clip: { start: number; end: number };
|
|
4330
|
+
* // ---cut---
|
|
4331
|
+
* const layer = plugin.timeline.layer();
|
|
4332
|
+
* // Only while the tab is on screen; [] takes the range away.
|
|
4333
|
+
* const show = () =>
|
|
4334
|
+
* layer.setRanges(
|
|
4335
|
+
* panel.state?.effective
|
|
4336
|
+
* ? [{ start: clip.start, end: clip.end, style: "selection", title: "Clip" }]
|
|
4337
|
+
* : [],
|
|
4338
|
+
* { ifCurrent: plugin.player.state },
|
|
4339
|
+
* );
|
|
4340
|
+
* panel.onChange(show);
|
|
4341
|
+
* ```
|
|
4342
|
+
*
|
|
4343
|
+
* @capability timeline.marks
|
|
4344
|
+
* @since 1.6.9
|
|
4345
|
+
*/
|
|
4346
|
+
setRanges(ranges: {
|
|
4347
|
+
start: number;
|
|
4348
|
+
end: number;
|
|
4349
|
+
style: RangeStyle;
|
|
4350
|
+
title?: string | Text;
|
|
4351
|
+
}[], options?: {
|
|
4352
|
+
ifCurrent?: PlayerState;
|
|
4353
|
+
}): void;
|
|
4277
4354
|
}
|
|
4278
4355
|
/**
|
|
4279
4356
|
* `plugin.timeline`: marks on the seek bar. Every plugin publishes one
|
|
@@ -4304,6 +4381,38 @@ export interface TimelineLayer extends Disposable {
|
|
|
4304
4381
|
export interface Timeline {
|
|
4305
4382
|
/** Every layer merged, by time (`playback.read`). Empty on a new source. */
|
|
4306
4383
|
readonly marks: readonly TimelineMark[];
|
|
4384
|
+
/**
|
|
4385
|
+
* Every layer's ranges merged, by start (`playback.read`; player 0.7.6:
|
|
4386
|
+
* on older players `ranges` does not exist and reads `undefined`). Empty
|
|
4387
|
+
* on a new source. Kept current like `marks` (with `events`): read it in
|
|
4388
|
+
* a {@link View.bind} function and the view follows it. `onChange` runs
|
|
4389
|
+
* only when the marks change.
|
|
4390
|
+
*
|
|
4391
|
+
* @example Draw the published ranges in a seek bar of your own
|
|
4392
|
+
* A bottom bar draws a band for every range on the seek bar, whoever
|
|
4393
|
+
* published it, as fractions of the duration.
|
|
4394
|
+
* ```ts
|
|
4395
|
+
* declare const bar: View;
|
|
4396
|
+
* // ---cut---
|
|
4397
|
+
* bar.bind(() => {
|
|
4398
|
+
* // Reading `ranges` here runs the binding again when they change.
|
|
4399
|
+
* const duration = plugin.player.state.duration ?? 0;
|
|
4400
|
+
* return {
|
|
4401
|
+
* ranges: duration
|
|
4402
|
+
* ? plugin.timeline.ranges.map((range) => ({
|
|
4403
|
+
* from: range.start / duration,
|
|
4404
|
+
* to: range.end / duration,
|
|
4405
|
+
* selection: range.style === "selection",
|
|
4406
|
+
* }))
|
|
4407
|
+
* : [],
|
|
4408
|
+
* };
|
|
4409
|
+
* });
|
|
4410
|
+
* ```
|
|
4411
|
+
*
|
|
4412
|
+
* @capability playback.read
|
|
4413
|
+
* @since 1.6.9
|
|
4414
|
+
*/
|
|
4415
|
+
readonly ranges: readonly TimelineRange[];
|
|
4307
4416
|
/**
|
|
4308
4417
|
* The merged list changed (needs `events`; at most every 100 ms).
|
|
4309
4418
|
*
|
|
@@ -6701,12 +6810,19 @@ export interface Osd {
|
|
|
6701
6810
|
*
|
|
6702
6811
|
* @param text - The template, 1–200 characters once translated and
|
|
6703
6812
|
* formatted; line breaks become spaces.
|
|
6813
|
+
* With `options.actions` (player 0.7.6) the message ends in up to two
|
|
6814
|
+
* buttons, each running one of the plugin's own commands
|
|
6815
|
+
* ({@link OsdShowOptions}). Older players show the message without them.
|
|
6816
|
+
*
|
|
6704
6817
|
* @param args - Values for its placeholders (player 0.4.3; older players
|
|
6705
|
-
* show the template as it is).
|
|
6818
|
+
* show the template as it is). Pass `null` with a `Text` and options.
|
|
6819
|
+
* @param options - Action buttons after the text (SDK 1.6.9).
|
|
6706
6820
|
* @returns Resolves once the message is on screen.
|
|
6707
6821
|
*
|
|
6708
6822
|
* @throws `invalid` (rejects) The shown text is empty, only white space,
|
|
6709
|
-
* or longer than 200 characters, or `args` is not a {@link TemplateArgs}
|
|
6823
|
+
* or longer than 200 characters, or `args` is not a {@link TemplateArgs};
|
|
6824
|
+
* or there are more than 2 actions, a title is empty or longer than 40
|
|
6825
|
+
* characters once translated, or a command is not one of the plugin's.
|
|
6710
6826
|
* @throws `unavailable` (rejects) The player runs without a user interface.
|
|
6711
6827
|
* @throws `capability` (rejects) The manifest does not declare `ui.osd`.
|
|
6712
6828
|
*
|
|
@@ -6720,9 +6836,28 @@ export interface Osd {
|
|
|
6720
6836
|
* await plugin.osd.show("Speed {}×", [plugin.player.state.rate]);
|
|
6721
6837
|
* ```
|
|
6722
6838
|
*
|
|
6839
|
+
* @example Offer "Show in Folder" after saving a file
|
|
6840
|
+
* The OSD reads "Saved clip.mp4 [Show in Folder]" for about 4 seconds,
|
|
6841
|
+
* longer while the pointer is on it. A click runs the plugin's own
|
|
6842
|
+
* `reveal` command, which knows the last saved file; the message goes.
|
|
6843
|
+
* ```ts
|
|
6844
|
+
* declare const path: string;
|
|
6845
|
+
* // ---cut---
|
|
6846
|
+
* let saved = path; // the command acts on the last saved file
|
|
6847
|
+
* plugin.commands.add({
|
|
6848
|
+
* id: "reveal",
|
|
6849
|
+
* title: "Show Last Saved File in Folder",
|
|
6850
|
+
* enabled: () => saved !== "",
|
|
6851
|
+
* run: () => plugin.system.reveal(saved),
|
|
6852
|
+
* });
|
|
6853
|
+
* await plugin.osd.show("Saved {}", [saved.split(/[\\/]/).pop() ?? saved], {
|
|
6854
|
+
* actions: [{ title: "Show in Folder", command: "reveal" }], // one button
|
|
6855
|
+
* });
|
|
6856
|
+
* ```
|
|
6857
|
+
*
|
|
6723
6858
|
* @since 1.0.0
|
|
6724
6859
|
*/
|
|
6725
|
-
show(text: TextValue, args?: TemplateArgs): Promise<void>;
|
|
6860
|
+
show(text: TextValue, args?: TemplateArgs | null, options?: OsdShowOptions): Promise<void>;
|
|
6726
6861
|
/**
|
|
6727
6862
|
* Create this plugin's information block.
|
|
6728
6863
|
*
|
|
@@ -6749,6 +6884,54 @@ export interface Osd {
|
|
|
6749
6884
|
*/
|
|
6750
6885
|
panel(): OsdPanel;
|
|
6751
6886
|
}
|
|
6887
|
+
/**
|
|
6888
|
+
* One button at the end of an OSD message ({@link Osd.show}, player 0.7.6).
|
|
6889
|
+
*
|
|
6890
|
+
* @since 1.6.9
|
|
6891
|
+
* @category UI
|
|
6892
|
+
*/
|
|
6893
|
+
export interface OsdAction {
|
|
6894
|
+
/**
|
|
6895
|
+
* The button's label: English source text the player translates with the
|
|
6896
|
+
* plugin's catalog, or a {@link Text}; 1–40 characters once translated
|
|
6897
|
+
* (`OSD_LIMITS.actionChars`). A verb, as on a menu item: "Show in
|
|
6898
|
+
* Folder", "Copy", "Undo".
|
|
6899
|
+
*/
|
|
6900
|
+
title: TextValue;
|
|
6901
|
+
/**
|
|
6902
|
+
* The local id of one of this plugin's own commands
|
|
6903
|
+
* ({@link CommandOptions.id}), declared when the message is shown. A
|
|
6904
|
+
* click runs it as if the user picked it from a menu: a disabled command
|
|
6905
|
+
* does nothing. The command takes no arguments, so it acts on what the
|
|
6906
|
+
* plugin remembers (the file it just saved).
|
|
6907
|
+
*/
|
|
6908
|
+
command: string;
|
|
6909
|
+
}
|
|
6910
|
+
/**
|
|
6911
|
+
* Options of {@link Osd.show} (SDK 1.6.9).
|
|
6912
|
+
*
|
|
6913
|
+
* @remarks
|
|
6914
|
+
* A message with actions stays about 4 seconds instead of 2, and does not
|
|
6915
|
+
* fade while the pointer is on it and moving: it goes 2 seconds after the
|
|
6916
|
+
* pointer leaves or rests (the player's idle time), and at the latest 30
|
|
6917
|
+
* seconds after it showed, hovered or not. A click on a button runs its
|
|
6918
|
+
* command and removes the message.
|
|
6919
|
+
* It is still one line: the buttons follow the text. Buttons take no
|
|
6920
|
+
* keyboard focus; screen readers can press them. A newer message, from any
|
|
6921
|
+
* plugin or the player, replaces the message with its buttons, and the
|
|
6922
|
+
* buttons go when the plugin stops. While its buttons show, the plugin is
|
|
6923
|
+
* not stopped for being idle.
|
|
6924
|
+
*
|
|
6925
|
+
* Players before 0.7.6 ignore `actions` and show the text alone for 2
|
|
6926
|
+
* seconds, so do not make an action the only way to reach something.
|
|
6927
|
+
*
|
|
6928
|
+
* @since 1.6.9
|
|
6929
|
+
* @category UI
|
|
6930
|
+
*/
|
|
6931
|
+
export interface OsdShowOptions {
|
|
6932
|
+
/** At most 2 buttons (`OSD_LIMITS.actions`), in order after the text. */
|
|
6933
|
+
actions?: readonly OsdAction[];
|
|
6934
|
+
}
|
|
6752
6935
|
/**
|
|
6753
6936
|
* The state of a filter, display layer or render options handle.
|
|
6754
6937
|
* After `failed` nothing retries automatically until the next `set()`,
|
package/dist/wire.d.ts
CHANGED
|
@@ -262,6 +262,19 @@ export interface WireMark {
|
|
|
262
262
|
title: string | null;
|
|
263
263
|
plugin: string;
|
|
264
264
|
}
|
|
265
|
+
/** One timeline range as the player merges them (player 0.7.6). */
|
|
266
|
+
export interface WireRange {
|
|
267
|
+
start: number;
|
|
268
|
+
end: number;
|
|
269
|
+
style: "selection" | "region";
|
|
270
|
+
title: string | null;
|
|
271
|
+
plugin: string;
|
|
272
|
+
}
|
|
273
|
+
/** `timeline.marks` and `timeline.changed`; `ranges` from player 0.7.6. */
|
|
274
|
+
export interface WireTimeline {
|
|
275
|
+
marks: WireMark[];
|
|
276
|
+
ranges?: WireRange[];
|
|
277
|
+
}
|
|
265
278
|
/** The backdrop as `layout.state` reports it; `null` without one. */
|
|
266
279
|
export interface LayoutBackdrop {
|
|
267
280
|
owner: number;
|
|
@@ -568,9 +581,7 @@ export declare function createWire(transport: Transport): {
|
|
|
568
581
|
};
|
|
569
582
|
/** Mark layers on the seek bar (`plugin.timeline`). */
|
|
570
583
|
timeline: {
|
|
571
|
-
marks: () => Promise<
|
|
572
|
-
marks: WireMark[];
|
|
573
|
-
}>;
|
|
584
|
+
marks: () => Promise<WireTimeline>;
|
|
574
585
|
set: (marks: {
|
|
575
586
|
time: number;
|
|
576
587
|
kind: string;
|
|
@@ -578,6 +589,15 @@ export declare function createWire(transport: Transport): {
|
|
|
578
589
|
}[], sourceId?: number) => Promise<{
|
|
579
590
|
applied: boolean;
|
|
580
591
|
}>;
|
|
592
|
+
/** Player 0.7.6. */
|
|
593
|
+
setRanges: (ranges: {
|
|
594
|
+
start: number;
|
|
595
|
+
end: number;
|
|
596
|
+
style: string;
|
|
597
|
+
title?: string | TextJson;
|
|
598
|
+
}[], sourceId?: number) => Promise<{
|
|
599
|
+
applied: boolean;
|
|
600
|
+
}>;
|
|
581
601
|
};
|
|
582
602
|
/** Chapters and the A-B loop of the current media. */
|
|
583
603
|
marks: {
|
|
@@ -666,7 +686,10 @@ export declare function createWire(transport: Transport): {
|
|
|
666
686
|
};
|
|
667
687
|
/** `text` is a template in the plugin's catalog, formatted with `args` (player 0.4.3). */
|
|
668
688
|
osd: {
|
|
669
|
-
show: (text: TextValueJson, args?: TemplateArgsJson
|
|
689
|
+
show: (text: TextValueJson, args?: TemplateArgsJson, actions?: {
|
|
690
|
+
title: TextValueJson;
|
|
691
|
+
command: string;
|
|
692
|
+
}[]) => Promise<void>;
|
|
670
693
|
panel: (text: TextValueJson | null, args?: TemplateArgsJson, maxColumns?: number) => Promise<void>;
|
|
671
694
|
};
|
|
672
695
|
layout: {
|
package/dist/wire.js
CHANGED
|
@@ -156,6 +156,11 @@ export function createWire(transport) {
|
|
|
156
156
|
marks,
|
|
157
157
|
...(sourceId === undefined ? {} : { sourceId }),
|
|
158
158
|
}),
|
|
159
|
+
/** Player 0.7.6. */
|
|
160
|
+
setRanges: (ranges, sourceId) => transport.request("timeline.setRanges", {
|
|
161
|
+
ranges,
|
|
162
|
+
...(sourceId === undefined ? {} : { sourceId }),
|
|
163
|
+
}),
|
|
159
164
|
},
|
|
160
165
|
/** Chapters and the A-B loop of the current media. */
|
|
161
166
|
marks: {
|
|
@@ -245,9 +250,11 @@ export function createWire(transport) {
|
|
|
245
250
|
},
|
|
246
251
|
/** `text` is a template in the plugin's catalog, formatted with `args` (player 0.4.3). */
|
|
247
252
|
osd: {
|
|
248
|
-
show: (text, args) => transport.request("osd.show", {
|
|
253
|
+
show: (text, args, actions) => transport.request("osd.show", {
|
|
249
254
|
text,
|
|
250
255
|
...(args === undefined ? {} : { args }),
|
|
256
|
+
// Player 0.7.6; older players ignore it.
|
|
257
|
+
...(actions === undefined ? {} : { actions }),
|
|
251
258
|
}),
|
|
252
259
|
panel: (text, args, maxColumns) => transport.request("osd.panel", {
|
|
253
260
|
text,
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vestra Player SDK
|
|
2
2
|
|
|
3
|
-
> @vestra-player/sdk 1.6.
|
|
3
|
+
> @vestra-player/sdk 1.6.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. 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
|
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
- `/API/Commands`: 15 entries: CommandState, Bindable, Condition, When, MenuId, BarButtonIcon, CommandButton, CommandOptions, Command, Commands, HostAction, Host, BindingRef, BindingInfo, Bindings
|
|
32
32
|
- `/API/Media`: 6 entries: CaptureOptions, Snapshot, ExportOptions, JobState, ExportJob, MediaCapture
|
|
33
33
|
- `/API/Packages`: 10 entries: PackageManifest, PackageSource, InstallOptions, PackageCandidate, PackageChangeStatus, PackageChange, PluginInfo, PluginDisplay, PluginWarning, Packages
|
|
34
|
-
- `/API/Playback`:
|
|
34
|
+
- `/API/Playback`: 20 entries: MarkKind, TimelineMark, RangeStyle, TimelineRange, TimelineLayer, Timeline, AudioTrack, PlayerState, AudioDevice, Chapter, Conditional, Media, Scrub, StreamFrame, StreamOptions,…
|
|
35
35
|
- `/API/Plugin`: 13 entries: Disposable, PluginError, Scope, Plugin, StopReason, DisposeInfo, WindowState, MainWindow, AppInfo, App, SystemInfo, DisplayInfo, Json
|
|
36
36
|
- `/API/Processing`: 18 entries: FilterStatus, VideoFilter, AudioFilter, ViewSettings, VideoView, RenderSettings, RenderOptions, VideoShaders, UpscalingReasonCode, UpscalingReason, UpscalingDecodingCause,…
|
|
37
37
|
- `/API/Services`: 15 entries: Clipboard, Power, ToolResult, Tools, JsonStore, Storage, SessionStorage, System, Secrets, RenderingMode, RenderingPreference, RenderingReasonCode, RenderingReason, RenderingState,…
|
|
38
38
|
- `/API/Sources`: 7 entries: ResolverOptions, WebResolverOptions, FileResolverOptions, ResolvedStream, Resolver, Resolvers, ResolvedMedia
|
|
39
39
|
- `/API/Subtitles`: 5 entries: SubtitleTrack, SubtitlesState, SubtitleConditional, Subtitles, SubtitleStyle
|
|
40
|
-
- `/API/UI`:
|
|
41
|
-
- `/API/Testing`:
|
|
40
|
+
- `/API/UI`: 44 entries: ImageRef, ImageOptions, MarkdownRef, MarkdownOptions, PropValue, PropData, Props, Ui, View, Window, Windows, SlotState, SlotPanel, PanelState, PanelSlot, SidebarSlot, Panel,…
|
|
41
|
+
- `/API/Testing`: 33 entries: CapabilityInfo, CAPABILITY_INFO, MESSAGE_LIMIT, COMMAND_LIMITS, MENU_IDS, BAR_BUTTON_ICONS, BAR_BUTTON_LIMITS, BuiltinSubmenu, BUILTIN_SUBMENUS, BuiltinCommand, BUILTIN_COMMANDS, LOCALES,…
|
|
42
42
|
- `/API/Docs`: 4 entries: DOCS_PAGE_BYTES, DocsOptions, docs, searchDocs
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
// Command buttons of
|
|
1
|
+
// Command buttons of the bottom bar (player 0.5.10, SDK 1.5.29): the buttons
|
|
2
2
|
// that plugins' commands contribute (`commands.add({ button })`) and the
|
|
3
|
-
// player's
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
3
|
+
// player's own. Since SDK 1.6.8 (menu redesign step 3a) the player draws
|
|
4
|
+
// the strip itself, at the right end of the bottom slot, its 40px cells on
|
|
5
|
+
// the slot's bottom edge (a bar's 40px button row), and also when no plugin
|
|
6
|
+
// mounts a bottom bar: `[plugin buttons…][»][Command Palette][Toggle
|
|
7
|
+
// Sidebar]`. A bottom bar places nothing: it lays its controls out left of
|
|
8
|
+
// the strip and says how wide they must stay:
|
|
9
|
+
// import { BarButtonsHost } from "@vestra/bar-buttons.slint";
|
|
10
|
+
// export component MyBar inherits Rectangle {
|
|
11
|
+
// out property <length> content-min-width: ...; // the least your row needs
|
|
12
|
+
// // your row ends at: root.width - BarButtonsHost.width - 4px
|
|
13
|
+
// }
|
|
14
|
+
// The player gives its strip `bar width - content-min-width - 4px` (all of
|
|
15
|
+
// the width without `content-min-width`), so plugin buttons never cover
|
|
16
|
+
// what the bar needs (its time label, UI-BAR-10). Plugin buttons go left to
|
|
17
|
+
// right by ascending `order`, then plugin id, then registration; at most 8
|
|
18
|
+
// are in the strip, and the ones past 8 or past the room are in the `»`
|
|
19
|
+
// menu, in the same order: the lowest order stays longest. `»` shows only
|
|
20
|
+
// while something is in it; the player's own cells always show.
|
|
21
|
+
//
|
|
22
|
+
// `BarButtons` (below) is deprecated: the strip a bar placed itself before
|
|
23
|
+
// SDK 1.6.8. While a bar still places it, the player draws no second strip.
|
|
13
24
|
//
|
|
14
25
|
// The cells look like the bar's own icon buttons: a 32×32 plate on hover
|
|
15
26
|
// and press, the bar's tooltip (ToolTipArea). Every enabled cell draws its
|
|
@@ -43,14 +54,56 @@ export struct BarButtonItem {
|
|
|
43
54
|
dimmed: bool,
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
// Filled by the player
|
|
57
|
+
// Filled by the player. A bar reads `width` (to end its own row left of
|
|
58
|
+
// the strip) and `fixed`; everything else is the player's.
|
|
47
59
|
export global BarButtonsHost {
|
|
48
|
-
// The plugins' buttons, left to right, at most 8.
|
|
60
|
+
// The plugins' buttons for the strip, left to right, at most 8.
|
|
49
61
|
in property <[BarButtonItem]> buttons;
|
|
62
|
+
// How many plugin buttons are past those 8 (always in the `»` menu).
|
|
63
|
+
in property <int> overflow;
|
|
50
64
|
// The sidebar toggle (`token` "" while there is none).
|
|
51
65
|
in property <BarButtonItem> toggle;
|
|
52
|
-
//
|
|
66
|
+
// The command palette (`host/palette`; `token` "" while there is none).
|
|
67
|
+
in property <BarButtonItem> palette;
|
|
68
|
+
// Set when a (deprecated) `BarButtons` exists in this window.
|
|
53
69
|
in-out property <bool> placed;
|
|
70
|
+
// The width the player gives its strip (the player sets it).
|
|
71
|
+
in-out property <length> room;
|
|
72
|
+
// The player's own cells, always shown (step 3b adds Adjust).
|
|
73
|
+
private property <int> own: (root.palette.token != "" ? 1 : 0) + (root.toggle.token != "" ? 1 : 0);
|
|
74
|
+
// The cells a bar must always leave free, 41px each: the player's own,
|
|
75
|
+
// and the `»` cell whenever any plugin button exists (drawn only on
|
|
76
|
+
// overflow, but always reserved, so `»` never covers the bar). Never
|
|
77
|
+
// depends on `room`. A bar that keeps an optional control ahead of the
|
|
78
|
+
// plugins' buttons counts it in `content-min-width` while it fits
|
|
79
|
+
// beside these.
|
|
80
|
+
out property <int> fixed: root.own + (root.buttons.length > 0 || root.overflow > 0 ? 1 : 0);
|
|
81
|
+
// The strip's layout for a room, as pure functions, so the player's
|
|
82
|
+
// strip binds them to its own `room` (no frame behind the shell's
|
|
83
|
+
// layout) and the properties below give the same numbers for `room`.
|
|
84
|
+
// The plugin buttons in the strip (the first of `buttons`) at `room`.
|
|
85
|
+
public pure function shown-in(room: length) -> int {
|
|
86
|
+
// Cells left for plugin buttons and `»`.
|
|
87
|
+
let free = Math.max(0, Math.floor(room / 41px) - root.own);
|
|
88
|
+
if root.overflow == 0 && root.buttons.length <= free {
|
|
89
|
+
return root.buttons.length;
|
|
90
|
+
}
|
|
91
|
+
return Math.max(0, Math.min(root.buttons.length, free - 1));
|
|
92
|
+
}
|
|
93
|
+
// Whether `»` shows at `room` (a button past 8 or past the room).
|
|
94
|
+
public pure function more-in(room: length) -> bool {
|
|
95
|
+
return root.shown-in(room) < root.buttons.length || root.overflow > 0;
|
|
96
|
+
}
|
|
97
|
+
// The strip's width at `room` (0 while a bar places `BarButtons`).
|
|
98
|
+
public pure function width-in(room: length) -> length {
|
|
99
|
+
if root.placed {
|
|
100
|
+
return 0px;
|
|
101
|
+
}
|
|
102
|
+
return (root.shown-in(room) + (root.more-in(room) ? 1 : 0) + root.own) * 41px;
|
|
103
|
+
}
|
|
104
|
+
out property <int> shown: root.shown-in(root.room);
|
|
105
|
+
out property <bool> more: root.more-in(root.room);
|
|
106
|
+
out property <length> width: root.width-in(root.room);
|
|
54
107
|
// A click on the cell with this token.
|
|
55
108
|
callback clicked(string);
|
|
56
109
|
}
|
|
@@ -127,8 +180,11 @@ component Cell inherits Rectangle {
|
|
|
127
180
|
}
|
|
128
181
|
}
|
|
129
182
|
|
|
130
|
-
//
|
|
131
|
-
//
|
|
183
|
+
// Deprecated (SDK 1.6.8; the player places its strip): the strip a bar
|
|
184
|
+
// placed at its right end with the width it could spare. A bar that still
|
|
185
|
+
// places it shows this one instead of the player's (no palette cell, no
|
|
186
|
+
// `»`): the cells that fit in `room`, lost from its outer (left) end
|
|
187
|
+
// inward, the sidebar toggle last; it is as wide as the cells it shows.
|
|
132
188
|
export component BarButtons {
|
|
133
189
|
// The width the bar can give the strip; the cells that fit show.
|
|
134
190
|
in property <length> room;
|