diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 850cc63f8..6725a62e6 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -238,6 +238,7 @@ struct impl { unsigned int drained:1; unsigned int rate_adjust:1; unsigned int port_ignore_latency:1; + unsigned int monitor_passthrough:1; uint32_t scratch_size; uint32_t scratch_ports; @@ -2191,8 +2192,6 @@ impl_node_port_enum_params(void *object, int seq, case 0: case 1: { uint32_t idx = result.index; - if (port->is_monitor) - idx = idx ^ 1; param = spa_latency_build(&b, id, &port->latency[idx]); break; } @@ -2258,9 +2257,6 @@ static int port_set_latency(void *object, this, direction, port_id, latency); port = GET_PORT(this, direction, port_id); - if (port->is_monitor) - return 0; - if (latency == NULL) { info = SPA_LATENCY_INFO(other); have_latency = false; @@ -2282,32 +2278,50 @@ static int port_set_latency(void *object, info.min_rate, info.max_rate, info.min_ns, info.max_ns); - spa_latency_info_combine_start(&info, other); - for (i = 0; i < this->dir[direction].n_ports; i++) { - oport = GET_PORT(this, direction, i); - if (oport->is_monitor || !oport->have_latency) - continue; - spa_log_debug(this->log, "%p: combine %d", this, i); - spa_latency_info_combine(&info, &oport->latency[other]); - } - spa_latency_info_combine_finish(&info); + 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; - spa_log_debug(this->log, "%p: combined %s latency %f-%f %d-%d %"PRIu64"-%"PRIu64, this, - info.direction == SPA_DIRECTION_INPUT ? "input" : "output", - info.min_quantum, info.max_quantum, - info.min_rate, info.max_rate, - info.min_ns, info.max_ns); - - for (i = 0; i < this->dir[other].n_ports; i++) { - oport = GET_PORT(this, other, i); - - spa_log_debug(this->log, "%p: change %d", this, i); - if (spa_latency_info_compare(&info, &oport->latency[other]) != 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); + for (i = 0; i < this->dir[direction].n_ports; i++) { + oport = GET_PORT(this, direction, i); + if ((oport->is_monitor) || !oport->have_latency) + continue; + spa_log_debug(this->log, "%p: combine %d", this, i); + spa_latency_info_combine(&info, &oport->latency[other]); + } + spa_latency_info_combine_finish(&info); + + spa_log_debug(this->log, "%p: combined %s latency %f-%f %d-%d %"PRIu64"-%"PRIu64, this, + info.direction == SPA_DIRECTION_INPUT ? "input" : "output", + info.min_quantum, info.max_quantum, + info.min_rate, info.max_rate, + info.min_ns, info.max_ns); + + for (i = 0; i < this->dir[other].n_ports; i++) { + oport = GET_PORT(this, other, i); + if (oport->is_monitor) + continue; + spa_log_debug(this->log, "%p: change %d", this, i); + if (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); + } + } } if (emit) { port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; @@ -2332,7 +2346,7 @@ static int port_set_tag(void *object, this, direction, port_id, tag); port = GET_PORT(this, direction, port_id); - if (port->is_monitor) + if (port->is_monitor && !this->monitor_passthrough) return 0; 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)) this->port_ignore_latency = spa_atob(s); + else if (spa_streq(k, "monitor.passthrough")) + this->monitor_passthrough = spa_atob(s); else audioconvert_set_param(this, k, s); } diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index 9bd6fed02..d710af67e 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -319,6 +319,7 @@ context.objects = [ # node.description = "Microphone" # media.class = "Audio/Source/Virtual" # audio.position = "FL,FR" + # monitor.passthrough = true # adapter.auto-port-config = { # mode = dsp # monitor = true diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index 1a1e82a15..9e42e0ce7 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -255,6 +255,7 @@ context.objects = [ # node.description = "Microphone" # media.class = "Audio/Source/Virtual" # audio.position = "FL,FR" + # monitor.passthrough = true # } #} diff --git a/src/modules/module-protocol-pulse/modules/module-null-sink.c b/src/modules/module-protocol-pulse/modules/module-null-sink.c index 2d85cd484..e7a9ae6fd 100644 --- a/src/modules/module-protocol-pulse/modules/module-null-sink.c +++ b/src/modules/module-protocol-pulse/modules/module-null-sink.c @@ -196,6 +196,8 @@ static int module_null_sink_prepare(struct module * const module) if (pw_properties_get(props, "monitor.channel-volumes") == NULL) 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; }