⚠ ESTE PARCHE NO ERA EL BLOQUEO — leer antes de sacar conclusiones.

Se escribió creyendo que `SOUND_INITIALIZED` era lo que impedía enumerar, y **no lo era**: con el
parche aplicado, `wpctl status` seguía dando `Devices:` vacío. La causa real está más abajo en el mismo
fichero y es ESTRUCTURAL, no una propiedad que falte (ver la nota al final).

El parche se conserva porque la incompatibilidad que describe es REAL y volvería a morder en cuanto la
enumeración funcione: sin él, SPA descarta toda tarjeta en un sistema sin udevd. Pero no es la
solución del problema de audio.

pipewire/SPA: no exigir `SOUND_INITIALIZED`, una propiedad que sólo pone udevd con sus reglas.

EL SÍNTOMA, y por qué es caro de leer: con ALSA encendido en el kernel, la tarjeta detectada y
`/dev/snd/controlC0` presente, `wpctl status` seguía dando

    Audio
     ├─ Devices:            ← vacío
     ├─ Sinks:  * 33. Dummy Output

o sea el MISMO cuadro que cuando no había kernel con sonido. Tres cosas distintas —no hay ALSA, no hay
tarjeta, hay tarjeta y el stack no la ve— se ven idénticas en esa salida.

LA CAUSA, en la fuente: `spa/plugins/alsa/alsa-udev.c:167`

    if (udev_device_get_property_value(udev_device, "SOUND_INITIALIZED") == NULL)
            return SPA_ID_INVALID;      /* descarta la tarjeta */

`SOUND_INITIALIZED` no es una propiedad del kernel: **la pone udevd al ejecutar sus reglas**
(`78-sound-card.rules` de systemd/eudev marca la tarjeta cuando todos sus devices están listos). Esta
distro usa **libudev-zero**, que lee /sys directo y NO EJECUTA REGLAS por diseño — su
`udev_enumerate_scan_devices` recorre `/sys/dev/block` y `/sys/dev/char`, así que la tarjeta SÍ se
enumera, pero llega sin esa propiedad. Resultado: SPA descarta todas las tarjetas, siempre.

POR QUÉ SE PARCHEA PIPEWIRE Y NO libudev-zero: sintetizar `SOUND_INITIALIZED` en libudev-zero sería
igual de correcto, pero `yupana radio libudev-zero` da **51 artefactos sellados cayendo a deuda** —
está en el cierre de las cinco imágenes. El radio de pipewire son 2. Se paga el barato.

POR QUÉ QUITAR EL GUARDA ES LEGÍTIMO Y NO UN ATAJO: ese `if` existe para no correr una carrera contra
udevd —evitar tomar una tarjeta cuyos devices todavía no aparecieron—. **Con libudev-zero no hay
udevd, así que no hay carrera que perder**: cuando `/sys/dev/char` lista el device, el device existe.
Se elimina una comprobación cuya premisa no se cumple acá, no una que nos moleste.

Lo que NO se toca: los otros tres guardas del mismo bloque (`ACP_IGNORE`, `SOUND_CLASS=modem`,
`DEVPATH`). Los dos primeros son opt-out explícitos del administrador y el tercero es un dato real del
kernel — ésos siguen valiendo.

diff -Naur a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c
--- a/spa/plugins/alsa/alsa-udev.c
+++ b/spa/plugins/alsa/alsa-udev.c
@@ -164,8 +164,13 @@
 	if ((str = udev_device_get_property_value(udev_device, "SOUND_CLASS")) && spa_streq(str, "modem"))
 		return SPA_ID_INVALID;

-	if (udev_device_get_property_value(udev_device, "SOUND_INITIALIZED") == NULL)
-		return SPA_ID_INVALID;
+	/* hammer: NO exigir SOUND_INITIALIZED. Esa propiedad la pone udevd al correr
+	 * 78-sound-card.rules, y esta distro usa libudev-zero, que lee /sys directo y no
+	 * ejecuta reglas. El guarda existe para no competir con udevd por una tarjeta a
+	 * medio inicializar; sin udevd no hay carrera: si /sys/dev/char lista el device,
+	 * el device esta. Ver recipes/incoming-gnome/pipewire-sound-initialized.patch.
+	 * Los otros guardas de este bloque (ACP_IGNORE, SOUND_CLASS=modem, DEVPATH) se
+	 * respetan tal cual: son opt-out del administrador o datos reales del kernel. */

 	if ((str = udev_device_get_property_value(udev_device, "DEVPATH")) == NULL)
 		return SPA_ID_INVALID;

══ LO QUE SÍ BLOQUEA, medido después ═════════════════════════════════════════════════════════════
`get_card_nr` sigue con dos comprobaciones más (alsa-udev.c:178-183):

    if ((e = strrchr(str, '/')) == NULL) return SPA_ID_INVALID;
    if (strlen(e) <= 5 || strncmp(e, "/card", 5) != 0) return SPA_ID_INVALID;

o sea que **sólo acepta el device CARD** (`/sys/.../sound/card0`), no `controlC0` ni `pcmC0D0p`. Y
`card0` es un device de CLASE: no tiene major:minor, no tiene nodo en /dev.

`udev_enumerate_scan_devices` de libudev-zero recorre **exclusivamente** `/sys/dev/block` y
`/sys/dev/char` (udev_enumerate.c:281) — o sea sólo devices CON nodo. El udev real enumera
`/sys/class/*` entero, con nodo o sin él.

⇒ **El device que SPA necesita nunca entra en la enumeración.** No hay guarda que sacar: falta la
mitad del espacio de búsqueda.

**YA RESUELTO (2026-07-30)**, y por el camino (a): `recipes/libudev-zero-scan-class.patch` enseña a
libudev-zero a enumerar devices de CLASE para una lista acotada de subsistemas (hoy `sound`). Se
descartó eudev porque sin udevd es PEOR —rompió el input en otro frente— y correr udevd contradice la
arquitectura. El audio funciona: `48. HDA Intel [alsa]` con sink y source reales. Los detalles, y por
qué la lista es acotada (recorrer `/sys/class` entero rompía el VÍDEO), están en ese parche.
