UI hooks

Scripts cannot draw Slint widgets, so packages reach Vivi's UI through script messages:

Need Use
Short status / confirmation vivi-toast <text>
Pairing link or code vivi-qr <title> <text> [caption]
Folder chooser vivi-pick-folder <id> <key>
Seek-bar hover previews write seek-NN.jpg and send vivi-preview-frames <dir>
Chapter pictures in the Chapters tab write chapter-N.jpg and send vivi-chapter-thumbs <dir>
Buttons in Settings action settings
Overlay text mp.osd_message / mp.create_osd_overlay (drawn under Vivi's UI)
Keys mp.add_forced_key_binding

Need a widget that does not exist yet? Open an issue in Loafer19/vivi: new hooks are added as script messages.

Built-in (Rust) plugins

Features with rich UI (visualizer, Skip Intro, Lyrics, Subtitle Search, Auto-tagger, Free Music, Network Streams) are compiled into Vivi in src/plugins/. Each implements the Plugin trait and is listed in plugins::builtin(); the Registry calls the enabled ones on the UI thread:

Hook When
enable(cx) / disable(cx) Switched on / off (and at startup).
file_loaded(cx) mpv loaded a new file.
tick(cx) Every 100 ms; poll worker-thread channels here.
setting_changed(cx, key) A setting changed (already saved).
command(cx, name, args) An action button or a Slint plugin-command(id, name, args) callback.

Ctx gives cx.app (the Slint window), cx.player (mpv), cx.get / cx.flag / cx.set for settings and cx.toast. Hooks run on the UI thread: do network and disk work on a thread and send results through a channel. These live in the vivi repository and also need an entry in plugins/index.json here (kind = "builtin").

Next: System binaries & shared ffmpeg →