mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: Use device set for ASHA
While ASHA does not really use the D-Bus device set interface but since ASHA has a device-wide HiSyncId and needs to handle left and right side via a combine sink, use the device set notion for ASHA as well.
This commit is contained in:
		
							parent
							
								
									1b6830f68f
								
							
						
					
					
						commit
						9586ef891e
					
				
					 2 changed files with 92 additions and 46 deletions
				
			
		| 
						 | 
				
			
			@ -2113,7 +2113,8 @@ static void device_update_set_status(struct spa_bt_device *device, bool force, c
 | 
			
		|||
int spa_bt_device_connect_profile(struct spa_bt_device *device, enum spa_bt_profile profile)
 | 
			
		||||
{
 | 
			
		||||
	device->connected_profiles |= profile;
 | 
			
		||||
	if (profile & SPA_BT_PROFILE_BAP_DUPLEX)
 | 
			
		||||
	if (profile & SPA_BT_PROFILE_BAP_DUPLEX ||
 | 
			
		||||
			profile & SPA_BT_PROFILE_ASHA_SINK)
 | 
			
		||||
		device_update_set_status(device, true, NULL);
 | 
			
		||||
	spa_bt_device_check_profiles(device, false);
 | 
			
		||||
	spa_bt_device_emit_profiles_changed(device, profile);
 | 
			
		||||
| 
						 | 
				
			
			@ -2145,7 +2146,10 @@ static bool device_set_update_leader(struct spa_bt_set_membership *set)
 | 
			
		|||
	 * appear under a specific device.
 | 
			
		||||
	 */
 | 
			
		||||
	spa_bt_for_each_set_member(s, set) {
 | 
			
		||||
		if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_DUPLEX))
 | 
			
		||||
		bool bap_duplex = s->device->connected_profiles & SPA_BT_PROFILE_BAP_DUPLEX;
 | 
			
		||||
		bool is_asha = s->device->connected_profiles & SPA_BT_PROFILE_ASHA_SINK;
 | 
			
		||||
 | 
			
		||||
		if (!bap_duplex && !is_asha)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (leader == NULL || s->rank < leader->rank ||
 | 
			
		||||
| 
						 | 
				
			
			@ -2972,6 +2976,7 @@ void spa_bt_transport_free(struct spa_bt_transport *transport)
 | 
			
		|||
{
 | 
			
		||||
	struct spa_bt_monitor *monitor = transport->monitor;
 | 
			
		||||
	struct spa_bt_device *device = transport->device;
 | 
			
		||||
	char hisyncid[32] = { 0 };
 | 
			
		||||
 | 
			
		||||
	spa_log_debug(monitor->log, "transport %p: free %s", transport, transport->path);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3020,6 +3025,12 @@ void spa_bt_transport_free(struct spa_bt_transport *transport)
 | 
			
		|||
		if (transport->profile & SPA_BT_PROFILE_BAP_DUPLEX)
 | 
			
		||||
			device_update_set_status(device, true, NULL);
 | 
			
		||||
 | 
			
		||||
		if (transport->profile & SPA_BT_PROFILE_ASHA_SINK) {
 | 
			
		||||
			spa_scnprintf(hisyncid, sizeof(hisyncid), "/asha/%" PRIu64, transport->hisyncid);
 | 
			
		||||
			device_update_set_status(device, true, hisyncid);
 | 
			
		||||
			device_remove_device_set(device, hisyncid);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		spa_bt_device_emit_profiles_changed(device, transport->profile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4114,6 +4125,7 @@ static int setup_asha_transport(struct spa_bt_remote_endpoint *remote_endpoint,
 | 
			
		|||
	const struct media_codec * const * const media_codecs = monitor->media_codecs;
 | 
			
		||||
	const struct media_codec *codec = NULL;
 | 
			
		||||
	struct spa_bt_transport *transport;
 | 
			
		||||
	char hisyncid[32] = { 0 };
 | 
			
		||||
	char *tpath;
 | 
			
		||||
 | 
			
		||||
	if (!remote_endpoint->transport_path) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4173,6 +4185,10 @@ static int setup_asha_transport(struct spa_bt_remote_endpoint *remote_endpoint,
 | 
			
		|||
 | 
			
		||||
	transport_sync_volume(transport);
 | 
			
		||||
 | 
			
		||||
	spa_scnprintf(hisyncid, sizeof(hisyncid), "/asha/%" PRIu64, transport->hisyncid);
 | 
			
		||||
	device_add_device_set(transport->device, hisyncid, transport->asha_right_side ? 1 : 0);
 | 
			
		||||
	device_update_set_status(transport->device, true, hisyncid);
 | 
			
		||||
 | 
			
		||||
	const char *side = transport->asha_right_side ? "right" : "left";
 | 
			
		||||
	spa_log_debug(monitor->log, "ASHA transport setup complete for %s side", side);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -684,7 +684,7 @@ static void emit_node(struct impl *this, struct spa_bt_transport *t,
 | 
			
		|||
		items[n_items] = SPA_DICT_ITEM_INIT("api.bluez5.a2dp-duplex", "true");
 | 
			
		||||
		n_items++;
 | 
			
		||||
	}
 | 
			
		||||
	if (in_device_set) {
 | 
			
		||||
	if (in_device_set || t->media_codec->asha) {
 | 
			
		||||
		items[n_items] = SPA_DICT_ITEM_INIT("api.bluez5.set", this->device_set.path);
 | 
			
		||||
		n_items++;
 | 
			
		||||
		items[n_items] = SPA_DICT_ITEM_INIT("api.bluez5.internal", "true");
 | 
			
		||||
| 
						 | 
				
			
			@ -696,14 +696,6 @@ static void emit_node(struct impl *this, struct spa_bt_transport *t,
 | 
			
		|||
		items[n_items] = SPA_DICT_ITEM_INIT("object.path", object_path);
 | 
			
		||||
		n_items++;
 | 
			
		||||
	}
 | 
			
		||||
	if (t->media_codec->asha) {
 | 
			
		||||
		char hisyncid[32] = { 0 };
 | 
			
		||||
		spa_scnprintf(hisyncid, sizeof(hisyncid), "%zd", t->hisyncid);
 | 
			
		||||
		items[n_items] = SPA_DICT_ITEM_INIT("api.bluez5.asha.hisyncid", hisyncid);
 | 
			
		||||
		n_items++;
 | 
			
		||||
		items[n_items] = SPA_DICT_ITEM_INIT("api.bluez5.asha.side", t->asha_right_side ? "right" : "left");
 | 
			
		||||
		n_items++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info = SPA_DEVICE_OBJECT_INFO_INIT();
 | 
			
		||||
	info.type = SPA_TYPE_INTERFACE_Node;
 | 
			
		||||
| 
						 | 
				
			
			@ -1000,6 +992,7 @@ static void device_set_update(struct impl *this, struct device_set *dset)
 | 
			
		|||
	spa_list_for_each(set, membership_list, link) {
 | 
			
		||||
		struct spa_bt_set_membership *s;
 | 
			
		||||
		int num_devices = 0;
 | 
			
		||||
		bool is_asha_member = false;
 | 
			
		||||
 | 
			
		||||
		device_set_clear(this, dset);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,44 +1001,71 @@ static void device_set_update(struct impl *this, struct device_set *dset)
 | 
			
		|||
			bool active = false;
 | 
			
		||||
			uint32_t source_id = DEVICE_ID_SOURCE;
 | 
			
		||||
			uint32_t sink_id = DEVICE_ID_SINK;
 | 
			
		||||
			bool bap_duplex = s->device->connected_profiles & SPA_BT_PROFILE_BAP_DUPLEX;
 | 
			
		||||
			bool is_asha = s->device->connected_profiles & SPA_BT_PROFILE_ASHA_SINK;
 | 
			
		||||
 | 
			
		||||
			if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_DUPLEX))
 | 
			
		||||
			if (!bap_duplex && !is_asha)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			spa_list_for_each(t, &s->device->transport_list, device_link) {
 | 
			
		||||
				if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE))
 | 
			
		||||
					continue;
 | 
			
		||||
				if (!transport_enabled(t, SPA_BT_PROFILE_BAP_SOURCE))
 | 
			
		||||
					continue;
 | 
			
		||||
				if (dset->sources >= SPA_N_ELEMENTS(dset->source))
 | 
			
		||||
					break;
 | 
			
		||||
			if (is_asha) {
 | 
			
		||||
				spa_list_for_each(t, &s->device->transport_list, device_link) {
 | 
			
		||||
					if (!(s->device->connected_profiles & SPA_BT_PROFILE_ASHA_SINK))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (!transport_enabled(t, SPA_BT_PROFILE_ASHA_SINK))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (dset->sinks >= SPA_N_ELEMENTS(dset->sink))
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
				active = true;
 | 
			
		||||
				dset->source[dset->sources].impl = this;
 | 
			
		||||
				dset->source[dset->sources].transport = t;
 | 
			
		||||
				dset->source[dset->sources].id = source_id;
 | 
			
		||||
				source_id += 2;
 | 
			
		||||
				spa_bt_transport_add_listener(t, &dset->source[dset->sources].listener,
 | 
			
		||||
						&device_set_transport_events, &dset->source[dset->sources]);
 | 
			
		||||
				++dset->sources;
 | 
			
		||||
					active = true;
 | 
			
		||||
					is_asha_member = true;
 | 
			
		||||
					dset->leader = set->leader = t->asha_right_side;
 | 
			
		||||
					dset->path = strdup(set->path);
 | 
			
		||||
					dset->sink[dset->sinks].impl = this;
 | 
			
		||||
					dset->sink[dset->sinks].transport = t;
 | 
			
		||||
					dset->sink[dset->sinks].id = sink_id;
 | 
			
		||||
					sink_id += 2;
 | 
			
		||||
					spa_bt_transport_add_listener(t, &dset->sink[dset->sinks].listener,
 | 
			
		||||
							&device_set_transport_events, &dset->sink[dset->sinks]);
 | 
			
		||||
					++dset->sinks;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			spa_list_for_each(t, &s->device->transport_list, device_link) {
 | 
			
		||||
				if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_SINK))
 | 
			
		||||
					continue;
 | 
			
		||||
				if (!transport_enabled(t, SPA_BT_PROFILE_BAP_SINK))
 | 
			
		||||
					continue;
 | 
			
		||||
				if (dset->sinks >= SPA_N_ELEMENTS(dset->sink))
 | 
			
		||||
					break;
 | 
			
		||||
			if (bap_duplex) {
 | 
			
		||||
				spa_list_for_each(t, &s->device->transport_list, device_link) {
 | 
			
		||||
					if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (!transport_enabled(t, SPA_BT_PROFILE_BAP_SOURCE))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (dset->sources >= SPA_N_ELEMENTS(dset->source))
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
				active = true;
 | 
			
		||||
				dset->sink[dset->sinks].impl = this;
 | 
			
		||||
				dset->sink[dset->sinks].transport = t;
 | 
			
		||||
				dset->sink[dset->sinks].id = sink_id;
 | 
			
		||||
				sink_id += 2;
 | 
			
		||||
				spa_bt_transport_add_listener(t, &dset->sink[dset->sinks].listener,
 | 
			
		||||
						&device_set_transport_events, &dset->sink[dset->sinks]);
 | 
			
		||||
				++dset->sinks;
 | 
			
		||||
					active = true;
 | 
			
		||||
					dset->source[dset->sources].impl = this;
 | 
			
		||||
					dset->source[dset->sources].transport = t;
 | 
			
		||||
					dset->source[dset->sources].id = source_id;
 | 
			
		||||
					source_id += 2;
 | 
			
		||||
					spa_bt_transport_add_listener(t, &dset->source[dset->sources].listener,
 | 
			
		||||
							&device_set_transport_events, &dset->source[dset->sources]);
 | 
			
		||||
					++dset->sources;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				spa_list_for_each(t, &s->device->transport_list, device_link) {
 | 
			
		||||
					if (!(s->device->connected_profiles & SPA_BT_PROFILE_BAP_SINK))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (!transport_enabled(t, SPA_BT_PROFILE_BAP_SINK))
 | 
			
		||||
						continue;
 | 
			
		||||
					if (dset->sinks >= SPA_N_ELEMENTS(dset->sink))
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
					active = true;
 | 
			
		||||
					dset->sink[dset->sinks].impl = this;
 | 
			
		||||
					dset->sink[dset->sinks].transport = t;
 | 
			
		||||
					dset->sink[dset->sinks].id = sink_id;
 | 
			
		||||
					sink_id += 2;
 | 
			
		||||
					spa_bt_transport_add_listener(t, &dset->sink[dset->sinks].listener,
 | 
			
		||||
							&device_set_transport_events, &dset->sink[dset->sinks]);
 | 
			
		||||
					++dset->sinks;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (active)
 | 
			
		||||
| 
						 | 
				
			
			@ -1062,8 +1082,10 @@ static void device_set_update(struct impl *this, struct device_set *dset)
 | 
			
		|||
			/* XXX: device set nodes for BAP server not supported,
 | 
			
		||||
			 * XXX: it'll appear as multiple streams
 | 
			
		||||
			 */
 | 
			
		||||
			dset->path = NULL;
 | 
			
		||||
			dset->leader = false;
 | 
			
		||||
			if (!is_asha_member) {
 | 
			
		||||
				dset->path = NULL;
 | 
			
		||||
				dset->leader = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (num_devices > 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -1126,10 +1148,13 @@ static int emit_nodes(struct impl *this)
 | 
			
		|||
		break;
 | 
			
		||||
	case DEVICE_PROFILE_ASHA:
 | 
			
		||||
		if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_ASHA_SINK) {
 | 
			
		||||
			struct device_set *set = &this->device_set;
 | 
			
		||||
			t = find_transport(this, SPA_BT_PROFILE_ASHA_SINK);
 | 
			
		||||
			if (t) {
 | 
			
		||||
				this->props.codec = t->media_codec->id;
 | 
			
		||||
				emit_node(this, t, DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false);
 | 
			
		||||
				if (set->sink_enabled && set->leader)
 | 
			
		||||
					emit_device_set_node(this, DEVICE_ID_SINK_SET);
 | 
			
		||||
			} else {
 | 
			
		||||
				spa_log_warn(this->log, "Unable to find transport for ASHA");
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1409,7 +1434,8 @@ static bool device_set_needs_update(struct impl *this)
 | 
			
		|||
	struct device_set dset = { .impl = this };
 | 
			
		||||
	bool changed;
 | 
			
		||||
 | 
			
		||||
	if (this->profile != DEVICE_PROFILE_BAP)
 | 
			
		||||
	if (this->profile != DEVICE_PROFILE_BAP &&
 | 
			
		||||
			this->profile != DEVICE_PROFILE_ASHA)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	device_set_update(this, &dset);
 | 
			
		||||
| 
						 | 
				
			
			@ -1490,7 +1516,8 @@ static void device_set_changed(void *userdata)
 | 
			
		|||
{
 | 
			
		||||
	struct impl *this = userdata;
 | 
			
		||||
 | 
			
		||||
	if (this->profile != DEVICE_PROFILE_BAP)
 | 
			
		||||
	if (this->profile != DEVICE_PROFILE_BAP &&
 | 
			
		||||
			this->profile != DEVICE_PROFILE_ASHA)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (!device_set_needs_update(this)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1851,6 +1878,9 @@ static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *
 | 
			
		|||
		n_sink++;
 | 
			
		||||
		priority = 1;
 | 
			
		||||
 | 
			
		||||
		if (this->device_set.sink_enabled)
 | 
			
		||||
			n_sink = this->device_set.leader ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case DEVICE_PROFILE_A2DP:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue