File 0006-alsamixer-fix-handling-of-removed-controls.patch of Package alsa-utils

From f2826072732951b1d4e1bacd8115f9e6a98932d5 Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <clemens@ladisch.de>
Date: Fri, 19 Oct 2012 12:16:33 +0200
Subject: [PATCH 6/9] 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>
---
 alsamixer/mainloop.c      |  9 ++++++++-
 alsamixer/mixer_display.c |  1 -
 alsamixer/mixer_widget.c  | 20 ++++++++------------
 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);
-- 
1.8.0.1
openSUSE Build Service is sponsored by