Repository navigation
2 Button configuration
Buttons are defined in ucm.conf as button1 … button15 (15 slots, gaps allowed).
Each button is a name followed by comma-separated states; each state is a name, then @, then key=value fields separated by :.
# conf format: one line, states separated by commas, fields by @/:
button1=example,state_1@icon=list_alt:badge=1:active=true:tooltip=Files:command=script-message-to uosc open-file,state_2@icon=folder_open:tooltip=File Dialog:command=script-message-to uosc show-in-directory
The same button, pushed from another script, looks like a compact JSON table (see Script messages):
local button = {
state_1 = {
icon = "list_alt", badge = "1", active = true,
tooltip = "Files",
command = "script-message-to uosc open-file",
},
state_2 = {
icon = "folder_open",
tooltip = "File Dialog",
command = "script-message-to uosc show-in-directory",
},
}
mp.commandv('script-message-to', 'ucm', 'set-button', 'example', mp.utils.format_json(button))You can name states anything — state_1 / state_2 is just a convention (numbers are easy to keep in mind).
Buttons are referenced in uosc.conf with button:<name>:
controls=button:alt_control_items,button:alt_control_loop,gap,fullscreen,gap,button:alt_format,gap,<video>button:alt_resolution
All fields are optional; a state inherits missing fields from the button's default state (see Fill-up).
| Field | Meaning |
|---|---|
icon |
Material Design icon name (picker) |
badge |
badge text; keep it short (use gap in uosc.conf to fix spacing) |
active |
makes the button active (white background) when its value is true |
tooltip |
hover text |
command |
command(s) executed on press; command1;command2;... — passed through to uosc |
hide |
hides the button (useful when you want to unhide it later via script) |
badge
-
UCM_NILor{}→ nil (badge hidden — explicit nil intent, survives fill-up) - any other string is kept as literal badge text — including
"false","0","" - automatically hidden when empty after substitution (e.g.
?(f)with no file loaded)
active
-
"true"/true→ active;"false"/false→ inactive - other values are checked against
active_truthy_values(anything not in the list = inactive) - a
[[property]]reference makes the button active while the property is truthy - a
[[property??value]]reference makes the button active while the property equalsvalue
hide
-
"true"/true→ hidden;"false"/false→ visible; other values preserved
The most common button is one where several states all look the same but do different things. With fill-up you write the shared fields once (in the default state) and each extra state only names the field that changes — usually just the command:
# same icon + tooltip across all three states; each extra state is only a command
state_1=icon=skip_next:tooltip=Jump:command=add 0
state_2=command=add 5
state_3=command=add 30state_2 and state_3 don't repeat the icon or tooltip — they inherit them from state_1 (the default state). That's the whole point: change the icon once and all three states follow, instead of editing three copies. Without inheritance you'd write the full button per state:
state_1=icon=skip_next:tooltip=Jump:command=add 0
state_2=icon=skip_next:tooltip=Jump:command=add 5
state_3=icon=skip_next:tooltip=Jump:command=add 30So inheritance keeps each state short enough to read at a glance, and the shared look lives in one place.
A few rules:
- A state inherits from the button's default state (the one mapped to
defaultinstate_map; without astate_map, the first state of the first button). - Scalars are copied by value — states don't share references.
- To clear a field in a non-default state, set it explicitly to
UCM_NIL/{}(for badge) — omission means "inherit". - Buttons pushed via
set-buttonare deep-copied, so the sending script's payload tables are never mutated.
The script-level options (state_map, state_cycle_map, revert_delay, …) configure ucm as a whole, not one button — see Global configuration.
- Fields are separated by
:, but the parser only splits at:followed by a known field name — commands containing colons (ports, UUIDs,wasapi/{…}) are safe. - Buttons already have a default command fallback: states without a
commandgetcommand=noop, so pressing them is a no-op ping instead of an undefined message.