What SurfaceCast keeps about this computer, as opposed to what it keeps about a show. The show is in scene and show files; everything here stays behind when a show travels.
Nothing in this file has to be edited by hand — every value has a control, and the reference says which. It is documented because a light rig is real work, and copying one to a second machine, or diffing two venues, is easier from the file than from a dialog.
| Platform | Path |
|---|---|
| Windows | %APPDATA%\SurfaceCast\settings.json |
| Anything else | ~/.config/SurfaceCast/settings.json |
The log sits beside it in logs\surfacecast.log, and the crash-recovery copy
beside that. Help ▸ Open log folder shows them.
It is written to a temporary file and renamed into place, so an interrupted save cannot leave a truncated settings file behind. A file that cannot be read is replaced by defaults rather than failing the launch, and an individual value that cannot be read falls back to its default without disturbing the rest — so hand-editing can cost you one setting but not the whole file.
{
"projector_screen": -1,
"auto_open_projector": false,
"match_canvas_to_screen": true,
"canvas_width": 1920,
"canvas_height": 1080,
"show_grid": true,
"grid_divisions": 12,
"snap_to_grid": false,
"show_safe_area": false,
"blackout": false,
"master_volume": 1.0,
"confirm_take": false,
"autosave_enabled": true,
"autosave_seconds": 60,
"show_cue_controls": true,
"remote_enabled": false,
"remote_address": "",
"slot_count": 5,
"remote_port": 50505,
"remote_allow_edit": true,
"remote_allow_upload": false,
"lights_enabled": false,
"lights_host": "",
"lights_port": 21324,
"lights_rate_hz": 30,
"lights_saturation": 1.0,
"lights_dmx_protocol": "",
"lights_dmx_host": "",
"lights_dmx_port": "",
"lights_dmx_universe": 1,
"lights_dmx_cid": "",
"lights_rig": {},
"media_dir": "",
"last_scene_dir": "",
"last_media_dir": "",
"recent_shows": [],
"window_geometry": "",
"window_state": ""
}
| Key | Default | Meaning |
|---|---|---|
projector_screen |
-1 |
Index into the attached screens. -1 means none chosen; the projector then defaults to the second screen if there is one. |
auto_open_projector |
false |
Open the output window at startup. Ignored while projector_screen is -1. |
match_canvas_to_screen |
true |
Follow the projector's native resolution. |
canvas_width / canvas_height |
1920 / 1080 |
Used when the above is false. 320–16384. |
blackout |
false |
Remembered across launches, deliberately: a show that ended blacked out opens blacked out. |
| Key | Default | Meaning |
|---|---|---|
show_grid |
true |
Alignment grid on the preview. Never on the output. |
grid_divisions |
12 |
2–64. |
snap_to_grid |
false |
|
show_safe_area |
false |
|
master_volume |
1.0 |
0–1, multiplied by each video layer's own volume. |
confirm_take |
false |
Ask before a click puts a scene live. |
show_cue_controls |
true |
The per-slot cue settings under the scene strip. |
slot_count |
5 |
How many scene slots to open with. 1–20. |
| Key | Default | Meaning |
|---|---|---|
autosave_enabled |
true |
Keep a recovery copy while anything is unsaved. |
autosave_seconds |
60 |
15–900. |
media_dir |
"" |
The media folder. Empty means the default — media/ in a checkout, or the config folder in a built copy, which has nowhere writable of its own. |
last_scene_dir / last_media_dir |
"" |
Where the file dialogs open. |
recent_shows |
[] |
Up to ten paths, most recent first. |
window_geometry / window_state |
"" |
Base64 Qt window and dock layout. Delete both to reset the layout; Shift+F5 does the same from inside. |
| Key | Default | Meaning |
|---|---|---|
remote_enabled |
false |
It has no password. |
remote_address |
"" |
The one adapter to bind to. Empty means none chosen, and the remote will not start. |
remote_port |
50505 |
1024–65535. |
remote_allow_edit |
true |
Whether the phone may edit scenes as well as run the show. |
remote_allow_upload |
false |
Whether the phone may write files into the media folder. Separate from editing, and off by default: everything else the remote does stays inside the show. |
| Key | Default | Meaning |
|---|---|---|
lights_enabled |
false |
|
lights_host |
"" |
The WLED controller's address. |
lights_port |
21324 |
WLED's realtime port. |
lights_rate_hz |
30 |
10–60. |
lights_saturation |
1.0 |
0–2. How far sampled colors are pushed from gray on the way out. |
lights_dmx_protocol |
"" |
"", "artnet", "sacn" or "usb". |
lights_dmx_host |
"" |
Art-Net: the node, required. sACN: empty multicasts. Unused for usb. |
lights_dmx_port |
"" |
The serial port, for usb only. |
lights_dmx_universe |
1 |
Which universe a USB widget carries. |
lights_dmx_cid |
"" |
This installation's sACN source identifier, generated once. Receivers tell sources apart by it, so a fresh one each launch would look like a new console appearing. Leave it alone. |
lights_rig |
{} |
The rig. See below. |
"lights_rig": {
"zones": [
{
"name": "1,1",
"x": 0.0, "y": 0.0, "width": 0.25, "height": 1.0,
"start": 0, "count": 4, "gain": 1.0
},
{
"name": "house left pars",
"x": 0.25, "y": 0.0, "width": 0.25, "height": 1.0,
"start": 0, "count": 2, "gain": 0.8,
"target": "dmx", "universe": 3, "channel": 9,
"profile": "Dimmer + RGB (4 channels)"
}
],
"fixtures": [
{
"name": "Cheap mover",
"channels": [
{"role": "fixed", "value": 128},
{"role": "fixed", "value": 64},
{"role": "dimmer", "value": 255},
{"role": "red", "value": 0},
{"role": "green", "value": 0},
{"role": "blue", "value": 0},
{"role": "fixed", "value": 0}
]
}
]
}
A zone is a rectangle of the canvas tied to a run of lamps. Coordinates are a share of the canvas, 0 to 1, exactly as object placement is, so a rig survives a change of projector resolution.
| Key | Default | Meaning |
|---|---|---|
name |
"" |
|
x, y |
0.0 |
Top-left corner, 0–1. |
width, height |
1.0 |
0.001–1, clamped to stay inside the canvas. |
count |
1 |
How many things take this color — LEDs on a strip, fixtures in a row on DMX. 1–4096. |
gain |
1.0 |
0–4, applied to this zone alone. |
spread |
"flat" |
Which way the run travels across the rectangle: "flat", "right", "left", "down" or "up". Only written when it is not "flat", so a rig saved before this field existed is written back unchanged. A value this does not recognise reads as "flat". |
target |
"wled" |
"wled" or "dmx". Only written when it is "dmx", so a WLED-only rig keeps the file it had before DMX existed. |
start |
0 |
WLED only: the first LED, counting from 0. The dialog shows it counting from 1. |
universe |
1 |
DMX only. 1–63999. |
channel |
1 |
DMX only: the fixture's first channel, counting from 1. 1–512. |
profile |
"RGB (3 channels)" |
DMX only: which fixture profile lays the color out, by name. A name that no longer exists falls back to plain RGB — lit wrongly rather than silently stopped. |
A rig drives at most 4096 LEDs. Gaps between zones are sent black rather than repeating the last zone.
Profiles beyond the two built in. Omitted entirely when there are none.
| Key | Meaning |
|---|---|
name |
What zones refer to it by. Renaming it in the dialog takes its zones along; renaming it here does not. |
channels |
One entry per DMX channel, in order. |
Each channel has a role and a value:
| Role | Effect |
|---|---|
red, green, blue |
Driven by the picture. value is ignored. |
dimmer |
Held at value. Named separately from fixed only so the dialog can label it. |
fixed |
Held at value. Park a gobo wheel, a pan, a tilt, a strobe. |
Anything else reads as fixed. An unreadable entry becomes a held zero rather
than disappearing — channels are positional, and dropping one would pull every
channel after it down by one and misaddress the whole fixture.
The two built-in profiles are not stored here. They are
RGB (3 channels) — red, green, blue — and
Dimmer + RGB (4 channels) — a dimmer held at 255, then red, green, blue.