The media bus
The resources say what should exist. The bus carries what happens
while it runs: reports, commands, button events, and state. It is
one MQTT broker, and every running piece of this operator connects
to it: the operator, each playback pod, each Remote’s pod, and
each idle pod. Your program can connect too. A phone app, a
Home Assistant instance, and a library application all join the same
way, with a plain MQTT client and no Kubernetes credentials.
The broker is deploy/bus.yaml: one Mosquitto Deployment with its
Service and ConfigMap, all named bus, beside the operator’s
Deployment and never inside it. The two are separate so the
operator restarts without dropping a message: a button press reaches
mpv while the operator is down. The broker holds no volume, so a
broker restart loses only the retained set, and the next report from
each running Play refills it within seconds.
The topic base
Every topic extends one base, liken/media by default. The operator
holds the base as one string and passes it to every pod it creates,
so the whole tree moves together when a cluster chooses another
base. The pages in this reference write topics without the base.
Two rules shape the tree
State is retained and events are not. A retained topic always holds the current value, so a program that just connected reads the live state without asking. An event topic carries one moment: a button press, a command, a request to move focus.
The topic names the object and the payload does not. A Play’s namespace and name are segments of its topic path, and its report body carries only the playback numbers. Parse the topic path to learn which object a message belongs to.
The trees
Every topic on the bus belongs to one resource’s tree, and that resource’s page gives the topics, the payloads, and who writes each.
| Tree | What it carries | Page |
|---|---|---|
plays/{namespace}/{name}/... |
one run’s commands, report, and availability | Plays |
players/{namespace}/{name}/... |
one unit’s activity, volume, and panel | Players |
remotes/{namespace}/{name}/... |
one controller’s events, presence, and focus | Remotes |
keymaps/{name} |
one Keymap’s compiled binding table | Keymaps |
The keymaps tree has no namespace segment because a Keymap is
cluster-scoped.
Availability
Retained state outlives the pod that wrote it, so a reader needs a
signal that the writer is gone. The playback pod and the
Remote’s pod each name an
availability topic in their tree as the MQTT Last Will, with
offline as the payload, and publish online there once connected.
Both messages are retained. When a pod dies without a clean
disconnect, the broker publishes the will, so retained state a dead
pod left behind does not read as live. A reader that folds state
from one of these trees reads the availability topic beside it.