diff --git a/src/pipewire/client.c b/src/pipewire/client.c index a29c56926..d47d7efc8 100644 --- a/src/pipewire/client.c +++ b/src/pipewire/client.c @@ -195,7 +195,7 @@ struct pw_client *pw_client_new(struct pw_core *core, pw_core_add_listener(core, &impl->core_listener, &core_events, impl); - this->info.props = this->properties ? &this->properties->dict : NULL; + this->info.props = &this->properties->dict; return this; } @@ -321,8 +321,7 @@ void pw_client_destroy(struct pw_client *client) pw_map_clear(&client->objects); pw_array_clear(&impl->permissions); - if (client->properties) - pw_properties_free(client->properties); + pw_properties_free(client->properties); free(impl); } @@ -354,20 +353,17 @@ const struct pw_client_info *pw_client_get_info(struct pw_client *client) int pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict) { struct pw_resource *resource; + uint32_t i, changed = 0; - if (client->properties == NULL) { - if (dict) - client->properties = pw_properties_new_dict(dict); - } else { - uint32_t i; + for (i = 0; i < dict->n_items; i++) + changed += pw_properties_set(client->properties, + dict->items[i].key, dict->items[i].value); - for (i = 0; i < dict->n_items; i++) - pw_properties_set(client->properties, - dict->items[i].key, dict->items[i].value); - } + if (!changed) + return 0; client->info.change_mask |= PW_CLIENT_CHANGE_MASK_PROPS; - client->info.props = client->properties ? &client->properties->dict : NULL; + client->info.props = &client->properties->dict; pw_client_events_info_changed(client, &client->info); @@ -376,7 +372,7 @@ int pw_client_update_properties(struct pw_client *client, const struct spa_dict client->info.change_mask = 0; - return 0; + return changed; } struct permissions_update { diff --git a/src/pipewire/core.c b/src/pipewire/core.c index 250463094..85f6a1088 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -573,10 +573,13 @@ const struct pw_properties *pw_core_get_properties(struct pw_core *core) int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value); + + if (!changed) + return 0; core->info.change_mask = PW_CORE_CHANGE_MASK_PROPS; core->info.props = &core->properties->dict; @@ -588,7 +591,7 @@ int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict) core->info.change_mask = 0; - return 0; + return changed; } int pw_core_for_each_global(struct pw_core *core, diff --git a/src/pipewire/module.c b/src/pipewire/module.c index d99c52b5c..efb7484f3 100644 --- a/src/pipewire/module.c +++ b/src/pipewire/module.c @@ -334,10 +334,13 @@ const struct pw_properties *pw_module_get_properties(struct pw_module *module) int pw_module_update_properties(struct pw_module *module, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(module->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(module->properties, dict->items[i].key, dict->items[i].value); + + if (!changed) + return 0; module->info.props = &module->properties->dict; @@ -346,7 +349,7 @@ int pw_module_update_properties(struct pw_module *module, const struct spa_dict pw_module_resource_info(resource, &module->info); module->info.change_mask = 0; - return 0; + return changed; } const struct pw_module_info * diff --git a/src/pipewire/node.c b/src/pipewire/node.c index 6ef20fa42..5c18f6632 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -721,15 +721,19 @@ const struct pw_properties *pw_node_get_properties(struct pw_node *node) int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value); + + pw_log_debug("node %p: updated %d properties", node, changed); + + if (!changed) + return 0; check_properties(node); node->info.props = &node->properties->dict; - node->info.change_mask |= PW_NODE_CHANGE_MASK_PROPS; pw_node_events_info_changed(node, &node->info); @@ -738,7 +742,7 @@ int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict) node->info.change_mask = 0; - return 0; + return changed; } static void node_done(void *data, int seq, int res) diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 2b7503d76..0dda36706 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -283,13 +283,17 @@ const struct pw_properties *pw_port_get_properties(struct pw_port *port) int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value); + + pw_log_debug("port %p: updated %d properties", port, changed); + + if (!changed) + return 0; port->info.props = &port->properties->dict; - port->info.change_mask |= PW_PORT_CHANGE_MASK_PROPS; pw_port_events_info_changed(port, &port->info); @@ -298,7 +302,7 @@ int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict) port->info.change_mask = 0; - return 0; + return changed; } struct pw_node *pw_port_get_node(struct pw_port *port) diff --git a/src/pipewire/properties.c b/src/pipewire/properties.c index 03441b58e..6c95a6b50 100644 --- a/src/pipewire/properties.c +++ b/src/pipewire/properties.c @@ -247,31 +247,39 @@ void pw_properties_free(struct pw_properties *properties) free(impl); } -static int do_replace(struct pw_properties *properties, const char *key, char *value) +static int do_replace(struct pw_properties *properties, const char *key, char *value, bool copy) { struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this); int index = find_index(properties, key); if (index == -1) { - add_func(properties, strdup(key), value); + if (value == NULL) + return 0; + add_func(properties, strdup(key), copy ? strdup(value) : value); } else { struct spa_dict_item *item = pw_array_get_unchecked(&impl->items, index, struct spa_dict_item); - clear_item(item); + if (value && strcmp(item->value, value) == 0) { + if (!copy) + free(value); + return 0; + } + if (value == NULL) { struct spa_dict_item *other = pw_array_get_unchecked(&impl->items, pw_array_get_len(&impl->items, struct spa_dict_item) - 1, struct spa_dict_item); + clear_item(item); item->key = other->key; item->value = other->value; impl->items.size -= sizeof(struct spa_dict_item); } else { - item->key = strdup(key); - item->value = value; + free((char *) item->value); + item->value = copy ? strdup(value) : value; } } - return 0; + return 1; } /** Set a property value @@ -279,6 +287,9 @@ static int do_replace(struct pw_properties *properties, const char *key, char *v * \param properties the properties to change * \param key a key * \param value a value or NULL to remove the key + * \return 1 if the properties were changed. 0 if nothing was changed because + * the property already existed with the same value or because the key to remove + * did not exist. * * Set the property in \a properties with \a key to \a value. Any previous value * of \a key will be overwritten. When \a value is NULL, the key will be @@ -288,7 +299,7 @@ static int do_replace(struct pw_properties *properties, const char *key, char *v */ int pw_properties_set(struct pw_properties *properties, const char *key, const char *value) { - return do_replace(properties, key, value ? strdup(value) : NULL); + return do_replace(properties, key, (char*)value, true); } int @@ -297,7 +308,7 @@ pw_properties_setva(struct pw_properties *properties, { char *value; vasprintf(&value, format, args); - return do_replace(properties, key, value); + return do_replace(properties, key, value, false); } /** Set a property value by format diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c index 1c63563f3..6517a31ea 100644 --- a/src/pipewire/remote.c +++ b/src/pipewire/remote.c @@ -330,16 +330,20 @@ const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote) int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict) { - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(remote->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(remote->properties, dict->items[i].key, dict->items[i].value); + + if (!changed) + return 0; if (remote->core_proxy) pw_core_proxy_client_update(remote->core_proxy, &remote->properties->dict); - return 0; + return changed; } + void *pw_remote_get_user_data(struct pw_remote *remote) { return remote->user_data; diff --git a/src/tools/pipewire-monitor.c b/src/tools/pipewire-monitor.c index c9ed8c373..82dac1ca2 100644 --- a/src/tools/pipewire-monitor.c +++ b/src/tools/pipewire-monitor.c @@ -290,7 +290,7 @@ static void print_port(struct proxy_data *data) if (print_all) { int i; printf(" \tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); - printf("%c\tparams:\n", MARK_CHANGE(1)); + printf("%c\tparams:\n", MARK_CHANGE(2)); for (i = 0; i < data->n_params; i++) { if (spa_pod_is_object_type(data->params[i], SPA_TYPE_OBJECT_Format)) spa_debug_format(12, NULL, data->params[i]);