From b9b8dbc6dcdb3d928e6747d9f1f25c3f1e58874f Mon Sep 17 00:00:00 2001 From: 28allday Date: Fri, 1 May 2026 13:52:23 +0100 Subject: [PATCH] =?UTF-8?q?Add=20audio=20backend=20fix:=20DeckLink=20?= =?UTF-8?q?=E2=86=92=20ALSA=20+=20snd-aloop=20loopback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolve aborts on first launch on systems without a DeckLink card (default Local.Audio.Type = DeckLink), and Resolve's audio engine retries forever enumerating raw ALSA hardware when PipeWire owns every real card — the "render queue stuck in progress with no output" hang. Patches default-config.dat (and any existing user config.dat) to ALSA, then loads snd-aloop as a virtual ALSA card PipeWire ignores, persists it via /etc/modules-load.d/, and writes a PipeWire loopback bridge so monitor audio remains audible during playback. Skip with RESOLVE_NO_ALOOP=1. Ported from the Intel Arc installer where the fix was originally debugged. --- Omarchy_resolve_v2.sh | 113 +++++++++++++++++++++++++++++++++++++++++- README.md | 99 ++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) diff --git a/Omarchy_resolve_v2.sh b/Omarchy_resolve_v2.sh index 114ddc2..2c96600 100755 --- a/Omarchy_resolve_v2.sh +++ b/Omarchy_resolve_v2.sh @@ -432,9 +432,120 @@ EOF update-desktop-database "${HOME}/.local/share/applications" >/dev/null 2>&1 || true sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true +# ==================== Audio backend fix (DeckLink → ALSA) ==================== +# +# Resolve ships with `Local.Audio.Type = DeckLink` as the default in its +# system-wide config template at /opt/resolve/share/default-config.dat. +# That's correct for users with a Blackmagic DeckLink capture/playback card, +# but on systems without one Resolve aborts on first launch. Patch both the +# template (so future first-launches are correct) and any existing user +# config (so the current install isn't broken). +log "Switching Resolve audio backend default from DeckLink to ALSA..." +TEMPLATE=/opt/resolve/share/default-config.dat +if [[ -f "${TEMPLATE}" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "${TEMPLATE}"; then + sudo sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "${TEMPLATE}" + log " Patched system template ${TEMPLATE}" +fi +USER_CFG="${HOME}/.local/share/DaVinciResolve/configs/config.dat" +if [[ -f "${USER_CFG}" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "${USER_CFG}"; then + cp "${USER_CFG}" "${USER_CFG}.bak.$(date +%s)" + sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "${USER_CFG}" + log " Patched existing user config ${USER_CFG} (backup .bak. created)" +fi + +# ==================== snd-aloop (the actual render-blocker fix) ==================== +# +# Resolve's audio engine opens raw ALSA hardware via snd_pcm_open("hw:%d", ...) +# — it never goes through ALSA's plugin layer (default/pulse/pipewire) and it +# enumerates EVERY card under /dev/snd/controlC[0-32] looking for a usable PCM. +# When every real ALSA card on the system is owned/contested by PipeWire's +# session manager, Resolve's enumeration loops forever, the render queue +# never spawns the encoder, and the user sees: +# - alsa device meters "flickering" in wireplumber (each enumeration cycle +# briefly opens controlC*; PipeWire reacts) +# - render that "won't start" with no error in ResolveDebug.txt +# Confirmed via strace: 14000+ SNDRV_CTL_IOCTL_PCM_INFO ENXIO ioctls and +# 47000+ /dev/snd/controlCN ENOENT opens during the failed render attempt, +# concentrated AFTER the user clicks Render — i.e. a tight retry loop. +# +# THE FIX: load the kernel's snd-aloop module. It exposes a virtual ALSA +# loopback card that PipeWire ignores (no ACP profile, not auto-acquired). +# Resolve's enumerator finds it, can fully own it, settles on it, and the +# render proceeds. Side effect: a "Loopback" device shows up in alsamixer +# and pavucontrol — harmless. +# +# Skipped if RESOLVE_NO_ALOOP=1 (e.g. user already has a dedicated audio +# interface that Resolve uses). Persistent across reboots via +# /etc/modules-load.d/. +if [[ "${RESOLVE_NO_ALOOP:-0}" == "1" ]]; then + log "Skipping snd-aloop setup (RESOLVE_NO_ALOOP=1)" +else + log "Setting up snd-aloop (virtual ALSA card so Resolve render can start)..." + if ! lsmod | grep -qE '^snd_aloop'; then + if sudo modprobe snd-aloop 2>/dev/null; then + log " snd-aloop loaded for the current session" + else + warn " modprobe snd-aloop failed — kernel may lack the module." + warn " On Arch this is part of linux/linux-zen/linux-lts; verify: modinfo snd-aloop" + fi + else + log " snd-aloop already loaded" + fi + ALOOP_CONF=/etc/modules-load.d/snd-aloop.conf + if [[ ! -f "${ALOOP_CONF}" ]] || ! grep -qx 'snd-aloop' "${ALOOP_CONF}" 2>/dev/null; then + echo 'snd-aloop' | sudo tee "${ALOOP_CONF}" >/dev/null + log " Wrote ${ALOOP_CONF} (autoloads at boot)" + else + log " ${ALOOP_CONF} already configured" + fi + + # Bridge snd-aloop capture → default sink so monitor audio is audible. + # Without this, Resolve writes to the loopback and the audio goes nowhere + # (loopback is a black hole until something captures the other side). + # The bridge is a PipeWire loopback module loaded from user config; it + # tracks the default sink so headphone/HDMI switching keeps working. + ALOOP_BRIDGE_DIR="${HOME}/.config/pipewire/pipewire.conf.d" + ALOOP_BRIDGE_FILE="${ALOOP_BRIDGE_DIR}/50-resolve-aloop-bridge.conf" + mkdir -p "${ALOOP_BRIDGE_DIR}" + if [[ ! -f "${ALOOP_BRIDGE_FILE}" ]]; then + cat > "${ALOOP_BRIDGE_FILE}" <<'EOF' +# DaVinci Resolve aloop monitor bridge — managed by Omarchy_resolve_v2.sh +# Bridges snd-aloop's capture side to the system default sink so Resolve's +# monitor audio is audible while editing. Without this, Resolve renders fine +# but you hear nothing during playback. Remove this file + restart PipeWire +# to disable. +context.modules = [ + { name = libpipewire-module-loopback + args = { + node.description = "DaVinci Resolve aloop monitor bridge" + capture.props = { + node.name = "resolve-aloop-capture" + target.object = "alsa_input.platform-snd_aloop.0.analog-stereo" + node.passive = true + } + playback.props = { + node.name = "resolve-aloop-playback" + media.class = "Stream/Output/Audio" + } + } + } +] +EOF + 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 + log " ${ALOOP_BRIDGE_FILE} already in place" + fi +fi + echo echo "✅ DaVinci Resolve installed to /opt/resolve" -echo " (vendor libc++ kept; libcrypt.so.1 ensured)" +echo " (vendor libc++ kept; libcrypt.so.1 ensured; audio backend → ALSA + snd-aloop)" echo " Launch from your app menu, or run: resolve-nvidia-open" +echo " Skip snd-aloop module setup: RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh" echo " Logs: ~/.local/share/DaVinciResolve/logs/ResolveDebug.txt" echo diff --git a/README.md b/README.md index 406376c..04b578f 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,41 @@ Resolve doesn't support native Wayland. The wrapper script (`resolve-nvidia-open - Installs udev rules for Blackmagic hardware (capture cards, control panels) - Points all launchers at the XWayland wrapper +### 7. Audio Backend Fix (DeckLink → ALSA + `snd-aloop`) + +Two issues are fixed automatically: + +**Default audio backend.** Resolve's shipped `default-config.dat` sets +`Local.Audio.Type = DeckLink`, which causes Resolve to abort on first launch +on systems without a Blackmagic DeckLink capture/playback card. The script +patches both the system template and any existing user config to use `ALSA` +(backing up the user config to `config.dat.bak.`). + +**Render-blocker hang.** Resolve's audio engine opens raw ALSA hardware +(`hw:N`) and enumerates every card under `/dev/snd/control*`. When all real +ALSA cards are owned/contested by PipeWire's session manager, the +enumeration retries forever — the render queue never spawns the encoder, the +job sits at "in progress" with growing ETA, no output file appears, and +nothing useful lands in `ResolveDebug.txt`. `strace` shows tens of thousands +of `SNDRV_CTL_IOCTL_PCM_INFO` `ENXIO` ioctls per failed render. + +The fix is to load the kernel's `snd-aloop` module. PipeWire ignores it (no +ACP profile, not auto-acquired), so Resolve can fully own it and the render +proceeds normally. The script: + +- Runs `modprobe snd-aloop` for the current session +- Writes `/etc/modules-load.d/snd-aloop.conf` so it autoloads at boot +- Writes a PipeWire loopback bridge at + `~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` so + monitor audio routes from the loopback's capture side to the system + default sink (without it, Resolve renders fine but you hear nothing + during playback; headphone/HDMI sink switching keeps working through + the bridge) +- Restarts user PipeWire services so the bridge loads immediately + +Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a +dedicated audio interface Resolve already uses cleanly). + ## Files Installed ### Application @@ -145,6 +180,18 @@ By default, the script syncs the package database without upgrading. To include RESOLVE_FULL_UPGRADE=1 ./Omarchy_resolve_v2.sh ``` +### Skip the `snd-aloop` Audio Fix + +If you have a dedicated audio interface (e.g. Focusrite Scarlett, MOTU, etc.) +that Resolve already uses cleanly, you don't need the virtual loopback card: + +```bash +RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh +``` + +This skips the `modprobe snd-aloop`, the `/etc/modules-load.d/` entry, and +the PipeWire loopback bridge. The DeckLink → ALSA config patch still runs. + ### Hybrid GPU Laptops (Optimus) If you have an Intel iGPU + NVIDIA dGPU, edit the wrapper to force Resolve onto the NVIDIA GPU: @@ -180,6 +227,53 @@ Stale lockfiles from a previous crash. The wrapper clears these automatically, b rm -f /tmp/qtsingleapp-DaVinci* ``` +### Render queue says "in progress" forever, no output file + +This is the audio render-blocker hang — Resolve's audio engine is stuck +enumerating ALSA cards. Confirm `snd-aloop` is loaded: + +```bash +lsmod | grep snd_aloop +``` + +If absent, load it and retry: + +```bash +sudo modprobe snd-aloop +``` + +If you ran the installer with `RESOLVE_NO_ALOOP=1` and want to opt back in, +re-run the installer without that variable, or do it manually: + +```bash +sudo modprobe snd-aloop +echo 'snd-aloop' | sudo tee /etc/modules-load.d/snd-aloop.conf +``` + +If `lsmod` shows `snd_aloop` is loaded but renders still hang, check the +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 +fix. + +### No audio during playback / monitor sink switches don't work + +The PipeWire loopback bridge at +`~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` routes +the snd-aloop capture side to your default sink. If headphone/HDMI +switching stops working for Resolve playback, restart user PipeWire +services: + +```bash +systemctl --user restart pipewire pipewire-pulse wireplumber +``` + +To remove the bridge entirely: + +```bash +rm ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf +systemctl --user restart pipewire pipewire-pulse wireplumber +``` + ### Missing library errors Re-run the installer — it will re-patch RPATH and re-check dependencies: @@ -233,6 +327,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-DavinciPanel.rules +# Remove the snd-aloop autoload entry + PipeWire bridge (optional) +sudo rm -f /etc/modules-load.d/snd-aloop.conf +rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf +systemctl --user restart pipewire pipewire-pulse wireplumber + # Remove user data (WARNING: deletes all projects and settings) rm -rf ~/.local/share/DaVinciResolve