From e74e7b938e19d9c8a443bbd8298db44ae1b30062 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 25 Nov 2024 20:54:07 +0200 Subject: [PATCH] bluez5: don't re-emit nodes on device set events if unchanged Only re-emit nodes on BAP device set changes, if our configuration actually needs to be changed. --- spa/plugins/bluez5/bluez5-device.c | 40 ++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/spa/plugins/bluez5/bluez5-device.c b/spa/plugins/bluez5/bluez5-device.c index f376803f0..9f6872b51 100644 --- a/spa/plugins/bluez5/bluez5-device.c +++ b/spa/plugins/bluez5/bluez5-device.c @@ -923,9 +923,8 @@ static void remove_dynamic_node(struct dynamic_node *this) this->factory_name = NULL; } -static void device_set_clear(struct impl *impl) +static void device_set_clear(struct impl *impl, struct device_set *set) { - struct device_set *set = &impl->device_set; unsigned int i; for (i = 0; i < SPA_N_ELEMENTS(set->sink); ++i) @@ -959,10 +958,9 @@ static const struct spa_bt_transport_events device_set_transport_events = { .destroy = device_set_transport_destroy, }; -static void device_set_update(struct impl *this) +static void device_set_update(struct impl *this, struct device_set *dset) { struct spa_bt_device *device = this->bt_dev; - struct device_set *dset = &this->device_set; struct spa_bt_set_membership *set; struct spa_bt_set_membership tmp_set = { .device = device, @@ -987,7 +985,7 @@ static void device_set_update(struct impl *this) struct spa_bt_set_membership *s; int num_devices = 0; - device_set_clear(this); + device_set_clear(this, dset); spa_bt_for_each_set_member(s, set) { struct spa_bt_transport *t; @@ -1060,13 +1058,30 @@ static void device_set_update(struct impl *this) dset->source_enabled = dset->path && (dset->sources > 1); } +static bool device_set_equal(struct device_set *a, struct device_set *b) +{ + unsigned int i; + + if (!spa_streq(a->path, b->path) || a->sink_enabled != b->sink_enabled || + a->source_enabled != b->source_enabled || a->leader != b->leader || + a->sinks != b->sinks || a->sources != b->sources) + return false; + for (i = 0; i < a->sinks; ++i) + if (a->sink[i].transport != b->sink[i].transport) + return false; + for (i = 0; i < a->sources; ++i) + if (a->source[i].transport != b->source[i].transport) + return false; + return true; +} + static int emit_nodes(struct impl *this) { struct spa_bt_transport *t; this->props.codec = 0; - device_set_update(this); + device_set_update(this, &this->device_set); switch (this->profile) { case DEVICE_PROFILE_OFF: @@ -1426,10 +1441,21 @@ static void profiles_changed(void *userdata, uint32_t prev_profiles, uint32_t pr static void device_set_changed(void *userdata) { struct impl *this = userdata; + struct device_set dset = { .impl = this }; + bool changed; if (this->profile != DEVICE_PROFILE_BAP) return; + device_set_update(this, &dset); + changed = !device_set_equal(&dset, &this->device_set); + device_set_clear(this, &dset); + + if (!changed) { + spa_log_debug(this->log, "%p: device set not changed", this); + return; + } + spa_log_debug(this->log, "%p: device set changed", this); emit_remove_nodes(this); @@ -2784,7 +2810,7 @@ static int impl_clear(struct spa_handle *handle) free((void *)it->value); } - device_set_clear(this); + device_set_clear(this, &this->device_set); return 0; }