alsa-ucm: Disable old modifiers when switching profiles of same verb

While switching profiles of the same UCM verb, existing code first
disables devices that are only on the first profile to avoid conflicts.
However, it only disables devices, not modifiers. Even worse, modifiers
which have PlaybackPCM/CapturePCM are incorrectly treated as devices and
result in a segmentation fault.

Check what we are disabling, and call the appropriate disable function
for both devices and modifiers. Modifiers are disabled before devices,
because _dismod calls fail when the modifier's supported devices are
disabled.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/742>
This commit is contained in:
Alper Nebi Yasak 2022-06-29 15:37:18 +03:00 committed by PulseAudio Marge Bot
parent b382a00f8b
commit b74269016c

View file

@ -1498,15 +1498,28 @@ int pa_alsa_ucm_set_profile(pa_alsa_ucm_config *ucm, pa_card *card, pa_alsa_prof
}
} else if (ucm->active_verb) {
/* Disable devices not in new profile */
/* Disable modifiers not in new profile. Has to be done before
* devices, because _dismod fails if a modifier's supported
* devices are disabled. */
PA_IDXSET_FOREACH(map, old_profile->input_mappings, idx)
if (new_profile && !pa_idxset_contains(new_profile->input_mappings, map))
if (ucm_device_disable(ucm, map->ucm_context.ucm_device) < 0)
if (map->ucm_context.ucm_modifier && ucm_modifier_disable(ucm, map->ucm_context.ucm_modifier) < 0)
ret = -1;
PA_IDXSET_FOREACH(map, old_profile->output_mappings, idx)
if (new_profile && !pa_idxset_contains(new_profile->output_mappings, map))
if (ucm_device_disable(ucm, map->ucm_context.ucm_device) < 0)
if (map->ucm_context.ucm_modifier && ucm_modifier_disable(ucm, map->ucm_context.ucm_modifier) < 0)
ret = -1;
/* Disable devices not in new profile */
PA_IDXSET_FOREACH(map, old_profile->input_mappings, idx)
if (new_profile && !pa_idxset_contains(new_profile->input_mappings, map))
if (map->ucm_context.ucm_device && ucm_device_disable(ucm, map->ucm_context.ucm_device) < 0)
ret = -1;
PA_IDXSET_FOREACH(map, old_profile->output_mappings, idx)
if (new_profile && !pa_idxset_contains(new_profile->output_mappings, map))
if (map->ucm_context.ucm_device && ucm_device_disable(ucm, map->ucm_context.ucm_device) < 0)
ret = -1;
}
ucm->active_verb = verb;