98 lines
12 KiB
Markdown
98 lines
12 KiB
Markdown
# 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_QT` application 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 `XDamage` and other X11-specific features. Wayland's security model prevents direct screen access, requiring applications to use `xdg-desktop-portal` and 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-portal` for user consent.
|
||
* **Proof of Concept (POC):** Developed `wayland_poc.cpp` to test the `xdg-desktop-portal` interaction and PipeWire stream connection. Also used `tutorial5.c` from PipeWire documentation to verify core PipeWire API usage.
|
||
|
||
## 3. Build Environment Challenges & Docker Adoption
|
||
|
||
* **Initial Host Compilation Issues:** Attempting to compile `wayland_poc.cpp` directly on the user's Arch Linux host resulted in a persistent `fatal error: pipewire/extensions/session-manager/session-manager.h: No such file or directory`.
|
||
* **Troubleshooting:** Confirmed file existence and permissions, verified `pkg-config` output, modified `CMakeLists.txt` for 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.
|
||
* **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:latest` as base.
|
||
* **Error 1: `sudo: command not found`:** Occurred because `pacman` commands were run as `builder` user without `sudo` installed or configured.
|
||
* **Fix:** Moved `pacman` commands to run as `root` before switching to `builder` user.
|
||
* **Error 2: `mkdir: cannot create directory ‘build’: File exists` (Permission Denied):** Occurred because `build` directory was copied from host with `root` ownership, and `builder` user lacked permissions to modify it.
|
||
* **Fix:** Added `chown -R builder:builder` after `COPY` to transfer ownership to `builder` user.
|
||
* **Error 3: `CMakeCache.txt` mismatch:** Occurred because `CMakeCache.txt` from host's project root was copied into container, confusing CMake.
|
||
* **Fix:** Added `CMakeCache.txt` and `CMakeFiles/` to `.dockerignore` to prevent them from being copied.
|
||
* **Error 4: `X11/extensions/Xdamage.h: No such file or directory` (and `scrnsaver.h`, `Xrender.h`):** Occurred because necessary X11 development headers were missing in the Docker image.
|
||
* **Fix:** Added `libx11`, `libxext`, `libxdamage`, `libxss`, `libxrender` to `pacman` install list.
|
||
* **Persistent `session-manager.h` error:** Despite all fixes, the `fatal error: pipewire/extensions/session-manager/session-manager.h: No such file or directory` persisted 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:latest` to rule out Arch-specific packaging issues. Also switched to `clang` as the compiler.
|
||
* **Error: `fatal error: 'pipewire/extensions/session-manager/impl-session-manager.h' file not found`:** The `session-manager.h` issue persisted, even with Ubuntu and Clang. This confirmed the problem was not distribution-specific.
|
||
* **Attempt to bypass umbrella header:** Modified `wayland_poc.cpp` to include individual headers (`introspect.h`, `interfaces.h`, etc.) instead of `session-manager.h`. This also failed with similar "file not found" errors for the individual headers.
|
||
* **Conclusion:** The `session-manager.h` (and related `impl-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. The `session-manager.h` problem was specific to the `xdg-desktop-portal` interaction using PipeWire's session manager headers.
|
||
* **New Strategy:** Isolate the `xdg-desktop-portal` interaction using Qt's `QDBus` module, completely bypassing direct PipeWire session manager header includes.
|
||
* **`wayland_poc.cpp` Refactoring:** Simplified `wayland_poc.cpp` to *only* handle the `QDBus` interaction to get the `pipewire_node_id`. Removed all PipeWire stream creation/processing logic.
|
||
* **QDBus API Challenges:**
|
||
* **`QDBusMessage::createMethodCall` vs `createMethod`:** Discovered `createMethodCall` is the correct static method for creating method call messages in Qt 5.15.
|
||
* **`QDBusMessage` constructor:** Found that the direct constructor `QDBusMessage("service", "path", "interface", "method");` is the correct way to initialize `QDBusMessage` for method calls in the specific Qt5 version in Ubuntu.
|
||
* **`QDBusPendingCall` conversion:** Ensured `sessionBus.asyncCall(message)` is used, which returns `QDBusPendingCall`.
|
||
* **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 the `QDBus` approach for `xdg-desktop-portal` interaction is viable.
|
||
|
||
## 7. Runtime Challenges (D-Bus Connection)
|
||
|
||
* **Problem:** Running the compiled `wayland_poc` executable (from Docker) on the host failed with `Failed 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 run` parameters, the `wayland_poc` on the host failed with `D-Bus call to xdg-desktop-portal failed: "Invalid session"`.
|
||
* **Diagnosis:** This error indicates `xdg-desktop-portal` is not recognizing the session context. It's often related to `XDG_SESSION_ID`, `XDG_SESSION_TYPE`, or `XDG_CURRENT_DESKTOP` not being correctly propagated or interpreted.
|
||
* **Method Name Mismatch:** The `wayland_poc` was initially calling `PickSource` on `org.freedesktop.portal.ScreenCast`, but the correct method name is `SelectSources`.
|
||
* **Fix:** Changed method call from `PickSource` to `SelectSources` in `wayland_poc.cpp`.
|
||
* **Argument Type Mismatch:** The `SelectSources` method expects an object path (`o`) for the `parent_window` argument, but `wayland_poc` was sending an empty string (`s`).
|
||
* **Fix:** Changed the first argument to `QDBusObjectPath("/")` in `wayland_poc.cpp`.
|
||
* **Current Status:** The `wayland_poc` executable now compiles successfully. The D-Bus connection issue (`Failed to connect to D-Bus session bus.` or `Invalid 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_poc` execution on host:** The user needs to run the `wayland_poc` executable on their host with the provided `docker run` command (or directly if copied out) and confirm if the `xdg-desktop-portal` dialog 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 `QDBus` based `xdg-desktop-portal` interaction with the core PipeWire stream capture logic (from `tutorial5.c`) into the main Hyperion grabber.
|
||
* **Persistent `session-manager.h`:** The original `session-manager.h` compilation issue remains unresolved for direct PipeWire session manager API usage. The `QDBus` approach 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
|
||
|
||
* **`SelectSources` Request Denied:**
|
||
* **Problem:** After initial compilation, `wayland_poc`'s `SelectSources` call was denied by `xdg-desktop-portal`.
|
||
* **Diagnosis:** The D-Bus message for `SelectSources` was 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.cpp` to include these missing options in the `SelectSources` D-Bus message.
|
||
|
||
* **Persistent `QDateTime` Compilation 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()` with `QUuid::createUuid().toString()` for generating unique tokens, and added `#include <QUuid>`. This successfully bypassed the compilation error.
|
||
|
||
* **Docker Filesystem Isolation and `replace` Tool Misunderstanding:**
|
||
* **Problem:** Changes made to `wayland_poc.cpp` using the `replace` tool were not reflected in the Docker container's build process.
|
||
* **Diagnosis:** The `replace` tool 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.cpp` on the host, the updated file was explicitly copied into the running Docker container using `docker cp`.
|
||
|
||
* **Executable Retrieval from Docker Container:**
|
||
* **Problem:** Difficulty in copying the built `wayland_poc` executable from the Docker container to the host. The build container would exit immediately, and `docker cp` failed to find the file.
|
||
* **Diagnosis:** The original build container was not designed to stay running. `docker cp` requires a running container or a committed image. The initial `docker commit` did 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 using `docker cp`.
|
||
|
||
* **New Runtime Error: "Remote peer disconnected"**
|
||
* **Problem:** After successfully building and copying `wayland_poc` to 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-portal` not running, or permission issues.
|
||
* **Next Steps:** Investigate D-Bus environment variables (`DBUS_SESSION_BUS_ADDRESS`) and `xdg-desktop-portal` service status on the host.
|