diff --git a/spa/plugins/bluez5/a2dp-sink.c b/spa/plugins/bluez5/a2dp-sink.c index 0ae359244..ba05e36d6 100644 --- a/spa/plugins/bluez5/a2dp-sink.c +++ b/spa/plugins/bluez5/a2dp-sink.c @@ -308,7 +308,27 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) return 0; } -static void emit_node_props_changed(struct impl *this); +static void emit_node_info(struct impl *this, bool full); + +static int apply_props(struct impl *this, const struct spa_pod *param) +{ + struct props new_props = this->props; + int changed = 0; + + if (param == NULL) { + reset_props(&new_props); + } else { + spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), + SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency), + SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&new_props.latency_offset)); + } + + changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); + this->props = new_props; + return changed; +} static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) @@ -320,19 +340,11 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_Props: { - struct props *p = &this->props; - - if (param == NULL) { - reset_props(p); - emit_node_props_changed(this); - return 0; + if (apply_props(this, param) > 0) { + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; + emit_node_info(this, false); } - if (spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency), - SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&p->latency_offset)) > 0) - emit_node_props_changed(this); break; } default: @@ -869,13 +881,6 @@ static void emit_port_info(struct impl *this, struct port *port, bool full) } } -static void emit_node_props_changed(struct impl *this) -{ - this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; - this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; - emit_node_info(this, false); -} - static int impl_node_add_listener(void *object, struct spa_hook *listener, diff --git a/spa/plugins/bluez5/a2dp-source.c b/spa/plugins/bluez5/a2dp-source.c index 86e4d0fa1..49a589ee8 100644 --- a/spa/plugins/bluez5/a2dp-source.c +++ b/spa/plugins/bluez5/a2dp-source.c @@ -262,6 +262,27 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) return 0; } +static void emit_node_info(struct impl *this, bool full); + +static int apply_props(struct impl *this, const struct spa_pod *param) +{ + struct props new_props = this->props; + int changed = 0; + + if (param == NULL) { + reset_props(&new_props); + } else { + spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), + SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency)); + } + + changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); + this->props = new_props; + return changed; +} + static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -272,16 +293,11 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_Props: { - struct props *p = &this->props; - - if (param == NULL) { - reset_props(p); - return 0; + if (apply_props(this, param) > 0) { + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; + emit_node_info(this, false); } - spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency)); break; } default: diff --git a/spa/plugins/bluez5/bluez5-device.c b/spa/plugins/bluez5/bluez5-device.c index 089532ca3..ac9f4d132 100644 --- a/spa/plugins/bluez5/bluez5-device.c +++ b/spa/plugins/bluez5/bluez5-device.c @@ -919,14 +919,18 @@ static int node_set_volume(struct impl *this, struct node *node, float volumes[] struct spa_pod_builder b = { 0 }; struct spa_pod_frame f[1]; uint32_t i; + int changed = 0; if (n_volumes == 0) return -EINVAL; spa_log_info(this->log, "node %p volume %f", node, volumes[0]); - for (i = 0; i < node->n_channels; i++) + for (i = 0; i < node->n_channels; i++) { + if (node->volumes[i] != volumes[i % n_volumes]) + ++changed; node->volumes[i] = volumes[i % n_volumes]; + } spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_push_object(&b, &f[0], @@ -944,7 +948,7 @@ static int node_set_volume(struct impl *this, struct node *node, float volumes[] spa_device_emit_event(&this->hooks, event); - return 0; + return changed; } static int node_set_mute(struct impl *this, struct node *node, bool mute) @@ -953,8 +957,11 @@ static int node_set_mute(struct impl *this, struct node *node, bool mute) uint8_t buffer[4096]; struct spa_pod_builder b = { 0 }; struct spa_pod_frame f[1]; + int changed = 0; spa_log_info(this->log, "node %p mute %d", node, mute); + + changed = (node->mute != mute); node->mute = mute; spa_pod_builder_init(&b, buffer, sizeof(buffer)); @@ -971,7 +978,7 @@ static int node_set_mute(struct impl *this, struct node *node, bool mute) spa_device_emit_event(&this->hooks, event); - return 0; + return changed; } static int node_set_latency_offset(struct impl *this, struct node *node, int64_t latency_offset) @@ -980,8 +987,11 @@ static int node_set_latency_offset(struct impl *this, struct node *node, int64_t uint8_t buffer[4096]; struct spa_pod_builder b = { 0 }; struct spa_pod_frame f[1]; + int changed = 0; spa_log_info(this->log, "node %p latency offset %"PRIi64" nsec", node, latency_offset); + + changed = (node->latency_offset != latency_offset); node->latency_offset = latency_offset; spa_pod_builder_init(&b, buffer, sizeof(buffer)); @@ -998,7 +1008,7 @@ static int node_set_latency_offset(struct impl *this, struct node *node, int64_t spa_device_emit_event(&this->hooks, event); - return 0; + return changed; } static int apply_device_props(struct impl *this, struct node *node, struct spa_pod *props) @@ -1010,7 +1020,7 @@ static int apply_device_props(struct impl *this, struct node *node, struct spa_p int changed = 0; float volumes[SPA_AUDIO_MAX_CHANNELS]; uint32_t channels[SPA_AUDIO_MAX_CHANNELS]; - uint32_t n_volumes = 0, n_channels = 0; + uint32_t n_volumes = 0, SPA_UNUSED n_channels = 0; int64_t latency_offset = 0; if (!spa_pod_is_object_type(props, SPA_TYPE_OBJECT_Props)) @@ -1020,37 +1030,39 @@ static int apply_device_props(struct impl *this, struct node *node, struct spa_p switch (prop->key) { case SPA_PROP_volume: if (spa_pod_get_float(&prop->value, &volume) == 0) { - node_set_volume(this, node, &volume, 1); - changed++; + int res = node_set_volume(this, node, &volume, 1); + if (res > 0) + ++changed; } break; case SPA_PROP_mute: if (spa_pod_get_bool(&prop->value, &mute) == 0) { - node_set_mute(this, node, mute); - changed++; + int res = node_set_mute(this, node, mute); + if (res > 0) + ++changed; } break; case SPA_PROP_channelVolumes: - if ((n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { - changed++; - } + n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, + volumes, SPA_AUDIO_MAX_CHANNELS); break; case SPA_PROP_channelMap: - if ((n_channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, - channels, SPA_AUDIO_MAX_CHANNELS)) > 0) { - changed++; - } + n_channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, + channels, SPA_AUDIO_MAX_CHANNELS); break; case SPA_PROP_latencyOffsetNsec: if (spa_pod_get_long(&prop->value, &latency_offset) == 0) { - node_set_latency_offset(this, node, latency_offset); - changed++; + int res = node_set_latency_offset(this, node, latency_offset); + if (res > 0) + ++changed; } } } - if (n_volumes > 0) - node_set_volume(this, node, volumes, n_volumes); + if (n_volumes > 0) { + int res = node_set_volume(this, node, volumes, n_volumes); + if (res > 0) + ++changed; + } return changed; } @@ -1108,9 +1120,11 @@ static int impl_set_param(void *object, node = &this->nodes[device]; if (props) { - apply_device_props(this, node, props); - this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS; - this->params[IDX_Route].flags ^= SPA_PARAM_INFO_SERIAL; + int changed = apply_device_props(this, node, props); + if (changed > 0) { + this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS; + this->params[IDX_Route].flags ^= SPA_PARAM_INFO_SERIAL; + } emit_info(this, false); } break; diff --git a/spa/plugins/bluez5/sco-sink.c b/spa/plugins/bluez5/sco-sink.c index 0bcf6b6f7..4f2dee5ef 100644 --- a/spa/plugins/bluez5/sco-sink.c +++ b/spa/plugins/bluez5/sco-sink.c @@ -279,6 +279,27 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) return 0; } +static void emit_node_info(struct impl *this, bool full); + +static int apply_props(struct impl *this, const struct spa_pod *param) +{ + struct props new_props = this->props; + int changed = 0; + + if (param == NULL) { + reset_props(&new_props); + } else { + spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), + SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency)); + } + + changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); + this->props = new_props; + return changed; +} + static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -289,16 +310,11 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_Props: { - struct props *p = &this->props; - - if (param == NULL) { - reset_props(p); - return 0; + if (apply_props(this, param) > 0) { + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; + emit_node_info(this, false); } - spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency)); break; } default: diff --git a/spa/plugins/bluez5/sco-source.c b/spa/plugins/bluez5/sco-source.c index 338b81422..36f0d474e 100644 --- a/spa/plugins/bluez5/sco-source.c +++ b/spa/plugins/bluez5/sco-source.c @@ -236,6 +236,27 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) return 0; } +static void emit_node_info(struct impl *this, bool full); + +static int apply_props(struct impl *this, const struct spa_pod *param) +{ + struct props new_props = this->props; + int changed = 0; + + if (param == NULL) { + reset_props(&new_props); + } else { + spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency), + SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency)); + } + + changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0); + this->props = new_props; + return changed; +} + static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -246,16 +267,11 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_Props: { - struct props *p = &this->props; - - if (param == NULL) { - reset_props(p); - return 0; + if (apply_props(this, param) > 0) { + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; + emit_node_info(this, false); } - spa_pod_parse_object(param, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency)); break; } default: