Преглед на файлове

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
Georges Basile Stavracas Neto преди 4 години
родител
ревизия
26f1bfd05f
променени са 3 файла, в които са добавени 44 реда и са изтрити 0 реда
  1. 6 0
      plugins/linux-capture/pipewire-capture.c
  2. 37 0
      plugins/linux-capture/pipewire.c
  3. 1 0
      plugins/linux-capture/pipewire.h

+ 6 - 0
plugins/linux-capture/pipewire-capture.c

@@ -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,

+ 37 - 0
plugins/linux-capture/pipewire.c

@@ -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,

+ 1 - 0
plugins/linux-capture/pipewire.h

@@ -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,