The recollection that this used to exist is false — `git log --all -S
mpris` finds nothing on any branch. What has always been there is the
desktop *notification* on a track change, which is D-Bus but not MPRIS: a
popup is neither a status-bar entry nor a key target. So this is new, not
a regression.
Everything the protocol needs was already on the wire, so cbd-tui gains a
second front-end onto the two channels it already has: stream updates in,
MessageFromUi out. The MPRIS player is a peer of the UI thread — it
commands the server through the very channel the keybindings use, and it
learns the result the way the UI learns about a keypress from another
client. No proto change, no server change.
The decisions worth knowing (architecture/mpris.md):
- An absolute protocol over a toggling server. Play/Pause/SetShuffle/
SetLoopStatus consult the last state the server broadcast and send
nothing when it already matches, or the pause key would start playback
on a paused player. Volume is the same idea with arithmetic; muting is
spelled "volume 0", and the setter mutes on a zero target so the level
survives to be unmuted to.
- No URL reaches the bus. xesam:url would have to be the stream URL,
which clients never see and which several providers sign with
credentials, and every peer on a session bus can read properties. The
trackid is the queue position — also the only spelling that is a valid
object path.
- mpris:length is omitted when unknown rather than sent as zero, which
would make consumers draw a full progress bar.
- Unrepresentable requests are refused, not approximated: repeat-one,
rates other than 1.0, OpenUri, Raise, and Quit — a status-bar button
has no business closing someone's terminal.
- No session bus is a normal way to run (ssh, a tty, a container): the
connection carries a timeout and its failure is an info log, after
which the client behaves exactly as before.
Behind the `mpris` feature, on by default beside `notifications` and
forwarded by `cbd`; the nix package names it in headlessFeatures, since
naming a feature set at all replaces the crate defaults. It costs one
crate and no system library — zbus speaks D-Bus in pure Rust and
notify-rust had already brought it in.
Verified with the real thing, not only a test double: under
dbus-run-session, playerctl lists the player, reads its metadata
("Playing: the artist - the song (4:00)"), and drives play-pause,
`position 30+` and `volume 0.8` into the right commands. It also refuses
`next` when the queue is empty, which is CanGoNext being honest. The
committed bus test covers the round trip and skips where there is no bus.