Commit b0170751 by PLN (Algolia)

gig-log: the MIDI leg was a stale address, not the wrong port

Correcting my own reading from forty minutes ago, because the fix differs.
The first call was that find_seq_port had bound the driver's FB port, since it
matches port names by substring and 'ParVagues LCXL3 FB' contains 'ParVagues
LCXL3'. Then measured it: aseqdump -l lists SOURCES only, the FB port is an
input, and it does not appear in that listing at all. The resolver could never
have picked it. 131:0 was the right port -- at 10:38:12, fourteen hours ago.

The fault is one word in the docstring. 're-resolved every connect' only fires
when the aseqdump connection drops, and it never dropped. The driver's ALSA
client id moves on every republish -- 131 to 130 to 133 tonight alone -- and
when the client underneath disappears aseqdump keeps running, subscribed to an
address that no longer exists. No drop, no reconnect, and 16227 sample rows
with zero cc rows. A dead seq subscription looks exactly like a quiet surface,
which is why ten sessions passed without anyone noticing.

The matcher hardening here (exact name beats substring, FB excluded like HUI)
is kept because it is more precise, but it is NOT the fix and the comment says
so. The real fix is liveness -- rebind when the bound address leaves
aseqdump -l -- and that is post-gig. Tonight's session is rebound to 133:0.
parent afcbf091
......@@ -710,7 +710,7 @@ match the new track's *default* instead of the sound's *state*.
for free — `0 latches cleared` is a clean switch, `2 latches cleared` is two
gates you will have to press twice. Tonight's switches read 0, 0, 0, 2, 3, 3.
### And the reason this had to be read off the driver's journal: gig-log binds the FEEDBACK port
### And the reason this had to be read off the driver's journal: gig-log binds ONCE and never re-resolves
Zero `cc` records in `gig-20260923-103812.jsonl` — 16227 `s` samples, 28 `eval`,
9 `track`, and **0 `cc`**. That is the tenth session in a row with no MIDI. The
......@@ -727,12 +727,34 @@ client 130: 'RtMidiOut Client' 0 'ParVagues LCXL3 ' <- the translated outpu
client 131: 'RtMidiIn Client' 0 'ParVagues LCXL3 FB' <- the feedback input. gig-log bound THIS.
```
`find_seq_port` matches with `cand.lower() in line.lower()`, a **substring** test,
and `ParVagues LCXL3 FB` contains `ParVagues LCXL3`. So which of the two it binds
is decided by `aseqdump -l` ordering — a coin flip — and it lost. Nothing sends
corpus CCs to an RtMidi *input* port, so the reader subscribed successfully and
read silence, exactly the failure mode the comment above `SEQ_PREFERENCE` was
written to close. The name resolver was fixed; the *direction* was not.
**CORRECTED 00:59, and the first reading was wrong — keep the correction, it
changes the fix.** The initial call was "it bound the FB port", on the grounds
that `find_seq_port` matches port names by substring and `ParVagues LCXL3 FB`
contains `ParVagues LCXL3`. Measured afterwards: **`aseqdump -l` lists SOURCES
ONLY**, and the FB port is an input, so it does not appear in that listing at all
(`aseqdump -l | grep -c FB` = 0). The resolver could never have picked it. `131:0`
WAS the correct output port — at 10:38:12.
The real fault is one word in the docstring: *"re-resolved every connect"*. It
only re-resolves when the aseqdump connection **drops**, and it never dropped.
The driver's ALSA client id moves on every republish — tonight alone `131 → 130 →
133` — and when the client underneath vanishes, aseqdump keeps running,
subscribed to an address that no longer exists. No drop, no reconnect, no
records. Bound once at 10:38 and deaf for fourteen hours.
- [x] **Hardened the matcher anyway** (exact port-name match beats a substring,
and the `FB` suffix is excluded the way `HUI` already is). Harmless and
more precise, but say plainly what it is: **not the fix**. It resolves
correctly *today* and would have resolved correctly at 10:38 too.
- [x] **Rebound for tonight** — gig-log restarted 00:59:26,
`"k":"mbind","p":"133:0"`, which is the live port.
- [ ] **The actual fix, post-gig: LIVENESS, not name matching.** Re-run
`find_seq_port` on a timer (or watch the seq graph) and rebind when the
bound address is no longer in `aseqdump -l`, whether or not aseqdump
noticed. A subscription that outlives its port is the same stale-binding
family as everything else on this rig — and here the *reader* had no way to
know, because a dead seq subscription is indistinguishable from a quiet
surface.
- [ ] **One-line class fix** (safe — gig-log makes no sound): rank an EXACT name
match above a substring one, and exclude the pair's other half the same way
......
......@@ -553,11 +553,29 @@ def find_seq_port(want: str | None = None) -> tuple[str | None, str | None]:
return None, None
lines = (r.stdout or "").splitlines()
for cand in ((want,) if want else SEQ_PREFERENCE):
# EXACT port name beats a substring, because the driver publishes a PAIR
# and the two differ only by a suffix:
# 130:0 'ParVagues LCXL3 ' <- the translated output. This one.
# 131:0 'ParVagues LCXL3 FB' <- the feedback INPUT to the driver.
# A substring test matches both, so which one won was decided by
# `aseqdump -l` ordering, and on 2026-09-23 10:38 it lost the coin flip:
# the mbind line says 131:0 and the session recorded 16227 sample rows
# and ZERO cc rows. Nothing sends corpus CCs to an RtMidi *input*, so the
# reader subscribed successfully and read silence -- session ten in a row
# with no MIDI, the same stale-binding family as the "Launch Control XL"
# name above, except the name was right and the DIRECTION was wrong.
for want_exact in (True, False):
for line in lines:
if cand.lower() in line.lower() and "HUI" not in line:
m = re.match(r"\s*(\d+:\d+)", line)
if m:
return m.group(1), cand
if "HUI" in line:
continue
m = re.match(r"\s*(\d+:\d+)\s+(.*?)\s*$", line)
if not m:
continue
addr, name = m.group(1), m.group(2).strip().strip("'\"")
hit = (name.lower() == cand.lower() if want_exact
else cand.lower() in name.lower() and " FB" not in name)
if hit:
return addr, cand
return None, None
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment