Skip to content

4 Placeholders

Deulfi edited this page Oct 7, 2026 · 1 revision

Placeholders make button fields dynamic. Any string field (badge, tooltip, command, active, …) can reference an mpv property, and the field updates on the fly whenever that property changes.

What a property is. A property is a named piece of mpv's live state — the thing you'd read with mp.get_property in a script. The manual lists them all: media-title, volume, pause, loop-playlist, video-codec, audio-device, and hundreds more. It's the same mechanism that makes profiles work — a profile just sets properties and the player reacts. A placeholder is ucm's side of that: it reads the property and drops the answer into a button field, so your buttons react the way mpv itself does.

Why it's powerful. One line in the conf turns a static field into a live one that tracks the property for the whole video — no script, no event handlers:

  • tooltip=[[video-codec]] — the tooltip shows the current codec (h264, hevc, …).
  • active=[[loop-playlist]] — the button lights up only while loop-playlist is on.
  • badge=[[playlist-count]] — a badge with how many items are queued.
Notation Meaning
[[property_name]] Property reference — the field shows the property's current value
[[property??value]] Compare — in active, marks the button active while the property equals value
[[property?!value]] Swap-default marker — lets swap-default promote this state to the button's default
[[property!!values]] Value cycle — creates a user-data/<property> property cycled through values
?(f) Media format label (built-in pseudo-label)
?(p) Resolution label (built-in pseudo-label)
?(c) / ?(c-) Current state index / cycle commands

[[property_name]]

Plain reference — the field shows the property's current value and re-updates whenever it changes.

  • tooltip=[[video-codec]] — the tooltip shows the codec (e.g. h264)
  • badge=[[playlist/count]] — the badge shows the playlist count

[[property??value]] — compare (active highlight)

Resolves to true while property == value, else false — and in an active field that's exactly what lights the button up:

state_1@icon=earbuds:active=[[audio-device??auto]]:tooltip=Audiodevice is auto:command=script-binding uosc/audio-device

The button is active exactly while audio-device equals auto. In fields other than active the marker stays as literal text.

[[property?!value]] — swap-default marker

?? and ?! both answer "which of these states matches what's actually true" — but differently:

  • ?? highlights the matching state while you're looking at the state set.
  • ?! promotes the matching state to the button's default when swap-default <value> <button_name> is sent (by another button or script). The button then shows that state by default — you see directly which audio device is in use, without looking through all possible states.

Both markers go in the state's active field (one per state). Example — audio device, three states:

button1=audiodevice,
state_1@icon=earbuds:active=[[audio-device??auto]]:tooltip=Audiodevice is auto:command=script-binding uosc/audio-device,
state_2@icon=speaker:active=[[audio-device?!wasapi/{…}]]:tooltip=Audiodevice is speaker,
state_3@icon=headphones:active=[[audio-device?!wasapi/{…}]]:tooltip=Audiodevice is headphones
  • state_1 uses ?? — while auto is in use, it lights up passively.
  • state_2 / state_3 use ?! — a script (e.g. a uosc audio button) sends script-message-to ucm swap-default wasapi/{…} audiodevice, the matching state becomes the default, and the button shows it until the next swap.

[[property!!values]] — value cycle

Creates a user-data/<property> property (like mpv's cycle-values) and cycles it through values when the button is pressed. The placeholder is rewritten as a reference to that user-data property, and the button's command gets ; script-message-to ucm cycle-prop-values user-data/<property> <values> appended — so each press runs the original command and then advances to the next value (it starts at the first value).

  • Only the property name goes in the placeholder — user-data/ is prepended automatically. Writing [[user-data/name!!values]] would produce user-data/user-data/name.
  • In an active field the button is active while the cycled value is in active_truthy_values.
state_1@icon=shuffle:active=[[uosc_shuffle!!no yes]]:tooltip=Shuffle:command=script-binding uosc/shuffle

?(f) / ?(p) — built-in pseudo-labels

Two built-in labels, resolved automatically from tracked properties (no property reference needed):

  • ?(f) — media file format label, derived from the file's type/codec (via video_types / audio_types / image_types). Empty when no file is loaded.
  • ?(p) — resolution label from resolution_mapping (e.g. 1920x1080 → FHD); without a mapping it shows the raw height (1080p).

?(c) / ?(c-) — state cycle

  • In any string field: shows the current state's position in state_cycle_map as a number (the state in position 2 shows 2, not the state name).
  • As a command: ?(c) sends cycle, ?(c-) sends cycle-back.
state_1@icon=loop:tooltip=cycle states:badge=?(c):command=?(c)

UCM_NIL

The explicit-nil sentinel for clearing a field rather than inheriting it — see Button configuration. In JSON payloads (set-button / set-buttons) a null value is mapped to UCM_NIL automatically.

Clone this wiki locally