From b32c560b310e61ff3ffde99457ae751ae1d3d958 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 27 Aug 2023 00:32:18 +0200 Subject: [PATCH] basic groundwork for pw --- CMakeLists.txt | 2 +- src/core/PortalManager.cpp | 15 ++++++++++++++- src/core/PortalManager.hpp | 6 ++++++ src/portals/Screencopy.cpp | 35 +++++++++++++++++++++++++++++++++++ src/portals/Screencopy.hpp | 25 +++++++++++++++++++++++-- 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7ba24d..7ba6048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ add_subdirectory(subprojects/sdbus-cpp) find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols cairo pango pangocairo libjpeg libpipewire-0.3 libspa-0.2) file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") add_executable(xdg-desktop-portal-hyprland ${SRCFILES}) diff --git a/src/core/PortalManager.cpp b/src/core/PortalManager.cpp index ab34f58..622f23d 100644 --- a/src/core/PortalManager.cpp +++ b/src/core/PortalManager.cpp @@ -6,6 +6,8 @@ #include #include +#include + void handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { g_pPortalManager->onGlobal(data, registry, name, interface, version); } @@ -26,7 +28,7 @@ void CPortalManager::onGlobal(void* data, struct wl_registry* registry, uint32_t Debug::log(LOG, " | Got interface: {} (ver {})", INTERFACE, version); - if (INTERFACE == zwlr_screencopy_manager_v1_interface.name) + if (INTERFACE == zwlr_screencopy_manager_v1_interface.name && m_sPipewire.loop) m_sPortals.screencopy = std::make_unique((zwlr_screencopy_manager_v1*)wl_registry_bind(registry, name, &zwlr_screencopy_manager_v1_interface, version)); } @@ -58,10 +60,19 @@ void CPortalManager::init() { wl_registry* registry = wl_display_get_registry(m_sWaylandConnection.display); wl_registry_add_listener(registry, ®istryListener, nullptr); + pw_init(nullptr, nullptr); + m_sPipewire.loop = pw_loop_new(nullptr); + + if (!m_sPipewire.loop) + Debug::log(ERR, "Pipewire: refused to create a loop. Screensharing will not work."); + Debug::log(LOG, "Gathering exported interfaces"); wl_display_roundtrip(m_sWaylandConnection.display); + if (!m_sPortals.screencopy) + Debug::log(WARN, "Screencopy not started: compositor doesn't support zwlr_screencopy_v1 or pw refused a loop"); + while (1) { // dbus events while (m_pConnection->processPendingRequest()) { @@ -77,6 +88,8 @@ void CPortalManager::init() { break; } + // TODO: pipewire loop + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } diff --git a/src/core/PortalManager.hpp b/src/core/PortalManager.hpp index efec6ef..c74153c 100644 --- a/src/core/PortalManager.hpp +++ b/src/core/PortalManager.hpp @@ -6,6 +6,8 @@ #include "../portals/Screencopy.hpp" +struct pw_loop; + class CPortalManager { public: void init(); @@ -14,6 +16,10 @@ class CPortalManager { sdbus::IConnection* getConnection(); + struct { + pw_loop* loop = nullptr; + } m_sPipewire; + private: std::unique_ptr m_pConnection; diff --git a/src/portals/Screencopy.cpp b/src/portals/Screencopy.cpp index c4ddde2..a62f430 100644 --- a/src/portals/Screencopy.cpp +++ b/src/portals/Screencopy.cpp @@ -3,6 +3,8 @@ #include "../helpers/Log.hpp" #include "../helpers/MiscFunctions.hpp" +#include + void onCloseRequest(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess) { if (!sess || !sess->request) return; @@ -197,6 +199,7 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) { case TYPE_WINDOW: type = 1 << WINDOW; break; case TYPE_GEOMETRY: case TYPE_WORKSPACE: type = 1 << VIRTUAL; break; + default: type = 0; break; } options["source_type"] = type; @@ -226,5 +229,37 @@ CScreencopyPortal::CScreencopyPortal(zwlr_screencopy_manager_v1* mgr) { m_pObject->finishRegistration(); + m_sState.screencopy = mgr; + m_pPipewire = std::make_unique(); + Debug::log(LOG, "[screencopy] init successful"); +} + +bool CPipewireConnection::good() { + return m_pContext && m_pCore; +} + +CPipewireConnection::CPipewireConnection() { + m_pContext = pw_context_new(g_pPortalManager->m_sPipewire.loop, nullptr, 0); + + if (!m_pContext) { + Debug::log(ERR, "[pipewire] pw didn't allow for a context"); + return; + } + + m_pCore = pw_context_connect(m_pContext, nullptr, 0); + + if (!m_pCore) { + Debug::log(ERR, "[pipewire] pw didn't allow for a context connection"); + return; + } + + Debug::log(LOG, "[pipewire] connected"); +} + +CPipewireConnection::~CPipewireConnection() { + if (m_pCore) + pw_core_disconnect(m_pCore); + if (m_pContext) + pw_context_destroy(m_pContext); } \ No newline at end of file diff --git a/src/portals/Screencopy.hpp b/src/portals/Screencopy.hpp index c01dcce..0520e72 100644 --- a/src/portals/Screencopy.hpp +++ b/src/portals/Screencopy.hpp @@ -18,6 +18,21 @@ enum sourceTypes VIRTUAL = 4, }; +struct pw_context; +struct pw_core; + +class CPipewireConnection { + public: + CPipewireConnection(); + ~CPipewireConnection(); + + bool good(); + + private: + pw_context* m_pContext = nullptr; + pw_core* m_pCore = nullptr; +}; + class CScreencopyPortal { public: CScreencopyPortal(zwlr_screencopy_manager_v1*); @@ -46,6 +61,12 @@ class CScreencopyPortal { SSession* getSession(sdbus::ObjectPath& path); - const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.ScreenCast"; - const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop"; + std::unique_ptr m_pPipewire; + + struct { + zwlr_screencopy_manager_v1* screencopy = nullptr; + } m_sState; + + const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.ScreenCast"; + const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop"; }; \ No newline at end of file