12 KiB
12 KiB
Lessons Learned from Hyperion Grabber Wayland Adaptation
This document summarizes the key challenges, debugging steps, and solutions encountered during the process of adapting the Hyperion Grabber for Wayland, specifically focusing on the wayland_poc executable.
1. Initial Problem & Diagnosis
- Problem: The user's existing
Hyperion_Grabber_X11_QTapplication was not logging "picture recorded and sent" messages when run on a Wayland session, indicating a failure in screen capture and transmission. - Initial Analysis: The grabber is designed for X11, relying on
XDamageand other X11-specific features. Wayland's security model prevents direct screen access, requiring applications to usexdg-desktop-portaland PipeWire for screen sharing with user consent. - Conclusion: The X11 grabber would not work natively on Wayland. A Wayland-compatible screen grabbing solution was needed.
2. Wayland Grabber Adaptation Strategy
- Approach: Replace the X11 screen grabbing logic with a Wayland-compatible one, primarily using PipeWire for video streaming and
xdg-desktop-portalfor user consent. - Proof of Concept (POC): Developed
wayland_poc.cppto test thexdg-desktop-portalinteraction and PipeWire stream connection. Also usedtutorial5.cfrom PipeWire documentation to verify core PipeWire API usage.
3. Build Environment Challenges & Docker Adoption
- Initial Host Compilation Issues: Attempting to compile
wayland_poc.cppdirectly on the user's Arch Linux host resulted in a persistentfatal error: pipewire/extensions/session-manager/session-manager.h: No such file or directory.- Troubleshooting: Confirmed file existence and permissions, verified
pkg-configoutput, modifiedCMakeLists.txtfor include paths and C++ standards, tried different compilers (GCC). None resolved the issue. - Conclusion: The error was highly unusual and suggested a deep, system-specific problem with how PipeWire headers were exposed or how the compiler resolved includes on the host.
- Troubleshooting: Confirmed file existence and permissions, verified
- Adoption of Docker: Decided to use Docker to create a reproducible and controlled build environment, aiming to bypass host-specific compilation issues.
4. Docker Build Troubleshooting (Arch Linux Base)
- Dockerfile (Arch): Initial Dockerfile used
archlinux:latestas base. - Error 1:
sudo: command not found: Occurred becausepacmancommands were run asbuilderuser withoutsudoinstalled or configured.- Fix: Moved
pacmancommands to run asrootbefore switching tobuilderuser.
- Fix: Moved
- Error 2:
mkdir: cannot create directory ‘build’: File exists(Permission Denied): Occurred becausebuilddirectory was copied from host withrootownership, andbuilderuser lacked permissions to modify it.- Fix: Added
chown -R builder:builderafterCOPYto transfer ownership tobuilderuser.
- Fix: Added
- Error 3:
CMakeCache.txtmismatch: Occurred becauseCMakeCache.txtfrom host's project root was copied into container, confusing CMake.- Fix: Added
CMakeCache.txtandCMakeFiles/to.dockerignoreto prevent them from being copied.
- Fix: Added
- Error 4:
X11/extensions/Xdamage.h: No such file or directory(andscrnsaver.h,Xrender.h): Occurred because necessary X11 development headers were missing in the Docker image.- Fix: Added
libx11,libxext,libxdamage,libxss,libxrendertopacmaninstall list.
- Fix: Added
- Persistent
session-manager.herror: Despite all fixes, thefatal error: pipewire/extensions/session-manager/session-manager.h: No such file or directorypersisted even in the Arch Docker environment. This indicated the problem was not specific to the host Arch setup, but a deeper issue with PipeWire headers or their interaction with the compiler.
5. Docker Build Troubleshooting (Ubuntu Base & Clang)
- Switch to Ubuntu: Decided to switch the Docker base image to
ubuntu:latestto rule out Arch-specific packaging issues. Also switched toclangas the compiler. - Error:
fatal error: 'pipewire/extensions/session-manager/impl-session-manager.h' file not found: Thesession-manager.hissue persisted, even with Ubuntu and Clang. This confirmed the problem was not distribution-specific. - Attempt to bypass umbrella header: Modified
wayland_poc.cppto include individual headers (introspect.h,interfaces.h, etc.) instead ofsession-manager.h. This also failed with similar "file not found" errors for the individual headers. - Conclusion: The
session-manager.h(and relatedimpl-session-manager.h) compilation issue is extremely persistent and baffling, suggesting a very subtle, low-level problem that cannot be resolved by standard means or remote debugging.
6. Refocusing on xdg-desktop-portal with QDBus
- Realization: The
tutorial5.c(core PipeWire API) compiled successfully. Thesession-manager.hproblem was specific to thexdg-desktop-portalinteraction using PipeWire's session manager headers. - New Strategy: Isolate the
xdg-desktop-portalinteraction using Qt'sQDBusmodule, completely bypassing direct PipeWire session manager header includes. wayland_poc.cppRefactoring: Simplifiedwayland_poc.cppto only handle theQDBusinteraction to get thepipewire_node_id. Removed all PipeWire stream creation/processing logic.- QDBus API Challenges:
QDBusMessage::createMethodCallvscreateMethod: DiscoveredcreateMethodCallis the correct static method for creating method call messages in Qt 5.15.QDBusMessageconstructor: Found that the direct constructorQDBusMessage("service", "path", "interface", "method");is the correct way to initializeQDBusMessagefor method calls in the specific Qt5 version in Ubuntu.QDBusPendingCallconversion: EnsuredsessionBus.asyncCall(message)is used, which returnsQDBusPendingCall.
- Successful Compilation: The simplified
wayland_poc.cpp(QDBus-only) compiled successfully in the Ubuntu Docker container with Clang. This is a major breakthrough, confirming that theQDBusapproach forxdg-desktop-portalinteraction is viable.
7. Runtime Challenges (D-Bus Connection)
- Problem: Running the compiled
wayland_pocexecutable (from Docker) on the host failed withFailed to connect to D-Bus session bus. - Reason: Docker containers are isolated and do not have direct access to the host's D-Bus session bus by default. Environment variables (
DBUS_SESSION_BUS_ADDRESS,XDG_RUNTIME_DIR,DISPLAY,WAYLAND_DISPLAY) and volume mounts (/tmp/.X11-unix,$XDG_RUNTIME_DIR) are needed. - Further Problem: Even with correct
docker runparameters, thewayland_pocon the host failed withD-Bus call to xdg-desktop-portal failed: "Invalid session".- Diagnosis: This error indicates
xdg-desktop-portalis not recognizing the session context. It's often related toXDG_SESSION_ID,XDG_SESSION_TYPE, orXDG_CURRENT_DESKTOPnot being correctly propagated or interpreted.
- Diagnosis: This error indicates
- Method Name Mismatch: The
wayland_pocwas initially callingPickSourceonorg.freedesktop.portal.ScreenCast, but the correct method name isSelectSources.- Fix: Changed method call from
PickSourcetoSelectSourcesinwayland_poc.cpp.
- Fix: Changed method call from
- Argument Type Mismatch: The
SelectSourcesmethod expects an object path (o) for theparent_windowargument, butwayland_pocwas sending an empty string (s).- Fix: Changed the first argument to
QDBusObjectPath("/")inwayland_poc.cpp.
- Fix: Changed the first argument to
- Current Status: The
wayland_pocexecutable now compiles successfully. The D-Bus connection issue (Failed to connect to D-Bus session bus.orInvalid session) is still occurring when run on the host, indicating a persistent runtime environment issue with D-Bus access from the application.
8. Next Steps
- Verify
wayland_pocexecution on host: The user needs to run thewayland_pocexecutable on their host with the provideddocker runcommand (or directly if copied out) and confirm if thexdg-desktop-portaldialog appears and a PipeWire node ID is printed. The current D-Bus connection failure needs to be resolved. - Integrate: If successful, the next phase will involve integrating the
QDBusbasedxdg-desktop-portalinteraction with the core PipeWire stream capture logic (fromtutorial5.c) into the main Hyperion grabber. - Persistent
session-manager.h: The originalsession-manager.hcompilation issue remains unresolved for direct PipeWire session manager API usage. TheQDBusapproach is a workaround. If direct PipeWire session manager API interaction is ever needed, this issue would need further, likely local, investigation.
9. Recent Debugging and Solutions
-
SelectSourcesRequest Denied:- Problem: After initial compilation,
wayland_poc'sSelectSourcescall was denied byxdg-desktop-portal. - Diagnosis: The D-Bus message for
SelectSourceswas missing required options (e.g.,types,cursor_mode,persist_mode,handle_token) that are present in successful calls (e.g., from Firefox). - Fix: Modified
wayland_poc.cppto include these missing options in theSelectSourcesD-Bus message.
- Problem: After initial compilation,
-
Persistent
QDateTimeCompilation Error:- Problem: Encountered a persistent "incomplete type 'QDateTime'" error during compilation, even though
<QDateTime>was included and its position was adjusted. - Diagnosis: This was a highly unusual and difficult-to-diagnose error, possibly related to subtle interactions within the Qt build system or compiler.
- Workaround: Replaced all uses of
QDateTime::currentMSecsSinceEpoch()withQUuid::createUuid().toString()for generating unique tokens, and added#include <QUuid>. This successfully bypassed the compilation error.
- Problem: Encountered a persistent "incomplete type 'QDateTime'" error during compilation, even though
-
Docker Filesystem Isolation and
replaceTool Misunderstanding:- Problem: Changes made to
wayland_poc.cppusing thereplacetool were not reflected in the Docker container's build process. - Diagnosis: The
replacetool modifies the host's filesystem, while the Docker container operates on its own isolated filesystem. The container was building from an outdated copy of the source file. - Fix: After modifying
wayland_poc.cppon the host, the updated file was explicitly copied into the running Docker container usingdocker cp.
- Problem: Changes made to
-
Executable Retrieval from Docker Container:
- Problem: Difficulty in copying the built
wayland_pocexecutable from the Docker container to the host. The build container would exit immediately, anddocker cpfailed to find the file. - Diagnosis: The original build container was not designed to stay running.
docker cprequires a running container or a committed image. The initialdocker commitdid not seem to capture the build artifacts correctly. - Fix: Committed the original build container to a new image (
hyperion-grabber-build). Then, a new container was launched from this image with a command (tail -f /dev/null) to keep it running. The executable was then successfully copied from this running container usingdocker cp.
- Problem: Difficulty in copying the built
-
New Runtime Error: "Remote peer disconnected"
- Problem: After successfully building and copying
wayland_pocto the host, running it resulted in "D-Bus call to SelectSources failed: "Remote peer disconnected"". - Diagnosis: This indicates a problem with the D-Bus connection itself, rather than a rejection from the portal. Possible causes include incorrect D-Bus environment variables on the host,
xdg-desktop-portalnot running, or permission issues. - Next Steps: Investigate D-Bus environment variables (
DBUS_SESSION_BUS_ADDRESS) andxdg-desktop-portalservice status on the host.
- Problem: After successfully building and copying