Commit 63f53205 by PLN (Algolia)

fix(rig): Ardour hears the surface again — two stale identities, one webcam

PLN's report: "no impact of lcxl in ardour... why would i need to remap midi
controls there across lcxl gens?" He is right: he never needs to remap. The
session file has the learned bindings (v2 CC 77-84 + 13-16, channel 1) and the
lcxl3-driver emits exactly that. The path was broken in TWO places, both by
name-vs-identity rot:

1. midi-autoconnect resolved its source by NAME and connected "name:0" — but
   aconnect resolves CLIENT names only, and the driver's virtual port carries
   its name on the PORT line (client = python-rtmidi's 'RtMidiOut Client').
   The connect failed into 2>/dev/null for exactly the source the candidate
   list most prefers, so Midi Through carried NOTHING in DAW mode. Now the
   resolver returns a numeric client:port address (awk over aconnect -i,
   matching client AND port lines). Fourth name-identity bug of the day.

2. Ardour's Generic-MIDI input connection was saved by device identity, and
   that identity was "ALSA;;C922 Pro Stream Webcam" — the webcam had taken
   over the slot the surface once owned. The purest stale-binding specimen the
   rig has produced. tidal-ardour-autoroute now asserts
   Midi-Bridge Midi Through -> ardour:MIDI Control In on its 2 s cadence,
   no-op until Ardour registers the port, permanent once it does.

Midi Through stays the rendezvous ON PURPOSE: v2 raw or v3-translated, both
feed it, which is what keeps the classic LCXL plug-and-play (the BC
constraint). Ardour 9.7 note for the archives: the Control Surfaces page is
now a vendor tree built from the .map files' manufacturer field — the old
"Generic MIDI" lives under vendor "Any" (GenericMIDI.map, manufacturer="Any"),
NOT under "Other", and Novation's "Launch Control XL (generic)" entry is the
factory map that would OVERRIDE the learned bindings — do not enable it.
parent 857de5b2
......@@ -74,12 +74,23 @@ disconnect() { # $1 = source, $2 = dest ; silent when there was nothing to cut
# Echo the resolved source ONCE per change, never every INTERVAL: a line every
# 2s is not a log, it is a way to make a real change invisible.
#
# RESOLVE TO A NUMERIC ADDRESS, not a name. The driver's virtual port is named
# on the PORT line ('ParVagues LCXL3') while its CLIENT is python-rtmidi's
# 'RtMidiOut Client' — and `aconnect "name:0"` matches CLIENT names only. So
# the old name-based connect failed silently (2>/dev/null) for exactly the
# source we most prefer, and Midi Through carried NOTHING in DAW mode: Ardour
# heard no fader because this loop was connecting a name that cannot resolve.
# Fourth name-vs-port-identity bug of 2026-08-29. Identity = client:port id.
resolve_lcxl() {
local names; names="$(aconnect -i 2>/dev/null; aconnect -o 2>/dev/null)"
local cand
local cand addr
for cand in "${LCXL_CANDIDATES[@]}"; do
if printf '%s' "$names" | grep -qF "$cand"; then
printf '%s' "$cand"
addr="$(aconnect -i 2>/dev/null | awk -v want="$cand" '
/^client / { cid = $2; sub(":", "", cid); cline = $0 }
/^[ \t]/ { if (index(cline, want) || index($0, want)) {
print cid ":" $1; exit } }')"
if [ -n "$addr" ]; then
printf '%s %s' "$addr" "$cand"
return 0
fi
done
......@@ -87,20 +98,21 @@ resolve_lcxl() {
}
reconcile() {
local src
if ! src="$(resolve_lcxl)"; then
local resolved addr name
if ! resolved="$(resolve_lcxl)"; then
if [ "$LAST_SRC" != "__none__" ]; then
echo "midi-autoconnect: no surface present (looked for: ${LCXL_CANDIDATES[*]})"
LAST_SRC="__none__"
fi
return 0
fi
if [ "$src" != "$LAST_SRC" ]; then
echo "midi-autoconnect: surface = '$src'"
LAST_SRC="$src"
addr="${resolved%% *}"; name="${resolved#* }"
if [ "$name ($addr)" != "$LAST_SRC" ]; then
echo "midi-autoconnect: surface = '$name' at $addr"
LAST_SRC="$name ($addr)"
fi
connect "$src:$LCXL_PORT" "$THRU:$THRU_PORT" # rule 1: controls out
disconnect "$THRU:$THRU_PORT" "$src:$LCXL_PORT" # rule 2: kill the loop
connect "$addr" "$THRU:$THRU_PORT" # rule 1: controls out
disconnect "$THRU:$THRU_PORT" "$addr" # rule 2: kill the loop
}
echo "midi-autoconnect: reconciling every ${INTERVAL}s"
......
......@@ -42,7 +42,22 @@ sc_hw_playback_links() {
}'
}
# Ardour's Generic-MIDI control input. Ardour SAVES this connection by device
# identity, and on 2026-08-29 the saved identity was "ALSA;;C922 Pro Stream
# Webcam" — the webcam had taken over the slot the surface once owned, so the
# faders PLN learned (v2 CC 77-84 + 13-16, ch 1, stored in the session file)
# received nothing. A binding resolved once is a stale binding waiting to
# happen; this asserts the one true feed on the same 2 s cadence as the orbits.
# Midi Through is deliberately the source, NOT the surface: Midi Through is the
# stable rendezvous across controller generations (v2 raw, or v3 translated by
# lcxl3-driver), which is what keeps the classic LCXL plug-and-play.
CTRL_IN="ardour:MIDI Control In"
CTRL_SRC="Midi-Bridge:Midi Through: Port-0 (capture)"
reconcile() {
# ADD: the control surface feed (no-op until Ardour registers the port)
link "$CTRL_SRC" "$CTRL_IN"
# ADD: orbit pair -> matching Tidal track
while read -r nn; do
[ -n "${nn:-}" ] || continue
......
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