fix(audio): #138 — reprobe escalates to a graph restart, never opens with one
All checks were successful
Check / eval (push) Successful in 3m53s
All checks were successful
Check / eval (push) Successful in 3m53s
Bernardo's Meet calls lost their microphone because our own dock-audio reprobe restarted PipeWire/Pulse/WirePlumber on every monitoradded (#100). Chromium's audio service does not reconnect when the server disappears under it, so it kept running and enumerated nothing; Zoom, started fresh into a settled graph, looked fine and made it read like a browser bug. reprobe now escalates cheapest-first — select → repair a parked card's profile → restart the graph — so an ordinary plug never touches the graph and no client loses its connection. wait_for_dock_sink polls for the sink the plug is about to publish, so "not yet" is not mistaken for "not ever" and cannot fall through to the restart. The restart stays as rung 3 for the codec that only publishes its route after a re-probe: the one claim the original comment made, and the only one it never demonstrated. Verified on the dev box against the live graph: rung 1 selects the same sink the restart-first path picked (HiFi__HDMI1__sink) in 2.0s instead of ~3.5s with pipewire/pulse/wireplumber MainPIDs unchanged; rung 3 reachable and restarts+retries. Diagnosis proof was ordering across four boots — restart-after-Chromium in both broken sessions, 24s before it in the healthy one — and Bernardo reproduced on demand with a dock/undock. Sweep: BACKLOG #138 deleted, ROADMAP gets the design record (incl. the stale restart-first sentence in the #100 entry), V3 queued on the dev box (relogin first — the watcher is exec-once), journal entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -211,57 +211,6 @@ scaled splash — the LUKS prompt especially, since a passphrase box half off
|
||||
the panel is the failure that matters. Pass = docked boot + shutdown centred
|
||||
on both heads; undocked unchanged.
|
||||
|
||||
### 138. Our dock-audio reprobe restarts PipeWire under running apps (Chromium loses its devices)
|
||||
|
||||
Bernardo 2026-07-16, refined by his own hypothesis (pipewire restarts →
|
||||
Chromium never reconnects) — which the journal confirms, and names **our own
|
||||
code as the thing doing the restarting**. Symptom: Google Meet reports no mic
|
||||
or speakers in native Chromium; Zoom is unaffected; it did **not** reproduce on
|
||||
a fresh boot, only after days of uptime + a hibernate.
|
||||
|
||||
**Mechanism.** `modules/home/dock-audio.nix:153` — on every `monitoradded`, the
|
||||
`reprobe` path runs `systemctl --user restart pipewire.service
|
||||
pipewire-pulse.service wireplumber.service`. A full graph restart, on every
|
||||
physical monitor plug (#100). Chromium's audio service does not re-establish
|
||||
its PulseAudio connection when the server disappears under it, so it keeps
|
||||
running with a dead one and enumerates nothing — hence Meet's wording, hence
|
||||
"restarting Chromium fixes it". Zoom survives because it is a Flatpak that
|
||||
reconnects, and because it is generally started fresh into an already-restarted
|
||||
graph. **Hibernate is not the cause** — it is only how a Chromium survives long
|
||||
enough to still be running when a plug event arrives; resume-while-docked then
|
||||
generates the `monitoradded` that fires the reprobe.
|
||||
|
||||
**Evidence — ordering is the whole tell** (`Started app-org.chromium.Chromium-*.scope`
|
||||
vs `reprobe-start`, four boots, no exceptions):
|
||||
|
||||
| Session | Chromium | Graph restart | Order | Meet |
|
||||
|---|---|---|---|---|
|
||||
| boot -3 (Jul 14→15) | 14:06:49 | 14:07:52 (+2 more; then 10:52 next day) | **after** | broken |
|
||||
| boot -2 (Jul 15 daytime) | 11:10:34 | 11:31:22 | **after**, +21 min | broken |
|
||||
| boot 0 (Jul 16, fresh) | 08:04:19 | 08:03:55 | **before**, −24 s | works |
|
||||
|
||||
Today is the negative control, and it is luck, not a fix: the restart missed
|
||||
Chromium by 24 seconds. **Prediction that confirms this outright — dock/undock
|
||||
now, then reload Meet: it should break in the current session**, with no reboot
|
||||
and no hibernate. That is the cheap V3 for the diagnosis, and it is also the
|
||||
regression test.
|
||||
|
||||
**What to fix.** Not Chromium — the graph restart is a sledgehammer we
|
||||
inherited: the header comment justifies it only as "the recovery used by the
|
||||
old working flake", i.e. it was never shown to be *needed*, while its collateral
|
||||
(every long-lived audio client dropped) was never priced. It is also not rare —
|
||||
boot -3 took three restarts in 82 seconds (14:07:52 / 14:08:58 / 14:09:09;
|
||||
the `mkdir` debounce only collapses events within one run, not a plug storm),
|
||||
and each one drops audio for every app on the machine. Shape: **try selection
|
||||
first, restart only if nothing routable appears** — `select_first_dock` already
|
||||
falls back to `repair_dock_cards`, which fixes the parked-card case
|
||||
(`set-card-profile`) *without* touching the graph, so the restart may have no
|
||||
remaining job at all. If some HDMI codec really does need it (the other claim
|
||||
in that comment), prove it on this hardware and scope the restart to that case.
|
||||
Pass = plug/unplug the dock with Chromium open → output still follows to the
|
||||
monitor **and** Meet still sees its devices; `journalctl -t nomarchy-dock-audio`
|
||||
shows no graph restart on the ordinary path.
|
||||
|
||||
### 139. Terminal floats open full-screen — % size rules are ignored, and Kitty remembers
|
||||
|
||||
Bernardo 2026-07-16: calcurse and nomarchy-doctor float but fill the screen —
|
||||
|
||||
Reference in New Issue
Block a user