linux-capture: Implement stream restoration

With the version 4 of the screencast portal, it is now possible
to request and use restore tokens [1] so that apps can restore a
previously configured screencast session without user interaction.

Add the corresponding code to linux-capture's PipeWire source.
Store the restore token in the source data, since each restore
token corresponds to an OBS source, and use it as soon as we try
to create a new session. Implement the obs_source_info.save vfunc,
and save the restore token when it's received by the Start()
response using obs_source_save().

[1] https://github.com/flatpak/xdg-desktop-portal/pull/638
This commit is contained in:
Georges Basile Stavracas Neto 2021-11-09 01:00:35 -03:00 committed by Jim
parent 8537c7593c
commit 26f1bfd05f
3 changed files with 44 additions and 0 deletions

View File

@ -51,6 +51,11 @@ static void pipewire_capture_destroy(void *data)
obs_pipewire_destroy(data);
}
static void pipewire_capture_save(void *data, obs_data_t *settings)
{
obs_pipewire_save(data, settings);
}
static void pipewire_capture_get_defaults(obs_data_t *settings)
{
obs_pipewire_get_defaults(settings);
@ -132,6 +137,7 @@ void pipewire_capture_load(void)
.get_name = pipewire_desktop_capture_get_name,
.create = pipewire_desktop_capture_create,
.destroy = pipewire_capture_destroy,
.save = pipewire_capture_save,
.get_defaults = pipewire_capture_get_defaults,
.get_properties = pipewire_capture_get_properties,
.update = pipewire_capture_update,

View File

@ -65,6 +65,7 @@ struct _obs_pipewire_data {
char *sender_name;
char *session_handle;
char *restore_token;
uint32_t pipewire_node;
int pipewire_fd;
@ -808,6 +809,20 @@ static void on_start_response_received_cb(GDBusConnection *connection,
g_variant_iter_loop(&iter, "(u@a{sv})", &obs_pw->pipewire_node,
&stream_properties);
if (portal_get_screencast_version() >= 4) {
g_autoptr(GVariant) restore_token = NULL;
g_clear_pointer(&obs_pw->restore_token, bfree);
restore_token = g_variant_lookup_value(result, "restore_token",
G_VARIANT_TYPE_STRING);
if (restore_token)
obs_pw->restore_token = bstrdup(
g_variant_get_string(restore_token, NULL));
obs_source_save(obs_pw->source);
}
blog(LOG_INFO, "[pipewire] %s selected, setting up screencast",
capture_type_to_string(obs_pw->capture_type));
@ -941,6 +956,16 @@ static void select_source(obs_pipewire_data *obs_pw)
g_variant_builder_add(&builder, "{sv}", "cursor_mode",
g_variant_new_uint32(1));
if (portal_get_screencast_version() >= 4) {
g_variant_builder_add(&builder, "{sv}", "persist_mode",
g_variant_new_uint32(2));
if (obs_pw->restore_token && *obs_pw->restore_token) {
g_variant_builder_add(
&builder, "{sv}", "restore_token",
g_variant_new_string(obs_pw->restore_token));
}
}
g_dbus_proxy_call(portal_get_dbus_proxy(), "SelectSources",
g_variant_new("(oa{sv})", obs_pw->session_handle,
&builder),
@ -1104,6 +1129,8 @@ static bool reload_session_cb(obs_properties_t *properties,
obs_pipewire_data *obs_pw = data;
g_clear_pointer(&obs_pw->restore_token, bfree);
teardown_pipewire(obs_pw);
destroy_session(obs_pw);
@ -1123,6 +1150,8 @@ void *obs_pipewire_create(enum obs_pw_capture_type capture_type,
obs_pw->settings = settings;
obs_pw->capture_type = capture_type;
obs_pw->cursor.visible = obs_data_get_bool(settings, "ShowCursor");
obs_pw->restore_token =
bstrdup(obs_data_get_string(settings, "RestoreToken"));
if (!init_obs_pipewire(obs_pw))
g_clear_pointer(&obs_pw, bfree);
@ -1138,12 +1167,20 @@ void obs_pipewire_destroy(obs_pipewire_data *obs_pw)
teardown_pipewire(obs_pw);
destroy_session(obs_pw);
g_clear_pointer(&obs_pw->restore_token, bfree);
bfree(obs_pw);
}
void obs_pipewire_save(obs_pipewire_data *obs_pw, obs_data_t *settings)
{
obs_data_set_string(settings, "RestoreToken", obs_pw->restore_token);
}
void obs_pipewire_get_defaults(obs_data_t *settings)
{
obs_data_set_default_bool(settings, "ShowCursor", true);
obs_data_set_default_string(settings, "RestoreToken", NULL);
}
obs_properties_t *obs_pipewire_get_properties(obs_pipewire_data *obs_pw,

View File

@ -35,6 +35,7 @@ void *obs_pipewire_create(enum obs_pw_capture_type capture_type,
void obs_pipewire_destroy(obs_pipewire_data *obs_pw);
void obs_pipewire_save(obs_pipewire_data *obs_pw, obs_data_t *settings);
void obs_pipewire_get_defaults(obs_data_t *settings);
obs_properties_t *obs_pipewire_get_properties(obs_pipewire_data *obs_pw,