Skip to content
Русский

config.toml

A small per-user file under the same directory the presets live in — %APPDATA%\Ritmolux\ on Windows, ~/Library/Application Support/Ritmolux/ on macOS, and $XDG_DATA_HOME/Ritmolux/ on Linux, which is ~/.local/share/Ritmolux/ when XDG_DATA_HOME is unset (the capital R matters there). It is read once at startup and written back whenever a hotkey or a settings row changes a choice, so a stage setup survives a restart.

Every key is optional. A missing file, a missing section and an unknown extra key all degrade to the built-in default rather than failing, so the file below is a complete listing rather than something you have to write.

The other file: marks.toml

Beside config.toml, in the same directory, sits a second and much smaller file the app writes: marks.toml, holding the presets you have marked (see Running the app). It is user state rather than settings — it grows, it is edited from a hotkey rather than from the settings menu, and its two keys are lists rather than scalars — which is why it is not a section of the file below.

favourite = ["Echo Plate", "Gyre"]
hidden = ["Multibrot"]

Both keys are optional and both are lists of preset names. A missing, empty or malformed file means “no marks” and never stops the app starting; a malformed one says so on the console. Delete the file to forget every mark.

The third thing in that directory: thumbnails/

Beside the two files sits a directory the app fills by itself: thumbnails/, one cache entry per preset, each a 160x90 still of what that preset looks like. Nothing ships in it — the pictures are rendered on this machine, because the binary has room for neither the images nor an image codec (ADR-0230). The [thumbnails] section below turns the pass that fills it on and off.

An entry is named for its preset and carries the modification time and length of the .toml it was rendered from, which is what makes it stale: edit a preset in an RLX_PRESET_DIR library and its picture is rendered again. It is cache rather than state — delete the directory and it refills, and a directory that cannot be created turns the feature off with one line in diagnostics.log rather than stopping the app. Nothing prunes it, so an entry for a preset you no longer have stays until you delete it, the same standing cost marks.toml accepts.

[output]

Which display the show opens on, whether it opens fullscreen, and which graphics adapter draws it.

KeyDefaultWhat it means
display0Target monitor index — the fallback when no display_name matches
display_nameunsetPreferred monitor identity, matched by name before the raw index. Unset means “use the index”
fullscreenfalseOpen borderless-fullscreen on the target display; windowed otherwise
gpuunsetThe graphics adapter to render on, spelled as --gpu is: a name ("NVIDIA", or the full name the settings menu writes) or a bare roster index. Unset means the high-performance adapter

The name is tried before the index because the window system’s monitor ordering can shift across a boot or a hotplug, so a stored index alone may point at the wrong screen.

gpu is stored by name for the same reason: the adapter roster orders differently per operating system and driver, so an index alone can name the wrong GPU after an update. --gpu overrides it for one run without writing it. A name that matches more than one adapter is ambiguous, and a stored adapter that is absent, ambiguous or cannot drive the window falls back to the high-performance default with a line saying so, where the flag would refuse to start — see --gpu above. The settings menu’s Adapter row moves the running show and writes this key; Running the app says what a switch costs.

[input]

Where audio comes from. Windows-only; the macOS path taps system audio and the Linux path the default output’s monitor, and neither takes an endpoint choice — the keys are read and inert there.

KeyDefaultWhat it means
mode"loopback""loopback" taps a render device (what the system is playing); "line-in" captures an input device
device"default"Friendly device name to capture. "default", or a name matching no active endpoint, falls back to the selected mode’s default endpoint

[rotate]

The scene director’s auto-rotate policy.

KeyDefaultWhat it means
autofalseAuto-rotate on the dwell timer; manual-only (Space) when off
order"shuffled"The order rotation walks the eligible set in: "shuffled", or "sequential" for ascending preset-name order, wrapping
min_dwell_secs20Never rotate sooner than this many seconds after the last change
max_dwell_secs90Always rotate by this many seconds, even through a steady passage
track_changetrueLet the track-change novelty signal nudge rotation in on the same dwell
source"all"Which part of the library rotation draws from: "all", or "favourites" for the presets you have marked
seedabsentPins the shuffle’s order. Absent, the shell picks a different number each launch; set, the walk repeats exactly. Ignored by "sequential"

