diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index 75dde72c2..394971bc5 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -724,6 +724,7 @@ static int impl_clear(struct spa_handle *handle) spa_return_val_if_fail(handle != NULL, -EINVAL); this = (struct state *) handle; spa_alsa_close(this); + spa_alsa_clear(this); return 0; } @@ -805,8 +806,6 @@ impl_init(const struct spa_handle_factory *factory, spa_list_init(&this->ready); - snd_config_update_free_global(); - for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; const char *s = info->items[i].value; @@ -834,7 +833,8 @@ impl_init(const struct spa_handle_factory *factory, this->props.use_chmap = spa_atob(s); } } - return 0; + + return spa_alsa_init(this); } static const struct spa_interface_info impl_interfaces[] = { diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index f82ecee35..0993bd47b 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -744,6 +744,7 @@ static int impl_clear(struct spa_handle *handle) spa_return_val_if_fail(handle != NULL, -EINVAL); this = (struct state *) handle; spa_alsa_close(this); + spa_alsa_clear(this); return 0; } @@ -823,8 +824,6 @@ impl_init(const struct spa_handle_factory *factory, spa_list_init(&this->free); spa_list_init(&this->ready); - snd_config_update_free_global(); - for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; const char *s = info->items[i].value; @@ -850,7 +849,7 @@ impl_init(const struct spa_handle_factory *factory, this->props.use_chmap = spa_atob(s); } } - return 0; + return spa_alsa_init(this); } static const struct spa_interface_info impl_interfaces[] = { diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index 8834d7648..8b90cc823 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -15,6 +15,29 @@ #include "alsa-pcm.h" +int spa_alsa_init(struct state *state) +{ + int err; + + snd_config_update_free_global(); + + if (strncmp(state->props.device, "_ucm", 4) == 0 && + strlen(state->props.device) >= 12 && + state->props.device[8] == '.') { + if ((err = snd_use_case_mgr_open(&state->ucm, &state->props.device[9])) < 0) + return err; + } + return 0; +} + +int spa_alsa_clear(struct state *state) +{ + if (state->ucm) + snd_use_case_mgr_close(state->ucm); + state->ucm = NULL; + return 0; +} + #define CHECK(s,msg,...) if ((err = (s)) < 0) { spa_log_error(state->log, msg ": %s", ##__VA_ARGS__, snd_strerror(err)); return err; } int spa_alsa_open(struct state *state) diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 7e642ff0d..4c59f8697 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -33,6 +33,7 @@ extern "C" { #include #include +#include #include #include @@ -194,6 +195,8 @@ struct state { double max_error; struct spa_latency_info latency; + + snd_use_case_mgr_t *ucm; }; int @@ -203,6 +206,9 @@ spa_alsa_enum_format(struct state *state, int seq, int spa_alsa_set_format(struct state *state, struct spa_audio_info *info, uint32_t flags); +int spa_alsa_init(struct state *state); +int spa_alsa_clear(struct state *state); + int spa_alsa_open(struct state *state); int spa_alsa_start(struct state *state); int spa_alsa_reassign_follower(struct state *state);