Skip to content

Where preset files live

There are three copies of the curated set, and understanding the flow explains why “edit once, both frontends see it” works.

presets/*.toml core/build.rs -> EMBEDDED per-user preset dir
(repo, source of truth) ──> (globbed + include_str!'d ──> seeded on first run,
into the binary) then loaded + watched

What then happens to one file, from the moment it lands in that directory:

The one edge worth reading twice is Rejected -> Active: a bad edit never takes the picture down. The engine reports what it could not parse and keeps rendering what it had.

  1. presets/ at the repo root — the source of truth. These .toml files are what a contributor edits. Nothing reads them at runtime directly.

  2. EMBEDDED — generated at build time. core/build.rs globs presets/*.toml and emits an EMBEDDED slice of (filename, contents) tuples, each include_str!’d, so the compiled binary always carries the curated set (ADR-0022). default_presets() parses these as the fallback the C-ABI / foobar path renders even with no preset directory present. Adding a preset is dropping a file — there is no list to edit and no count to bump.

  3. The per-user directory — what actually gets loaded. On first run each frontend seeds this directory (writes every embedded preset that isn’t already there — never overwriting your edits) and then loads and watches it. The standalone and the foobar plugin resolve the same path, so a preset you edit shows up in both.

    OSPreset directory
    Windows%APPDATA%\Ritmolux\presets
    macOS~/Library/Application Support/ritmolux/presets
    Linux/other$XDG_DATA_HOME/ritmolux/presets (or ~/.local/share/ritmolux/presets)

A custom preset folder: RLX_PRESET_DIR

Set the RLX_PRESET_DIR environment variable to point the Rust frontends at any folder instead of the per-user directory above (ADR-0014):

Terminal window
# Windows (PowerShell) — run the app against a folder you keep elsewhere
$env:RLX_PRESET_DIR = "D:\my-presets"; cargo run -p standalone --release
# macOS / Linux
RLX_PRESET_DIR=~/my-presets cargo run -p standalone --release
  • Both the standalone app and the headless shot CLI honor it, through one shared resolver — they cannot disagree about which folder an edit lands in.
  • The override folder is yours: the app loads and hot-reloads it but never seeds the curated set into it. An empty or missing folder simply falls back to the presets compiled into the binary, exactly like an empty per-user directory.
  • Only the presets move. diagnostics.log and config.toml stay under the per-user app directory.
  • The foobar2000 plugin does not read it — the C++ side keeps resolving the per-user directory (a followup, not a current behavior).

Pointing it at the repo’s own presets/ is the preset-authoring loop: edit a version-controlled .toml and the running window follows within ~150 ms, with no rebuild. See Headless capture and video for that loop and for shot’s equivalent --presets / --preset-file flags.

Loading, cycling, and hot-reload

  • Seeding is write-if-absent. Your edits to a seeded preset survive re-seeding. The flip side: a curated preset changed in a new release does not replace the copy already on your disk — delete that file and relaunch to get the updated version (there is no “refresh curated” button yet).
  • Hot-reload (standalone). The app polls the directory ~every 150 ms and reloads on any change. Errors and warnings are printed and the last good set is kept — a bad edit never crashes a running visual.
  • Cycling. Standalone: the app holds one scene by defaultSpace cycles to the next preset (title bar shows the name), and A toggles auto-rotate on/off (auto is off out of the box; enable it per-run with A or persistently via auto = true under [rotate] in config.toml). foobar2000: Space, or right-click the visualization → Next scene.
  • Choosing by name. Both frontends select directly rather than cycling to it. Standalone: the browse overlay (Tab). foobar2000: right-click → Preset ▸, a flat list of everything that loaded with a mark on the one showing; the choice persists across restarts by name, so a preset whose file you later delete degrades to the roster’s default rather than to a stale position (ADR-0117). The list is the core’s roster, not a directory listing — a .toml the engine rejected is absent from it, which is how you tell a malformed file from a missed one.
  • foobar loads on init, and re-loads on demand. The plugin calls the core’s rlx_load_presets (C ABI v2, ADR-0006) against the shared directory when it starts, so it seeds and renders the same library — no loopback capture needed on that path. It has no file watcher: a file dropped in afterwards appears on right-click → Reload presets, which re-scans and keeps the preset you were watching selected. A reload re-seeds the running scene’s simulation state, the same way the standalone’s hot-reload does.
  • Two files may declare the same name. The roster tolerates it, but “select by name” then means first match wins — for persistence, for the reload’s keep-selection step, and for the standalone’s browse overlay alike. Rename one if you want both reachable.

Built from a8ce055 at version 0.115.0. This site tracks main and is not versioned per release.