What rotation draws from, and in what order. Hidden presets are excluded from both sources — that is what hiding one means. "favourites" is a hard filter with a fallback: it narrows to the marked presets, and while none are marked it draws from the whole eligible set rather than holding one scene forever. Within whichever set that leaves, order decides the walk. "shuffled", the default, shows every eligible preset once before showing any of them twice, reshuffles when the cycle is exhausted, and never ends one cycle and begins the next on the same preset. "sequential" walks the eligible set in ascending preset-name order and wraps, recomputing the successor against the set each draw — so hiding a preset mid-show skips it without the walk losing its place. Backspace steps back through what was actually shown, under either order. Both keys are also the R and L hotkeys and two rows of the settings menu, and a change made there is written back here.

seed is how a run is reproduced. With no seed key the shuffle starts from a number the shell varies per launch, so two runs of one build do not replay one order — which is what the shuffle has always claimed to do. That matters most on the --stream path, where rotation runs even with auto = false and nobody is at the keyboard to notice the order changed: a headless run someone wants to reproduce frame for frame needs seed set. Nothing enforces it. "sequential" ignores the key entirely, because its order is the library’s.

Hold one scene by default. Out of the box the app stays on a single scene until you opt in — the A hotkey, or auto = true here. Manual Space works either way. When auto is on the defaults favour a mostly-predictable, timer-led rotation: a steady passage holds to the 90 s cap and never rotates before 20 s. An energy drop can land a change early, but only well past the minimum dwell (a softened gate, around 37.5 s at these defaults), so it cannot flip scenes every few seconds.

[quality]

KeyDefaultWhat it means
tier"auto""auto" lets the engine resolve rich and demote it if the frame time says so; "floor" and "rich" pin it
grid_scale"auto"The fraction of the window the internal grids are drawn at: a number from 0.25 to 1, or "auto" to let the engine pick one for the tier and the kind of GPU from the table below. A number outside the range makes the file fail to parse, which the app reports before starting on the defaults

What "auto" resolves to in a window, by tier and the kind of GPU the adapter reports:

TierIntegrated GPUDiscrete GPUSoftware rasterizer, other
floor111
rich0.7511

The integrated row is a measurement: the largest scale at which the reference laptop’s integrated GPU held 60 fps at 1080p across the ten heaviest presets (ADR-0245). It is not a promise above 1080p, where no rich scale held on that machine. The other rows are 1 by decision. A tier change re-resolves the scale, so a rich window the governor demotes to floor goes back to 1. A headless run (shot, --stream) takes 1 whatever the GPU unless --grid-scale says otherwise.

Precedence, highest first, for both keys alike:

KeyHighestLowest
tier--tierRLX_TIER[quality] tierauto
grid_scale--grid-scaleRLX_GRID_SCALE[quality] grid_scaleauto

A choice made from inside the app — [ and ] or the settings menu’s Quality row for the tier, the Grid scale row for the scale — is written here, so it survives a restart, and the flag and the variable still win at the next launch.

[hud]

The furniture the shell paints over the show. Separate from [output] because it is about what is painted, not about which screen the window opens on.

KeyDefaultWhat it means
preset_nametrueDraw the active preset’s name in the top-left corner. Even when on, the name yields to a menu and to the F3 panel — this is “never show it”, not “show it always”
now_playingtrueAnnounce the current track in the lower-left corner when it changes. Off means no track ever reaches the visualizer, not a banner drawn transparent
next_rotationtrueCount down to the next auto-rotate, under the preset name. Nothing is drawn while auto-rotate is off, so this key only decides whether the line appears when there is a countdown
diagnosticsfalsePaint the diagnostics overlay — the panel F3 and the settings menu’s Diagnostics row toggle. Set it to true to come up with the panel already open on a machine you are measuring

[osc]

The lighting telemetry sink. Off by default, like every optional sink: a user who runs no lighting rig must not have a socket bound or a datagram leaving their machine because they installed the app.

KeyDefaultWhat it means
enabledfalsePublish telemetry
target"127.0.0.1:9000"Where to send, as host:port. Inert until enabled (or --osc) turns the sink on
rate_hz60Datagram sets per second; 0 means every rendered frame, whatever the frame rate

--osc overrides target and turns the sink on, and leaves rate_hz to the file — the one key it has no spelling for.

[control]

The studio control-in listener — the socket a studio, a lighting console or a MIDI bridge drives this player from (the control protocol). Off by default, and loopback by default, and those are two separate promises: off means a machine that was never asked to be driven binds no port at all, and loopback means one that was asked, and named no host, is reachable only from itself.

KeyDefaultWhat it means
enabledfalseListen for control messages
listen"127.0.0.1:9001"Where to listen, as host:port. Inert until enabled (or --control) turns the listener on

