If the sink rate is not updated, then the monitor source will appear to have a different rate than the sink, but in reality there's never any resampling done when moving data from the sink to the monitor source, so it's a lie that the monitor source has a different rate. The result of lying is that clients that capture from the monitor source will have streams that run too fast or slow. --- src/pulsecore/source.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index c692511..5e59a40 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -991,6 +991,13 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, bool passthrough) { return false; } + if (s->monitor_of) { + if (PA_SINK_IS_RUNNING(s->monitor_of->state)) { + pa_log_info("Cannot update rate, this is a monitor source and the sink is running."); + return false; + } + } + if (PA_UNLIKELY (desired_rate < 8000 || desired_rate > PA_RATE_MAX)) return false; @@ -1029,8 +1036,31 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, bool passthrough) { ret = s->update_rate(s, desired_rate); else { /* This is a monitor source. */ - s->sample_spec.rate = desired_rate; - ret = true; + + /* XXX: This code is written with non-passthrough streams in mind. I + * have no idea whether the behaviour with passthrough streams is + * sensible. */ + if (!passthrough) { + uint32_t old_rate = s->sample_spec.rate; + + s->sample_spec.rate = desired_rate; + ret = pa_sink_update_rate(s->monitor_of, desired_rate, false); + + if (!ret) { + /* Changing the sink rate failed, roll back the old rate for + * the monitor source. Why did we set the source rate before + * calling pa_sink_update_rate(), you may ask. The reason is + * that pa_sink_update_rate() tries to update the monitor + * source rate, but we are already in the process of updating + * the monitor source rate, so there's a risk of entering an + * infinite loop. Setting the source rate before calling + * pa_sink_update_rate() makes the rate == s->sample_spec.rate + * check in the beginning of this function return early, so we + * avoid looping. */ + s->sample_spec.rate = old_rate; + } + } else + ret = false; } if (ret) { -- 1.8.1.2