10 Commits

3 changed files with 50 additions and 45 deletions
+5 -4
View File
@@ -835,7 +835,7 @@ else:
else:
input_device2 = None
else:
input_device2 = saved_settings.get('secondary', {}).get('input_device')
input_device2 = saved_settings.get('input_device')
st.selectbox(
"Input Device (Radio 2)",
[input_device2 or "No device selected"],
@@ -1095,7 +1095,7 @@ else:
r1_tx_power = _tx_power_selectbox(
"TX Power (R1)",
key="dante_tx_power_r1",
default=saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT),
default=saved_r1_config.get('advertising_tx_power', saved_settings.get('advertising_tx_power', TX_POWER_DEFAULT)),
disabled=is_streaming,
)
@@ -1428,7 +1428,7 @@ else:
r2_tx_power = _tx_power_selectbox(
"TX Power (R2)",
key="dante_tx_power_r2",
default=saved_settings.get('secondary', {}).get('advertising_tx_power', TX_POWER_DEFAULT),
default=saved_r2_config.get('advertising_tx_power', saved_settings.get('secondary', {}).get('advertising_tx_power', TX_POWER_DEFAULT)),
disabled=is_streaming,
)
@@ -1612,7 +1612,6 @@ else:
if audio_mode in ("USB", "Network"):
# USB/Network: single set of controls shared with the single channel
# Use saved settings if audio_mode matches, otherwise use defaults
quality_options = list(QUALITY_MAP.keys())
saved_audio_mode = saved_settings.get('audio_mode')
if saved_audio_mode in ("USB", "Network"):
# Map saved sampling rate to quality label
@@ -1632,6 +1631,8 @@ else:
# Use defaults when switching from another mode
default_quality = "Medium (24kHz)" if "Medium (24kHz)" in quality_options else quality_options[0]
saved_pwd = ''
quality_options = list(QUALITY_MAP.keys())
if default_quality not in quality_options:
default_quality = quality_options[0]
quality = st.selectbox(
+44 -25
View File
@@ -5,8 +5,6 @@
# using nmcli device modify (active session only, NOT saved to the profile).
# The persistent profile always keeps ipv4.link-local=enabled so that
# direct-connect (no DHCP) plug-ins always activate and trigger events.
# Avahi is reloaded on each event — no /etc/avahi/hosts file, avahi uses
# natural per-interface advertisement so each segment gets the right IP.
#
# Triggers: up, down, dhcp4-change on ethernet interfaces
# Install to: /etc/NetworkManager/dispatcher.d/10-link-local-mgmt
@@ -14,31 +12,47 @@
INTERFACE="$1"
ACTION="$2"
CONNECTION_NAME="${CONNECTION_ID:-}"
# Only handle ethernet interfaces
if [[ ! "$INTERFACE" =~ ^eth ]]; then
exit 0
fi
reload_avahi() {
systemctl reload avahi-daemon 2>/dev/null || systemctl restart avahi-daemon 2>/dev/null
logger -t nm-link-local "[$INTERFACE] $ACTION — avahi reloaded"
# If CONNECTION_ID env var is not set, look up the active connection for this interface
if [ -z "$CONNECTION_NAME" ]; then
CONNECTION_NAME=$(nmcli -t -f NAME,DEVICE connection show --active 2>/dev/null \
| grep ":${INTERFACE}$" | cut -d: -f1 | head -n1)
[ -z "$CONNECTION_NAME" ] && exit 0
fi
# Update /etc/avahi/hosts to point mDNS hostname at the best available DHCP address
# across all ethernet interfaces (so Avahi doesn't advertise a link-local address).
update_avahi() {
local hostname
hostname=$(hostname)
# Find first non-link-local IPv4 across all ethernet interfaces
local dhcp_ip
dhcp_ip=$(ip -4 addr show 2>/dev/null \
| grep -A5 ': eth' \
| grep -oP '(?<=inet\s)\d+(\.\d+){3}' \
| grep -v '^127\.' \
| grep -v '^169\.254\.' \
| head -n1)
if [ -n "$dhcp_ip" ]; then
mkdir -p /etc/avahi
echo "$dhcp_ip $hostname $hostname.local" > /etc/avahi/hosts
logger -t nm-link-local "Avahi: pinned $hostname -> $dhcp_ip"
else
rm -f /etc/avahi/hosts
logger -t nm-link-local "Avahi: removed hosts pin, using all addresses"
fi
systemctl restart avahi-daemon 2>/dev/null
}
case "$ACTION" in
up)
# On 'up' the interface may still carry a stale DHCP address from the previous
# session (NM hasn't cleaned it up yet). Reading ip-addr here is unreliable.
# Always re-enable link-local as a clean slate; let dhcp4-change suppress it
# later if a real DHCP lease is obtained.
logger -t nm-link-local "[$INTERFACE] Up — ensuring link-local active (clean slate)"
(sleep 2 && nmcli device modify "$INTERFACE" ipv4.link-local enabled 2>/dev/null \
&& logger -t nm-link-local "[$INTERFACE] Link-local explicitly enabled on up") &
reload_avahi
;;
dhcp4-change)
# dhcp4-change fires only when DHCP actually succeeds (new/renewed lease).
# At this point the DHCP IP is reliably present — safe to read and suppress link-local.
up|dhcp4-change)
DHCP_IP=$(ip -4 addr show "$INTERFACE" 2>/dev/null \
| grep -oP '(?<=inet\s)\d+(\.\d+){3}' \
| grep -v '^127\.' \
@@ -46,19 +60,24 @@ case "$ACTION" in
| head -n1)
if [ -n "$DHCP_IP" ]; then
logger -t nm-link-local "[$INTERFACE] DHCP $DHCP_IP confirmed — suppressing link-local (session only)"
logger -t nm-link-local "[$INTERFACE] DHCP $DHCP_IP detected — suppressing link-local (session only)"
# Use device modify (not connection modify) so the persistent profile keeps
# ipv4.link-local=enabled. This ensures direct-connect plug-ins always activate.
# Run in background after a delay — nmcli blocks on NM, which is waiting for
# this dispatcher to return, causing a deadlock if called synchronously.
(sleep 2 && nmcli device modify "$INTERFACE" ipv4.link-local disabled 2>/dev/null \
&& logger -t nm-link-local "[$INTERFACE] Link-local suppressed for current session") &
else
logger -t nm-link-local "[$INTERFACE] No DHCP on $INTERFACE — keeping link-local active"
fi
reload_avahi
update_avahi
;;
down)
# NOTE: a carrier-change does NOT fully reset session-level 'device modify' state.
# The re-enable is therefore handled in the 'up' handler when no DHCP is detected.
logger -t nm-link-local "[$INTERFACE] Down — link-local will be re-enabled on next up without DHCP"
reload_avahi
# Profile always has ipv4.link-local=enabled so no action needed here.
# The suppression from device modify was session-only and is gone when the
# connection goes down.
logger -t nm-link-local "[$INTERFACE] Down — link-local will be active on next connect"
update_avahi
;;
esac
@@ -8,28 +8,13 @@ set -e
# Enable link-local for all wired ethernet connections
while IFS=: read -r name type; do
if [[ "$type" == *"ethernet"* ]]; then
echo "Configuring connection: $name"
# link-local: always enabled so direct-connect (no DHCP) works immediately
echo "Enabling IPv4 link-local for connection: $name"
sudo nmcli connection modify "$name" ipv4.link-local enabled 2>/dev/null || echo "Failed to modify $name"
# may-fail=yes: do NOT tear down the connection when DHCP times out.
# Without this, NM declares ip-config-unavailable after the 45s DHCP timeout
# and enters a reconnect loop that causes ~1.5 min outages every ~45 seconds.
sudo nmcli connection modify "$name" ipv4.may-fail yes 2>/dev/null || echo "Failed to set may-fail on $name"
# Infinite DHCP timeout: NM keeps retrying DHCP in the background but never
# declares ip-config-unavailable. This prevents the 45s reconnect loop that
# kills the link-local address in direct-connect (no DHCP server) scenarios.
sudo nmcli connection modify "$name" ipv4.dhcp-timeout infinity 2>/dev/null || echo "Failed to set dhcp-timeout on $name"
sudo nmcli connection up "$name" 2>/dev/null || echo "Failed to bring up $name"
fi
done < <(nmcli -t -f NAME,TYPE connection show)
# Remove stale avahi hosts pin — this file overrides per-interface advertisement
# and causes mDNS to always resolve to eth0's IP regardless of which interface
# the query arrived on, breaking eth1 mDNS entirely.
sudo rm -f /etc/avahi/hosts
sudo systemctl restart avahi-daemon
# Ensure Loopback is loaded with a fixed name and index
# Needed for dante
# TODO image when we create the next image this should be part of it