feat(agent): Wayland screen capture via dlopen PipeWire (VA-82) #87
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/VA-82-pipewire-dlopen"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Completes VA-82: the agent captures the screen on a Wayland desktop, while the single shipped binary still execs on headless hosts with no hard libpipewire/libgstreamer dependency. This is the end-state the maintainer asked for (one Linux binary like every other platform), achieved by loading PipeWire at runtime.
Background
VA-80 stopped the silent black X11 fallback on Wayland; a
--features wayland-portaltest build proved the existing ScreenCast + PipeWire consumer captures correctly on the GNOME/Wayland host. The blocker to shipping it: thepipewirecrate'slibspa-syslinkslibpipewire-0.3via pkg-config, adding aNEEDEDentry that would break the agent on headless hosts (binary won't exec). RustDesk avoids a libpipewire link only by going through GStreamer's plugin loader, trading it for a libgstreamer hard link. This PR removes the hard dependency entirely via dlopen.Changes
pw_ffi:dlopenslibpipewire-0.3.so.0withlibloadingand binds the ~dozenpw_*symbols the consumer needs. Thespa_buffer/spa_data/spa_chunk/pw_buffer/pw_stream_events/spa_hooklayouts are declared#[repr(C)]verbatim from the installed spa-0.2 / pipewire-0.3 headers. Loads lazily; absent library -> cleanNotAvailable(the VA-80 surfaced error), never a crash.spa_pod: pure-Rust SPA POD codec (no libspa link). Builds the EnumFormat object sent topw_stream_connectand parses the negotiated Format read inparam_changed. All SPA constants taken verbatim from headers. 7 unit tests (byte layout, fixated + Choice-wrapped parsing, 4K dims, non-Format/non-object/truncated rejection).portal::run_pipewire_loop: rewritten off thepipewirecrate ontopw_ffi+spa_pod;convert_to_rgbnow takes aSPA_VIDEO_FORMAT_*id. ashpd RemoteDesktop+ScreenCast session and input paths unchanged (still pure-Rust DBus; restore-token persistence viaPersistMode::Applicationretained).wayland-portalfeature dropspipewire, addslibloading; now pulls only pure-Rust deps (ashpd/zbus, image, libloading) so the feature build needs no system libs or libclang.Cargo.lockrefreshed (pipewire/libspa removed).release.Dockerfile: builds with--features wayland-portaland asserts viareadelf -dthat the binary has no NEEDED libpipewire, guarding the headless-safe property in CI.Verification (Docker only)
just pre-commitgreen (default build: fmt, clippy-D warnings, build, host+windows, lib+tpm tests; 7spa_podtests pass).-D warningsgreen.--features wayland-portal --locked) succeeds;readelf -don the resulting binary shows onlylibc,libgcc_s,libm- no pipewire/spa - and it runs--version.Functional on-device capture (actual frames on GNOME/Wayland) is validated separately on desktop-02 with a binary from this branch; the consumer logic is the same one already proven with the
pipewirecrate, so the risk here is confined to the FFI port, which the no-link release build compiles and links clean.Fixes VA-82. Relates to VA-80, VA-81.
🤖 Generated with Claude Code