diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index a966b7cc1..7606b1f7b 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -361,7 +361,7 @@ int sm_object_destroy(struct sm_object *obj) } static struct param *add_param(struct spa_list *param_list, - uint32_t id, const struct spa_pod *param) + int seq, int *param_seq, uint32_t id, const struct spa_pod *param) { struct param *p; @@ -372,6 +372,19 @@ static struct param *add_param(struct spa_list *param_list, if (id == SPA_ID_INVALID) id = SPA_POD_OBJECT_ID(param); + if (id >= SM_MAX_PARAMS) { + pw_log_error(NAME": too big param id %d", id); + errno = EINVAL; + return NULL; + } + + if (seq != param_seq[id]) { + pw_log_debug(NAME": ignoring param %d, seq:%d != current_seq:%d", + id, seq, param_seq[id]); + errno = EBUSY; + return NULL; + } + p = malloc(sizeof(struct param) + SPA_POD_SIZE(param)); if (p == NULL) return NULL; @@ -490,13 +503,21 @@ static void device_event_info(void *object, const struct pw_device_info *info) if (info->params[i].user == 0) continue; + if (id >= SM_MAX_PARAMS) { + pw_log_error(NAME" %p: too big param id %d", impl, id); + continue; + } + device->n_params -= clear_params(&device->param_list, id); if (info->params[i].flags & SPA_PARAM_INFO_READ) { - pw_log_debug(NAME" %p: device %d enum params %d", impl, - device->obj.id, id); - pw_device_enum_params((struct pw_device*)device->obj.proxy, - 1, id, 0, UINT32_MAX, NULL); + int res; + res = pw_device_enum_params((struct pw_device*)device->obj.proxy, + ++device->param_seq[id], id, 0, UINT32_MAX, NULL); + if (SPA_RESULT_IS_ASYNC(res)) + device->param_seq[id] = res; + pw_log_debug(NAME" %p: device %d enum params %d seq:%d", impl, + device->obj.id, id, device->param_seq[id]); } info->params[i].user = 0; } @@ -512,8 +533,8 @@ static void device_event_param(void *object, int seq, struct sm_device *device = object; struct impl *impl = SPA_CONTAINER_OF(device->obj.session, struct impl, this); - pw_log_debug(NAME" %p: device %p param %d index:%d", impl, device, id, index); - if (add_param(&device->param_list, id, param) != NULL) + pw_log_debug(NAME" %p: device %p param %d index:%d seq:%d", impl, device, id, index, seq); + if (add_param(&device->param_list, seq, device->param_seq, id, param) != NULL) device->n_params++; device->obj.avail |= SM_DEVICE_CHANGE_MASK_PARAMS; @@ -591,13 +612,21 @@ static void node_event_info(void *object, const struct pw_node_info *info) if (info->params[i].user == 0) continue; + if (id >= SM_MAX_PARAMS) { + pw_log_error(NAME" %p: too big param id %d", impl, id); + continue; + } + node->n_params -= clear_params(&node->param_list, id); if (info->params[i].flags & SPA_PARAM_INFO_READ) { - pw_log_debug(NAME" %p: node %d enum params %d", impl, - node->obj.id, id); - pw_node_enum_params((struct pw_node*)node->obj.proxy, - 1, id, 0, UINT32_MAX, NULL); + int res; + res = pw_node_enum_params((struct pw_node*)node->obj.proxy, + ++node->param_seq[id], id, 0, UINT32_MAX, NULL); + if (SPA_RESULT_IS_ASYNC(res)) + node->param_seq[id] = res; + pw_log_debug(NAME" %p: node %d enum params %d seq:%d", impl, + node->obj.id, id, node->param_seq[id]); } info->params[i].user = 0; } @@ -613,8 +642,8 @@ static void node_event_param(void *object, int seq, struct sm_node *node = object; struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this); - pw_log_debug(NAME" %p: node %p param %d index:%d", impl, node, id, index); - if (add_param(&node->param_list, id, param) != NULL) + pw_log_debug(NAME" %p: node %p param %d index:%d seq:%d", impl, node, id, index, seq); + if (add_param(&node->param_list, seq, node->param_seq, id, param) != NULL) node->n_params++; node->obj.avail |= SM_NODE_CHANGE_MASK_PARAMS; diff --git a/src/examples/media-session/media-session.h b/src/examples/media-session/media-session.h index edfb13310..7d036288f 100644 --- a/src/examples/media-session/media-session.h +++ b/src/examples/media-session/media-session.h @@ -35,6 +35,8 @@ extern "C" { #define SM_TYPE_MEDIA_SESSION PW_TYPE_INFO_OBJECT_BASE "SessionManager" +#define SM_MAX_PARAMS 32 + struct sm_media_session; struct sm_object_events { @@ -133,6 +135,7 @@ struct sm_device { #define SM_DEVICE_CHANGE_MASK_NODES (SM_OBJECT_CHANGE_MASK_LAST<<2) uint32_t n_params; struct spa_list param_list; /**< list of sm_param */ + int param_seq[SM_MAX_PARAMS]; struct pw_device_info *info; struct spa_list node_list; }; @@ -148,6 +151,7 @@ struct sm_node { #define SM_NODE_CHANGE_MASK_PORTS (SM_OBJECT_CHANGE_MASK_LAST<<2) uint32_t n_params; struct spa_list param_list; /**< list of sm_param */ + int param_seq[SM_MAX_PARAMS]; struct pw_node_info *info; struct spa_list port_list;