mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
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. For the cached params in the node/device/port we need to be careful because multiple clients might ask for updates concurrently. Clear the pending list whenever a new param update starts so that we always only keep the last set of updates. 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.
This commit is contained in:
parent
da5f17f653
commit
c25bdce645
6 changed files with 134 additions and 100 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ struct result_device_params_data {
|
|||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param);
|
||||
int seq;
|
||||
uint32_t count;
|
||||
unsigned int cache:1;
|
||||
};
|
||||
|
||||
|
|
@ -277,6 +278,8 @@ static void result_device_params(void *data, int seq, int res, uint32_t type, co
|
|||
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
|
||||
if (d->cache) {
|
||||
pw_log_debug(NAME" %p: add param %d", impl, r->id);
|
||||
if (d->count++ == 0)
|
||||
pw_param_add(&impl->pending_list, r->id, NULL);
|
||||
pw_param_add(&impl->pending_list, r->id, r->param);
|
||||
}
|
||||
break;
|
||||
|
|
@ -298,7 +301,7 @@ int pw_impl_device_for_each_param(struct pw_impl_device *device,
|
|||
{
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF(device, struct impl, this);
|
||||
struct result_device_params_data user_data = { impl, data, callback, seq, false };
|
||||
struct result_device_params_data user_data = { impl, data, callback, seq, 0, false };
|
||||
struct spa_hook listener;
|
||||
struct spa_param_info *pi;
|
||||
static const struct spa_device_events device_events = {
|
||||
|
|
@ -347,7 +350,8 @@ int pw_impl_device_for_each_param(struct pw_impl_device *device,
|
|||
}
|
||||
res = 0;
|
||||
} else {
|
||||
user_data.cache = impl->cache_params && filter == NULL;
|
||||
user_data.cache = impl->cache_params &&
|
||||
(filter == NULL && index == 0 && max == UINT32_MAX);
|
||||
|
||||
spa_zero(listener);
|
||||
spa_device_add_listener(device->device, &listener,
|
||||
|
|
@ -412,7 +416,9 @@ static int device_enum_params(void *object, int seq, uint32_t id, uint32_t start
|
|||
data->data.impl = impl;
|
||||
data->data.data = data;
|
||||
data->data.callback = reply_param;
|
||||
data->data.cache = impl->cache_params && filter == NULL;
|
||||
data->data.count = 0;
|
||||
data->data.cache = impl->cache_params &&
|
||||
(filter == NULL && start == 0);
|
||||
if (data->end == -1)
|
||||
spa_device_add_listener(device->device, &data->listener,
|
||||
&device_events, data);
|
||||
|
|
@ -714,7 +720,6 @@ static void emit_params(struct pw_impl_device *device, uint32_t *changed_ids, ui
|
|||
static void device_info(void *data, const struct spa_device_info *info)
|
||||
{
|
||||
struct pw_impl_device *device = data;
|
||||
struct impl *impl = SPA_CONTAINER_OF(device, struct impl, this);
|
||||
uint32_t changed_ids[MAX_PARAMS], n_changed_ids = 0;
|
||||
|
||||
pw_log_debug(NAME" %p: flags:%08"PRIx64" change_mask:%08"PRIx64,
|
||||
|
|
@ -741,7 +746,6 @@ 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);
|
||||
device->info.params[i] = info->params[i];
|
||||
device->info.params[i].user = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,6 @@ int pw_impl_node_update_properties(struct pw_impl_node *node, const struct spa_d
|
|||
static void node_info(void *data, const struct spa_node_info *info)
|
||||
{
|
||||
struct pw_impl_node *node = data;
|
||||
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
||||
uint32_t changed_ids[MAX_PARAMS], n_changed_ids = 0;
|
||||
bool flags_changed = false;
|
||||
|
||||
|
|
@ -1286,7 +1285,6 @@ 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);
|
||||
node->info.params[i] = info->params[i];
|
||||
node->info.params[i].user = 0;
|
||||
|
||||
|
|
@ -1766,6 +1764,7 @@ struct result_node_params_data {
|
|||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param);
|
||||
int seq;
|
||||
uint32_t count;
|
||||
unsigned int cache:1;
|
||||
};
|
||||
|
||||
|
|
@ -1779,8 +1778,11 @@ static void result_node_params(void *data, int seq, int res, uint32_t type, cons
|
|||
const struct spa_result_node_params *r = result;
|
||||
if (d->seq == seq) {
|
||||
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
|
||||
if (d->cache)
|
||||
if (d->cache) {
|
||||
if (d->count++ == 0)
|
||||
pw_param_add(&impl->pending_list, r->id, NULL);
|
||||
pw_param_add(&impl->pending_list, r->id, r->param);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1801,7 +1803,7 @@ int pw_impl_node_for_each_param(struct pw_impl_node *node,
|
|||
{
|
||||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
||||
struct result_node_params_data user_data = { impl, data, callback, seq, false };
|
||||
struct result_node_params_data user_data = { impl, data, callback, seq, 0, false };
|
||||
struct spa_hook listener;
|
||||
struct spa_param_info *pi;
|
||||
static const struct spa_node_events node_events = {
|
||||
|
|
@ -1850,7 +1852,8 @@ int pw_impl_node_for_each_param(struct pw_impl_node *node,
|
|||
}
|
||||
res = 0;
|
||||
} else {
|
||||
user_data.cache = impl->cache_params && filter == NULL;
|
||||
user_data.cache = impl->cache_params &&
|
||||
(filter == NULL && index == 0 && max == UINT32_MAX);
|
||||
|
||||
spa_zero(listener);
|
||||
spa_node_add_listener(node->node, &listener, &node_events, &user_data);
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ static void emit_params(struct pw_impl_port *port, uint32_t *changed_ids, uint32
|
|||
|
||||
static void update_info(struct pw_impl_port *port, const struct spa_port_info *info)
|
||||
{
|
||||
struct impl *impl = SPA_CONTAINER_OF(port, struct impl, this);
|
||||
uint32_t changed_ids[MAX_PARAMS], n_changed_ids = 0;
|
||||
|
||||
pw_log_debug(NAME" %p: flags:%08"PRIx64" change_mask:%08"PRIx64,
|
||||
|
|
@ -378,7 +377,6 @@ 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);
|
||||
port->info.params[i] = info->params[i];
|
||||
port->info.params[i].user = 0;
|
||||
|
||||
|
|
@ -1069,6 +1067,7 @@ struct result_port_params_data {
|
|||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param);
|
||||
int seq;
|
||||
uint32_t count;
|
||||
unsigned int cache:1;
|
||||
};
|
||||
|
||||
|
|
@ -1082,8 +1081,11 @@ static void result_port_params(void *data, int seq, int res, uint32_t type, cons
|
|||
const struct spa_result_node_params *r = result;
|
||||
if (d->seq == seq) {
|
||||
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
|
||||
if (d->cache)
|
||||
if (d->cache) {
|
||||
if (d->count++ == 0)
|
||||
pw_param_add(&impl->pending_list, r->id, NULL);
|
||||
pw_param_add(&impl->pending_list, r->id, r->param);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1105,7 +1107,7 @@ int pw_impl_port_for_each_param(struct pw_impl_port *port,
|
|||
int res;
|
||||
struct impl *impl = SPA_CONTAINER_OF(port, struct impl, this);
|
||||
struct pw_impl_node *node = port->node;
|
||||
struct result_port_params_data user_data = { impl, data, callback, seq, false };
|
||||
struct result_port_params_data user_data = { impl, data, callback, seq, 0, false };
|
||||
struct spa_hook listener;
|
||||
struct spa_param_info *pi;
|
||||
static const struct spa_node_events node_events = {
|
||||
|
|
@ -1154,7 +1156,8 @@ int pw_impl_port_for_each_param(struct pw_impl_port *port,
|
|||
}
|
||||
res = 0;
|
||||
} else {
|
||||
user_data.cache = filter == NULL;
|
||||
user_data.cache = impl->cache_params &&
|
||||
(filter == NULL && index == 0 && max == UINT32_MAX);
|
||||
|
||||
spa_zero(listener);
|
||||
spa_node_add_listener(node->node, &listener, &node_events, &user_data);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue