🎥 ScreenCast: el stream SE CREA — nodo cosmic-screencast vivo en pipewire
La receta de la sonda (b3:af49d32d) y lo que midió. Es la única receta de la campaña
cuyo producto no es una pieza del escritorio sino un instrumento para medirlo: entra
a la imagen porque un handshake de portal sólo se puede ejercer DESDE la sesión, con
bus y compositor vivos, y sale ESTÁTICA (0 NEEDED) porque un instrumento no debe
depender de aquello que mide.
[1/4] CreateSession → Response 0, session_handle ✓
[2/4] SelectSources → Response 0 ✓
[3/4] Start → el backend ABRE "Share your screen", con
miniatura EN VIVO del framebuffer y el output
Virtual-1; se elige, se pulsa Share…
y NO llega Response en 60s ✗
El log del backend da la línea exacta:
screencast_thread: state-changed 'Connecting' -> 'Paused'
Y `pw-cli ls Node` durante la espera da el veredicto INDEPENDIENTE:
node.name = "cosmic-screencast" media.class = "Video/Source"
EL NODO DE VIDEO EXISTE EN EL GRAFO DE PIPEWIRE. La cadena entera —cliente →
frontend → backend → compositor → demonio— funciona hasta crear y negociar el stream.
Lo único que no ocurre es el Response de vuelta tras quedar en `Paused`. Eso es un
lugar muy distinto del de esta mañana ("no hay demonio con quien negociar").
Sospecha para el próximo paso, y es HIPÓTESIS no medición: falta `wireplumber`. Sin
gestor de sesión nadie mueve el nodo de Paused a Streaming y el backend parece
esperarlo. Construirlo la confirma o la mata.
Gotchas que costaron corridas y quedan escritos:
· matar el backend se lleva puesto al frontend (ambos pierden dueño del bus);
· el lanzador busca por NOMBRE VISIBLE: `cosmic-term` no matchea, `Terminal` sí —
escribir el nombre del binario abre otra app;
· `| head -N` bufferiza y deja la terminal en blanco: parece colgada y está esperando;
· pkg-config OMITE los -L de dirs "estándar" y zig cc cross NO los busca ⇒
`-ldbus-1` pelado da "unable to find static system library", que suena a librería
faltante cuando lo que falta es la ruta.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -1009,14 +1009,95 @@ mutilado da 130).
|
||||
|
||||
**Lo que sigue faltando, y son dos cosas separadas:**
|
||||
|
||||
- **El handshake de ScreenCast de punta a punta** necesita un cliente `ashpd` **persistente**, y no
|
||||
hay atajo: el portal asocia la sesión al *sender* de D-Bus, así que `CreateSession` con un
|
||||
`dbus-send` y `SelectSources` con otro se rechazan por venir de nombres únicos distintos. Un
|
||||
cliente de prueba es una receta nueva, no un one-liner.
|
||||
- **El handshake de ScreenCast de punta a punta** necesita un cliente **persistente** — resuelto
|
||||
abajo con `portal-probe`.
|
||||
- **`wireplumber`**, que es lo que separa «hay stream de video» de «hay audio». Sin gestor de sesión
|
||||
pipewire arranca y sirve, pero no descubre tarjetas ni enruta. Para ScreenCast alcanza; para sonido
|
||||
no. Ni siquiera está construido.
|
||||
|
||||
## 🔌 portal-probe: la SONDA, y hasta dónde llega ScreenCast de verdad (2026-08-05)
|
||||
|
||||
`recipes/incoming-cosmic/portal-probe.toml` → **`b3:af49d32d`**. La única receta de la campaña cuyo
|
||||
producto no es una pieza del escritorio sino **un instrumento para medirlo**.
|
||||
|
||||
### Por qué no alcanzaba `dbus-send`, y por qué tampoco hacía falta `ashpd`
|
||||
|
||||
Los portales no son RPC: son **asíncronos en dos tiempos**. Cada método devuelve al instante un
|
||||
object path de `Request`, y el resultado llega DESPUÉS como señal `Request.Response` sobre ese path.
|
||||
`dbus-send` ya salió para entonces. Y hay un segundo muro, más duro: **el portal ata la sesión al
|
||||
SENDER**, así que `CreateSession` con un `dbus-send` y `SelectSources` con otro se rechazan por venir
|
||||
de nombres únicos distintos. Hace falta UNA conexión viva durante todo el intercambio.
|
||||
|
||||
`ashpd` era el camino obvio, pero el árbol fuente de una receta de código propio es el repo del
|
||||
**propio hammer** (no hay modo `path` en `[source]`: sólo git y tarball) ⇒ habría sumado ~150 crates
|
||||
al `Cargo.lock` de la herramienta de build por una sonda de diagnóstico. En C sobre `libdbus` cuesta
|
||||
**cero deps nuevas**, sale **estática (0 NEEDED)** —un instrumento no debe depender de lo que mide— y
|
||||
sobre todo: **el protocolo se ve**. Una sonda cuyo valor es documentar un handshake no debería
|
||||
esconderlo tras una biblioteca que lo abstrae.
|
||||
|
||||
Detalle que la especificación regala y hay que usar: **el path del `Request` se PREDICE**
|
||||
(`/…/request/<sender>/<token>`, con `sender` = nombre único sin `:` y con `.`→`_`). Existe justo para
|
||||
poder suscribirse ANTES de llamar; esperar al path devuelto para recién ahí hacer `AddMatch` es una
|
||||
carrera real, no teórica.
|
||||
|
||||
### Lo medido: el stream SE CREA, y el `Response` es lo único que falta
|
||||
|
||||
```
|
||||
portal-probe version ScreenCast v5 · Screenshot v2 · FileChooser v3 · Settings v2
|
||||
Access y RemoteDesktop AUSENTES
|
||||
portal-probe screencast
|
||||
[1/4] CreateSession → Response 0, session_handle = /…/session/1_108/hammersess ✓
|
||||
[2/4] SelectSources → Response 0 ✓
|
||||
[3/4] Start → el backend ABRE su diálogo «Share your screen», con
|
||||
miniatura EN VIVO del framebuffer y el output `Virtual-1`;
|
||||
se elige, se pulsa Share… y NO llega Response en 60s ✗
|
||||
```
|
||||
|
||||
El log del backend (`RUST_LOG=debug`) da la línea exacta:
|
||||
|
||||
```
|
||||
xdg_desktop_portal_cosmic::screencast_thread: state-changed 'Connecting' -> 'Paused'
|
||||
```
|
||||
|
||||
Y `pw-cli ls Node` durante la espera da el veredicto independiente:
|
||||
|
||||
```
|
||||
node.name = "cosmic-screencast"
|
||||
media.class = "Video/Source"
|
||||
```
|
||||
|
||||
**El nodo de video EXISTE en el grafo de pipewire.** O sea: la cadena entera —cliente → frontend →
|
||||
backend → compositor → demonio de pipewire— funciona hasta **crear y negociar el stream**. Lo único
|
||||
que no ocurre es que el backend emita el `Response` de vuelta al cliente tras quedar en `Paused`.
|
||||
|
||||
Ese es un lugar muy distinto del que ocupaba el frente esta mañana («no hay demonio con quien
|
||||
negociar»). El siguiente paso es el `Paused → Streaming`, y la sospecha razonable es
|
||||
**`wireplumber`**: sin gestor de sesión nadie mueve el nodo de `Paused`, y el backend parece
|
||||
esperarlo. Es una hipótesis, no una medición — construir `wireplumber` la confirma o la mata.
|
||||
|
||||
### Dos gotchas que costaron corridas
|
||||
|
||||
- **`NameHasOwner` no activa nada.** Los portales son servicios ACTIVABLES: el bus los arranca al
|
||||
pedirlos. La primera versión de la sonda rechazaba con «no hay frontend de portal en el bus» sobre
|
||||
un sistema donde el portal andaba perfecto, sólo que dormido. Se arregló con `StartServiceByName`
|
||||
(commit `ea210ba`) — y distingue «arrancado ahora» de «ya estaba corriendo», que no es lo mismo
|
||||
cuando lo que se investiga es una carrera.
|
||||
- **Matar el backend se lleva puesto al frontend.** `kill` sobre `xdg-desktop-portal-cosmic` dejó
|
||||
también sin dueño a `org.freedesktop.portal.Desktop`. Para diagnosticar con log hay que relanzar el
|
||||
backend Y forzar la reactivación del frontend.
|
||||
- **El lanzador busca por NOMBRE VISIBLE, no por binario**: `cosmic-term` no matchea nada,
|
||||
`Terminal` abre COSMIC Terminal. Escribir el nombre del ejecutable abre otra cosa (settings).
|
||||
- Y uno de shell, al automatizar por QMP: **`| head -N` bufferiza** y deja la terminal en blanco hasta
|
||||
que el programa termina. Parece que la sonda colgó cuando en realidad está esperando.
|
||||
|
||||
### El `-L/usr/lib` que pkg-config no da
|
||||
|
||||
`pkg-config` **omite los `-L` de directorios que considera estándar del sistema**, asumiendo que el
|
||||
linker ya los busca. Cierto para un `cc` nativo; **falso para `zig cc` cruzando a
|
||||
`x86_64-linux-musl`**, que trae sus propias rutas. Resultado: `--libs --static` devuelve `-ldbus-1`
|
||||
pelado y zig responde `unable to find static system library 'dbus-1' … searched paths: none` — un
|
||||
error que suena a «falta la librería» cuando lo que falta es la ruta.
|
||||
|
||||
**Y de paso se corrigió un comentario desactualizado de `cosmic-start`** que decía que
|
||||
`cosmic-settings-daemon` «todavía no se puede construir acá (arrastra pipewire)». Es falso hace
|
||||
tiempo: ese daemon está sellado y corre. Un comentario viejo manda a buscar un bloqueo que ya no
|
||||
@@ -1024,10 +1105,11 @@ existe, y eso cuesta igual que un bug.
|
||||
|
||||
## Lo que falta, en orden
|
||||
|
||||
1. ~~Arrancar el demonio de pipewire desde `cosmic-start`~~ **✅ hecho (2026-08-05)**, y el portal ya
|
||||
figura como cliente suyo. Queda el **cliente `ashpd` persistente** para ejercer el handshake de
|
||||
ScreenCast y, de paso, capturar la URI del `FileChooser` que `dbus-send` no puede ver — es una
|
||||
receta, no un one-liner, por lo del *sender* de D-Bus explicado arriba. Y `wireplumber` para audio.
|
||||
1. ~~Arrancar el demonio de pipewire~~ ✅ y ~~el cliente persistente~~ ✅ (`portal-probe`, `b3:af49d32d`).
|
||||
**Lo que queda es `wireplumber`**: el stream de ScreenCast se crea y llega a `Paused`, con nodo
|
||||
`cosmic-screencast` visible en pipewire, pero nadie lo pasa a `Streaming` y el backend no emite el
|
||||
`Response`. La hipótesis es que falta el gestor de sesión — construirlo la confirma o la mata.
|
||||
Falta también correr `portal-probe filechooser`, que ya puede capturar la URI.
|
||||
2. **Decidir `gvfs`** (ver la corrección de arriba: las piezas ya están selladas, lo que falta es la
|
||||
decisión sobre la segunda glib). Destrabaría los montajes remotos de cosmic-files y su applet.
|
||||
3. **Enchufar la tienda a `.swm`**: servir `org.freedesktop.PackageKit` y encender la feature
|
||||
|
||||
@@ -133,6 +133,10 @@ paquetes = [
|
||||
# Access/FileChooser/Screenshot/Settings/ScreenCast. Sin ellos no hay captura, ni selector de
|
||||
# ficheros de portal, ni compartir pantalla.
|
||||
"xdg-desktop-portal", "xdg-desktop-portal-cosmic",
|
||||
# Y la SONDA con que se mide esa cadena. No es escritorio: es el instrumento. Se lista como raíz
|
||||
# porque nadie la declara como dep y sin ella el perfil no incluiría con qué verificarse a sí
|
||||
# mismo — un handshake de portal sólo se puede ejercer DESDE la sesión, con bus y compositor vivos.
|
||||
"portal-probe",
|
||||
# Datos, no binarios: el tema de iconos (y el hicolor del que hereda), las tablas de xkb y una
|
||||
# tipografía. Ninguno es dep de build de nadie y sin ellos el escritorio arranca roto — sin puntero,
|
||||
# sin teclado o con tofu.
|
||||
|
||||
Reference in New Issue
Block a user