audio: wireplumber (b3:39a9a06c) + lua (b3:e6c35f98) — y el Devices vacío es del KERNEL

Cierra el gestor de sesión de PipeWire, que es lo que separa «PipeWire acepta clientes»
de «PipeWire tiene dispositivos». Su política está escrita en Lua, así que arrastró una
receta de Lua que hubo que autorar entera.

LO QUE LA RECETA DE LUA TIENE QUE INVENTAR: el Makefile de upstream sólo produce
liblua.a y los binarios — **no hay regla de .so ni fichero pkg-config**, los agrega cada
distro. Acá la compartida se enlaza a mano desde la .a con --whole-archive (una estática
sólo aporta lo referenciado y hay que llevarse todo) y el .pc se escribe con los TRES
nombres que se usan por ahí, porque wireplumber prueba lua-5.4, lua5.4 y lua54 en orden.
`-fPIC` no es opcional: libwplua es un objeto compartido.

Dos símbolos más en libelogind (tawasuyu 087230054 → re-pineado 749edfe41):
sd_uid_get_seats y sd_uid_get_state, que module-logind.c de wireplumber usa para saber si
el usuario está en un asiento antes de tomar los dispositivos. Van 28 símbolos sd-*.

**EL `Devices:` VACÍO DE wpctl NO ES UN FALLO DE wireplumber: el kernel no tiene ALSA.**
recipes/linux-metal.toml:111 lo apaga explícito (`-d SOUND -d SND`), así que no hay
/dev/snd que enumerar. Y esto NO se dio por supuesto: se agregó una ich9-intel-hda
emulada a QEMU (AUDIO=1, ahora el default de run-qemu-desktop.sh) justo porque un
«Devices: vacío» se lee IGUAL si wireplumber funciona sobre una VM sin hardware que si no
funciona. Con tarjeta y sin ALSA en el kernel, el resultado no cambia — la ambigüedad
queda resuelta. Encender el sonido en la distro es una decisión con costo (re-sellar el
kernel, rehacer la imagen metal) y queda a la vista en vez de escondida en un default.

Bug propio destapado en el camino: el bloque de wireplumber quedó DUPLICADO en
gnome-start y había DOS wireplumber peleándose el grafo. El síntoma no era un error sino
una lista de clientes que se lee normal si no se cuenta: dos «WirePlumber» con pids
distintos en wpctl status.

