module-loopback: request renegotiation when suspended

When one side of the loopback suspends, do a EnumFormat params to force
renegotiation on the other side as well.

Suppose this:

1. sink/filter/pw-play plays at 48000Hz
2. pw-play goes away, sink and filter-sink suspend, filter-playback
   idles
3. pw-play starts with 44100Hz
4. sink/filter-sink renegotiate to 44100Hz, filter-playback is still
   at 48000Hz and pitch shifted.

We might want to manually suspend the IDLE nodes instead but for now
this is a good workaround.

Fixes #2969
This commit is contained in:
Wim Taymans 2023-06-14 17:32:24 +02:00
parent b292e52740
commit 2c5a3e9593
2 changed files with 35 additions and 1 deletions

View file

@ -1124,6 +1124,18 @@ static void state_changed(void *data, enum pw_stream_state old,
}
}
static void param_format_cleared(struct impl *impl, struct pw_stream *other,
struct spa_audio_info_raw *other_info)
{
uint8_t buffer[1024];
struct spa_pod_builder b;
const struct spa_pod *params[1];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, other_info);
pw_stream_update_params(other, params, 1);
}
static void param_changed(void *data, uint32_t id, const struct spa_pod *param)
{
struct impl *impl = data;
@ -1134,6 +1146,8 @@ static void param_changed(void *data, uint32_t id, const struct spa_pod *param)
case SPA_PARAM_Format:
if (param == NULL) {
graph_cleanup(graph);
param_format_cleared(impl, impl->capture, &impl->capture_info);
param_format_cleared(impl, impl->playback, &impl->playback_info);
} else {
struct spa_audio_info_raw info;
spa_zero(info);

View file

@ -332,6 +332,18 @@ static void param_latency_changed(struct impl *impl, const struct spa_pod *param
impl->recalc_delay = true;
}
static void param_format_cleared(struct impl *impl, struct pw_stream *other,
struct spa_audio_info_raw *other_info)
{
uint8_t buffer[1024];
struct spa_pod_builder b;
const struct spa_pod *params[1];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, other_info);
pw_stream_update_params(other, params, 1);
}
static void stream_state_changed(void *data, enum pw_stream_state old,
enum pw_stream_state state, const char *error)
{
@ -386,8 +398,10 @@ static void capture_param_changed(void *data, uint32_t id, const struct spa_pod
case SPA_PARAM_Format:
{
struct spa_audio_info_raw info;
if (param == NULL)
if (param == NULL) {
param_format_cleared(impl, impl->playback, &impl->playback_info);
return;
}
if (spa_format_audio_raw_parse(param, &info) < 0)
return;
if (info.rate == 0 ||
@ -425,6 +439,12 @@ static void playback_param_changed(void *data, uint32_t id, const struct spa_pod
struct impl *impl = data;
switch (id) {
case SPA_PARAM_Format:
if (param == NULL) {
param_format_cleared(impl, impl->capture, &impl->capture_info);
return;
}
break;
case SPA_PARAM_Latency:
param_latency_changed(impl, param, &impl->playback_latency, impl->capture);
break;