#pragma once #include #include #include #include #ifdef __linux__ #include #include #endif // Forward declarations for Pipewire/sdbus to avoid header pollution struct pw_thread_loop; struct pw_stream; struct pw_context; namespace sdbus { class IConnection; class IProxy; } namespace scar { enum class ScreenCaptureBackend { FFMPEG_X11, // X11 via ffmpeg FFMPEG_WAYLAND, // Wayland via ffmpeg + portal FFMPEG_WINDOWS, // Windows GDI via ffmpeg PORTAL_PIPEWIRE // xdg-desktop-portal + Pipewire (Wayland/Hyprland) }; // Screen capture supporting multiple backends class ScreenCapture { public: ScreenCapture(); ~ScreenCapture(); // Auto-detect and start screen capture bool start(); // Start with specific backend bool start(ScreenCaptureBackend backend); // Stop capturing void stop(); // Check if currently capturing bool isCapturing() const { return capturing_; } // Set frame callback using FrameCallback = std::function& frameData, int width, int height)>; void setFrameCallback(FrameCallback callback); private: ScreenCaptureBackend detectBestBackend(); bool startX11Capture(); bool startWaylandCapture(); bool startWindowsCapture(); bool startPortalCapture(); // sdbus Portal methods bool initPortalConnection(); void cleanupPortalConnection(); std::string createPortalSession(); bool selectPortalSources(const std::string& session_handle); bool startPortalSession(const std::string& session_handle, uint32_t& node_id); int openPipeWireRemote(const std::string& session_handle); uint32_t getStreamsNodeId(const std::string& session_handle); // Pipewire methods bool initPipewire(int fd, uint32_t node_id); void cleanupPipewire(); static void onStreamProcess(void* userdata); static void onStreamParamChanged(void* userdata, uint32_t id, const struct spa_pod* param); bool capturing_; ScreenCaptureBackend backend_; FrameCallback frameCallback_; // sdbus members std::shared_ptr portal_connection_; std::unique_ptr screencast_proxy_; std::string session_path_; // Pipewire members pw_thread_loop* pw_loop_; pw_stream* pw_stream_; pw_context* pw_context_; spa_hook stream_listener_; int frame_width_; int frame_height_; // TODO: FFmpeg-specific members // AVFormatContext* formatCtx_; // AVCodecContext* codecCtx_; // AVFrame* frame_; }; } // namespace scar