From 5aa7746c95c1776d144638fdad012cfe857d34eb Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 4 Feb 2021 13:26:35 +0100 Subject: [PATCH] rework param updates Make it possible to add a NULL param to the pending list. The NULL param removes all previous updates. When applying the updates, the NULL param removes the params from the target list. This has two advantages: it actually removes params that become unreadable or that got removed and it allows us to update the target list more efficiently in one single loop. --- src/modules/module-protocol-pulse/manager.c | 66 +++++++++++--------- src/pipewire/impl-device.c | 2 +- src/pipewire/impl-node.c | 2 +- src/pipewire/impl-port.c | 2 +- src/pipewire/private.h | 60 ++++++++++-------- src/tools/pw-dump.c | 68 ++++++++++++--------- 6 files changed, 112 insertions(+), 88 deletions(-) diff --git a/src/modules/module-protocol-pulse/manager.c b/src/modules/module-protocol-pulse/manager.c index c4942aab4..97a05e14b 100644 --- a/src/modules/module-protocol-pulse/manager.c +++ b/src/modules/module-protocol-pulse/manager.c @@ -73,24 +73,45 @@ static void core_sync(struct manager *m) pw_log_debug("sync start %u", m->sync_seq); } +static uint32_t clear_params(struct spa_list *param_list, uint32_t id) +{ + struct pw_manager_param *p, *t; + uint32_t count = 0; + + spa_list_for_each_safe(p, t, param_list, link) { + if (id == SPA_ID_INVALID || p->id == id) { + spa_list_remove(&p->link); + free(p); + count++; + } + } + return count; +} + static struct pw_manager_param *add_param(struct spa_list *params, uint32_t id, const struct spa_pod *param) { struct pw_manager_param *p; - if (param == NULL || !spa_pod_is_object(param)) { - errno = EINVAL; - return NULL; - } - if (id == SPA_ID_INVALID) + if (id == SPA_ID_INVALID) { + if (param == NULL || !spa_pod_is_object(param)) { + errno = EINVAL; + return NULL; + } id = SPA_POD_OBJECT_ID(param); + } - p = malloc(sizeof(*p) + SPA_POD_SIZE(param)); + p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0)); if (p == NULL) return NULL; p->id = id; - p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); - memcpy(p->param, param, SPA_POD_SIZE(param)); + if (param != NULL) { + p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); + memcpy(p->param, param, SPA_POD_SIZE(param)); + } else { + clear_params(params, id); + p->param = NULL; + } spa_list_append(params, &p->link); return p; @@ -108,21 +129,6 @@ static bool has_param(struct spa_list *param_list, struct pw_manager_param *p) return false; } -static uint32_t clear_params(struct spa_list *param_list, uint32_t id) -{ - struct pw_manager_param *p, *t; - uint32_t count = 0; - - spa_list_for_each_safe(p, t, param_list, link) { - if (id == SPA_ID_INVALID || p->id == id) { - spa_list_remove(&p->link); - free(p); - count++; - } - } - return count; -} - static struct object *find_object(struct manager *m, uint32_t id) { @@ -140,12 +146,14 @@ static void object_update_params(struct object *o) { struct pw_manager_param *p; - spa_list_for_each(p, &o->pending_list, link) - clear_params(&o->this.param_list, p->id); - spa_list_consume(p, &o->pending_list, link) { spa_list_remove(&p->link); - spa_list_append(&o->this.param_list, &p->link); + if (p->param == NULL) { + clear_params(&o->this.param_list, p->id); + free(p); + } else { + spa_list_append(&o->this.param_list, &p->link); + } } } @@ -277,7 +285,7 @@ static void device_event_info(void *object, const struct pw_device_info *info) case SPA_PARAM_Route: break; } - clear_params(&o->pending_list, id); + add_param(&o->pending_list, id, NULL); if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) continue; @@ -382,7 +390,7 @@ static void node_event_info(void *object, const struct pw_node_info *info) info->params[i].user = 0; changed++; - clear_params(&o->pending_list, id); + add_param(&o->pending_list, id, NULL); if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) continue; diff --git a/src/pipewire/impl-device.c b/src/pipewire/impl-device.c index 0aeb8610d..5deee792e 100644 --- a/src/pipewire/impl-device.c +++ b/src/pipewire/impl-device.c @@ -741,7 +741,7 @@ static void device_info(void *data, const struct spa_device_info *info) continue; pw_log_debug(NAME" %p: update param %d", device, id); - pw_param_clear(&impl->pending_list, id); + pw_param_add(&impl->pending_list, id, NULL); device->info.params[i] = info->params[i]; device->info.params[i].user = 0; diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index a2c72bc1c..61844dedf 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -1286,7 +1286,7 @@ static void node_info(void *data, const struct spa_node_info *info) continue; pw_log_debug(NAME" %p: update param %d", node, id); - pw_param_clear(&impl->pending_list, id); + pw_param_add(&impl->pending_list, id, NULL); node->info.params[i] = info->params[i]; node->info.params[i].user = 0; diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index b01581d38..abfd1b02b 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -378,7 +378,7 @@ static void update_info(struct pw_impl_port *port, const struct spa_port_info *i continue; pw_log_debug(NAME" %p: update param %d", port, id); - pw_param_clear(&impl->pending_list, id); + pw_param_add(&impl->pending_list, id, NULL); port->info.params[i] = info->params[i]; port->info.params[i].user = 0; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index d8d8c3166..9830bf823 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -90,28 +90,6 @@ struct pw_param { struct spa_pod *param; }; -static inline struct pw_param *pw_param_add(struct spa_list *params, - uint32_t id, const struct spa_pod *param) -{ - struct pw_param *p; - - if (param == NULL || !spa_pod_is_object(param)) { - errno = EINVAL; - return NULL; - } - if (id == SPA_ID_INVALID) - id = SPA_POD_OBJECT_ID(param); - - if ((p = malloc(sizeof(*p) + SPA_POD_SIZE(param))) == NULL) - return NULL; - - p->id = id; - p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); - memcpy(p->param, param, SPA_POD_SIZE(param)); - spa_list_append(params, &p->link); - return p; -} - static inline uint32_t pw_param_clear(struct spa_list *param_list, uint32_t id) { struct pw_param *p, *t; @@ -127,16 +105,46 @@ static inline uint32_t pw_param_clear(struct spa_list *param_list, uint32_t id) return count; } +static inline struct pw_param *pw_param_add(struct spa_list *params, + uint32_t id, const struct spa_pod *param) +{ + struct pw_param *p; + + if (id == SPA_ID_INVALID) { + if (param == NULL || !spa_pod_is_object(param)) { + errno = EINVAL; + return NULL; + } + id = SPA_POD_OBJECT_ID(param); + } + + if ((p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0))) == NULL) + return NULL; + + p->id = id; + if (param != NULL) { + p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); + memcpy(p->param, param, SPA_POD_SIZE(param)); + } else { + pw_param_clear(params, id); + p->param = NULL; + } + spa_list_append(params, &p->link); + return p; +} + static inline void pw_param_update(struct spa_list *param_list, struct spa_list *pending_list) { struct pw_param *p; - spa_list_for_each(p, pending_list, link) - pw_param_clear(param_list, p->id); - spa_list_consume(p, pending_list, link) { spa_list_remove(&p->link); - spa_list_append(param_list, &p->link); + if (p->param == NULL) { + pw_param_clear(param_list, p->id); + free(p); + } else { + spa_list_append(param_list, &p->link); + } } } diff --git a/src/tools/pw-dump.c b/src/tools/pw-dump.c index 03536224d..9d8e79918 100644 --- a/src/tools/pw-dump.c +++ b/src/tools/pw-dump.c @@ -122,29 +122,6 @@ static void core_sync(struct data *d) pw_log_debug("sync start %u", d->sync_seq); } -static struct param *add_param(struct spa_list *params, uint32_t id, const struct spa_pod *param) -{ - struct param *p; - - if (param == NULL || !spa_pod_is_object(param)) { - errno = EINVAL; - return NULL; - } - if (id == SPA_ID_INVALID) - id = SPA_POD_OBJECT_ID(param); - - p = malloc(sizeof(*p) + SPA_POD_SIZE(param)); - if (p == NULL) - return NULL; - - p->id = id; - p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); - memcpy(p->param, param, SPA_POD_SIZE(param)); - spa_list_append(params, &p->link); - - return p; -} - static uint32_t clear_params(struct spa_list *param_list, uint32_t id) { struct param *p, *t; @@ -160,6 +137,35 @@ static uint32_t clear_params(struct spa_list *param_list, uint32_t id) return count; } +static struct param *add_param(struct spa_list *params, uint32_t id, const struct spa_pod *param) +{ + struct param *p; + + if (id == SPA_ID_INVALID) { + if (param == NULL || !spa_pod_is_object(param)) { + errno = EINVAL; + return NULL; + } + id = SPA_POD_OBJECT_ID(param); + } + + p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0)); + if (p == NULL) + return NULL; + + p->id = id; + if (param != NULL) { + p->param = SPA_MEMBER(p, sizeof(*p), struct spa_pod); + memcpy(p->param, param, SPA_POD_SIZE(param)); + } else { + clear_params(params, id); + p->param = NULL; + } + spa_list_append(params, &p->link); + + return p; +} + static struct object *find_object(struct data *d, uint32_t id) { struct object *o; @@ -174,12 +180,14 @@ static void object_update_params(struct object *o) { struct param *p; - spa_list_for_each(p, &o->pending_list, link) - clear_params(&o->param_list, p->id); - spa_list_consume(p, &o->pending_list, link) { spa_list_remove(&p->link); - spa_list_append(&o->param_list, &p->link); + if (p->param == NULL) { + clear_params(&o->param_list, p->id); + free(p); + } else { + spa_list_append(&o->param_list, &p->link); + } } } @@ -482,7 +490,7 @@ static void put_params(struct data *d, const char *key, put_begin(d, spa_debug_type_find_short_name(spa_type_param, pi->id), "[", flags); spa_list_for_each(p, list, link) { - if (p->id == pi->id && flags == 0) + if (p->id == pi->id) put_pod(d, NULL, p->param); } put_end(d, "]", flags); @@ -834,7 +842,7 @@ static void node_event_info(void *object, const struct pw_node_info *info) info->params[i].user = 0; changed++; - clear_params(&o->pending_list, id); + add_param(&o->pending_list, id, NULL); if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) continue; @@ -917,7 +925,7 @@ static void port_event_info(void *object, const struct pw_port_info *info) info->params[i].user = 0; changed++; - clear_params(&o->pending_list, id); + add_param(&o->pending_list, id, NULL); if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) continue;