diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2012-10-19 12:16:33 +0200 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2012-10-19 12:16:33 +0200 |
commit | f2826072732951b1d4e1bacd8115f9e6a98932d5 (patch) | |
tree | 31673d509c219098c0808f371036ffbaa6fbcb5b | |
parent | 6017849f1b9d406ac2c882ddbde408ada38c3d61 (diff) |
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>
-rw-r--r-- | alsamixer/mainloop.c | 9 | ||||
-rw-r--r-- | alsamixer/mixer_display.c | 1 | ||||
-rw-r--r-- | alsamixer/mixer_widget.c | 20 | ||||
-rw-r--r-- | alsamixer/mixer_widget.h | 1 |
4 files changed, 17 insertions, 14 deletions
diff --git a/alsamixer/mainloop.c b/alsamixer/mainloop.c index dbfef9b..351f57f 100644 --- a/alsamixer/mainloop.c +++ b/alsamixer/mainloop.c @@ -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); } diff --git a/alsamixer/mixer_display.c b/alsamixer/mixer_display.c index 8ba396a..b1f79d0 100644 --- a/alsamixer/mixer_display.c +++ b/alsamixer/mixer_display.c @@ -657,7 +657,6 @@ void display_controls(void) display_no_controls(); } display_scroll_indicators(); - controls_changed = FALSE; } void compute_controls_layout(void) diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c index caaf777..0c2b9e0 100644 --- a/alsamixer/mixer_widget.c +++ b/alsamixer/mixer_widget.c @@ -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; } diff --git a/alsamixer/mixer_widget.h b/alsamixer/mixer_widget.h index da8628e..086611c 100644 --- a/alsamixer/mixer_widget.h +++ b/alsamixer/mixer_widget.h @@ -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); |