diff --git a/0002-media-session-don-t-remove-default.configured-when-d.patch b/0002-media-session-don-t-remove-default.configured-when-d.patch new file mode 100644 index 0000000..bc4e850 --- /dev/null +++ b/0002-media-session-don-t-remove-default.configured-when-d.patch @@ -0,0 +1,264 @@ +From b9d6b098a9bdfa4d4295e8a9e05ab4044df9db81 Mon Sep 17 00:00:00 2001 +From: Pauli Virtanen +Date: Sun, 8 Aug 2021 13:11:43 +0300 +Subject: [PATCH 2/3] media-session: don't remove default.configured when + devices go away + +There's no particular problem to have default.configured to point to a +non-existent device, it will be ignored. This was left over when +default and configured default were made separate things. + +default-nodes also doesn't need to track the id of the configured +default, so remove also other stuff that's no longer necessary. It can +simply load the values to metadata on startup, and save them to a file +when they are changed, without needing to understand what the values +mean. + +Also fixes commit 707156233431 causing defaults to be forgotten when +nodes are removed. +--- + src/examples/media-session/default-nodes.c | 153 ++------------------- + 1 file changed, 14 insertions(+), 139 deletions(-) + +diff --git a/src/examples/media-session/default-nodes.c b/src/examples/media-session/default-nodes.c +index 46298a020..c9517079b 100644 +--- a/src/examples/media-session/default-nodes.c ++++ b/src/examples/media-session/default-nodes.c +@@ -34,9 +34,7 @@ + + #include + #include +-#include + #include +-#include + + #include "pipewire/pipewire.h" + #include "pipewire/extensions/metadata.h" +@@ -48,7 +46,6 @@ + + #define NAME "default-nodes" + #define SESSION_KEY "default-nodes" +-#define PREFIX "default." + + #define SAVE_INTERVAL 1 + +@@ -56,14 +53,7 @@ + #define DEFAULT_CONFIG_AUDIO_SOURCE_KEY "default.configured.audio.source" + #define DEFAULT_CONFIG_VIDEO_SOURCE_KEY "default.configured.video.source" + +-struct default_node { +- char *key; +- uint32_t value; +-}; +- + struct impl { +- struct timespec now; +- + struct sm_media_session *session; + struct spa_hook listener; + +@@ -72,72 +62,14 @@ struct impl { + + struct spa_hook meta_listener; + +- struct default_node defaults[4]; +- + struct pw_properties *properties; +- +- unsigned int sync:1; +-}; +- +-static struct default_node *find_default(struct impl *impl, const char *key) +-{ +- struct default_node *def; +- /* Check that the item key is a valid default key */ +- for (def = impl->defaults; def->key != NULL; ++def) +- if (spa_streq(key, def->key)) +- return def; +- return NULL; +-} +- +-struct find_data { +- struct impl *impl; +- const char *name; +- uint32_t id; + }; + +-static int find_name(void *data, struct sm_object *object) +-{ +- struct find_data *d = data; +- const char *str; +- +- if (spa_streq(object->type, PW_TYPE_INTERFACE_Node) && +- object->props && +- (str = pw_properties_get(object->props, PW_KEY_NODE_NAME)) != NULL && +- spa_streq(str, d->name)) { +- d->id = object->id; +- return 1; +- } +- return 0; +-} +- +-static uint32_t find_id_for_name(struct impl *impl, const char *name) ++static bool is_default_key(const char *key) + { +- struct find_data d = { impl, name, SPA_ID_INVALID }; +- sm_media_session_for_each_object(impl->session, find_name, &d); +- return d.id; +-} +- +-static int json_object_find(const char *obj, const char *key, char *value, size_t len) +-{ +- struct spa_json it[2]; +- const char *v; +- char k[128]; +- +- spa_json_init(&it[0], obj, strlen(obj)); +- if (spa_json_enter_object(&it[0], &it[1]) <= 0) +- return -EINVAL; +- +- while (spa_json_get_string(&it[1], k, sizeof(k)-1) > 0) { +- if (spa_streq(k, key)) { +- if (spa_json_get_string(&it[1], value, len) <= 0) +- continue; +- return 0; +- } else { +- if (spa_json_next(&it[1], &v) <= 0) +- break; +- } +- } +- return -ENOENT; ++ return spa_streq(key, DEFAULT_CONFIG_AUDIO_SINK_KEY) || ++ spa_streq(key, DEFAULT_CONFIG_AUDIO_SOURCE_KEY) || ++ spa_streq(key, DEFAULT_CONFIG_VIDEO_SOURCE_KEY); + } + + static void remove_idle_timeout(struct impl *impl) +@@ -180,35 +112,15 @@ static int metadata_property(void *object, uint32_t subject, + struct impl *impl = object; + int changed = 0; + +- if (impl->sync) +- return 0; +- + if (subject == PW_ID_CORE) { + if (key == NULL) { + pw_properties_clear(impl->properties); + changed++; + } else { +- uint32_t id; +- struct default_node *def; +- char name[1024]; +- +- if ((def = find_default(impl, key)) == NULL) ++ if (!is_default_key(key)) + return 0; + +- if (value == NULL) { +- def->value = SPA_ID_INVALID; +- changed += pw_properties_set(impl->properties, key, NULL); +- } else { +- if (json_object_find(value, "name", name, sizeof(name)) < 0) +- return 0; +- +- if ((id = find_id_for_name(impl, name)) == SPA_ID_INVALID) +- return 0; +- +- def->value = id; +- changed += pw_properties_set(impl->properties, +- key, value); +- } ++ changed += pw_properties_set(impl->properties, key, value); + } + } + if (changed) +@@ -222,51 +134,18 @@ static const struct pw_metadata_events metadata_events = { + .property = metadata_property, + }; + +-static void session_create(void *data, struct sm_object *object) ++static void load_metadata(struct impl *impl) + { +- struct impl *impl = data; + const struct spa_dict_item *item; + +- if (!spa_streq(object->type, PW_TYPE_INTERFACE_Node)) +- return; +- + spa_dict_for_each(item, &impl->properties->dict) { +- char name [1024] = "\0"; +- struct find_data d; +- +- if (find_default(impl, item->key) == NULL) +- continue; +- +- if (json_object_find(item->value, "name", name, sizeof(name)) < 0) ++ if (!is_default_key(item->key)) + continue; + +- d = (struct find_data){ impl, name, SPA_ID_INVALID }; +- if (find_name(&d, object)) { +- if (impl->session->metadata != NULL) { +- pw_log_info("found %s with id:%u restore as %s", +- name, d.id, item->key); +- pw_metadata_set_property(impl->session->metadata, ++ if (impl->session->metadata != NULL) { ++ pw_log_info("restoring %s=%s", item->key, item->value); ++ pw_metadata_set_property(impl->session->metadata, + PW_ID_CORE, item->key, "Spa:String:JSON", item->value); +- } +- } +- } +-} +- +-static void session_remove(void *data, struct sm_object *object) +-{ +- struct impl *impl = data; +- struct default_node *def; +- +- if (!spa_streq(object->type, PW_TYPE_INTERFACE_Node)) +- return; +- +- for (def = impl->defaults; def->key != NULL; ++def) { +- if (def->value == object->id) { +- def->value = SPA_ID_INVALID; +- if (impl->session->metadata != NULL) { +- pw_metadata_set_property(impl->session->metadata, +- PW_ID_CORE, def->key, NULL, NULL); +- } + } + } + } +@@ -284,8 +163,6 @@ static void session_destroy(void *data) + + static const struct sm_media_session_events session_events = { + SM_VERSION_MEDIA_SESSION_EVENTS, +- .create = session_create, +- .remove = session_remove, + .destroy = session_destroy, + }; + +@@ -301,11 +178,6 @@ int sm_default_nodes_start(struct sm_media_session *session) + impl->session = session; + impl->context = session->context; + +- impl->defaults[0] = (struct default_node){ DEFAULT_CONFIG_AUDIO_SINK_KEY, }; +- impl->defaults[1] = (struct default_node){ DEFAULT_CONFIG_AUDIO_SOURCE_KEY, }; +- impl->defaults[2] = (struct default_node){ DEFAULT_CONFIG_VIDEO_SOURCE_KEY, }; +- impl->defaults[3] = (struct default_node){ NULL, }; +- + impl->properties = pw_properties_new(NULL, NULL); + if (impl->properties == NULL) { + free(impl); +@@ -323,5 +195,8 @@ int sm_default_nodes_start(struct sm_media_session *session) + &impl->meta_listener, + &metadata_events, impl); + } ++ ++ load_metadata(impl); ++ + return 0; + } +-- +2.31.1 + diff --git a/pipewire.spec b/pipewire.spec index 6ad088c..1f17a34 100644 --- a/pipewire.spec +++ b/pipewire.spec @@ -8,7 +8,7 @@ %global libversion %{soversion}.%(bash -c '((intversion = (%{minorversion} * 100) + %{microversion})); echo ${intversion}').0 # For rpmdev-bumpspec and releng automation -%global baserelease 1 +%global baserelease 2 #global snapdate 20210107 #global gitcommit b17db2cebc1a5ab2c01851d29c05f79cd2f262bb @@ -54,6 +54,7 @@ Source0: https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/%{ver %endif ## upstream patches +Patch0001: 0002-media-session-don-t-remove-default.configured-when-d.patch ## upstreamable patches @@ -522,6 +523,9 @@ systemctl --no-reload preset --global pipewire.socket >/dev/null 2>&1 || : %endif %changelog +* Tue Aug 10 2021 Wim Taymans - 0.3.33-2 +- Add patch to fix default device persistence. + * Thu Aug 5 2021 Wim Taymans - 0.3.33-1 - Update to 0.3.33