mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -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
10830ab9f8
commit
ea524b158c
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;
|
||||||
|
|
@ -2250,8 +2251,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;
|
||||||
}
|
}
|
||||||
|
|
@ -2317,9 +2316,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;
|
||||||
|
|
@ -2341,10 +2337,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]);
|
||||||
|
|
@ -2359,7 +2371,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;
|
||||||
|
|
@ -2368,6 +2381,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++;
|
||||||
|
|
@ -2391,7 +2405,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) {
|
||||||
|
|
@ -3448,6 +3462,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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,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
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,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