From 9eaf1184c2ef0247e69d415d3d628c4c15c95d05 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Wed, 18 Oct 2023 18:58:28 +0300 Subject: [PATCH] module-protocol-native: multiple names to try in PW_KEY_REMOTE_NAME Allow PIPEWIRE_REMOTE / PW_KEY_REMOTE_NAME to contain a JSON array of sockets to try to connect to, in order, instead of just one name. JSON is restricted to utf-8 encoding. Also, this forces using JSON syntax for paths that start with '['. This probably will not usually cause much problem. --- .../module-protocol-native/local-socket.c | 53 ++++++++++++++----- src/pipewire/keys.h | 4 +- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/modules/module-protocol-native/local-socket.c b/src/modules/module-protocol-native/local-socket.c index c35cd1170..f514881aa 100644 --- a/src/modules/module-protocol-native/local-socket.c +++ b/src/modules/module-protocol-native/local-socket.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #endif #include +#include #define DEFAULT_SYSTEM_RUNTIME_DIR "/run/pipewire" @@ -119,31 +121,56 @@ error: return res; } -int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client, - const struct spa_dict *props, - void (*done_callback) (void *data, int res), - void *data) +static int try_connect_name(struct pw_protocol_client *client, + const char *name, + void (*done_callback) (void *data, int res), + void *data) { - const char *runtime_dir, *name; + const char *runtime_dir; int res; - name = get_remote(props); - if (name == NULL) - return -EINVAL; - if (name[0] == '/') { - res = try_connect(client, NULL, name, done_callback, data); + return try_connect(client, NULL, name, done_callback, data); } else { runtime_dir = get_runtime_dir(); if (runtime_dir != NULL) { res = try_connect(client, runtime_dir, name, done_callback, data); if (res >= 0) - goto exit; + return res; } runtime_dir = get_system_dir(); if (runtime_dir != NULL) - res = try_connect(client, runtime_dir, name, done_callback, data); + return try_connect(client, runtime_dir, name, done_callback, data); } -exit: + + return -EINVAL; +} + +int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client, + const struct spa_dict *props, + void (*done_callback) (void *data, int res), + void *data) +{ + const char *name; + struct spa_json it[2]; + char path[PATH_MAX]; + int res = -EINVAL; + + name = get_remote(props); + if (name == NULL) + return -EINVAL; + + spa_json_init(&it[0], name, strlen(name)); + + if (spa_json_enter_array(&it[0], &it[1]) < 0) + return try_connect_name(client, name, done_callback, data); + + while (spa_json_get_string(&it[1], path, sizeof(path)) > 0) { + res = try_connect_name(client, path, done_callback, data); + if (res < 0) + continue; + break; + } + return res; } diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index 630e416b4..0b8a7737d 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -90,7 +90,9 @@ extern "C" { /* remote keys */ #define PW_KEY_REMOTE_NAME "remote.name" /**< The name of the remote to connect to, * default pipewire-0, overwritten by - * env(PIPEWIRE_REMOTE) */ + * env(PIPEWIRE_REMOTE). May also be + * a SPA-JSON array of sockets, to be tried + * in order. */ #define PW_KEY_REMOTE_INTENTION "remote.intention" /**< The intention of the remote connection, * "generic", "screencast" */