From c18f1ea7ed117e67ed523e11ccf7a8df469cad86 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 11 Jun 2021 16:44:57 -0300 Subject: [PATCH] linux-capture: Conditionally register PipeWire captures Right now we just assume that every compositor and portal implementation exposes both window and monitor captures, but that's not true, and in fact the Desktop portal provides a simple mechanism to check which source types are available: a D-Bus property called "AvailableSourceTypes". Read this D-Bus property, and use it to conditionally register the desktop and the window captures. Related: https://github.com/obsproject/obs-studio/issues/4815 --- plugins/linux-capture/CMakeLists.txt | 2 + plugins/linux-capture/pipewire-capture.c | 24 +++++++- plugins/linux-capture/portal.c | 74 ++++++++++++++++++++++++ plugins/linux-capture/portal.h | 25 ++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 plugins/linux-capture/portal.c create mode 100644 plugins/linux-capture/portal.h diff --git a/plugins/linux-capture/CMakeLists.txt b/plugins/linux-capture/CMakeLists.txt index 0b27ea1718f54b..e8dd6c9b28acb5 100644 --- a/plugins/linux-capture/CMakeLists.txt +++ b/plugins/linux-capture/CMakeLists.txt @@ -72,11 +72,13 @@ if(ENABLE_PIPEWIRE) ${linux-capture_SOURCES} pipewire.c pipewire-capture.c + portal.c ) set(linux-capture_HEADERS ${linux-capture_HEADERS} pipewire.h pipewire-capture.h + portal.h ) set(linux-capture_LIBRARIES ${linux-capture_LIBRARIES} diff --git a/plugins/linux-capture/pipewire-capture.c b/plugins/linux-capture/pipewire-capture.c index deb6bfb9312588..72f0df5816fb48 100644 --- a/plugins/linux-capture/pipewire-capture.c +++ b/plugins/linux-capture/pipewire-capture.c @@ -19,6 +19,7 @@ */ #include "pipewire.h" +#include "portal.h" /* obs_source_info methods */ @@ -106,6 +107,23 @@ static void pipewire_capture_video_render(void *data, gs_effect_t *effect) void pipewire_capture_load(void) { + uint32_t available_capture_types = portal_get_available_capture_types(); + bool desktop_capture_available = + (available_capture_types & DESKTOP_CAPTURE) != 0; + bool window_capture_available = + (available_capture_types & WINDOW_CAPTURE) != 0; + + if (available_capture_types == 0) { + blog(LOG_INFO, "[pipewire] No captures available"); + return; + } + + blog(LOG_INFO, "[pipewire] Available captures:"); + if (desktop_capture_available) + blog(LOG_INFO, "[pipewire] - Desktop capture"); + if (window_capture_available) + blog(LOG_INFO, "[pipewire] - Window capture"); + // Desktop capture const struct obs_source_info pipewire_desktop_capture_info = { .id = "pipewire-desktop-capture-source", @@ -124,7 +142,8 @@ void pipewire_capture_load(void) .video_render = pipewire_capture_video_render, .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; - obs_register_source(&pipewire_desktop_capture_info); + if (desktop_capture_available) + obs_register_source(&pipewire_desktop_capture_info); // Window capture const struct obs_source_info pipewire_window_capture_info = { @@ -144,7 +163,8 @@ void pipewire_capture_load(void) .video_render = pipewire_capture_video_render, .icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, }; - obs_register_source(&pipewire_window_capture_info); + if (window_capture_available) + obs_register_source(&pipewire_window_capture_info); pw_init(NULL, NULL); } diff --git a/plugins/linux-capture/portal.c b/plugins/linux-capture/portal.c new file mode 100644 index 00000000000000..6aeb17a09fdf75 --- /dev/null +++ b/plugins/linux-capture/portal.c @@ -0,0 +1,74 @@ +/* portal.c + * + * Copyright 2021 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "portal.h" +#include "pipewire.h" + +static GDBusConnection *connection = NULL; +static GDBusProxy *proxy = NULL; + +static void ensure_proxy(void) +{ + g_autoptr(GError) error = NULL; + if (!connection) { + connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + + if (error) { + blog(LOG_WARNING, + "[portals] Error retrieving D-Bus connection: %s", + error->message); + return; + } + } + + if (!proxy) { + proxy = g_dbus_proxy_new_sync( + connection, G_DBUS_PROXY_FLAGS_NONE, NULL, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.ScreenCast", NULL, &error); + + if (error) { + blog(LOG_WARNING, + "[portals] Error retrieving D-Bus proxy: %s", + error->message); + return; + } + } +} + +uint32_t portal_get_available_capture_types(void) +{ + g_autoptr(GVariant) cached_source_types = NULL; + uint32_t available_source_types; + + ensure_proxy(); + + if (!proxy) + return 0; + + cached_source_types = + g_dbus_proxy_get_cached_property(proxy, "AvailableSourceTypes"); + available_source_types = + cached_source_types ? g_variant_get_uint32(cached_source_types) + : 0; + + return available_source_types; +} diff --git a/plugins/linux-capture/portal.h b/plugins/linux-capture/portal.h new file mode 100644 index 00000000000000..67aeb7646d2ee1 --- /dev/null +++ b/plugins/linux-capture/portal.h @@ -0,0 +1,25 @@ +/* portal.c + * + * Copyright 2021 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include + +uint32_t portal_get_available_capture_types(void);