mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-10-29 05:40:27 -04: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
	
	 Sanchayan Maity
						Sanchayan Maity