tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1569Shell 203Rust 109Markdown 993728 Definitions

audio: PipeWire es el servidor de la distro (decisión del usuario) — gvc conecta

Cierra una pregunta que estaba explícitamente abierta en varias recetas, y que es la
razón por la que `pulseaudio` se había construido con `-Ddaemon=false`: sólo el cliente,
para que gvc hablara el protocolo sin cerrar la decisión de prestado.

**Los dos conviven y por eso la decisión no rompe nada**: pipewire va con
`-Dlibpulse=enabled` ⇒ `pipewire-pulse`, un servidor que habla el protocolo de
PulseAudio. gnome-shell usa libpulse sin enterarse de qué hay del otro lado. No hubo que
tocar una línea del cliente.

  == gnome-qemu :: socket pipewire-0 OK
  == gnome-qemu :: socket pulse/native OK — gvc va a poder conectar
  Gvc-DEBUG: Updating client: index=32 name='pipewire'
  Gvc-DEBUG: Updating sink: index=33 name='auto_null' description='Dummy Output'

El `Failed to connect context: Connection refused` desapareció. El sink es auto_null, que
es la respuesta honesta: la VM no tiene tarjeta de sonido.

**⚠ Falta wireplumber** (gestor de sesión, Lua + su cierre). Sin él PipeWire acepta
clientes pero NO enumera ni enruta dispositivos. «El shell conecta» ≠ «hay sonido», y el
log de arriba es justo el caso donde confundirlos sería fácil. Queda escrito en la receta
y en el runbook.

GOTCHA MEDIDO: ya existía incoming-kde/pipewire.toml sellada y NO se puede reusar
hidratándola acá — los dos cierres traen glib y **no son la misma glib**:
incoming-kde/glib-shared y incoming-gnome/glib producen libglib-2.0.so.0.8800.1 con bytes
distintos (verificado con cmp) y comparten 370 rutas. Proyectar las dos deja que una gane
por orden de proyección ⇒ dos registros de GType en un proceso, el cuadro que costó el
episodio de colord. De ahí la copia en la cola GNOME (glib-shared→glib, dbus→dbus-shared,
pcre2-shared→pcre2), que sí re-construye. Lo que FUE gratis: alsa-lib, cuya única dep es
pkgconf y resuelve al catálogo PADRE ⇒ hash idéntico y cache hit (b3:93cae411).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

5faa259603762d754b13d31b5bf98323f1e200f1 · by sergio · (2 months ago) · parent d250d57c2 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

6 files · +170 −3

diff --git a/docs/evidencia/gnome-shell-qemu-2026-07-29.png b/docs/evidencia/gnome-shell-qemu-2026-07-29.png
index 00b5043e..32842460 100644
Binary files a/docs/evidencia/gnome-shell-qemu-2026-07-29.png and b/docs/evidencia/gnome-shell-qemu-2026-07-29.png differ
diff --git a/docs/runbooks/gnome-qemu-desktop.md b/docs/runbooks/gnome-qemu-desktop.md
index 7ceecbab..26b74bdf 100644
--- a/docs/runbooks/gnome-qemu-desktop.md
+++ b/docs/runbooks/gnome-qemu-desktop.md
@@ -155,13 +155,43 @@ Dos gotchas del empaquetado, los dos medidos:
   fichero que venga de un artefacto; agregar al lado, o `rm -f` primero — y entonces se está pisando
   algo sellado, que es una decisión, no un descuido.
 
+### Audio: PipeWire (cerrado — decisión del usuario, 2026-07-29)
+
+**El servidor de audio de la distro es PipeWire, no PulseAudio.** Cierra una pregunta que estaba
+explícitamente abierta en varias recetas, y por eso `pulseaudio` se había construido `-Ddaemon=false`:
+sólo el cliente, para que gvc hablara el protocolo sin cerrar la decisión de prestado.
+
+Los dos conviven, y eso es lo que hace que la decisión no rompa nada: `pipewire` va con
+`-Dlibpulse=enabled`, que produce **`pipewire-pulse`** — un servidor que habla el protocolo de
+PulseAudio. gnome-shell usa libpulse sin enterarse de qué hay del otro lado. **No hubo que tocar una
+línea del cliente.**
+
+```
+== gnome-qemu :: socket pipewire-0 OK
+== gnome-qemu :: socket pulse/native OK — gvc va a poder conectar
+Gvc-DEBUG: get server info / update server
+Gvc-DEBUG: Updating client: index=32 name='pipewire'
+Gvc-DEBUG: Updating sink: index=33 name='auto_null' description='Dummy Output'
+```
+
+El `Failed to connect context: Connection refused` desapareció y gvc ve el servidor. El sink es
+`auto_null` («Dummy Output»), que es la respuesta honesta: la VM no tiene tarjeta de sonido.
+
+**⚠ Falta `wireplumber`** (el gestor de sesión; Lua + su propio cierre). Sin él PipeWire arranca y
+acepta clientes pero **no enumera ni enruta dispositivos**. **«El shell conecta» ≠ «hay sonido»**, y el
+log de arriba es exactamente el caso donde confundirlos sería fácil.
+
+Gotcha de empaquetado, medido: ya existía `incoming-kde/pipewire.toml` sellada y **no se puede reusar**
+hidratándola acá — los dos cierres traen glib y **no son la misma glib**: `incoming-kde/glib-shared` y
+`incoming-gnome/glib` producen `libglib-2.0.so.0.8800.1` con bytes distintos (`cmp`) y comparten 370
+rutas. Proyectar las dos deja que una gane por orden ⇒ dos registros de GType en un proceso, el cuadro
+de colord. Hay copia en la cola GNOME. Lo que SÍ fue gratis: `alsa-lib`, cuya única dep resuelve al
+catálogo padre ⇒ hash idéntico y cache hit.
+
 ### Lo que queda, y ninguno impide el escritorio
 
 - **colord** sigue sin arrancar (gestión de color de pantalla). Su activación por bus ya está
   permitida; falta ver por qué el demonio no sube.
-- **PulseAudio**: `Gvc-WARNING: Failed to connect context: Connection refused` — el control de volumen
-  del shell no tiene servidor de sonido. Coherente con que `pulseaudio` se construyó **sólo cliente**
-  (`-Ddaemon=false`): el demonio de sonido de la distro sigue sin decidirse (PulseAudio vs PipeWire).
 - `Missing required core component Settings` — es gnome-control-center, que no está en el corpus.
 
 ### Dos lecciones de método que costaron una iteración cada una
