mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: replace sco-source with media-source
Change media-source to use sco-io for HFP codecs. Replace sco-source with media-source. sco-source is mostly copypaste from media-source, only differed in the IO handling.
This commit is contained in:
		
							parent
							
								
									5b4e9dc33e
								
							
						
					
					
						commit
						665a27f281
					
				
					 3 changed files with 139 additions and 1615 deletions
				
			
		| 
						 | 
					@ -133,6 +133,7 @@ struct impl {
 | 
				
			||||||
	unsigned int following:1;
 | 
						unsigned int following:1;
 | 
				
			||||||
	unsigned int matching:1;
 | 
						unsigned int matching:1;
 | 
				
			||||||
	unsigned int resampling:1;
 | 
						unsigned int resampling:1;
 | 
				
			||||||
 | 
						unsigned int io_error:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned int is_input:1;
 | 
						unsigned int is_input:1;
 | 
				
			||||||
	unsigned int is_duplex:1;
 | 
						unsigned int is_duplex:1;
 | 
				
			||||||
| 
						 | 
					@ -460,6 +461,8 @@ static int32_t decode_data(struct impl *this, uint8_t *src, uint32_t src_size,
 | 
				
			||||||
				src, src_size, NULL, NULL)) < 0)
 | 
									src, src_size, NULL, NULL)) < 0)
 | 
				
			||||||
		return processed;
 | 
							return processed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TODO: check seqnum and handle PLC */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	src += processed;
 | 
						src += processed;
 | 
				
			||||||
	src_size -= processed;
 | 
						src_size -= processed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -573,12 +576,65 @@ static void media_on_ready_read(struct spa_source *source)
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
stop:
 | 
					stop:
 | 
				
			||||||
 | 
						this->io_error = true;
 | 
				
			||||||
	if (this->source.loop)
 | 
						if (this->source.loop)
 | 
				
			||||||
		spa_loop_remove_source(this->data_loop, &this->source);
 | 
							spa_loop_remove_source(this->data_loop, &this->source);
 | 
				
			||||||
	if (this->transport && this->transport->iso_io)
 | 
						if (this->transport && this->transport->iso_io)
 | 
				
			||||||
		spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
							spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int media_sco_pull(void *userdata, uint8_t *buffer_read, int size_read, uint64_t now)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct impl *this = userdata;
 | 
				
			||||||
 | 
						struct port *port = &this->port;
 | 
				
			||||||
 | 
						void *buf;
 | 
				
			||||||
 | 
						int32_t decoded;
 | 
				
			||||||
 | 
						uint32_t avail;
 | 
				
			||||||
 | 
						uint64_t dt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->transport == NULL) {
 | 
				
			||||||
 | 
							spa_log_debug(this->log, "no transport, stop reading");
 | 
				
			||||||
 | 
							goto stop;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (size_read == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* decode to buffer */
 | 
				
			||||||
 | 
						buf = spa_bt_decode_buffer_get_write(&port->buffer, &avail);
 | 
				
			||||||
 | 
						spa_log_trace(this->log, "read socket data size:%d, avail:%d", size_read, avail);
 | 
				
			||||||
 | 
						decoded = decode_data(this, buffer_read, size_read, buf, avail);
 | 
				
			||||||
 | 
						if (decoded < 0) {
 | 
				
			||||||
 | 
							spa_log_debug(this->log, "failed to decode data: %d", decoded);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (decoded == 0) {
 | 
				
			||||||
 | 
							spa_log_trace(this->log, "no decoded socket data");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* discard when not started */
 | 
				
			||||||
 | 
						if (!this->started)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_bt_decode_buffer_write_packet(&port->buffer, decoded, now);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dt = now - this->now;
 | 
				
			||||||
 | 
						this->now = now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_log_trace(this->log, "decoded socket data size:%d frames:%d dt:%d dms",
 | 
				
			||||||
 | 
								(int)decoded, (int)decoded/port->frame_size,
 | 
				
			||||||
 | 
								(int)(dt / 100000));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stop:
 | 
				
			||||||
 | 
						this->io_error = true;
 | 
				
			||||||
 | 
						if (this->transport && this->transport->sco_io)
 | 
				
			||||||
 | 
							spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL);
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int setup_matching(struct impl *this)
 | 
					static int setup_matching(struct impl *this)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct port *port = &this->port;
 | 
						struct port *port = &this->port;
 | 
				
			||||||
| 
						 | 
					@ -715,12 +771,15 @@ static void update_delay_event(void *data, uint64_t count)
 | 
				
			||||||
	update_transport_delay(data);
 | 
						update_transport_delay(data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int do_start_iso_io(struct spa_loop *loop, bool async, uint32_t seq,
 | 
					static int do_start_sco_iso_io(struct spa_loop *loop, bool async, uint32_t seq,
 | 
				
			||||||
		const void *data, size_t size, void *user_data)
 | 
							const void *data, size_t size, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *this = user_data;
 | 
						struct impl *this = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_bt_iso_io_set_cb(this->transport->iso_io, media_iso_pull, this);
 | 
						if (this->transport->sco_io)
 | 
				
			||||||
 | 
							spa_bt_sco_io_set_source_cb(this->transport->sco_io, media_sco_pull, this);
 | 
				
			||||||
 | 
						if (this->transport->iso_io)
 | 
				
			||||||
 | 
							spa_bt_iso_io_set_cb(this->transport->iso_io, media_iso_pull, this);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -767,8 +826,6 @@ static int transport_start(struct impl *this)
 | 
				
			||||||
	if (setsockopt(this->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
 | 
						if (setsockopt(this->fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
 | 
				
			||||||
		spa_log_warn(this->log, "SO_PRIORITY failed: %m");
 | 
							spa_log_warn(this->log, "SO_PRIORITY failed: %m");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_bt_recvmsg_init(&this->recv, this->fd, this->data_system, this->log);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	reset_buffers(port);
 | 
						reset_buffers(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_bt_decode_buffer_clear(&port->buffer);
 | 
						spa_bt_decode_buffer_clear(&port->buffer);
 | 
				
			||||||
| 
						 | 
					@ -777,7 +834,11 @@ static int transport_start(struct impl *this)
 | 
				
			||||||
			this->quantum_limit, this->quantum_limit)) < 0)
 | 
								this->quantum_limit, this->quantum_limit)) < 0)
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->is_duplex) {
 | 
						if (this->codec->kind == MEDIA_CODEC_HFP) {
 | 
				
			||||||
 | 
							/* 40 ms max buffer (on top of duration) */
 | 
				
			||||||
 | 
							spa_bt_decode_buffer_set_max_extra_latency(&port->buffer,
 | 
				
			||||||
 | 
									port->current_format.info.raw.rate * 40 / 1000);
 | 
				
			||||||
 | 
						} else if (this->is_duplex) {
 | 
				
			||||||
		/* 80 ms max extra buffer */
 | 
							/* 80 ms max extra buffer */
 | 
				
			||||||
		spa_bt_decode_buffer_set_max_extra_latency(&port->buffer,
 | 
							spa_bt_decode_buffer_set_max_extra_latency(&port->buffer,
 | 
				
			||||||
				port->current_format.info.raw.rate * 80 / 1000);
 | 
									port->current_format.info.raw.rate * 80 / 1000);
 | 
				
			||||||
| 
						 | 
					@ -790,22 +851,39 @@ static int transport_start(struct impl *this)
 | 
				
			||||||
	this->sample_count = 0;
 | 
						this->sample_count = 0;
 | 
				
			||||||
	this->errqueue_count = 0;
 | 
						this->errqueue_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->source.data = this;
 | 
						this->io_error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->source.fd = this->fd;
 | 
						if (this->codec->kind != MEDIA_CODEC_HFP) {
 | 
				
			||||||
	this->source.func = media_on_ready_read;
 | 
							spa_bt_recvmsg_init(&this->recv, this->fd, this->data_system, this->log);
 | 
				
			||||||
	this->source.mask = SPA_IO_IN;
 | 
					 | 
				
			||||||
	this->source.rmask = 0;
 | 
					 | 
				
			||||||
	if ((res = spa_loop_add_source(this->data_loop, &this->source)) < 0)
 | 
					 | 
				
			||||||
		spa_log_error(this->log, "%p: failed to add poll source: %s", this,
 | 
					 | 
				
			||||||
				spa_strerror(res));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->transport->iso_io)
 | 
							this->source.data = this;
 | 
				
			||||||
		spa_loop_locked(this->data_loop, do_start_iso_io, 0, NULL, 0, this);
 | 
					
 | 
				
			||||||
 | 
							this->source.fd = this->fd;
 | 
				
			||||||
 | 
							this->source.func = media_on_ready_read;
 | 
				
			||||||
 | 
							this->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
							this->source.rmask = 0;
 | 
				
			||||||
 | 
							if ((res = spa_loop_add_source(this->data_loop, &this->source)) < 0)
 | 
				
			||||||
 | 
								spa_log_error(this->log, "%p: failed to add poll source: %s", this,
 | 
				
			||||||
 | 
										spa_strerror(res));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							spa_zero(this->source);
 | 
				
			||||||
 | 
							if (spa_bt_transport_ensure_sco_io(this->transport, this->data_loop, this->data_system) < 0)
 | 
				
			||||||
 | 
								goto fail;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->transport->iso_io || this->transport->sco_io)
 | 
				
			||||||
 | 
							spa_loop_locked(this->data_loop, do_start_sco_iso_io, 0, NULL, 0, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->transport_started = true;
 | 
						this->transport_started = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
						if (this->codec_data) {
 | 
				
			||||||
 | 
							this->codec->deinit(this->codec_data);
 | 
				
			||||||
 | 
							this->codec_data = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -EIO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int do_start(struct impl *this)
 | 
					static int do_start(struct impl *this)
 | 
				
			||||||
| 
						 | 
					@ -825,7 +903,9 @@ static int do_start(struct impl *this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_debug(this->log, "%p: transport %p acquire", this,
 | 
						spa_log_debug(this->log, "%p: transport %p acquire", this,
 | 
				
			||||||
			this->transport);
 | 
								this->transport);
 | 
				
			||||||
	if ((res = spa_bt_transport_acquire(this->transport, false)) < 0) {
 | 
					
 | 
				
			||||||
 | 
						bool do_accept = (this->transport->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY);
 | 
				
			||||||
 | 
						if ((res = spa_bt_transport_acquire(this->transport, do_accept)) < 0) {
 | 
				
			||||||
		this->start_ready = false;
 | 
							this->start_ready = false;
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -861,6 +941,8 @@ static int do_remove_source(struct spa_loop *loop,
 | 
				
			||||||
		spa_loop_remove_source(this->data_loop, &this->timer_source);
 | 
							spa_loop_remove_source(this->data_loop, &this->timer_source);
 | 
				
			||||||
	if (this->transport && this->transport->iso_io)
 | 
						if (this->transport && this->transport->iso_io)
 | 
				
			||||||
		spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
							spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
				
			||||||
 | 
						if (this->transport && this->transport->sco_io)
 | 
				
			||||||
 | 
							spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL);
 | 
				
			||||||
	set_timeout(this, 0);
 | 
						set_timeout(this, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->update_delay_event) {
 | 
						if (this->update_delay_event) {
 | 
				
			||||||
| 
						 | 
					@ -888,6 +970,8 @@ static int do_remove_transport_source(struct spa_loop *loop,
 | 
				
			||||||
		spa_loop_remove_source(this->data_loop, &this->source);
 | 
							spa_loop_remove_source(this->data_loop, &this->source);
 | 
				
			||||||
	if (this->transport->iso_io)
 | 
						if (this->transport->iso_io)
 | 
				
			||||||
		spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
							spa_bt_iso_io_set_cb(this->transport->iso_io, NULL, NULL);
 | 
				
			||||||
 | 
						if (this->transport->sco_io)
 | 
				
			||||||
 | 
							spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -978,6 +1062,7 @@ static void emit_node_info(struct impl *this, bool full)
 | 
				
			||||||
	char latency[64];
 | 
						char latency[64];
 | 
				
			||||||
	char rate[64];
 | 
						char rate[64];
 | 
				
			||||||
	char media_name[256];
 | 
						char media_name[256];
 | 
				
			||||||
 | 
						const char *media_role = NULL;
 | 
				
			||||||
	struct port *port = &this->port;
 | 
						struct port *port = &this->port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_scnprintf(
 | 
						spa_scnprintf(
 | 
				
			||||||
| 
						 | 
					@ -989,6 +1074,10 @@ static void emit_node_info(struct impl *this, bool full)
 | 
				
			||||||
		this->codec->description
 | 
							this->codec->description
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!this->is_input && this->transport &&
 | 
				
			||||||
 | 
								(this->transport->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY))
 | 
				
			||||||
 | 
							media_role = "Communication";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_dict_item node_info_items[] = {
 | 
						struct spa_dict_item node_info_items[] = {
 | 
				
			||||||
		{ SPA_KEY_DEVICE_API, "bluez5" },
 | 
							{ SPA_KEY_DEVICE_API, "bluez5" },
 | 
				
			||||||
		{ SPA_KEY_MEDIA_CLASS, this->is_internal ? "Audio/Source/Internal" :
 | 
							{ SPA_KEY_MEDIA_CLASS, this->is_internal ? "Audio/Source/Internal" :
 | 
				
			||||||
| 
						 | 
					@ -997,6 +1086,7 @@ static void emit_node_info(struct impl *this, bool full)
 | 
				
			||||||
		{ "media.name", media_name },
 | 
							{ "media.name", media_name },
 | 
				
			||||||
		{ "node.rate", this->is_input ? "" : rate },
 | 
							{ "node.rate", this->is_input ? "" : rate },
 | 
				
			||||||
		{ SPA_KEY_NODE_DRIVER, this->is_input ? "true" : "false" },
 | 
							{ SPA_KEY_NODE_DRIVER, this->is_input ? "true" : "false" },
 | 
				
			||||||
 | 
							{ SPA_KEY_MEDIA_ROLE, media_role },
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_scnprintf(latency, sizeof(latency), "%u/%u", this->node_latency, port->current_format.info.raw.rate);
 | 
						spa_scnprintf(latency, sizeof(latency), "%u/%u", this->node_latency, port->current_format.info.raw.rate);
 | 
				
			||||||
| 
						 | 
					@ -1251,7 +1341,8 @@ static int port_set_format(struct impl *this, struct port *port,
 | 
				
			||||||
		port->frame_size = info.info.raw.channels;
 | 
							port->frame_size = info.info.raw.channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (info.info.raw.format) {
 | 
							switch (info.info.raw.format) {
 | 
				
			||||||
		case SPA_AUDIO_FORMAT_S16:
 | 
							case SPA_AUDIO_FORMAT_S16_LE:
 | 
				
			||||||
 | 
							case SPA_AUDIO_FORMAT_S16_BE:
 | 
				
			||||||
			port->frame_size *= 2;
 | 
								port->frame_size *= 2;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SPA_AUDIO_FORMAT_S24:
 | 
							case SPA_AUDIO_FORMAT_S24:
 | 
				
			||||||
| 
						 | 
					@ -1562,7 +1653,10 @@ static void process_buffering(struct impl *this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memcpy(datas[0].data, buf, avail);
 | 
							memcpy(datas[0].data, buf, avail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* pad with silence */
 | 
							/* pad with silence
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * TODO: should do PLC instead
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		if (avail < data_size)
 | 
							if (avail < data_size)
 | 
				
			||||||
			memset(SPA_PTROFF(datas[0].data, avail, void), 0, data_size - avail);
 | 
								memset(SPA_PTROFF(datas[0].data, avail, void), 0, data_size - avail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1611,7 +1705,7 @@ static int produce_buffer(struct impl *this)
 | 
				
			||||||
		io->buffer_id = SPA_ID_INVALID;
 | 
							io->buffer_id = SPA_ID_INVALID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->transport_started && !this->source.loop) {
 | 
						if (this->io_error) {
 | 
				
			||||||
		io->status = -EIO;
 | 
							io->status = -EIO;
 | 
				
			||||||
		return SPA_STATUS_STOPPED;
 | 
							return SPA_STATUS_STOPPED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1875,19 +1969,8 @@ impl_init(const struct spa_handle_factory *factory,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->quantum_limit = 8192;
 | 
						this->quantum_limit = 8192;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (info != NULL) {
 | 
						if (info && (str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_TRANSPORT)) != NULL)
 | 
				
			||||||
		if (info && (str = spa_dict_lookup(info, "clock.quantum-limit")))
 | 
							sscanf(str, "pointer:%p", &this->transport);
 | 
				
			||||||
			spa_atou32(str, &this->quantum_limit, 0);
 | 
					 | 
				
			||||||
		if ((str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_TRANSPORT)) != NULL)
 | 
					 | 
				
			||||||
			sscanf(str, "pointer:%p", &this->transport);
 | 
					 | 
				
			||||||
		if ((str = spa_dict_lookup(info, "bluez5.media-source-role")) != NULL)
 | 
					 | 
				
			||||||
			this->is_input = spa_streq(str, "input");
 | 
					 | 
				
			||||||
		if ((str = spa_dict_lookup(info, "api.bluez5.a2dp-duplex")) != NULL)
 | 
					 | 
				
			||||||
			this->is_duplex = spa_atob(str);
 | 
					 | 
				
			||||||
		if ((str = spa_dict_lookup(info, "api.bluez5.internal")) != NULL)
 | 
					 | 
				
			||||||
			this->is_internal = spa_atob(str);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (this->transport == NULL) {
 | 
						if (this->transport == NULL) {
 | 
				
			||||||
		spa_log_error(this->log, "a transport is needed");
 | 
							spa_log_error(this->log, "a transport is needed");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -1898,6 +1981,20 @@ impl_init(const struct spa_handle_factory *factory,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	this->codec = this->transport->media_codec;
 | 
						this->codec = this->transport->media_codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->transport->profile & SPA_BT_PROFILE_HEADSET_HEAD_UNIT)
 | 
				
			||||||
 | 
							this->is_input = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info) {
 | 
				
			||||||
 | 
							if ((str = spa_dict_lookup(info, "clock.quantum-limit")))
 | 
				
			||||||
 | 
								spa_atou32(str, &this->quantum_limit, 0);
 | 
				
			||||||
 | 
							if ((str = spa_dict_lookup(info, "bluez5.media-source-role")) != NULL)
 | 
				
			||||||
 | 
								this->is_input = spa_streq(str, "input");
 | 
				
			||||||
 | 
							if ((str = spa_dict_lookup(info, "api.bluez5.a2dp-duplex")) != NULL)
 | 
				
			||||||
 | 
								this->is_duplex = spa_atob(str);
 | 
				
			||||||
 | 
							if ((str = spa_dict_lookup(info, "api.bluez5.internal")) != NULL)
 | 
				
			||||||
 | 
								this->is_internal = spa_atob(str);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->is_duplex) {
 | 
						if (this->is_duplex) {
 | 
				
			||||||
		if (!this->codec->duplex_codec) {
 | 
							if (!this->codec->duplex_codec) {
 | 
				
			||||||
			spa_log_error(this->log, "transport codec doesn't support duplex");
 | 
								spa_log_error(this->log, "transport codec doesn't support duplex");
 | 
				
			||||||
| 
						 | 
					@ -1979,3 +2076,13 @@ const struct spa_handle_factory spa_a2dp_source_factory = {
 | 
				
			||||||
	impl_init,
 | 
						impl_init,
 | 
				
			||||||
	impl_enum_interface_info,
 | 
						impl_enum_interface_info,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Retained for backward compatibility: */
 | 
				
			||||||
 | 
					const struct spa_handle_factory spa_sco_source_factory = {
 | 
				
			||||||
 | 
						SPA_VERSION_HANDLE_FACTORY,
 | 
				
			||||||
 | 
						SPA_NAME_API_BLUEZ5_SCO_SOURCE,
 | 
				
			||||||
 | 
						&info,
 | 
				
			||||||
 | 
						impl_get_size,
 | 
				
			||||||
 | 
						impl_init,
 | 
				
			||||||
 | 
						impl_enum_interface_info,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,6 @@ bluez5_sources = [
 | 
				
			||||||
  'media-codecs.c',
 | 
					  'media-codecs.c',
 | 
				
			||||||
  'media-sink.c',
 | 
					  'media-sink.c',
 | 
				
			||||||
  'media-source.c',
 | 
					  'media-source.c',
 | 
				
			||||||
  'sco-source.c',
 | 
					 | 
				
			||||||
  'sco-io.c',
 | 
					  'sco-io.c',
 | 
				
			||||||
  'iso-io.c',
 | 
					  'iso-io.c',
 | 
				
			||||||
  'quirks.c',
 | 
					  'quirks.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue