mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	audioconvert: add monitor.passthrough option
Add a monitor.passthrough option. This will pass all latency information directly between the port and its monitor ports. This is interesting when the adapter (and audioconvert) is used with a null-audio-sink that simply forwards the data to a real sink/souce. In that case, we want the sink/source latency to be passed unmodified. Set the monitor.passthrough on the pulseaudio null-sink because a passthrough virtual sink is the most likely use case for this. Add some monitor.passthrough default config where it makes sense. Fixes #3888
This commit is contained in:
		
							parent
							
								
									6d3790d794
								
							
						
					
					
						commit
						863b3be343
					
				
					 4 changed files with 46 additions and 26 deletions
				
			
		| 
						 | 
					@ -238,6 +238,7 @@ struct impl {
 | 
				
			||||||
	unsigned int drained:1;
 | 
						unsigned int drained:1;
 | 
				
			||||||
	unsigned int rate_adjust:1;
 | 
						unsigned int rate_adjust:1;
 | 
				
			||||||
	unsigned int port_ignore_latency:1;
 | 
						unsigned int port_ignore_latency:1;
 | 
				
			||||||
 | 
						unsigned int monitor_passthrough:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t scratch_size;
 | 
						uint32_t scratch_size;
 | 
				
			||||||
	uint32_t scratch_ports;
 | 
						uint32_t scratch_ports;
 | 
				
			||||||
| 
						 | 
					@ -2191,8 +2192,6 @@ impl_node_port_enum_params(void *object, int seq,
 | 
				
			||||||
		case 0: case 1:
 | 
							case 0: case 1:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			uint32_t idx = result.index;
 | 
								uint32_t idx = result.index;
 | 
				
			||||||
			if (port->is_monitor)
 | 
					 | 
				
			||||||
				idx = idx ^ 1;
 | 
					 | 
				
			||||||
			param = spa_latency_build(&b, id, &port->latency[idx]);
 | 
								param = spa_latency_build(&b, id, &port->latency[idx]);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2258,9 +2257,6 @@ static int port_set_latency(void *object,
 | 
				
			||||||
			this, direction, port_id, latency);
 | 
								this, direction, port_id, latency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port = GET_PORT(this, direction, port_id);
 | 
						port = GET_PORT(this, direction, port_id);
 | 
				
			||||||
	if (port->is_monitor)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (latency == NULL) {
 | 
						if (latency == NULL) {
 | 
				
			||||||
		info = SPA_LATENCY_INFO(other);
 | 
							info = SPA_LATENCY_INFO(other);
 | 
				
			||||||
		have_latency = false;
 | 
							have_latency = false;
 | 
				
			||||||
| 
						 | 
					@ -2282,10 +2278,26 @@ static int port_set_latency(void *object,
 | 
				
			||||||
			info.min_rate, info.max_rate,
 | 
								info.min_rate, info.max_rate,
 | 
				
			||||||
			info.min_ns, info.max_ns);
 | 
								info.min_ns, info.max_ns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->monitor_passthrough) {
 | 
				
			||||||
 | 
							if (port->is_monitor)
 | 
				
			||||||
 | 
								oport = GET_PORT(this, other, port_id-1);
 | 
				
			||||||
 | 
							else if (this->monitor && direction == SPA_DIRECTION_INPUT)
 | 
				
			||||||
 | 
								oport = GET_PORT(this, other, port_id+1);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (oport != NULL &&
 | 
				
			||||||
 | 
							    spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
 | 
				
			||||||
 | 
								oport->latency[other] = info;
 | 
				
			||||||
 | 
								oport->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
 | 
				
			||||||
 | 
								oport->params[IDX_Latency].user++;
 | 
				
			||||||
 | 
								emit_port_info(this, oport, false);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		spa_latency_info_combine_start(&info, other);
 | 
							spa_latency_info_combine_start(&info, other);
 | 
				
			||||||
		for (i = 0; i < this->dir[direction].n_ports; i++) {
 | 
							for (i = 0; i < this->dir[direction].n_ports; i++) {
 | 
				
			||||||
			oport = GET_PORT(this, direction, i);
 | 
								oport = GET_PORT(this, direction, i);
 | 
				
			||||||
		if (oport->is_monitor || !oport->have_latency)
 | 
								if ((oport->is_monitor) || !oport->have_latency)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			spa_log_debug(this->log, "%p: combine %d", this, i);
 | 
								spa_log_debug(this->log, "%p: combine %d", this, i);
 | 
				
			||||||
			spa_latency_info_combine(&info, &oport->latency[other]);
 | 
								spa_latency_info_combine(&info, &oport->latency[other]);
 | 
				
			||||||
| 
						 | 
					@ -2300,7 +2312,8 @@ static int port_set_latency(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < this->dir[other].n_ports; i++) {
 | 
							for (i = 0; i < this->dir[other].n_ports; i++) {
 | 
				
			||||||
			oport = GET_PORT(this, other, i);
 | 
								oport = GET_PORT(this, other, i);
 | 
				
			||||||
 | 
								if (oport->is_monitor)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			spa_log_debug(this->log, "%p: change %d", this, i);
 | 
								spa_log_debug(this->log, "%p: change %d", this, i);
 | 
				
			||||||
			if (spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
 | 
								if (spa_latency_info_compare(&info, &oport->latency[other]) != 0) {
 | 
				
			||||||
				oport->latency[other] = info;
 | 
									oport->latency[other] = info;
 | 
				
			||||||
| 
						 | 
					@ -2309,6 +2322,7 @@ static int port_set_latency(void *object,
 | 
				
			||||||
				emit_port_info(this, oport, false);
 | 
									emit_port_info(this, oport, false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (emit) {
 | 
						if (emit) {
 | 
				
			||||||
		port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
 | 
							port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
 | 
				
			||||||
		port->params[IDX_Latency].user++;
 | 
							port->params[IDX_Latency].user++;
 | 
				
			||||||
| 
						 | 
					@ -2332,7 +2346,7 @@ static int port_set_tag(void *object,
 | 
				
			||||||
			this, direction, port_id, tag);
 | 
								this, direction, port_id, tag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port = GET_PORT(this, direction, port_id);
 | 
						port = GET_PORT(this, direction, port_id);
 | 
				
			||||||
	if (port->is_monitor)
 | 
						if (port->is_monitor && !this->monitor_passthrough)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tag != NULL) {
 | 
						if (tag != NULL) {
 | 
				
			||||||
| 
						 | 
					@ -3428,6 +3442,8 @@ impl_init(const struct spa_handle_factory *factory,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY))
 | 
							else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY))
 | 
				
			||||||
			this->port_ignore_latency = spa_atob(s);
 | 
								this->port_ignore_latency = spa_atob(s);
 | 
				
			||||||
 | 
							else if (spa_streq(k, "monitor.passthrough"))
 | 
				
			||||||
 | 
								this->monitor_passthrough = spa_atob(s);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			audioconvert_set_param(this, k, s);
 | 
								audioconvert_set_param(this, k, s);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -319,6 +319,7 @@ context.objects = [
 | 
				
			||||||
    #        node.description = "Microphone"
 | 
					    #        node.description = "Microphone"
 | 
				
			||||||
    #        media.class      = "Audio/Source/Virtual"
 | 
					    #        media.class      = "Audio/Source/Virtual"
 | 
				
			||||||
    #        audio.position   = "FL,FR"
 | 
					    #        audio.position   = "FL,FR"
 | 
				
			||||||
 | 
					    #        monitor.passthrough = true
 | 
				
			||||||
    #        adapter.auto-port-config = {
 | 
					    #        adapter.auto-port-config = {
 | 
				
			||||||
    #            mode = dsp
 | 
					    #            mode = dsp
 | 
				
			||||||
    #            monitor = true
 | 
					    #            monitor = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,6 +255,7 @@ context.objects = [
 | 
				
			||||||
    #        node.description = "Microphone"
 | 
					    #        node.description = "Microphone"
 | 
				
			||||||
    #        media.class      = "Audio/Source/Virtual"
 | 
					    #        media.class      = "Audio/Source/Virtual"
 | 
				
			||||||
    #        audio.position   = "FL,FR"
 | 
					    #        audio.position   = "FL,FR"
 | 
				
			||||||
 | 
					    #        monitor.passthrough = true
 | 
				
			||||||
    #    }
 | 
					    #    }
 | 
				
			||||||
    #}
 | 
					    #}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,6 +196,8 @@ static int module_null_sink_prepare(struct module * const module)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pw_properties_get(props, "monitor.channel-volumes") == NULL)
 | 
						if (pw_properties_get(props, "monitor.channel-volumes") == NULL)
 | 
				
			||||||
		pw_properties_set(props, "monitor.channel-volumes", "true");
 | 
							pw_properties_set(props, "monitor.channel-volumes", "true");
 | 
				
			||||||
 | 
						if (pw_properties_get(props, "monitor.passthrough") == NULL)
 | 
				
			||||||
 | 
							pw_properties_set(props, "monitor.passthrough", "true");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue