Add wireplumber rule excluding aloop from default-sink selection

Without this, wireplumber's auto-default algorithm promotes aloop to
default whenever Resolve plays audio (because aloop becomes RUNNING),
and the bridge's "send to default sink" output ends up back in aloop —
renders complete, but monitor audio loops onto itself with nothing
reaching real hardware.

Writes 51-resolve-aloop-no-default.conf with priority.session = 0,
priority.driver = 0, and node.dont-fallback / node.disable-fallback
to cover wireplumber 0.4 and 0.5+. Restart order changed to
wireplumber-first so the rule is in place when the aloop nodes
republish.
This commit is contained in:
28allday 2026-05-01 15:25:08 +01:00
parent b9b8dbc6dc
commit 2173563632
2 changed files with 89 additions and 23 deletions

View file

@ -502,8 +502,10 @@ else
# Bridge snd-aloop capture → default sink so monitor audio is audible. # Bridge snd-aloop capture → default sink so monitor audio is audible.
# Without this, Resolve writes to the loopback and the audio goes nowhere # Without this, Resolve writes to the loopback and the audio goes nowhere
# (loopback is a black hole until something captures the other side). # (loopback is a black hole until something captures the other side).
# The bridge is a PipeWire loopback module loaded from user config; it # The bridge is a PipeWire loopback module loaded from user config; its
# tracks the default sink so headphone/HDMI switching keeps working. # playback side uses media.class = Stream/Output/Audio so it follows the
# current system default sink — headphone/HDMI/analog switching keeps
# working without editing this file.
ALOOP_BRIDGE_DIR="${HOME}/.config/pipewire/pipewire.conf.d" ALOOP_BRIDGE_DIR="${HOME}/.config/pipewire/pipewire.conf.d"
ALOOP_BRIDGE_FILE="${ALOOP_BRIDGE_DIR}/50-resolve-aloop-bridge.conf" ALOOP_BRIDGE_FILE="${ALOOP_BRIDGE_DIR}/50-resolve-aloop-bridge.conf"
mkdir -p "${ALOOP_BRIDGE_DIR}" mkdir -p "${ALOOP_BRIDGE_DIR}"
@ -532,14 +534,58 @@ context.modules = [
] ]
EOF EOF
log " Wrote ${ALOOP_BRIDGE_FILE} (PipeWire loopback bridge)" log " Wrote ${ALOOP_BRIDGE_FILE} (PipeWire loopback bridge)"
# Reload user PipeWire services so the new conf is picked up
if systemctl --user is-active --quiet pipewire 2>/dev/null; then
systemctl --user restart pipewire pipewire-pulse wireplumber 2>/dev/null || true
log " Reloaded user PipeWire services"
fi
else else
log " ${ALOOP_BRIDGE_FILE} already in place" log " ${ALOOP_BRIDGE_FILE} already in place"
fi fi
# Wireplumber rule: keep aloop OUT of the default-sink rotation.
# Wireplumber's auto-default algorithm promotes whichever sink is RUNNING
# — and aloop is RUNNING precisely while Resolve plays audio. Without
# this rule, aloop becomes default mid-session, the bridge's "send to
# default sink" output lands back in aloop, and monitor audio loops onto
# itself (renders still complete, but you hear nothing during playback).
# Lowering priority + dont-fallback / disable-fallback excludes aloop
# from default selection without disabling the device.
WPRULE_DIR="${HOME}/.config/wireplumber/wireplumber.conf.d"
WPRULE_FILE="${WPRULE_DIR}/51-resolve-aloop-no-default.conf"
mkdir -p "${WPRULE_DIR}"
if [[ ! -f "${WPRULE_FILE}" ]]; then
cat > "${WPRULE_FILE}" <<'EOF'
# DaVinci Resolve aloop — keep snd-aloop out of the default-sink rotation.
# Managed by Omarchy_resolve_v2.sh. Without this, wireplumber promotes
# aloop to default whenever Resolve makes it RUNNING, and the bridge loops
# audio back into aloop instead of reaching real hardware. Setting both
# dont-fallback (older) and disable-fallback (newer) covers wireplumber
# 0.4 and 0.5+.
monitor.alsa.rules = [
{
matches = [
{ node.name = "alsa_output.platform-snd_aloop.0.analog-stereo" }
{ node.name = "alsa_input.platform-snd_aloop.0.analog-stereo" }
]
actions = {
update-props = {
priority.session = 0
priority.driver = 0
node.dont-fallback = true
node.disable-fallback = true
}
}
}
]
EOF
log " Wrote ${WPRULE_FILE} (wireplumber default-sink exclusion)"
else
log " ${WPRULE_FILE} already in place"
fi
# Reload user PipeWire + wireplumber so the new configs are picked up.
# Restart wireplumber FIRST so its monitor reapplies the alsa rule when
# pipewire republishes the aloop nodes.
if systemctl --user is-active --quiet pipewire 2>/dev/null; then
systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
log " Reloaded user wireplumber + PipeWire services"
fi
fi fi
echo echo

View file

@ -123,11 +123,18 @@ proceeds normally. The script:
- Writes `/etc/modules-load.d/snd-aloop.conf` so it autoloads at boot - Writes `/etc/modules-load.d/snd-aloop.conf` so it autoloads at boot
- Writes a PipeWire loopback bridge at - Writes a PipeWire loopback bridge at
`~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` so `~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` so
monitor audio routes from the loopback's capture side to the system monitor audio routes from the loopback's capture side to the current
default sink (without it, Resolve renders fine but you hear nothing system default sink (without it, Resolve renders fine but you hear
during playback; headphone/HDMI sink switching keeps working through nothing during playback; headphone/HDMI sink switching keeps working
the bridge) through the bridge)
- Restarts user PipeWire services so the bridge loads immediately - Writes a Wireplumber rule at
`~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf`
that excludes the aloop card from default-sink selection — without this,
Wireplumber would promote aloop to default whenever Resolve plays audio
(because aloop is RUNNING), and the bridge would loop audio back into
aloop instead of your real hardware
- Restarts user Wireplumber + PipeWire services so the configs load
immediately
Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a
dedicated audio interface Resolve already uses cleanly). dedicated audio interface Resolve already uses cleanly).
@ -255,23 +262,35 @@ clip codec with `ffprobe` — ProRes RAW will hang silently on Linux without
Apple's ProRes RAW SDK plugins, which is a separate issue from this audio Apple's ProRes RAW SDK plugins, which is a separate issue from this audio
fix. fix.
### No audio during playback / monitor sink switches don't work ### No audio during playback / sink keeps flipping to "Loopback"
The PipeWire loopback bridge at If your system default sink keeps switching to "Loopback Analog Stereo"
`~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` routes the moment Resolve starts playing, the wireplumber exclusion rule isn't
the snd-aloop capture side to your default sink. If headphone/HDMI in effect. Confirm the rule file exists:
switching stops working for Resolve playback, restart user PipeWire
services:
```bash ```bash
systemctl --user restart pipewire pipewire-pulse wireplumber cat ~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf
``` ```
To remove the bridge entirely: If absent, re-run the installer or pin your real sink manually:
```bash
pactl set-default-sink <your-real-sink-name> # e.g. alsa_output.pci-0000_01_00.1.hdmi-stereo
```
If headphone/HDMI switching stops working for Resolve playback, restart
the user audio stack (wireplumber first):
```bash
systemctl --user restart wireplumber pipewire pipewire-pulse
```
To remove the bridge + rule entirely:
```bash ```bash
rm ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf rm ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
systemctl --user restart pipewire pipewire-pulse wireplumber rm ~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf
systemctl --user restart wireplumber pipewire pipewire-pulse
``` ```
### Missing library errors ### Missing library errors
@ -327,10 +346,11 @@ sudo rm -f /usr/lib/udev/rules.d/99-BlackmagicDevices.rules
sudo rm -f /usr/lib/udev/rules.d/99-ResolveKeyboardHID.rules sudo rm -f /usr/lib/udev/rules.d/99-ResolveKeyboardHID.rules
sudo rm -f /usr/lib/udev/rules.d/99-DavinciPanel.rules sudo rm -f /usr/lib/udev/rules.d/99-DavinciPanel.rules
# Remove the snd-aloop autoload entry + PipeWire bridge (optional) # Remove the snd-aloop autoload entry + PipeWire bridge + wireplumber rule
sudo rm -f /etc/modules-load.d/snd-aloop.conf sudo rm -f /etc/modules-load.d/snd-aloop.conf
rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
systemctl --user restart pipewire pipewire-pulse wireplumber rm -f ~/.config/wireplumber/wireplumber.conf.d/51-resolve-aloop-no-default.conf
systemctl --user restart wireplumber pipewire pipewire-pulse
# Remove user data (WARNING: deletes all projects and settings) # Remove user data (WARNING: deletes all projects and settings)
rm -rf ~/.local/share/DaVinciResolve rm -rf ~/.local/share/DaVinciResolve