diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index b97ed6796..c86b20bcb 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -783,9 +783,18 @@ impl_init(const struct spa_handle_factory *factory, this->default_rate = atoi(info->items[i].value); } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_FORMAT)) { this->default_format = spa_alsa_format_from_name(info->items[i].value, 128); + } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) { + size_t len; + const char *p = info->items[i].value; + while (*p && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) { + if ((len = strcspn(p, ",")) == 0) + break; + this->default_pos.pos[this->default_pos.channels++] = + spa_alsa_channel_from_name(p, len); + p += len + strspn(p+len, ","); + } } } - return 0; } diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index e24a1b16b..c7c57441e 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -804,6 +804,16 @@ impl_init(const struct spa_handle_factory *factory, this->default_rate = atoi(info->items[i].value); } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_FORMAT)) { this->default_format = spa_alsa_format_from_name(info->items[i].value, 128); + } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) { + size_t len; + const char *p = info->items[i].value; + while (*p && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) { + if ((len = strcspn(p, ",")) == 0) + break; + this->default_pos.pos[this->default_pos.channels++] = + spa_alsa_channel_from_name(p, len); + p += len + strspn(p+len, ","); + } } } return 0; diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index 503dff508..23bcd90a1 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -198,12 +198,7 @@ static const struct def_mask default_layouts[] = { #define _C(ch) (SPA_AUDIO_CHANNEL_ ##ch) -struct def_map { - uint32_t channels; - uint32_t pos[SPA_AUDIO_MAX_CHANNELS]; -}; - -static const struct def_map default_map[] = { +static const struct channel_map default_map[] = { { 0, { 0, } } , { 1, { _C(MONO), } }, { 2, { _C(FL), _C(FR), } }, @@ -417,6 +412,8 @@ skip_channels: snd_pcm_free_chmaps(maps); } else { + const struct channel_map *map = NULL; + if (result.index > 0) goto enum_end; @@ -430,8 +427,13 @@ skip_channels: } spa_pod_builder_pop(&b, &f[1]); - if (min == max && min <= 8) { - const struct def_map *map = &default_map[min]; + if (min == max) { + if (state->default_pos.channels == min) + map = &state->default_pos; + else if (min == max && min <= 8) + map = &default_map[min]; + } + if (map) { spa_pod_builder_prop(&b, SPA_FORMAT_AUDIO_position, 0); spa_pod_builder_push_array(&b, &f[1]); for (j = 0; j < map->channels; j++) { diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 22fe99fcd..1204a90e4 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -80,6 +80,10 @@ struct buffer { #define BW_MIN 0.016 #define BW_PERIOD (3 * SPA_NSEC_PER_SEC) +struct channel_map { + uint32_t channels; + uint32_t pos[SPA_AUDIO_MAX_CHANNELS]; +}; struct state { struct spa_handle handle; struct spa_node node; @@ -109,6 +113,7 @@ struct state { uint32_t default_format; unsigned int default_channels; unsigned int default_rate; + struct channel_map default_pos; snd_pcm_uframes_t buffer_frames; snd_pcm_uframes_t period_frames; @@ -195,6 +200,16 @@ static inline uint32_t spa_alsa_format_from_name(const char *name, size_t len) return SPA_AUDIO_FORMAT_UNKNOWN; } +static inline uint32_t spa_alsa_channel_from_name(const char *name, size_t len) +{ + int i; + for (i = 0; spa_type_audio_channel[i].name; i++) { + if (strncmp(name, spa_debug_type_short_name(spa_type_audio_channel[i].name), len) == 0) + return spa_type_audio_channel[i].type; + } + return SPA_AUDIO_CHANNEL_UNKNOWN; +} + #ifdef __cplusplus } /* extern "C" */ #endif