Files
Aime/app/aime-iphone-route.sh
T
schakal00783 e1c81bea9a fix(iphone-bt): iPhone-Route-Watcher greift wieder — Gegenseite fehlte in Aufnahme
aime-iphone-route.sh v1 hat seit dem Reboot am 29.07. nie gegriffen (0 Zeilen in
journalctl -t aime-iphone-route über den ganzen Boot). Zwei Gründe:

1. Die Portnamen waren hartcodiert auf input_FL/input_FR. HFP/mSBC ist mono, die
   Ports heißen playback_MONO/capture_MONO — der grep matchte nie.
2. Der Guard "micgate.out schon verlinkt -> überspringen" war einmal pro Anruf.
   WirePlumber legt die HFP-Nodes nicht atomar an, der Uplink erscheint vor der
   Gegenseite. War bluez_input in genau diesem Durchlauf noch nicht da, wurde die
   Gegenseite für den ganzen Anruf nicht mehr nachverlinkt. Ein erst mitten im
   Anruf gesetztes callrec_mix->Uplink wurde ebenso nie entfernt.

Folge: Gegenseite -> callmix fehlte (nicht in der Aufnahme, #80/#81 hatten je nur
1 Sprecher) und der Uplink führte den ungegateten Mix statt micgate.out, also
wieder das Echo von vor dem Fix am 13.07.

v2 ermittelt die Portnamen über pw-link -i/-o und prüft alle drei Links in jedem
Durchlauf einzeln nach. link_all legt genau einen Link pro Ziel-Port an: eine
Mono-Quelle speist beide Kanäle, eine Stereo-Quelle auf einem Mono-HFP-Port sendet
nur FL, weil beide Links in denselben Port summieren würden (+6 dB Uplink).

Gegenprobe am echten Anruf steht noch aus.
2026-07-30 15:48:59 +02:00

83 lines
3.2 KiB
Bash

#!/bin/bash
# Auto-route iPhone HFP calls (the bluez nodes exist only during a live call):
# uplink (what far-end hears) <- micgate.out (GATED mic only -> no self-echo)
# far-end voice (bluez_input) -> callmix (recorded digitally, clean)
# and remove WirePlumber's default callrec_mix->uplink auto-link (that mix carries
# the ungated mic AND the far-end, i.e. a digital echo loop = far-end hears itself).
#
# v2 (2026-07-30): two fixes after a call recorded near-end only + far-end doubling
# 1. every link is verified on EVERY pass, not once per call. The old one-shot
# guard ("micgate.out already linked -> skip") meant: if the far-end node
# appeared a tick later than the uplink node (WirePlumber does not create the
# HFP nodes atomically), far-end->callmix was never made for the whole call,
# and a callrec_mix->uplink link added mid-call was never removed.
# 2. port names are discovered instead of hardcoded. HFP/mSBC is MONO, so the
# ports are playback_MONO/capture_MONO, not input_FL/input_FR. The old
# hardcoded FL/FR grep never matched a mono node at all.
export XDG_RUNTIME_DIR=/run/user/1000
MAC=B4_96_A5_42_BD_D6
# ports_in/ports_out: list "node:port" for nodes whose name matches $1
ports_in() { pw-link -i 2>/dev/null | grep -E "^$1"; }
ports_out() { pw-link -o 2>/dev/null | grep -E "^$1"; }
# link_all SRC_PORTS DST_PORTS -- exactly one link per DESTINATION port, cycling
# the sources. So a mono source feeds both destination channels, and a stereo
# source feeding a mono HFP port sends FL only (linking both would sum them into
# the same port = +6 dB on the uplink).
link_all() {
local -n _src=$1 _dst=$2
local mode=$3 i n=${#_src[@]} m=${#_dst[@]}
[ "$n" -eq 0 ] || [ "$m" -eq 0 ] && return
for ((i=0; i<m; i++)); do
pw-link $mode "${_src[i % n]}" "${_dst[i]}" 2>/dev/null
done
}
log_once=""
while true; do
mapfile -t UP < <(ports_in "bluez_output\.${MAC}")
if [ ${#UP[@]} -gt 0 ]; then
B=${UP[0]%%:*}
LINKS=$(pw-link -l "$B" 2>/dev/null)
CHANGED=""
# 1) drop WirePlumber's ungated-mix -> uplink link (echo source). Checked every
# pass because WP can (re-)add it at any point during the call.
if echo "$LINKS" | grep -q 'callrec_mix'; then
mapfile -t MIX < <(ports_out 'callrec_mix')
link_all MIX UP -d
CHANGED="$CHANGED -callrec_mix"
fi
# 2) ensure gated mic -> uplink
if ! echo "$LINKS" | grep -q 'micgate\.out'; then
mapfile -t GATE < <(ports_out 'micgate\.out')
link_all GATE UP ""
CHANGED="$CHANGED +micgate"
fi
# 3) ensure far-end -> record mix. Retried every pass: this node often shows up
# later than the uplink node.
mapfile -t FAR < <(ports_out "bluez_input\.${MAC}")
if [ ${#FAR[@]} -gt 0 ]; then
I=${FAR[0]%%:*}
if ! pw-link -l "$I" 2>/dev/null | grep -q 'callmix'; then
mapfile -t REC < <(ports_in 'callmix')
link_all FAR REC ""
CHANGED="$CHANGED +far-end"
fi
else
CHANGED="$CHANGED (no-far-end-node-yet)"
fi
if [ -n "$CHANGED" ] && [ "$CHANGED" != "$log_once" ]; then
logger -t aime-iphone-route "iPhone call $B:$CHANGED"
log_once="$CHANGED"
fi
else
log_once=""
fi
sleep 1
done