summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2012-10-19 12:16:33 +0200
committerClemens Ladisch <clemens@ladisch.de>2012-10-19 12:16:33 +0200
commitf2826072732951b1d4e1bacd8115f9e6a98932d5 (patch)
tree31673d509c219098c0808f371036ffbaa6fbcb5b
parent6017849f1b9d406ac2c882ddbde408ada38c3d61 (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.c9
-rw-r--r--alsamixer/mixer_display.c1
-rw-r--r--alsamixer/mixer_widget.c20
-rw-r--r--alsamixer/mixer_widget.h1
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);