pulse-server: add support for overriding fix format

Add support for using custom format, rate or channels when the streams
asks to fix those parameters for us.

Some streams might expect to see S16LE when they connect to a sink in
S16LE when the FIX_FORMAT flag is set but this is not the case in
PipeWire because the audio DSP pipeline works in F32, and so F32 is
choosen. Make it possible to use a pulse.rule with a audio.format
property to control this.
This commit is contained in:
Wim Taymans 2023-02-22 18:04:44 +01:00
parent 84eafcd12f
commit d28990af34

View file

@ -1693,26 +1693,33 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
} }
} }
if (sample_spec_valid(&ss)) { if (sample_spec_valid(&ss)) {
if (fix_format || fix_rate || fix_channels) { struct sample_spec sfix = ss;
struct sample_spec sfix = ss; const char *str;
if (fix_format)
rate = ss.rate;
if (fix_format) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_FORMAT)) != NULL)
sfix.format = format_name2id(str);
else
sfix.format = SPA_AUDIO_FORMAT_UNKNOWN; sfix.format = SPA_AUDIO_FORMAT_UNKNOWN;
if (fix_rate)
sfix.rate = 0;
if (fix_channels)
sfix.channels = 0;
if (n_params < MAX_FORMATS &&
(params[n_params] = format_build_param(&b,
SPA_PARAM_EnumFormat, &sfix,
sfix.channels > 0 ? &map : NULL)) != NULL) {
n_params++;
n_valid_formats++;
}
} }
else if (n_params < MAX_FORMATS && if (fix_rate) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_RATE)) != NULL)
sfix.rate = atoi(str);
else
sfix.rate = 0;
}
if (fix_channels) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_CHANNELS)) != NULL)
sfix.channels = atoi(str);
else
sfix.channels = 0;
}
if (n_params < MAX_FORMATS &&
(params[n_params] = format_build_param(&b, (params[n_params] = format_build_param(&b,
SPA_PARAM_EnumFormat, &ss, SPA_PARAM_EnumFormat, &sfix,
ss.channels > 0 ? &map : NULL)) != NULL) { sfix.channels > 0 ? &map : NULL)) != NULL) {
n_params++; n_params++;
n_valid_formats++; n_valid_formats++;
} else { } else {
@ -1720,7 +1727,6 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
impl, format_id2name(ss.format), ss.rate, impl, format_id2name(ss.format), ss.rate,
ss.channels); ss.channels);
} }
rate = ss.rate;
} }
if (m->offset != m->length) if (m->offset != m->length)
@ -1950,26 +1956,33 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
volume_set = false; volume_set = false;
} }
if (sample_spec_valid(&ss)) { if (sample_spec_valid(&ss)) {
if (fix_format || fix_rate || fix_channels) { struct sample_spec sfix = ss;
struct sample_spec sfix = ss; const char *str;
if (fix_format)
rate = ss.rate;
if (fix_format) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_FORMAT)) != NULL)
sfix.format = format_name2id(str);
else
sfix.format = SPA_AUDIO_FORMAT_UNKNOWN; sfix.format = SPA_AUDIO_FORMAT_UNKNOWN;
if (fix_rate)
sfix.rate = 0;
if (fix_channels)
sfix.channels = 0;
if (n_params < MAX_FORMATS &&
(params[n_params] = format_build_param(&b,
SPA_PARAM_EnumFormat, &sfix,
sfix.channels > 0 ? &map : NULL)) != NULL) {
n_params++;
n_valid_formats++;
}
} }
else if (n_params < MAX_FORMATS && if (fix_rate) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_RATE)) != NULL)
sfix.rate = atoi(str);
else
sfix.rate = 0;
}
if (fix_channels) {
if ((str = pw_properties_get(props, SPA_KEY_AUDIO_CHANNELS)) != NULL)
sfix.channels = atoi(str);
else
sfix.channels = 0;
}
if (n_params < MAX_FORMATS &&
(params[n_params] = format_build_param(&b, (params[n_params] = format_build_param(&b,
SPA_PARAM_EnumFormat, &ss, SPA_PARAM_EnumFormat, &sfix,
ss.channels > 0 ? &map : NULL)) != NULL) { sfix.channels > 0 ? &map : NULL)) != NULL) {
n_params++; n_params++;
n_valid_formats++; n_valid_formats++;
} else { } else {
@ -1977,7 +1990,6 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
impl, format_id2name(ss.format), ss.rate, impl, format_id2name(ss.format), ss.rate,
ss.channels); ss.channels);
} }
rate = ss.rate;
} }
if (m->offset != m->length) if (m->offset != m->length)
goto error_protocol; goto error_protocol;