From: Janos Kovacs <jankovac503@xxxxxxxxx> --- src/Makefile.am | 1 + src/modules/alsa/alsa-mixer.c | 80 ++++++++++++--------- src/modules/alsa/alsa-mixer.h | 19 ++++- src/modules/alsa/alsa-sink.c | 58 +++++++++++--- src/modules/alsa/alsa-source.c | 53 +++++++++++--- src/modules/alsa/module-alsa-card.c | 138 +++++++++++++++++++++-------------- 6 files changed, 234 insertions(+), 115 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index b5de764..0c97b7a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1563,6 +1563,7 @@ libalsa_util_la_SOURCES = \ modules/alsa/alsa-mixer.c modules/alsa/alsa-mixer.h \ modules/alsa/alsa-sink.c modules/alsa/alsa-sink.h \ modules/alsa/alsa-source.c modules/alsa/alsa-source.h \ + modules/alsa/alsa-ucm.c modules/alsa/alsa-ucm.h \ modules/reserve-wrap.c modules/reserve-wrap.h libalsa_util_la_LDFLAGS = -avoid-version libalsa_util_la_LIBADD = $(MODULE_LIBADD) $(ASOUNDLIB_LIBS) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 9a5c066..c063fed 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -557,6 +557,11 @@ void pa_alsa_path_free(pa_alsa_path *p) { pa_xfree(p->name); pa_xfree(p->description); + pa_xfree(p->ucm_verb); + pa_xfree(p->ucm_device); + + pa_xstrfreev(p->ucm_modifiers); + pa_xfree(p); } @@ -1232,14 +1237,14 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { return r; } -int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { +int pa_alsa_mixer_path_select(pa_alsa_path *p, snd_mixer_t *m) { pa_alsa_element *e; int r = 0; pa_assert(m); pa_assert(p); - pa_log_debug("Activating path %s", p->name); + pa_log_debug("Activating mixer path %s", p->name); pa_alsa_path_dump(p); PA_LLIST_FOREACH(e, p->elements) { @@ -3070,32 +3075,36 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) { pa_alsa_path *p2; void *state2; + if (p->use_ucm) + continue; + PA_HASHMAP_FOREACH(p2, ps->paths, state2) { pa_alsa_element *ea, *eb; pa_bool_t is_subset = TRUE; - if (p == p2) + if (p == p2 || p2->use_ucm) continue; /* Compare the elements of each set... */ - pa_assert_se(ea = p->elements); - pa_assert_se(eb = p2->elements); - - while (is_subset) { - if (pa_streq(ea->alsa_name, eb->alsa_name)) { - if (element_is_subset(ea, eb, m)) { - ea = ea->next; - eb = eb->next; - if ((ea && !eb) || (!ea && eb)) - is_subset = FALSE; - else if (!ea && !eb) - break; - } else - is_subset = FALSE; - - } else - is_subset = FALSE; - } + if (!(ea = p->elements) || !(eb = p2->elements)) + is_subset= FALSE; + else { + while (is_subset) { + if (pa_streq(ea->alsa_name, eb->alsa_name)) { + if (element_is_subset(ea, eb, m)) { + ea = ea->next; + eb = eb->next; + if ((ea && !eb) || (!ea && eb)) + is_subset = FALSE; + else if (!ea && !eb) + break; + } else + is_subset = FALSE; + + } else + is_subset = FALSE; + } + } if (is_subset) { pa_log_debug("Removing path '%s' as it is a subset of '%s'.", p->name, p2->name); @@ -3188,6 +3197,9 @@ static void profile_free(pa_alsa_profile *p) { if (p->output_mappings) pa_idxset_free(p->output_mappings, NULL, NULL); + pa_xfree(p->ucm_verb); + pa_xstrfreev(p->ucm_modifiers); + pa_xfree(p); } @@ -3242,7 +3254,7 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *ps) { pa_xfree(ps); } -static pa_alsa_mapping *mapping_get(pa_alsa_profile_set *ps, const char *name) { +pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name) { pa_alsa_mapping *m; if (!pa_startswith(name, "Mapping ")) @@ -3317,7 +3329,7 @@ static int mapping_parse_device_strings( pa_assert(ps); - if (!(m = mapping_get(ps, section))) { + if (!(m = pa_alsa_mapping_get(ps, section))) { pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section); return -1; } @@ -3345,7 +3357,7 @@ static int mapping_parse_channel_map( pa_assert(ps); - if (!(m = mapping_get(ps, section))) { + if (!(m = pa_alsa_mapping_get(ps, section))) { pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section); return -1; } @@ -3372,7 +3384,7 @@ static int mapping_parse_paths( pa_assert(ps); - if (!(m = mapping_get(ps, section))) { + if (!(m = pa_alsa_mapping_get(ps, section))) { pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section); return -1; } @@ -3402,7 +3414,7 @@ static int mapping_parse_element( pa_assert(ps); - if (!(m = mapping_get(ps, section))) { + if (!(m = pa_alsa_mapping_get(ps, section))) { pa_log("[%s:%u] %s invalid in section %s", filename, line, lvalue, section); return -1; } @@ -3432,7 +3444,7 @@ static int mapping_parse_direction( pa_assert(ps); - if (!(m = mapping_get(ps, section))) { + if (!(m = pa_alsa_mapping_get(ps, section))) { pa_log("[%s:%u] Section name %s invalid.", filename, line, section); return -1; } @@ -3466,7 +3478,7 @@ static int mapping_parse_description( pa_assert(ps); - if ((m = mapping_get(ps, section))) { + if ((m = pa_alsa_mapping_get(ps, section))) { pa_xfree(m->description); m->description = pa_xstrdup(rvalue); } else if ((p = profile_get(ps, section))) { @@ -3501,7 +3513,7 @@ static int mapping_parse_priority( return -1; } - if ((m = mapping_get(ps, section))) + if ((m = pa_alsa_mapping_get(ps, section))) m->priority = prio; else if ((p = profile_get(ps, section))) p->priority = prio; @@ -3744,7 +3756,7 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, pa_alsa_path_set_dump(ps); } -static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) { +int pa_alsa_mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) { static const struct description_map well_known_descriptions[] = { { "analog-mono", N_("Analog Mono") }, @@ -3882,7 +3894,7 @@ static void profile_set_add_auto(pa_alsa_profile_set *ps) { profile_set_add_auto_pair(ps, NULL, n); } -static int profile_verify(pa_alsa_profile *p) { +int pa_alsa_profile_verify(pa_alsa_profile *p) { static const struct description_map well_known_descriptions[] = { { "output:analog-mono+input:analog-mono", N_("Analog Mono Duplex") }, @@ -4067,7 +4079,7 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix) { pa_xfree(db_values); } -pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus) { +pa_alsa_profile_set* pa_alsa_mixer_profile_set_new(const char *fname, const pa_channel_map *bonus) { pa_alsa_profile_set *ps; pa_alsa_profile *p; pa_alsa_mapping *m; @@ -4126,14 +4138,14 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel goto fail; PA_HASHMAP_FOREACH(m, ps->mappings, state) - if (mapping_verify(m, bonus) < 0) + if (pa_alsa_mapping_verify(m, bonus) < 0) goto fail; if (ps->auto_profiles) profile_set_add_auto(ps); PA_HASHMAP_FOREACH(p, ps->profiles, state) - if (profile_verify(p) < 0) + if (pa_alsa_profile_verify(p) < 0) goto fail; PA_HASHMAP_FOREACH(db_fix, ps->decibel_fixes, state) diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 74d12d6..55d3e0c 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -169,6 +169,7 @@ struct pa_alsa_path { pa_bool_t has_mute:1; pa_bool_t has_volume:1; pa_bool_t has_dB:1; + pa_bool_t use_ucm:1; /* These two are used during probing only */ pa_bool_t has_req_any:1; pa_bool_t req_any_present:1; @@ -184,6 +185,11 @@ struct pa_alsa_path { PA_LLIST_HEAD(pa_alsa_element, elements); PA_LLIST_HEAD(pa_alsa_setting, settings); + + /* UCM stuff used only if use_ucm were TRUE */ + char *ucm_verb; + char *ucm_device; + char **ucm_modifiers; }; /* A path set is simply a set of paths that are applicable to a @@ -209,7 +215,7 @@ int pa_alsa_path_get_volume(pa_alsa_path *p, snd_mixer_t *m, const pa_channel_ma int pa_alsa_path_get_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t *muted); int pa_alsa_path_set_volume(pa_alsa_path *path, snd_mixer_t *m, const pa_channel_map *cm, pa_cvolume *v, pa_bool_t deferred_volume, pa_bool_t write_to_hw); int pa_alsa_path_set_mute(pa_alsa_path *path, snd_mixer_t *m, pa_bool_t muted); -int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m); +int pa_alsa_mixer_path_select(pa_alsa_path *p, snd_mixer_t *m); void pa_alsa_path_set_callback(pa_alsa_path *p, snd_mixer_t *m, snd_mixer_elem_callback_t cb, void *userdata); void pa_alsa_path_free(pa_alsa_path *p); @@ -262,6 +268,9 @@ struct pa_alsa_profile { pa_idxset *input_mappings; pa_idxset *output_mappings; + + char *ucm_verb; + char **ucm_modifiers; }; struct pa_alsa_decibel_fix { @@ -290,16 +299,22 @@ struct pa_alsa_profile_set { pa_bool_t auto_profiles; pa_bool_t ignore_dB:1; pa_bool_t probed:1; + pa_bool_t use_ucm; }; void pa_alsa_mapping_dump(pa_alsa_mapping *m); void pa_alsa_profile_dump(pa_alsa_profile *p); void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix); -pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus); +pa_alsa_profile_set* pa_alsa_mixer_profile_set_new(const char *fname, const pa_channel_map *bonus); void pa_alsa_profile_set_probe(pa_alsa_profile_set *ps, const char *dev_id, const pa_sample_spec *ss, unsigned default_n_fragments, unsigned default_fragment_size_msec); void pa_alsa_profile_set_free(pa_alsa_profile_set *s); void pa_alsa_profile_set_dump(pa_alsa_profile_set *s); +int pa_alsa_profile_verify(pa_alsa_profile *p); + +pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name); +int pa_alsa_mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus); + snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device); diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 647b0cd..fc2455d 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -58,6 +58,7 @@ #include "alsa-util.h" #include "alsa-sink.h" +#include "alsa-ucm.h" /* #define DEBUG_TIMING */ @@ -1445,15 +1446,24 @@ static void mixer_volume_init(struct userdata *u) { static int sink_set_port_cb(pa_sink *s, pa_device_port *p) { struct userdata *u = s->userdata; pa_alsa_port_data *data; + struct pa_alsa_ucm_config *ucm; + pa_alsa_path *newpath, *oldpath; + pa_assert(u); pa_assert(p); pa_assert(u->mixer_handle); data = PA_DEVICE_PORT_DATA(p); + ucm = pa_alsa_card_get_ucm_config(s->card); + oldpath = u->mixer_path; + + pa_assert_se(u->mixer_path = newpath = data->path); - pa_assert_se(u->mixer_path = data->path); - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + if (newpath->use_ucm) + pa_alsa_ucm_path_select(newpath, oldpath, ucm); + else + pa_alsa_mixer_path_select(newpath, u->mixer_handle); mixer_volume_init(u); @@ -1872,8 +1882,13 @@ fail: static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { pa_bool_t need_mixer_callback = FALSE; + struct pa_alsa_ucm_config *ucm; + pa_alsa_path *path; pa_assert(u); + pa_assert(u->sink); + + ucm = pa_alsa_card_get_ucm_config(u->sink->card); if (!u->mixer_handle) return 0; @@ -1885,9 +1900,12 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { * one that has been chosen as active */ data = PA_DEVICE_PORT_DATA(u->sink->active_port); - u->mixer_path = data->path; + path = u->mixer_path = data->path; - pa_alsa_path_select(data->path, u->mixer_handle); + if (path->use_ucm) + pa_alsa_ucm_path_select(path, NULL, ucm); + else + pa_alsa_mixer_path_select(path, u->mixer_handle); if (data->setting) pa_alsa_setting_select(data->setting, u->mixer_handle); @@ -1897,13 +1915,16 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { if (!u->mixer_path && u->mixer_path_set) u->mixer_path = pa_hashmap_first(u->mixer_path_set->paths); - if (u->mixer_path) { + if ((path = u->mixer_path)) { /* Hmm, we have only a single path, then let's activate it */ - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + if (path->use_ucm) + pa_alsa_ucm_path_select(path, NULL, ucm); + else + pa_alsa_mixer_path_select(path, u->mixer_handle); - if (u->mixer_path->settings) - pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle); + if (path->settings) + pa_alsa_setting_select(path->settings, u->mixer_handle); } else return 0; } @@ -2088,7 +2109,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca } else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) { - if (!(profile_set = pa_alsa_profile_set_new(NULL, &map))) + if (!(profile_set = pa_alsa_mixer_profile_set_new(NULL, &map))) goto fail; if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto( @@ -2328,7 +2349,13 @@ fail: } static void userdata_free(struct userdata *u) { + struct pa_alsa_ucm_config *ucm; + struct pa_alsa_path *path; + pa_assert(u); + pa_assert(u->sink); + ucm = pa_alsa_card_get_ucm_config(u->sink->card); + pa_assert(ucm); if (u->sink) pa_sink_unlink(u->sink); @@ -2363,10 +2390,15 @@ static void userdata_free(struct userdata *u) { if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); -/* if (u->mixer_path_set) - pa_alsa_path_set_free(u->mixer_path_set); Owned by the profile set */ - if (u->mixer_path && !u->mixer_path_set) - pa_alsa_path_free(u->mixer_path); + if ((path = u->mixer_path)) { + if (path->use_ucm) + pa_alsa_ucm_path_select(NULL, path, ucm); + + /* if (u->mixer_path_set) + pa_alsa_path_set_free(u->mixer_path_set); Owned by the profile set */ + if (!u->mixer_path_set) + pa_alsa_path_free(path); + } if (u->mixer_handle) snd_mixer_close(u->mixer_handle); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index cff8ce1..4a0a64f 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -53,6 +53,7 @@ #include "alsa-util.h" #include "alsa-source.h" +#include "alsa-ucm.h" /* #define DEBUG_TIMING */ @@ -1348,15 +1349,23 @@ static void mixer_volume_init(struct userdata *u) { static int source_set_port_cb(pa_source *s, pa_device_port *p) { struct userdata *u = s->userdata; pa_alsa_port_data *data; + struct pa_alsa_ucm_config *ucm; + pa_alsa_path *newpath, *oldpath; pa_assert(u); pa_assert(p); pa_assert(u->mixer_handle); data = PA_DEVICE_PORT_DATA(p); + ucm = pa_alsa_card_get_ucm_config(s->card); + oldpath = u->mixer_path; - pa_assert_se(u->mixer_path = data->path); - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + pa_assert_se(u->mixer_path = newpath = data->path); + + if (newpath->use_ucm) + pa_alsa_ucm_path_select(newpath, oldpath, ucm); + else + pa_alsa_mixer_path_select(newpath, u->mixer_handle); mixer_volume_init(u); @@ -1613,8 +1622,13 @@ fail: static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { pa_bool_t need_mixer_callback = FALSE; + struct pa_alsa_ucm_config *ucm; + pa_alsa_path *path; pa_assert(u); + pa_assert(u->source); + + ucm = pa_alsa_card_get_ucm_config(u->source->card); if (!u->mixer_handle) return 0; @@ -1626,9 +1640,12 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { * one that has been chosen as active */ data = PA_DEVICE_PORT_DATA(u->source->active_port); - u->mixer_path = data->path; + path = u->mixer_path = data->path; - pa_alsa_path_select(data->path, u->mixer_handle); + if (path->use_ucm) + pa_alsa_ucm_path_select(path, NULL, ucm); + else + pa_alsa_mixer_path_select(path, u->mixer_handle); if (data->setting) pa_alsa_setting_select(data->setting, u->mixer_handle); @@ -1638,13 +1655,16 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { if (!u->mixer_path && u->mixer_path_set) u->mixer_path = pa_hashmap_first(u->mixer_path_set->paths); - if (u->mixer_path) { + if ((path = u->mixer_path)) { /* Hmm, we have only a single path, then let's activate it */ - pa_alsa_path_select(u->mixer_path, u->mixer_handle); + if (path->use_ucm) + pa_alsa_ucm_path_select(path, NULL, ucm); + else + pa_alsa_mixer_path_select(path, u->mixer_handle); - if (u->mixer_path->settings) - pa_alsa_setting_select(u->mixer_path->settings, u->mixer_handle); + if (path->settings) + pa_alsa_setting_select(path->settings, u->mixer_handle); } else return 0; } @@ -1822,7 +1842,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p } else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) { - if (!(profile_set = pa_alsa_profile_set_new(NULL, &map))) + if (!(profile_set = pa_alsa_mixer_profile_set_new(NULL, &map))) goto fail; if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto( @@ -2036,7 +2056,13 @@ fail: } static void userdata_free(struct userdata *u) { + struct pa_alsa_ucm_config *ucm; + struct pa_alsa_path *path; + pa_assert(u); + pa_assert(u->source); + ucm = pa_alsa_card_get_ucm_config(u->source->card); + pa_assert(ucm); if (u->source) pa_source_unlink(u->source); @@ -2068,8 +2094,13 @@ static void userdata_free(struct userdata *u) { if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); - if (u->mixer_path && !u->mixer_path_set) - pa_alsa_path_free(u->mixer_path); + if ((path = u->mixer_path)) { + if (path->use_ucm) + pa_alsa_ucm_path_select(NULL, path, ucm); + + if (!u->mixer_path_set) + pa_alsa_path_free(path); + } if (u->mixer_handle) snd_mixer_close(u->mixer_handle); diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 6bcf48b..1bed403 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -39,6 +39,7 @@ #include "alsa-util.h" #include "alsa-sink.h" #include "alsa-source.h" +#include "alsa-ucm.h" #include "module-alsa-card-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); @@ -109,12 +110,23 @@ struct userdata { pa_modargs *modargs; pa_alsa_profile_set *profile_set; -}; -struct profile_data { - pa_alsa_profile *profile; + pa_alsa_ucm_config ucm; }; + +pa_alsa_ucm_config *pa_alsa_card_get_ucm_config(pa_card *card) +{ + struct userdata *u; + pa_alsa_ucm_config *ucm = NULL; + + + if (card && (u = card->userdata)) + ucm = &u->ucm; + + return ucm; +} + static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) { pa_alsa_profile *ap; void *state; @@ -184,59 +196,69 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { nd = PA_CARD_PROFILE_DATA(new_profile); od = PA_CARD_PROFILE_DATA(c->active_profile); - if (od->profile && od->profile->output_mappings) - PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) { - if (!am->sink) - continue; - - if (nd->profile && - nd->profile->output_mappings && - pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL)) - continue; - - sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs); - pa_alsa_sink_free(am->sink); - am->sink = NULL; - } - - if (od->profile && od->profile->input_mappings) - PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) { - if (!am->source) - continue; - - if (nd->profile && - nd->profile->input_mappings && - pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL)) - continue; + pa_assert(nd); + pa_assert(od); + + if (od->profile) { + if (od->profile->output_mappings) + PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) { + if (!am->sink) + continue; + + if (nd->profile && + nd->profile->output_mappings && + pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL)) + continue; + + sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs); + pa_alsa_sink_free(am->sink); + am->sink = NULL; + } + + if (od->profile->input_mappings) + PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) { + if (!am->source) + continue; + + if (nd->profile && + nd->profile->input_mappings && + pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL)) + continue; + + source_outputs = pa_source_move_all_start(am->source, source_outputs); + pa_alsa_source_free(am->source); + am->source = NULL; + } + } - source_outputs = pa_source_move_all_start(am->source, source_outputs); - pa_alsa_source_free(am->source); - am->source = NULL; - } + if (u->ucm.enabled) + pa_alsa_ucm_profile_select(nd->profile, od->profile, &u->ucm); - if (nd->profile && nd->profile->output_mappings) - PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) { + if (nd->profile) { + if (nd->profile->output_mappings) + PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) { - if (!am->sink) - am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am); + if (!am->sink) + am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am); - if (sink_inputs && am->sink) { - pa_sink_move_all_finish(am->sink, sink_inputs, FALSE); - sink_inputs = NULL; - } - } + if (sink_inputs && am->sink) { + pa_sink_move_all_finish(am->sink, sink_inputs, FALSE); + sink_inputs = NULL; + } + } - if (nd->profile && nd->profile->input_mappings) - PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) { + if (nd->profile && nd->profile->input_mappings) + PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) { - if (!am->source) - am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am); + if (!am->source) + am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am); - if (source_outputs && am->source) { - pa_source_move_all_finish(am->source, source_outputs, FALSE); - source_outputs = NULL; - } - } + if (source_outputs && am->source) { + pa_source_move_all_finish(am->source, source_outputs, FALSE); + source_outputs = NULL; + } + } + } if (sink_inputs) pa_sink_move_all_fail(sink_inputs); @@ -302,6 +324,7 @@ int pa__init(pa_module *m) { const char *profile = NULL; char *fn = NULL; pa_bool_t namereg_fail = FALSE; + pa_channel_map *def_chmap; pa_alsa_refcnt_inc(); @@ -340,18 +363,23 @@ int pa__init(pa_module *m) { } } + def_chmap = &u->core->default_channel_map; + + if (!(u->profile_set = pa_alsa_ucm_profile_set_new(alsa_card_index, &u->ucm, def_chmap))) { + #ifdef HAVE_UDEV - fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET"); + fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET"); #endif - if (pa_modargs_get_value(ma, "profile_set", NULL)) { + if (pa_modargs_get_value(ma, "profile_set", NULL)) { + pa_xfree(fn); + fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL)); + } + + u->profile_set = pa_alsa_mixer_profile_set_new(fn, &u->core->default_channel_map); pa_xfree(fn); - fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL)); } - u->profile_set = pa_alsa_profile_set_new(fn, &u->core->default_channel_map); - pa_xfree(fn); - u->profile_set->ignore_dB = ignore_dB; if (!u->profile_set) -- 1.7.5.2