[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] 2 commits: alsa-mixer: fix the re-attach code for the mixer control element
PulseAudio Marge Bot (@pulseaudio-merge-bot)
gitlab at gitlab.freedesktop.org
Mon Jul 18 13:54:16 UTC 2022
PulseAudio Marge Bot pushed to branch master at PulseAudio / pulseaudio
Commits:
d1675df0 by Jaroslav Kysela at 2022-07-18T13:51:33+00:00
alsa-mixer: fix the re-attach code for the mixer control element
The new helem must be tracked and old helem must be cleared
to make the code work properly. Introduce the pointer to helem
as the private value for melem and add the necessary code.
Also, add a check for the duplicate mixer elements. The duplicate
mixer element invokes the abort check in alsa-lib. Print a warning
instead and handle the exit gracefully.
Fixes: def8eb074 ("alsa-mixer: allow to re-attach the mixer control element")
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/730>
- - - - -
81a05108 by Jaroslav Kysela at 2022-07-18T13:51:33+00:00
alsa-mixer: extend pa_alsa_mixer_find with the subdevice check
The full identifier check must be executed for the new melem
creation, otherwise the duplicate control element code check
is reached.
Example (using the snd-aloop driver):
numid=56,iface=PCM,name='PCM Notify',device=1,subdevice=1
numid=62,iface=PCM,name='PCM Notify',device=1,subdevice=2
Signed-off-by: Jaroslav Kysela <perex at perex.cz>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/730>
- - - - -
2 changed files:
- src/modules/alsa/alsa-util.c
- src/modules/alsa/module-alsa-card.c
Changes:
=====================================
src/modules/alsa/alsa-util.c
=====================================
@@ -1614,14 +1614,16 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
snd_ctl_elem_iface_t iface,
const char *name,
unsigned int index,
- unsigned int device) {
+ unsigned int device,
+ unsigned int subdevice) {
snd_mixer_elem_t *elem;
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
- snd_hctl_elem_t *helem;
+ snd_hctl_elem_t **_helem, *helem;
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
continue;
- helem = snd_mixer_elem_get_private(elem);
+ _helem = snd_mixer_elem_get_private(elem);
+ helem = *_helem;
if (snd_hctl_elem_get_interface(helem) != iface)
continue;
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
@@ -1630,17 +1632,19 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
continue;
if (snd_hctl_elem_get_device(helem) != device)
continue;
+ if (snd_hctl_elem_get_subdevice(helem) != subdevice)
+ continue;
return elem;
}
return NULL;
}
snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
- return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device, 0);
}
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
- return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device);
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device, 0);
}
static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
@@ -1649,16 +1653,26 @@ static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_
return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1);
}
+static void mixer_melem_free(snd_mixer_elem_t *elem)
+{
+ snd_hctl_elem_t **_helem;
+ _helem = snd_mixer_elem_get_private(elem);
+ pa_xfree(_helem);
+}
+
static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
{
int err;
const char *name = snd_hctl_elem_get_name(helem);
+ snd_hctl_elem_t **_helem;
/* NOTE: The remove event is defined as '~0U`. */
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
/* NOTE: Unless we remove the pointer to melem from the linked-list at
* private_data of helem, an assertion will be hit in alsa-lib since
* the list is not empty. */
+ _helem = snd_mixer_elem_get_private(melem);
+ *_helem = NULL;
snd_mixer_elem_detach(melem, helem);
} else if (mask & SND_CTL_EVENT_MASK_ADD) {
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
@@ -1668,26 +1682,50 @@ static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
const char *name = snd_hctl_elem_get_name(helem);
const int index = snd_hctl_elem_get_index(helem);
const int device = snd_hctl_elem_get_device(helem);
+ const int subdevice = snd_hctl_elem_get_subdevice(helem);
snd_mixer_elem_t *new_melem;
-
- new_melem = pa_alsa_mixer_find(mixer, iface, name, index, device);
+ bool found = true;
+
+ new_melem = pa_alsa_mixer_find(mixer, iface, name, index, device, subdevice);
if (!new_melem) {
+ _helem = pa_xmalloc(sizeof(snd_hctl_elem_t *));
+ *_helem = helem;
/* Put the hctl pointer as our private data - it will be useful for callbacks */
- if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) {
+ if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, _helem, mixer_melem_free)) < 0) {
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
return 0;
}
+ found = false;
+ } else {
+ _helem = snd_mixer_elem_get_private(new_melem);
+ if (_helem) {
+ char *s1, *s2;
+ snd_ctl_elem_id_t *id1, *id2;
+ snd_ctl_elem_id_alloca(&id1);
+ snd_ctl_elem_id_alloca(&id2);
+ snd_hctl_elem_get_id(helem, id1);
+ snd_hctl_elem_get_id(*_helem, id2);
+ s1 = snd_ctl_ascii_elem_id_get(id1);
+ s2 = snd_ctl_ascii_elem_id_get(id2);
+ pa_log_warn("mixer_class_event - duplicate mixer controls: %s | %s", s1, s2);
+ free(s2);
+ free(s1);
+ return 0;
+ }
+ *_helem = helem;
}
if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
- snd_mixer_elem_free(melem);
+ snd_mixer_elem_free(melem);
return 0;
}
- if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
- pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
- return 0;
+ if (!found) {
+ if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
+ pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
+ return 0;
+ }
}
}
}
=====================================
src/modules/alsa/module-alsa-card.c
=====================================
@@ -370,7 +370,7 @@ struct temp_port_avail {
static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
- snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
+ snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
snd_ctl_elem_value_t *elem_value;
bool plugged_in;
void *state;
@@ -380,6 +380,8 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
pa_available_t active_available = PA_AVAILABLE_UNKNOWN;
pa_assert(u);
+ pa_assert(_elem);
+ elem = *_elem;
/* Changing the jack state may cause a port change, and a port change will
* make the sink or source change the mixer settings. If there are multiple
@@ -562,13 +564,18 @@ static pa_device_port* find_port_with_eld_device(struct userdata *u, int device)
static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
struct userdata *u = snd_mixer_elem_get_callback_private(melem);
- snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
- int device = snd_hctl_elem_get_device(elem);
+ snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
+ int device;
const char *old_monitor_name;
pa_device_port *p;
pa_hdmi_eld eld;
bool changed = false;
+ pa_assert(u);
+ pa_assert(_elem);
+ elem = *_elem;
+ device = snd_hctl_elem_get_device(elem);
+
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return 0;
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/eb870fcba9f1d3d9e4d0823012ff04ac2bea00ca...81a051089f3a5890972006256737776d22de9883
--
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/compare/eb870fcba9f1d3d9e4d0823012ff04ac2bea00ca...81a051089f3a5890972006256737776d22de9883
You're receiving this email because of your account on gitlab.freedesktop.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20220718/b4ad5e84/attachment-0001.htm>
More information about the pulseaudio-commits
mailing list