diff --git a/recipes/incoming-gnome/alsa-lib.toml b/recipes/incoming-gnome/alsa-lib.toml
new file mode 100644
index 00000000..2a07f967
--- /dev/null
+++ b/recipes/incoming-gnome/alsa-lib.toml
@@ -0,0 +1,25 @@
+# alsa-lib 1.2.14 — API de audio del kernel Linux (libasound.so). Campaña KDE (ADR 0011): sustrato de
+# PulseAudio → pulseaudio-qt → plasma-pa (el applet de volumen). Primer eslabón de la cadena de AUDIO real
+# (hasta ahora el lab sólo tenía libcanberra con backend NULL, sin reproducción).
+#
+# --disable-python: los bindings pyalsa exigen headers de python + no hacen falta. Sin deps externas.
+name    = "alsa-lib"
+version = "1.2.14"
+
+[source]
+tarball = "https://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.14.tar.bz2"
+sha256  = "be9c88a0b3604367dd74167a2b754a35e142f670292ae47a2fdef27a2ee97a32"
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "dynamic"
+flags    = []
+
+[build.phases]
+configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --enable-shared --disable-static --disable-python'
+compile   = 'make -j"$(nproc)"'
+install   = "make DESTDIR=/out install && find /out -name '*.la' -delete"
+
+[deps]
+build = ["pkgconf"]
diff --git a/recipes/incoming-gnome/pipewire.toml b/recipes/incoming-gnome/pipewire.toml
new file mode 100644
index 00000000..4c3badf7
--- /dev/null
+++ b/recipes/incoming-gnome/pipewire.toml
@@ -0,0 +1,78 @@
+# pipewire 1.2.7 — EL SERVIDOR DE AUDIO DE LA DISTRO. Decisión tomada por el usuario (2026-07-29):
+# **PipeWire, no PulseAudio.** Hasta hoy el corpus tenía sólo el CLIENTE libpulse y el demonio quedaba
+# sin decidir; esta receta cierra esa pregunta abierta.
+#
+# CÓMO CONVIVE CON EL `pulseaudio` DE ESTA MISMA COLA, que es lo que hace que la decisión no rompa
+# nada: `pulseaudio` se construyó `-Ddaemon=false` (sólo cliente, para que gvc pueda HABLAR el
+# protocolo) y pipewire va con `-Dlibpulse=enabled`, que produce **`pipewire-pulse`**: un servidor que
+# habla el protocolo de PulseAudio. O sea que gnome-shell sigue usando libpulse sin saber que del otro
+# lado hay PipeWire. Elegir PipeWire NO obligó a tocar una línea del cliente.
+#
+# ⚠ SIN GESTOR DE SESIÓN todavía (`-Dsession-managers=[]`). PipeWire arranca y acepta clientes —lo que
+# quita el `Gvc-WARNING: Failed to connect context: Connection refused` del shell— pero sin
+# wireplumber no enumera ni enruta dispositivos: no hay política de qué entra y qué sale. Para una VM
+# sin tarjeta de sonido alcanza; **para audio de verdad falta autorar `wireplumber`** (Lua + su propio
+# cierre). Queda dicho para no confundir «el shell conecta» con «hay sonido».
+#
+# POR QUÉ UNA COPIA EN ESTA COLA Y NO REUSAR incoming-kde/pipewire.toml: los dos cierres traen glib y
+# **NO son la misma glib** — `incoming-kde/glib-shared` y `incoming-gnome/glib` producen
+# `libglib-2.0.so.0.8800.1` con bytes DISTINTOS (verificado con `cmp`), y comparten 370 ficheros de
+# rutas. Hidratar la receta de KDE en el rootfs de GNOME pondría las dos en la misma ruta, y una
+# ganaría por orden de proyección: dos registros de GType en el mismo proceso, que es el cuadro que ya
+# costó el episodio de colord. La copia resuelve contra la glib de la isla dinámica.
+#
+# EL PRECIO DE LA COPIA, medido: cambian `glib-shared`→`glib`, `dbus`→`dbus-shared` y
+# `pcre2-shared`→`pcre2`, así que el ArtifactHash NO coincide con el de KDE y se reconstruye. Lo que
+# SÍ fue gratis es `alsa-lib`: su única dep es `pkgconf`, que resuelve al catálogo PADRE, ⇒ copiarla
+# dio **hash idéntico y cache hit** (b3:93cae411). Es la regla de [[frente-gnome]] sobre duplicar
+# recetas entre colas, aplicada con la medición delante.
+#
+# Fuente del gitlab.freedesktop.org (como networkmanager/modemmanager).
+# Recortado al core + SPA: sin bluez5 (cadena de códecs aptx/ldac/aac/opus enorme), sin jack/v4l2/
+# libcamera/gstreamer/ffmpeg/vulkan/roc/lv2/avahi/x11/echo-cancel-webrtc/libusb/flatpak/snap.
+# systemd/logind/selinux/rtkit off (no hay systemd acá). alsa=enabled + sndfile=enabled + libpulse=enabled
+# (el emulador pulse: deja que los clientes libpulse hablen con pipewire) — las 3 ya selladas.
+#
+# SIN ncurses a propósito: la única consumidora es la tool `pw-top` (monitor de terminal), guardada por
+# `if ncurses_dep.found()`. El ncurses del catálogo es static-only y su .pc arrastra `-static` al link ⇒
+# "error: using shared libraries requires dynamic linking" al enlazar pw-top contra libpipewire-0.3.so.
+# Quitando la dep, meson saltea pw-top y el resto construye.
+name    = "pipewire"
+version = "1.2.7"
+
+[source]
+tarball = "https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/1.2.7/pipewire-1.2.7.tar.gz"
+sha256  = "e75568ed18bcbe75e9779af57cb9cc256fd7ebfaadc12bb347a0717055d1d3a9"
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "dynamic"
+flags    = []
+
+[build.phases]
+configure = '''
+PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release \
+  -Ddefault_library=shared \
+  -Ddocs=disabled -Dman=disabled -Dexamples=disabled -Dtests=disabled \
+  -Dgstreamer=disabled -Dgstreamer-device-provider=disabled \
+  -Dsystemd=disabled -Dlogind=disabled -Dsystemd-system-service=disabled \
+  -Dsystemd-user-service=disabled -Dselinux=disabled -Dlegacy-rtkit=false \
+  -Dpipewire-jack=disabled -Dpipewire-v4l2=disabled -Djack=disabled -Dv4l2=disabled \
+  -Dlibcamera=disabled -Dbluez5=disabled -Dffmpeg=disabled -Dvulkan=disabled \
+  -Droc=disabled -Dlv2=disabled -Davahi=disabled -Dx11=disabled -Dx11-xfixes=disabled \
+  -Decho-cancel-webrtc=disabled -Dlibusb=disabled -Dflatpak=disabled -Dsnap=disabled \
+  -Dlibmysofa=disabled -Dsdl2=disabled -Dopus=disabled -Dlibffado=disabled -Dcompress-offload=disabled \
+  -Dlibcanberra=disabled -Dgsettings=disabled -Dreadline=disabled -Draop=disabled -Davb=disabled \
+  -Dsession-managers=[] \
+  -Dalsa=enabled -Dsndfile=enabled -Dlibpulse=enabled -Ddbus=enabled -Dudev=enabled \
+  -Dpipewire-alsa=disabled \
+  -Dspa-plugins=enabled -Daudioconvert=enabled -Daudiomixer=enabled -Dcontrol=enabled \
+  -Dvideoconvert=enabled -Dsupport=enabled
+'''
+compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
+install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild"
+
+[deps]
+build = ["meson", "samurai", "python3", "pkgconf", "dbus-shared", "expat", "alsa-lib", "libsndfile",
+  "pulseaudio", "glib", "pcre2", "libffi", "libudev-zero", "zlib-shared", "gettext-tiny"]
diff --git a/scripts/gnome/gnome-start-qemu.sh b/scripts/gnome/gnome-start-qemu.sh
index 485de982..83ae6869 100755
--- a/scripts/gnome/gnome-start-qemu.sh
+++ b/scripts/gnome/gnome-start-qemu.sh
@@ -291,6 +291,37 @@ esperar_nombre() {
   dump /tmp/busnames.log
   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.
+#
+# 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.
+if [ -x /usr/bin/pipewire ]; then
+  /usr/bin/pipewire >/tmp/pipewire.log 2>&1 &
+  say "pipewire lanzado (pid $!)"
+  i=0; while [ $i -lt 20 ] && [ ! -S "$XDG_RUNTIME_DIR/pipewire-0" ]; do i=$((i+1)); sleep 0.25; done
+  if [ -S "$XDG_RUNTIME_DIR/pipewire-0" ]; then
+    say "socket pipewire-0 OK"
+    /usr/bin/pipewire-pulse >/tmp/pipewire-pulse.log 2>&1 &
+    say "pipewire-pulse lanzado (pid $!)"
+    i=0; while [ $i -lt 20 ] && [ ! -S "$XDG_RUNTIME_DIR/pulse/native" ]; do i=$((i+1)); sleep 0.25; done
+    if [ -S "$XDG_RUNTIME_DIR/pulse/native" ]; then
+      say "socket pulse/native OK — gvc va a poder conectar"
+    else
+      say "!! pipewire-pulse no creó pulse/native:"; dump /tmp/pipewire-pulse.log
+    fi
+  else
+    say "!! pipewire no creó su socket:"; dump /tmp/pipewire.log
+  fi
+else
+  say "!! sin /usr/bin/pipewire — el shell va a avisar 'Failed to connect context'"
+fi
+
 esperar_nombre org.freedesktop.login1 /tmp/logind-compat.log
 esperar_nombre org.freedesktop.PolicyKit1 /tmp/polkit-compat.log
 esperar_nombre org.freedesktop.Accounts /tmp/accounts-daemon.log
diff --git a/scripts/gnome/hydrate-gnome.sh b/scripts/gnome/hydrate-gnome.sh
index 454e4211..42f60d07 100755
--- a/scripts/gnome/hydrate-gnome.sh
+++ b/scripts/gnome/hydrate-gnome.sh
@@ -51,6 +51,9 @@ else
     # el escritorio sea usable— los CURSORES. Con el cursor por software (obligatorio en virtio-gpu)
     # y sin tema, el puntero se mueve invisible. Arrastra hicolor-icon-theme por `Inherits=hicolor`.
     recipes/incoming-gnome/adwaita-icon-theme.toml
+    # 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
   )
 fi