瀏覽代碼

linux-capture: Query used PipeWire versions

This enables us in the following commit to announce different
capabilities wrt. those versions.
columbarius 3 年之前
父節點
當前提交
9f7de79004
共有 1 個文件被更改,包括 53 次插入3 次删除
  1. 53 3
      plugins/linux-capture/pipewire.c

+ 53 - 3
plugins/linux-capture/pipewire.c

@@ -35,6 +35,7 @@
 #include <spa/debug/format.h>
 #include <spa/debug/types.h>
 #include <spa/param/video/type-info.h>
+#include <spa/utils/result.h>
 
 #define REQUEST_PATH "/org/freedesktop/portal/desktop/request/%s/obs%u"
 #define SESSION_PATH "/org/freedesktop/portal/desktop/session/%s/obs%u"
@@ -60,6 +61,12 @@
 	fourcc_code('A', 'B', '2', \
 		    '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
 
+struct obs_pw_version {
+	int major;
+	int minor;
+	int micro;
+};
+
 struct _obs_pipewire_data {
 	GCancellable *cancellable;
 
@@ -82,6 +89,9 @@ struct _obs_pipewire_data {
 
 	struct pw_core *core;
 	struct spa_hook core_listener;
+	int server_version_sync;
+
+	struct obs_pw_version server_version;
 
 	struct pw_stream *stream;
 	struct spa_hook stream_listener;
@@ -116,6 +126,35 @@ struct dbus_call_data {
 
 /* auxiliary methods */
 
+static bool parse_pw_version(struct obs_pw_version *dst, const char *version)
+{
+	int n_matches = sscanf(version, "%d.%d.%d", &dst->major, &dst->minor,
+			       &dst->micro);
+	return n_matches == 3;
+}
+
+static bool check_pw_version(const struct obs_pw_version *pw_version, int major,
+			     int minor, int micro)
+{
+	if (pw_version->major != major)
+		return pw_version->major > major;
+	if (pw_version->minor != minor)
+		return pw_version->minor > minor;
+	return pw_version->micro >= micro;
+}
+
+static void update_pw_versions(obs_pipewire_data *obs_pw, const char *version)
+{
+	blog(LOG_INFO, "[pipewire] server version: %s", version);
+	blog(LOG_INFO, "[pipewire] library version: %s",
+	     pw_get_library_version());
+	blog(LOG_INFO, "[pipewire] header version: %s",
+	     pw_get_headers_version());
+
+	if (!parse_pw_version(&obs_pw->server_version, version))
+		blog(LOG_WARNING, "[pipewire] failed to parse server version");
+}
+
 static const char *capture_type_to_string(enum obs_pw_capture_type capture_type)
 {
 	switch (capture_type) {
@@ -595,6 +634,13 @@ static const struct pw_stream_events stream_events = {
 	.process = on_process_cb,
 };
 
+static void on_core_info_cb(void *user_data, const struct pw_core_info *info)
+{
+	obs_pipewire_data *obs_pw = user_data;
+
+	update_pw_versions(obs_pw, info->version);
+}
+
 static void on_core_error_cb(void *user_data, uint32_t id, int seq, int res,
 			     const char *message)
 {
@@ -610,16 +656,15 @@ static void on_core_error_cb(void *user_data, uint32_t id, int seq, int res,
 
 static void on_core_done_cb(void *user_data, uint32_t id, int seq)
 {
-	UNUSED_PARAMETER(seq);
-
 	obs_pipewire_data *obs_pw = user_data;
 
-	if (id == PW_ID_CORE)
+	if (id == PW_ID_CORE && obs_pw->server_version_sync == seq)
 		pw_thread_loop_signal(obs_pw->thread_loop, FALSE);
 }
 
 static const struct pw_core_events core_events = {
 	PW_VERSION_CORE_EVENTS,
+	.info = on_core_info_cb,
 	.done = on_core_done_cb,
 	.error = on_core_error_cb,
 };
@@ -655,6 +700,11 @@ static void play_pipewire_stream(obs_pipewire_data *obs_pw)
 	pw_core_add_listener(obs_pw->core, &obs_pw->core_listener, &core_events,
 			     obs_pw);
 
+	// Dispatch to receive the info core event
+	obs_pw->server_version_sync = pw_core_sync(obs_pw->core, PW_ID_CORE,
+						   obs_pw->server_version_sync);
+	pw_thread_loop_wait(obs_pw->thread_loop);
+
 	/* Stream */
 	obs_pw->stream = pw_stream_new(
 		obs_pw->core, "OBS Studio",