Y una nota de ADR 0012 que costó un rato: la cascada de libelogind cortó a mitad y dejó
el `output/` de mutter a medio hacer; el reintento moría con «error opening
'...c.o.d': No such file or directory». Un `rm -rf output` en el configure NO alcanzó
—el árbol tenía estado viejo más allá del build dir—; lo que lo arregló fue BORRAR
work/sources/mutter-* para que el fetch lo re-extraiga limpio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-29 20:40:12 -04:00
co-authored by Claude Opus 5
parent d57fb8c5c7
commit 51c6830f58
7 changed files with 242 additions and 12 deletions
+32 -8
View File
@@ -292,15 +292,18 @@ esperar_nombre() {
return 1
}
# ── AUDIO: PipeWire (decisión del usuario, 2026-07-29) ──────────────────────────────────────────
# Van DOS procesos y el orden importa: `pipewire` es el servidor, y `pipewire-pulse` es el puente que
# habla el protocolo de PulseAudio contra él. gnome-shell usa libpulse (gvc), así que lo que necesita
# es el SEGUNDO; sin el primero, el segundo no tiene con quién hablar.
# Van TRES procesos y el orden importa, porque cada uno es cliente del anterior:
# 1. `pipewire` — el servidor. Crea $XDG_RUNTIME_DIR/pipewire-0.
# 2. `pipewire-pulse` — el puente que habla el protocolo de PulseAudio contra él. Es lo que
# gnome-shell necesita (gvc usa libpulse), y sin (1) no tiene con quién hablar.
# 3. `wireplumber` — el gestor de sesión: enumera dispositivos y aplica la política. Sin él (1) y
# (2) funcionan pero el único sink es `auto_null`, el nodo de descarte.
# Los tres son servicios de USUARIO: sus sockets viven en $XDG_RUNTIME_DIR, creado más arriba.
#
# Los dos son servicios de USUARIO: su socket vive en $XDG_RUNTIME_DIR, que ya está creado más arriba.
#
# ⚠ Sin gestor de sesión (wireplumber todavía no está autorado): esto hace que el shell CONECTE y deje
# de tirar `Gvc-WARNING: Failed to connect context: Connection refused`, pero NO enumera ni enruta
# dispositivos. «El shell conecta» no es «hay sonido», y conviene no confundirlos.
# ⚠ NO duplicar el bloque de wireplumber. Estuvo dos veces por un merge descuidado de este script y el
# resultado fue DOS wireplumber vivos peleándose el grafo — visible en `wpctl status` como dos clientes
# «WirePlumber» con pids distintos. El síntoma no es un error: es una lista de clientes que se lee
# normal si no se cuenta.
if [ -x /usr/bin/pipewire ]; then
/usr/bin/pipewire >/tmp/pipewire.log 2>&1 &
say "pipewire lanzado (pid $!)"
@@ -315,6 +318,27 @@ if [ -x /usr/bin/pipewire ]; then
else
say "!! pipewire-pulse no creó pulse/native:"; dump /tmp/pipewire-pulse.log
fi
# wireplumber: el GESTOR DE SESIÓN. Va tercero porque necesita que el servidor ya esté; es el que
# convierte «PipeWire acepta clientes» en «PipeWire tiene dispositivos»: enumera por udev/alsa y
# aplica la política (qué es entrada, qué es salida, qué se enlaza con qué), y esa política está
# escrita en Lua. Sin él el único sink es `auto_null`, el nodo de descarte.
if [ -x /usr/bin/wireplumber ]; then
/usr/bin/wireplumber >/tmp/wireplumber.log 2>&1 &
WP_PID=$!
say "wireplumber lanzado (pid $WP_PID)"
sleep 2
if alive $WP_PID; then
say "wireplumber sigue vivo"
# El dato que importa no es el pid sino QUÉ VE. `wpctl status` lista los nodos que la política
# creó: si sale vacío, wireplumber corre pero no enumeró nada.
wpctl status >/tmp/wpctl.log 2>&1 || true
dump /tmp/wpctl.log
else
say "!! wireplumber MURIÓ:"; dump /tmp/wireplumber.log
fi
else
say "!! sin wireplumber — PipeWire acepta clientes pero no habrá dispositivos"
fi
else
say "!! pipewire no creó su socket:"; dump /tmp/pipewire.log
fi
+2
View File
@@ -54,6 +54,8 @@ else
# El SERVIDOR de audio (decisión del usuario: PipeWire, no PulseAudio). No es dep de build de
# nadie: el shell habla libpulse y `pipewire-pulse` le contesta por el otro lado.
recipes/incoming-gnome/pipewire.toml
# Y su gestor de sesión, que es lo que hace que PipeWire tenga DISPOSITIVOS y no sólo un socket.
recipes/incoming-gnome/wireplumber.toml
)
fi
+11
View File
@@ -49,6 +49,17 @@ QEMU_ARGS=(
-no-reboot
)
# AUDIO=1 (default): darle a la VM una tarjeta de sonido EMULADA. No es para oír nada —el backend es
# `none`, que descarta las muestras— sino para que HAYA UN DISPOSITIVO QUE ENUMERAR.
#
# Sin esto, `wpctl status` sale con «Devices:» vacío y un único sink `auto_null`, y ese resultado es
# AMBIGUO: se lee igual si wireplumber funciona sobre una VM sin hardware que si wireplumber no
# funciona. Con una ich9-intel-hda emulada, el árbol de /sys/class/sound existe y la respuesta
# distingue las dos cosas. AUDIO=0 para volver al caso sin tarjeta.
if [ "${AUDIO:-1}" = 1 ]; then
QEMU_ARGS+=(-audiodev none,id=snd0 -device ich9-intel-hda -device hda-duplex,audiodev=snd0)
fi
echo "==> QEMU (DISP=$DISP, serial=$SERIAL)"
echo " imagen: $IMG"
if [ -n "${TIMEOUT:-}" ]; then