mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	stream: reimplement volume changes with notify stream
Implement volume changes with a notify stream. Do volume changes in the channel mixer with control streams.
This commit is contained in:
		
							parent
							
								
									7cdb980b1a
								
							
						
					
					
						commit
						0bce72d898
					
				
					 2 changed files with 96 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -555,11 +555,11 @@ impl_node_port_enum_params(struct spa_node *node,
 | 
			
		|||
 | 
			
		||||
	this = SPA_CONTAINER_OF(node, struct impl, node);
 | 
			
		||||
 | 
			
		||||
	switch (id) {
 | 
			
		||||
      next:
 | 
			
		||||
	case SPA_PARAM_PropInfo:
 | 
			
		||||
		spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
			
		||||
	spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
			
		||||
 | 
			
		||||
	switch (id) {
 | 
			
		||||
	case SPA_PARAM_PropInfo:
 | 
			
		||||
		switch (*index) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			param = spa_pod_builder_object(builder,
 | 
			
		||||
| 
						 | 
				
			
			@ -571,17 +571,42 @@ impl_node_port_enum_params(struct spa_node *node,
 | 
			
		|||
		default:
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		(*index)++;
 | 
			
		||||
 | 
			
		||||
		if (spa_pod_filter(builder, result, param, filter) < 0)
 | 
			
		||||
			goto next;
 | 
			
		||||
 | 
			
		||||
		return 1;
 | 
			
		||||
	case SPA_PARAM_IO:
 | 
			
		||||
		switch (*index) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			param = spa_pod_builder_object(builder,
 | 
			
		||||
				SPA_TYPE_OBJECT_ParamIO, id,
 | 
			
		||||
				":", SPA_PARAM_IO_id, "I", SPA_IO_Buffers,
 | 
			
		||||
				":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_buffers));
 | 
			
		||||
			break;
 | 
			
		||||
		case 1:
 | 
			
		||||
			param = spa_pod_builder_object(builder,
 | 
			
		||||
				SPA_TYPE_OBJECT_ParamIO, id,
 | 
			
		||||
				":", SPA_PARAM_IO_id, "I", SPA_IO_Range,
 | 
			
		||||
				":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_range));
 | 
			
		||||
			break;
 | 
			
		||||
		case 2:
 | 
			
		||||
			param = spa_pod_builder_object(builder,
 | 
			
		||||
				SPA_TYPE_OBJECT_ParamIO, id,
 | 
			
		||||
				":", SPA_PARAM_IO_id, "I", SPA_IO_Control,
 | 
			
		||||
				":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence));
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		return spa_node_port_enum_params(this->fmt[direction], direction, port_id,
 | 
			
		||||
			id, index, filter, result, builder);
 | 
			
		||||
	}
 | 
			
		||||
	(*index)++;
 | 
			
		||||
 | 
			
		||||
	if (spa_pod_filter(builder, result, param, filter) < 0)
 | 
			
		||||
		goto next;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
| 
						 | 
				
			
			@ -652,6 +677,9 @@ impl_node_port_set_io(struct spa_node *node,
 | 
			
		|||
	case SPA_IO_Range:
 | 
			
		||||
		res = spa_node_port_set_io(this->resample, direction, 0, id, data, size);
 | 
			
		||||
		break;
 | 
			
		||||
	case SPA_IO_Control:
 | 
			
		||||
		res = spa_node_port_set_io(this->channelmix, direction, 0, id, data, size);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		res = spa_node_port_set_io(this->fmt[direction], direction, port_id, id, data, size);
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,6 +76,7 @@ struct param {
 | 
			
		|||
#define DEFAULT_VOLUME	1.0
 | 
			
		||||
 | 
			
		||||
struct props {
 | 
			
		||||
	bool changed;
 | 
			
		||||
	float volume;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +107,9 @@ struct stream {
 | 
			
		|||
	const struct spa_node_callbacks *callbacks;
 | 
			
		||||
	void *callbacks_data;
 | 
			
		||||
	struct spa_io_buffers *io;
 | 
			
		||||
	struct spa_io_control *io_control;
 | 
			
		||||
	struct spa_io_sequence *io_control;
 | 
			
		||||
	struct spa_io_sequence *io_notify;
 | 
			
		||||
	uint32_t io_notify_size;
 | 
			
		||||
 | 
			
		||||
	struct pw_array params;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -344,6 +347,16 @@ static int impl_port_set_io(struct spa_node *node, enum spa_direction direction,
 | 
			
		|||
		else
 | 
			
		||||
			impl->io_control = NULL;
 | 
			
		||||
		break;
 | 
			
		||||
	case SPA_IO_Notify:
 | 
			
		||||
		if (data && size >= sizeof(struct spa_io_sequence)) {
 | 
			
		||||
			impl->io_notify = data;
 | 
			
		||||
			impl->io_notify_size = size;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			impl->io_notify = NULL;
 | 
			
		||||
			impl->io_notify_size = size;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		return -ENOENT;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -604,6 +617,33 @@ static int impl_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint3
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_control(struct stream *impl, struct spa_pod_sequence *sequence)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_notify(struct stream *impl, struct spa_pod_sequence *sequence)
 | 
			
		||||
{
 | 
			
		||||
	struct spa_pod_builder b = { 0 };
 | 
			
		||||
 | 
			
		||||
        spa_pod_builder_init(&b, impl->io_notify, impl->io_notify_size);
 | 
			
		||||
	spa_pod_builder_push_sequence(&b, 0);
 | 
			
		||||
	if (impl->props.changed) {
 | 
			
		||||
		spa_pod_builder_control_header(&b, 0, SPA_CONTROL_Properties);
 | 
			
		||||
		spa_pod_builder_push_object(&b, SPA_TYPE_OBJECT_Props, 0);
 | 
			
		||||
		spa_pod_builder_push_prop(&b, SPA_PROP_volume, 0);
 | 
			
		||||
		spa_pod_builder_float(&b, impl->props.volume);
 | 
			
		||||
		spa_pod_builder_pop(&b);
 | 
			
		||||
		spa_pod_builder_pop(&b);
 | 
			
		||||
		impl->props.changed = false;
 | 
			
		||||
	}
 | 
			
		||||
	spa_pod_builder_pop(&b);
 | 
			
		||||
 | 
			
		||||
	if (impl->props.changed)
 | 
			
		||||
		spa_debug_pod(2, NULL, &impl->io_notify->sequence.pod);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void copy_quantum(struct stream *impl, int64_t queued)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_driver_quantum *q = impl->node->rt.quantum;
 | 
			
		||||
| 
						 | 
				
			
			@ -614,6 +654,11 @@ static inline void copy_quantum(struct stream *impl, int64_t queued)
 | 
			
		|||
	impl->time.delay = q->delay;
 | 
			
		||||
	impl->time.queued = queued;
 | 
			
		||||
	impl->seq2 = impl->seq1;
 | 
			
		||||
 | 
			
		||||
	if (impl->io_control)
 | 
			
		||||
		process_control(impl, &impl->io_control->sequence);
 | 
			
		||||
	if (impl->io_notify)
 | 
			
		||||
		process_notify(impl, &impl->io_notify->sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int impl_node_process_input(struct spa_node *node)
 | 
			
		||||
| 
						 | 
				
			
			@ -951,21 +996,22 @@ struct pw_remote *pw_stream_get_remote(struct pw_stream *stream)
 | 
			
		|||
 | 
			
		||||
static void add_controls(struct pw_stream *stream)
 | 
			
		||||
{
 | 
			
		||||
#if 0
 | 
			
		||||
	struct stream *s = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
			
		||||
	uint8_t buffer[4096];
 | 
			
		||||
	struct spa_pod_builder b;
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_init(&b, buffer, 4096);
 | 
			
		||||
 | 
			
		||||
	add_param(stream, PARAM_TYPE_INIT,
 | 
			
		||||
			spa_pod_builder_object(&b,
 | 
			
		||||
                                t->param_io.idPropsOut, t->param_io.Prop,
 | 
			
		||||
                                ":", t->param_io.id, "I", s->type.io_prop_volume,
 | 
			
		||||
                                ":", t->param_io.size, "i", sizeof(struct spa_pod_float),
 | 
			
		||||
                                ":", t->param.propId, "I", s->type.prop_volume,
 | 
			
		||||
                                ":", t->param.propType, "fru", s->props.volume,
 | 
			
		||||
                                        SPA_POD_PROP_MIN_MAX(0.0, 10.0)));
 | 
			
		||||
#endif
 | 
			
		||||
		spa_pod_builder_object(&b,
 | 
			
		||||
			SPA_TYPE_OBJECT_ParamIO, SPA_PARAM_IO,
 | 
			
		||||
			":", SPA_PARAM_IO_id,   "I", SPA_IO_Notify,
 | 
			
		||||
			":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence) + 1024));
 | 
			
		||||
 | 
			
		||||
	add_param(stream, PARAM_TYPE_INIT,
 | 
			
		||||
		spa_pod_builder_object(&b,
 | 
			
		||||
			SPA_TYPE_OBJECT_ParamIO, SPA_PARAM_IO,
 | 
			
		||||
			":", SPA_PARAM_IO_id,   "I", SPA_IO_Control,
 | 
			
		||||
			":", SPA_PARAM_IO_size, "i", sizeof(struct spa_io_sequence)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
| 
						 | 
				
			
			@ -1064,6 +1110,8 @@ int pw_stream_set_control(struct pw_stream *stream,
 | 
			
		|||
	else
 | 
			
		||||
		return -ENOTSUP;
 | 
			
		||||
 | 
			
		||||
	impl->props.changed = true;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue