alsamixer: fix handling of removed controls

When we get a notification that an element has been removed, we have to
recreate our internal control representation to avoid accessing freed
memory.  (And the checking for SND_CTL_EVENT_MASK_REMOVE should actually
be done correctly while we're at it.)

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
Clemens Ladisch 2012-10-19 12:16:33 +02:00
parent 6017849f1b
commit f282607273
4 changed files with 17 additions and 14 deletions

View file

@ -128,8 +128,15 @@ void mainloop(void)
}
if (!active_widget)
break;
if (controls_changed)
if (controls_changed) {
controls_changed = FALSE;
create_controls();
control_values_changed = FALSE;
display_controls();
} else if (control_values_changed) {
control_values_changed = FALSE;
display_controls();
}
}
free(pollfds);
}

View file

@ -657,7 +657,6 @@ void display_controls(void)
display_no_controls();
}
display_scroll_indicators();
controls_changed = FALSE;
}
void compute_controls_layout(void)

View file

@ -50,6 +50,7 @@ int focus_control_index;
snd_mixer_selem_id_t *current_selem_id;
unsigned int current_control_flags;
bool control_values_changed;
bool controls_changed;
enum channel_mask {
@ -59,20 +60,15 @@ enum channel_mask {
static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask)
{
unsigned int i;
if (mask & (SND_CTL_EVENT_MASK_REMOVE |
SND_CTL_EVENT_MASK_INFO |
SND_CTL_EVENT_MASK_VALUE))
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
controls_changed = TRUE;
} else {
if (mask & SND_CTL_EVENT_MASK_VALUE)
control_values_changed = TRUE;
if (mask & SND_CTL_EVENT_MASK_INFO)
for (i = 0; i < controls_count; ++i)
if (controls[i].elem == elem) {
controls[i].flags &= ~IS_ACTIVE;
if (snd_mixer_selem_is_active(controls[i].elem))
controls[i].flags |= IS_ACTIVE;
}
if (mask & SND_CTL_EVENT_MASK_INFO)
controls_changed = TRUE;
}
return 0;
}

View file

@ -24,6 +24,7 @@ extern int focus_control_index;
extern snd_mixer_selem_id_t *current_selem_id;
extern unsigned int current_control_flags;
extern bool control_values_changed;
extern bool controls_changed;
void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt);