From 67f4acaf1de507ec3bf6722f04675c1d78951de2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 14 Sep 2020 11:06:11 +0200 Subject: [PATCH] pulse: try hard to always create a valid channel map Unknown channel names are mapped to aux channels. Add extra AUX channels when we don't know the channel layout. This makes sure apps always receive valid channel layouts so they don't abort (pactl). --- pipewire-pulseaudio/src/core-format.c | 11 ++++++----- pipewire-pulseaudio/src/introspect.c | 16 ++++++++++------ pipewire-pulseaudio/src/stream.c | 5 +++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pipewire-pulseaudio/src/core-format.c b/pipewire-pulseaudio/src/core-format.c index 94ed4cbc3..c68774895 100644 --- a/pipewire-pulseaudio/src/core-format.c +++ b/pipewire-pulseaudio/src/core-format.c @@ -128,14 +128,14 @@ static inline uint32_t channel_pa2id(pa_channel_position_t channel) return audio_channels[channel]; } -static inline pa_channel_position_t channel_id2pa(uint32_t id) +static inline pa_channel_position_t channel_id2pa(uint32_t id, uint32_t *aux) { size_t i; for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) { if (id == audio_channels[i]) return i; } - return PA_CHANNEL_POSITION_INVALID; + return PA_CHANNEL_POSITION_AUX0 + (*aux)++; } SPA_EXPORT @@ -362,7 +362,7 @@ int pa_format_info_to_sample_spec_fake(const pa_format_info *f, pa_sample_spec * int pa_format_parse_param(const struct spa_pod *param, pa_sample_spec *spec, pa_channel_map *map) { struct spa_audio_info info = { 0 }; - uint32_t i; + uint32_t i, aux; if (param == NULL) return -EINVAL; @@ -383,13 +383,14 @@ int pa_format_parse_param(const struct spa_pod *param, pa_sample_spec *spec, pa_ spec->rate = info.info.raw.rate; spec->channels = info.info.raw.channels; + aux = 0; pa_channel_map_init(map); map->channels = info.info.raw.channels; for (i = 0; i < info.info.raw.channels; i++) - map->map[i] = channel_id2pa(info.info.raw.position[i]); + map->map[i] = channel_id2pa(info.info.raw.position[i], &aux); if (!pa_channel_map_valid(map)) - pa_channel_map_init_auto(map, info.info.raw.channels, PA_CHANNEL_MAP_DEFAULT); + pa_channel_map_init_extend(map, info.info.raw.channels, PA_CHANNEL_MAP_OSS); return 0; } diff --git a/pipewire-pulseaudio/src/introspect.c b/pipewire-pulseaudio/src/introspect.c index 910cbeaf6..2c3aea589 100644 --- a/pipewire-pulseaudio/src/introspect.c +++ b/pipewire-pulseaudio/src/introspect.c @@ -125,7 +125,8 @@ static int sink_callback(pa_context *c, struct global *g, struct sink_data *d) if (i.sample_spec.channels == g->node_info.channel_map.channels) i.channel_map = g->node_info.channel_map; else - pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); + pa_channel_map_init_extend(&i.channel_map, + i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.owner_module = g->id; i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) @@ -855,7 +856,8 @@ static int source_callback(pa_context *c, struct global *g, struct source_data * if (i.sample_spec.channels == g->node_info.channel_map.channels) i.channel_map = g->node_info.channel_map; else - pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); + pa_channel_map_init_extend(&i.channel_map, + i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.owner_module = g->id; i.volume.channels = i.sample_spec.channels; for (n = 0; n < i.volume.channels; n++) @@ -2061,7 +2063,7 @@ static int sink_input_callback(pa_context *c, struct sink_input_data *d, struct if (s->channel_map.channels == s->sample_spec.channels) i.channel_map = s->channel_map; else - pa_channel_map_init_auto(&i.channel_map, + pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.format = s->format; } @@ -2074,7 +2076,8 @@ static int sink_input_callback(pa_context *c, struct sink_input_data *d, struct if (i.sample_spec.channels == g->node_info.channel_map.channels) i.channel_map = g->node_info.channel_map; else - pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); + pa_channel_map_init_extend(&i.channel_map, + i.sample_spec.channels, PA_CHANNEL_MAP_OSS); ii[0].encoding = PA_ENCODING_PCM; ii[0].plist = pa_proplist_new(); i.format = ii; @@ -2463,7 +2466,7 @@ static int source_output_callback(struct source_output_data *d, pa_context *c, s if (s->channel_map.channels == s->sample_spec.channels) i.channel_map = s->channel_map; else - pa_channel_map_init_auto(&i.channel_map, + pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); i.format = s->format; } @@ -2476,7 +2479,8 @@ static int source_output_callback(struct source_output_data *d, pa_context *c, s if (i.sample_spec.channels == g->node_info.channel_map.channels) i.channel_map = g->node_info.channel_map; else - pa_channel_map_init_auto(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_OSS); + pa_channel_map_init_extend(&i.channel_map, + i.sample_spec.channels, PA_CHANNEL_MAP_OSS); ii[0].encoding = PA_ENCODING_PCM; ii[0].plist = pa_proplist_new(); i.format = ii; diff --git a/pipewire-pulseaudio/src/stream.c b/pipewire-pulseaudio/src/stream.c index b0956ddc0..b52342f1f 100644 --- a/pipewire-pulseaudio/src/stream.c +++ b/pipewire-pulseaudio/src/stream.c @@ -569,7 +569,8 @@ pa_stream* pa_stream_new_with_proplist(pa_context *c, const char *name, pa_channel_map tmap; if (!map) - PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_extend(&tmap, + ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID); return stream_new(c, name, ss, map, NULL, 0, p); } @@ -879,7 +880,7 @@ static int create_stream(pa_stream_direction_t direction, continue; } if (pa_format_info_get_channel_map(s->req_formats[i], &chmap) < 0) - pa_channel_map_init_auto(&chmap, ss.channels, PA_CHANNEL_MAP_DEFAULT); + pa_channel_map_init_extend(&chmap, ss.channels, PA_CHANNEL_MAP_DEFAULT); params[n_params++] = pa_format_build_param(&b, SPA_PARAM_EnumFormat, &ss, &chmap);