X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/6a6ee8fd22356f70ee70fa6a92d450d6018a34fe..eca082a93f2619cfa10733947a81fa779cb49573:/src/modules/alsa/alsa-mixer.c diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 71dfa797..58f91820 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -523,6 +523,7 @@ void pa_alsa_path_free(pa_alsa_path *p) { pa_proplist_free(p->proplist); pa_xfree(p->name); pa_xfree(p->description); + pa_xfree(p->description_key); pa_xfree(p); } @@ -2574,7 +2575,7 @@ static bool element_create_settings(pa_alsa_element *e, pa_alsa_setting *templat if (template) { s = pa_xnewdup(pa_alsa_setting, template, 1); - s->options = pa_idxset_copy(template->options); + s->options = pa_idxset_copy(template->options, NULL); s->name = pa_sprintf_malloc("%s+%s", template->name, o->name); s->description = (template->description[0] && o->description[0]) @@ -3748,7 +3749,7 @@ fail: } static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, - pa_alsa_direction_t direction) { + pa_alsa_direction_t direction, pa_hashmap *used_paths) { pa_alsa_path *p; void *state; @@ -3775,8 +3776,8 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, pa_assert(pcm_handle); mixer_handle = pa_alsa_open_mixer_for_pcm(pcm_handle, NULL, &hctl_handle); - if (!mixer_handle || !hctl_handle) { - /* Cannot open mixer, remove all entries */ + if (!mixer_handle) { + /* Cannot open mixer, remove all entries */ pa_hashmap_remove_all(ps->paths); return; } @@ -3793,6 +3794,9 @@ static void mapping_paths_probe(pa_alsa_mapping *m, pa_alsa_profile *profile, if (mixer_handle) snd_mixer_close(mixer_handle); + PA_HASHMAP_FOREACH(p, ps->paths, state) + pa_hashmap_put(used_paths, p, p); + pa_log_debug("Available mixer paths (after tidying):"); pa_alsa_path_set_dump(ps); } @@ -4281,19 +4285,19 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m, &try_buffer_size, 0, NULL, NULL, true); } -static void paths_drop_unsupported(pa_hashmap* h) { +static void paths_drop_unused(pa_hashmap* h, pa_hashmap *keep) { void* state = NULL; const void* key; pa_alsa_path* p; pa_assert(h); + pa_assert(keep); + p = pa_hashmap_iterate(h, &state, &key); while (p) { - if (p->supported <= 0) { - pa_hashmap_remove(h, key); - pa_alsa_path_free(p); - } + if (pa_hashmap_get(keep, p) == NULL) + pa_hashmap_remove_and_free(h, key); p = pa_hashmap_iterate(h, &state, &key); } } @@ -4308,7 +4312,7 @@ void pa_alsa_profile_set_probe( void *state; pa_alsa_profile *p, *last = NULL; pa_alsa_mapping *m; - pa_hashmap *broken_inputs, *broken_outputs; + pa_hashmap *broken_inputs, *broken_outputs, *used_paths; pa_assert(ps); pa_assert(dev_id); @@ -4319,6 +4323,7 @@ void pa_alsa_profile_set_probe( broken_inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); broken_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + used_paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); PA_HASHMAP_FOREACH(p, ps->profiles, state) { uint32_t idx; @@ -4406,12 +4411,12 @@ void pa_alsa_profile_set_probe( if (p->output_mappings) PA_IDXSET_FOREACH(m, p->output_mappings, idx) if (m->output_pcm) - mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT); + mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths); if (p->input_mappings) PA_IDXSET_FOREACH(m, p->input_mappings, idx) if (m->input_pcm) - mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT); + mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths); } /* Clean up */ @@ -4419,10 +4424,11 @@ void pa_alsa_profile_set_probe( pa_alsa_profile_set_drop_unsupported(ps); - paths_drop_unsupported(ps->input_paths); - paths_drop_unsupported(ps->output_paths); + paths_drop_unused(ps->input_paths, used_paths); + paths_drop_unused(ps->output_paths, used_paths); pa_hashmap_free(broken_inputs); pa_hashmap_free(broken_outputs); + pa_hashmap_free(used_paths); ps->probed = true; } @@ -4460,17 +4466,13 @@ void pa_alsa_profile_set_drop_unsupported(pa_alsa_profile_set *ps) { void *state; PA_HASHMAP_FOREACH(p, ps->profiles, state) { - if (!p->supported) { - pa_hashmap_remove(ps->profiles, p->name); - profile_free(p); - } + if (!p->supported) + pa_hashmap_remove_and_free(ps->profiles, p->name); } PA_HASHMAP_FOREACH(m, ps->mappings, state) { - if (m->supported <= 0) { - pa_hashmap_remove(ps->mappings, m->name); - mapping_free(m); - } + if (m->supported <= 0) + pa_hashmap_remove_and_free(ps->mappings, m->name); } }