linux-capture: Use portal's D-Bus on PipeWire captures

Intead of creating one pair of GDBusConnection + GDBusProxy objects
for each PipeWire capture, be it window or desktop, use the global
ones managed by portal.c.

Even if g_bus_get_sync() ends up reusing the same object under the
hood, it's still a net gain, since it has to perform some thread
synchronization routines that aren't necessary here. Creating the
proxy object was a worse offender, because despite being asynchronous,
it would still incur in a few socket messages + a cancellable fd +
thread synchronization.

Reuse these objects from portal.c. The biggest code change here is
that create_proxy() and on_proxy_created_cb() were merged into
init_obs_pipewire().
This commit is contained in:
Georges Basile Stavracas Neto 2021-06-11 17:13:27 -03:00 committed by Jim
parent e1c38a1f77
commit fdce267a9a

View File

@ -20,6 +20,8 @@
#include "pipewire.h"
#include "portal.h"
#include <util/dstr.h>
#include <gio/gio.h>
@ -58,8 +60,6 @@
'4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
struct _obs_pipewire_data {
GDBusConnection *connection;
GDBusProxy *proxy;
GCancellable *cancellable;
char *sender_name;
@ -180,7 +180,7 @@ static void on_cancelled_cb(GCancellable *cancellable, void *data)
blog(LOG_INFO, "[pipewire] screencast session cancelled");
g_dbus_connection_call(
call->obs_pw->connection, "org.freedesktop.portal.Desktop",
portal_get_dbus_connection(), "org.freedesktop.portal.Desktop",
call->request_path, "org.freedesktop.portal.Request", "Close",
NULL, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
@ -198,7 +198,7 @@ static struct dbus_call_data *subscribe_to_signal(obs_pipewire_data *obs_pw,
G_CALLBACK(on_cancelled_cb),
call);
call->signal_id = g_dbus_connection_signal_subscribe(
obs_pw->connection, "org.freedesktop.portal.Desktop",
portal_get_dbus_connection(), "org.freedesktop.portal.Desktop",
"org.freedesktop.portal.Request", "Response",
call->request_path, NULL, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
callback, call, NULL);
@ -212,8 +212,8 @@ static void dbus_call_data_free(struct dbus_call_data *call)
return;
if (call->signal_id)
g_dbus_connection_signal_unsubscribe(call->obs_pw->connection,
call->signal_id);
g_dbus_connection_signal_unsubscribe(
portal_get_dbus_connection(), call->signal_id);
if (call->cancelled_id > 0)
g_signal_handler_disconnect(call->obs_pw->cancellable,
@ -247,11 +247,13 @@ static void teardown_pipewire(obs_pipewire_data *obs_pw)
static void destroy_session(obs_pipewire_data *obs_pw)
{
if (obs_pw->session_handle) {
g_dbus_connection_call(
obs_pw->connection, "org.freedesktop.portal.Desktop",
obs_pw->session_handle,
"org.freedesktop.portal.Session", "Close", NULL, NULL,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
g_dbus_connection_call(portal_get_dbus_connection(),
"org.freedesktop.portal.Desktop",
obs_pw->session_handle,
"org.freedesktop.portal.Session",
"Close", NULL, NULL,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL,
NULL);
g_clear_pointer(&obs_pw->session_handle, g_free);
}
@ -261,8 +263,6 @@ static void destroy_session(obs_pipewire_data *obs_pw)
g_clear_pointer(&obs_pw->texture, gs_texture_destroy);
g_cancellable_cancel(obs_pw->cancellable);
g_clear_object(&obs_pw->cancellable);
g_clear_object(&obs_pw->connection);
g_clear_object(&obs_pw->proxy);
}
static inline bool has_effective_crop(obs_pipewire_data *obs_pw)
@ -730,7 +730,7 @@ static void open_pipewire_remote(obs_pipewire_data *obs_pw)
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
g_dbus_proxy_call_with_unix_fd_list(
obs_pw->proxy, "OpenPipeWireRemote",
portal_get_dbus_proxy(), "OpenPipeWireRemote",
g_variant_new("(oa{sv})", obs_pw->session_handle, &builder),
G_DBUS_CALL_FLAGS_NONE, -1, NULL, obs_pw->cancellable,
on_pipewire_remote_opened_cb, obs_pw);
@ -841,7 +841,7 @@ static void start(obs_pipewire_data *obs_pw)
g_variant_builder_add(&builder, "{sv}", "handle_token",
g_variant_new_string(request_token));
g_dbus_proxy_call(obs_pw->proxy, "Start",
g_dbus_proxy_call(portal_get_dbus_proxy(), "Start",
g_variant_new("(osa{sv})", obs_pw->session_handle, "",
&builder),
G_DBUS_CALL_FLAGS_NONE, -1, obs_pw->cancellable,
@ -932,7 +932,7 @@ static void select_source(obs_pipewire_data *obs_pw)
g_variant_builder_add(&builder, "{sv}", "cursor_mode",
g_variant_new_uint32(1));
g_dbus_proxy_call(obs_pw->proxy, "SelectSources",
g_dbus_proxy_call(portal_get_dbus_proxy(), "SelectSources",
g_variant_new("(oa{sv})", obs_pw->session_handle,
&builder),
G_DBUS_CALL_FLAGS_NONE, -1, obs_pw->cancellable,
@ -1016,7 +1016,7 @@ static void create_session(obs_pipewire_data *obs_pw)
g_variant_builder_add(&builder, "{sv}", "session_handle_token",
g_variant_new_string(session_token));
g_dbus_proxy_call(obs_pw->proxy, "CreateSession",
g_dbus_proxy_call(portal_get_dbus_proxy(), "CreateSession",
g_variant_new("(a{sv})", &builder),
G_DBUS_CALL_FLAGS_NONE, -1, obs_pw->cancellable,
on_session_created_cb, call);
@ -1028,13 +1028,14 @@ static void create_session(obs_pipewire_data *obs_pw)
/* ------------------------------------------------- */
static void update_available_cursor_modes(obs_pipewire_data *obs_pw)
static void update_available_cursor_modes(obs_pipewire_data *obs_pw,
GDBusProxy *proxy)
{
g_autoptr(GVariant) cached_cursor_modes = NULL;
uint32_t available_cursor_modes;
cached_cursor_modes = g_dbus_proxy_get_cached_property(
obs_pw->proxy, "AvailableCursorModes");
cached_cursor_modes =
g_dbus_proxy_get_cached_property(proxy, "AvailableCursorModes");
available_cursor_modes =
cached_cursor_modes ? g_variant_get_uint32(cached_cursor_modes)
: 0;
@ -1050,52 +1051,26 @@ static void update_available_cursor_modes(obs_pipewire_data *obs_pw)
blog(LOG_INFO, "[pipewire] - Hidden");
}
static void on_proxy_created_cb(GObject *source, GAsyncResult *res,
void *user_data)
{
UNUSED_PARAMETER(source);
g_autoptr(GError) error = NULL;
obs_pipewire_data *obs_pw = user_data;
obs_pw->proxy = g_dbus_proxy_new_finish(res, &error);
if (error) {
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
blog(LOG_ERROR, "[pipewire] Error creating proxy: %s",
error->message);
return;
}
update_available_cursor_modes(obs_pw);
create_session(obs_pw);
}
static void create_proxy(obs_pipewire_data *obs_pw)
{
g_dbus_proxy_new(obs_pw->connection, G_DBUS_PROXY_FLAGS_NONE, NULL,
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.ScreenCast",
obs_pw->cancellable, on_proxy_created_cb, obs_pw);
}
/* ------------------------------------------------- */
static gboolean init_obs_pipewire(obs_pipewire_data *obs_pw)
{
g_autoptr(GError) error = NULL;
GDBusConnection *connection;
GDBusProxy *proxy;
char *aux;
obs_pw->cancellable = g_cancellable_new();
obs_pw->connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (error) {
g_error("Error getting session bus: %s", error->message);
connection = portal_get_dbus_connection();
if (!connection)
return FALSE;
proxy = portal_get_dbus_proxy();
if (!proxy)
return FALSE;
}
obs_pw->sender_name = bstrdup(
g_dbus_connection_get_unique_name(obs_pw->connection) + 1);
update_available_cursor_modes(obs_pw, proxy);
obs_pw->sender_name =
bstrdup(g_dbus_connection_get_unique_name(connection) + 1);
/* Replace dots by underscores */
while ((aux = strstr(obs_pw->sender_name, ".")) != NULL)
@ -1104,7 +1079,7 @@ static gboolean init_obs_pipewire(obs_pipewire_data *obs_pw)
blog(LOG_INFO, "PipeWire initialized (sender name: %s)",
obs_pw->sender_name);
create_proxy(obs_pw);
create_session(obs_pw);
return TRUE;
}