--control overrides listen and turns the listener on, exactly as --osc does for the sink. The port is one above [osc] target’s so the two OSC surfaces read as a pair and a machine running both needs neither moved.

Binding anywhere but loopback is a decision, not a default. Anything that can reach the port can move a parameter on the running show, which is the whole feature and also the whole of the exposure — there is no authentication, and OSC has no channel to carry one. On a venue network, leave it on 127.0.0.1 and run the studio on the same machine.

[console]

The operator console’s second window. Off by default, for the reason every optional surface here is: a config that has never heard of a console produces exactly one window, one surface, no intermediate render target and no extra copy per frame.

KeyDefaultWhat it means
enabledfalseOpen the console at launch
display_nameunsetPreferred monitor identity for the console, matched by name before the index. Unset means “use the index”
display1Fallback monitor index when no display_name matches
frame_latency1The console swapchain’s desired_maximum_frame_latency, clamped to 1..=3. At 1 the surface holds a single in-flight image, so acquiring the next one waits for its own previous present to retire
present_every_n1Present the console every Nth output frame. At 1 every frame; at 2 the console’s readout updates at half rate, which is visible on the transport strip and the preview

Neither of the last two needs touching on a machine that keeps up. They exist so the console’s cost can be measured rather than argued about; the defaults above are the shipped ones, and what they cost in practice is in Running the app.

display defaults to 1, not 0: a console’s whole point is to be on a display other than the show’s, and the show defaults to 0. On a single-monitor machine this falls back to the only monitor there is, which is the correct degrade rather than a failure.

[thumbnails]

The background pass that renders the browser’s pictures into thumbnails/. On by default, because the pictures are what the browser’s pane is for.

KeyDefaultWhat it means
enabledtrueRender missing and stale pictures in the background, from launch

The pass starts when the app does, whether or not the browser is ever opened, and renders one preset at a time by starting the app’s own executable with --thumb, at low priority (nice on Linux and macOS, below-normal priority on Windows). It parks when every preset has a current picture, walks the library again when an RLX_PRESET_DIR edit reloads it, and at the next launch picks up whatever is still missing. It never waits in the show’s frame loop, and closing the app kills a render in flight; the half-written file that leaves is discarded by the next pass.

It gives up rather than retrying. A render that fails is named once in diagnostics.log with the reason the child printed, and is not retried until its file changes or the app restarts; three failures in a row stop the pass for the rest of the run. That is where a machine with no room for a second graphics context, or security software that blocks an app from starting copies of itself, shows up. Every pass writes a thumbnail pass: line to the same log when it starts and when it ends, which splits the log’s frame-time rows into the stretch the pass ran in and the stretch after it.

Turn it off on a machine running on battery or under security software that objects: the settings menu’s Thumbnails row writes this key, and turning it off also stops a pass that is running. Pictures already in the cache still show either way.

[ui]

How the interface drawn over the show behaves, where [hud] is what it draws.

KeyDefaultWhat it means
motion"full""full": the browser and the settings menu fade and slide as they open and close, the selection glides between rows, the corner name crossfades when the preset changes, and the now-playing banner eases in and out. "reduced": every one of those is a step, so things appear and vanish in one frame

| hints | true | Show the key hint — ? help Tab browse S settings — in the lower-right corner for a few seconds at launch, and again whenever the pointer moves over the window. It is never drawn while a menu is open |

The animation is only ever a view: a key pressed while a menu is still opening acts on that frame, under either value. The settings menu’s Motion and Key hints rows write these two keys.

A complete file

Every key at its default. display_name in [output] and [console], and gpu in [output], are absent because “unset” is their default and the file format has no spelling for one.

[output]
display = 0
fullscreen = false
[input]
mode = "loopback"
device = "default"
[rotate]
auto = false
order = "shuffled"
min_dwell_secs = 20
max_dwell_secs = 90
track_change = true
source = "all"
# seed = 7 # absent: the shuffle varies per launch. Set: it repeats exactly.
[quality]
tier = "auto"
grid_scale = "auto"
[hud]
preset_name = true
now_playing = true
next_rotation = true
diagnostics = false
[osc]
enabled = false
target = "127.0.0.1:9000"
rate_hz = 60
[control]
enabled = false
listen = "127.0.0.1:9001"
[console]
enabled = false
display = 1
frame_latency = 1
present_every_n = 1
[thumbnails]
enabled = true
[ui]
motion = "full"
hints = true

Built from 13c7582 at version 0.158.0. This site tracks main and is not versioned per release.