i3 - improved tiling WM


print_volume(linux): Open a new mixer every time.

Patch status: merged

Patch by oblique

Long description:

This fix the following bug:
    If you switch your sound card on-the-fly, print_volume continued to
    use the old sound card.

To apply this patch, use:
curl http://cr.i3wm.org/patch/161/raw.patch | git am

b/src/print_volume.c

16
@@ -26,29 +26,6 @@
17
 #include "i3status.h"
18
 #include "queue.h"
19
 
20
-#ifdef LINUX
21
-struct mixer_hdl {
22
-	char *device;
23
-	char *mixer;
24
-	int mixer_idx;
25
-	snd_mixer_selem_id_t *sid;
26
-	snd_mixer_t *m;
27
-	snd_mixer_elem_t *elem;
28
-	long min;
29
-	long max;
30
-
31
-	TAILQ_ENTRY(mixer_hdl) handles;
32
-};
33
-
34
-TAILQ_HEAD(handles_head, mixer_hdl) cached = TAILQ_HEAD_INITIALIZER(cached);
35
-
36
-static void free_hdl(struct mixer_hdl *hdl) {
37
-	free(hdl->device);
38
-	free(hdl->mixer);
39
-	free(hdl);
40
-}
41
-#endif
42
-
43
 void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *device, const char *mixer, int mixer_idx) {
44
         char *outwalk = buffer;
45
 	int pbval = 1;
46
@@ -61,100 +38,69 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
47
                 free(instance);
48
         }
49
 #ifdef LINUX
50
-	/* Check if we already opened the mixer and get the handle
51
-	 * from cache if so */
52
-	bool found = false;
53
 	int err;
54
-	struct mixer_hdl *hdl;
55
-	TAILQ_FOREACH(hdl, &cached, handles) {
56
-		if (strcmp(hdl->device, device) != 0 ||
57
-		    strcmp(hdl->mixer, mixer) != 0 ||
58
-		    hdl->mixer_idx != mixer_idx)
59
-			continue;
60
-		found = true;
61
-		break;
62
-	}
63
-
64
-	if (!found) {
65
-		if ((hdl = calloc(sizeof(struct mixer_hdl), 1)) == NULL)
66
-			goto out;
67
-
68
-		if ((hdl->device = strdup(device)) == NULL) {
69
-			free(hdl);
70
-			goto out;
71
-		}
72
-
73
-		if ((hdl->mixer = strdup(mixer)) == NULL) {
74
-			free(hdl->device);
75
-			free(hdl);
76
-			goto out;
77
-		}
78
-
79
-		hdl->mixer_idx = mixer_idx;
80
-		snd_mixer_selem_id_malloc(&(hdl->sid));
81
-		if (hdl->sid == NULL) {
82
-			free_hdl(hdl);
83
-			goto out;
84
-		}
85
+	snd_mixer_t *m;
86
+	snd_mixer_selem_id_t *sid;
87
+	snd_mixer_elem_t *elem;
88
+	long min, max, val;
89
+	int avg;
90
 
91
-		if ((err = snd_mixer_open(&(hdl->m), 0)) < 0) {
92
-			fprintf(stderr, "i3status: ALSA: Cannot open mixer: %s\n", snd_strerror(err));
93
-			free_hdl(hdl);
94
-			goto out;
95
-		}
96
+	if ((err = snd_mixer_open(&m, 0)) < 0) {
97
+		fprintf(stderr, "i3status: ALSA: Cannot open mixer: %s\n", snd_strerror(err));
98
+		goto out;
99
+	}
100
 
101
-		/* Attach this mixer handle to the given device */
102
-		if ((err = snd_mixer_attach(hdl->m, device)) < 0) {
103
-			fprintf(stderr, "i3status: ALSA: Cannot attach mixer to device: %s\n", snd_strerror(err));
104
-			snd_mixer_close(hdl->m);
105
-			free_hdl(hdl);
106
-			goto out;
107
-		}
108
+	/* Attach this mixer handle to the given device */
109
+	if ((err = snd_mixer_attach(m, device)) < 0) {
110
+		fprintf(stderr, "i3status: ALSA: Cannot attach mixer to device: %s\n", snd_strerror(err));
111
+		snd_mixer_close(m);
112
+		goto out;
113
+	}
114
 
115
-		/* Register this mixer */
116
-		if ((err = snd_mixer_selem_register(hdl->m, NULL, NULL)) < 0) {
117
-			fprintf(stderr, "i3status: ALSA: snd_mixer_selem_register: %s\n", snd_strerror(err));
118
-			snd_mixer_close(hdl->m);
119
-			free_hdl(hdl);
120
-			goto out;
121
-		}
122
+	/* Register this mixer */
123
+	if ((err = snd_mixer_selem_register(m, NULL, NULL)) < 0) {
124
+		fprintf(stderr, "i3status: ALSA: snd_mixer_selem_register: %s\n", snd_strerror(err));
125
+		snd_mixer_close(m);
126
+		goto out;
127
+	}
128
 
129
-		if ((err = snd_mixer_load(hdl->m)) < 0) {
130
-			fprintf(stderr, "i3status: ALSA: snd_mixer_load: %s\n", snd_strerror(err));
131
-			snd_mixer_close(hdl->m);
132
-			free_hdl(hdl);
133
-			goto out;
134
-		}
135
+	if ((err = snd_mixer_load(m)) < 0) {
136
+		fprintf(stderr, "i3status: ALSA: snd_mixer_load: %s\n", snd_strerror(err));
137
+		snd_mixer_close(m);
138
+		goto out;
139
+	}
140
 
141
-		/* Find the given mixer */
142
-		snd_mixer_selem_id_set_index(hdl->sid, mixer_idx);
143
-		snd_mixer_selem_id_set_name(hdl->sid, mixer);
144
-		if (!(hdl->elem = snd_mixer_find_selem(hdl->m, hdl->sid))) {
145
-			fprintf(stderr, "i3status: ALSA: Cannot find mixer %s (index %i)\n",
146
-				snd_mixer_selem_id_get_name(hdl->sid), snd_mixer_selem_id_get_index(hdl->sid));
147
-			snd_mixer_close(hdl->m);
148
-			free_hdl(hdl);
149
-			goto out;
150
-		}
151
+	snd_mixer_selem_id_malloc(&sid);
152
+	if (sid == NULL) {
153
+		snd_mixer_close(m);
154
+		goto out;
155
+	}
156
 
157
-		/* Get the volume range to convert the volume later */
158
-		snd_mixer_selem_get_playback_volume_range(hdl->elem, &(hdl->min), &(hdl->max));
159
-		TAILQ_INSERT_TAIL(&cached, hdl, handles);
160
+	/* Find the given mixer */
161
+	snd_mixer_selem_id_set_index(sid, mixer_idx);
162
+	snd_mixer_selem_id_set_name(sid, mixer);
163
+	if (!(elem = snd_mixer_find_selem(m, sid))) {
164
+		fprintf(stderr, "i3status: ALSA: Cannot find mixer %s (index %i)\n",
165
+			snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
166
+		snd_mixer_close(m);
167
+		snd_mixer_selem_id_free(sid);
168
+		goto out;
169
 	}
170
 
171
-	long val;
172
-	snd_mixer_handle_events (hdl->m);
173
-	snd_mixer_selem_get_playback_volume (hdl->elem, 0, &val);
174
-	int avg;
175
-	if (hdl->max != 100) {
176
-		float avgf = ((float)val / hdl->max) * 100;
177
+	/* Get the volume range to convert the volume later */
178
+	snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
179
+
180
+	snd_mixer_handle_events (m);
181
+	snd_mixer_selem_get_playback_volume (elem, 0, &val);
182
+	if (max != 100) {
183
+		float avgf = ((float)val / max) * 100;
184
 		avg = (int)avgf;
185
 		avg = (avgf - avg < 0.5 ? avg : (avg+1));
186
 	} else avg = (int)val;
187
 
188
 	/* Check for mute */
189
-	if (snd_mixer_selem_has_playback_switch(hdl->elem)) {
190
-		if ((err = snd_mixer_selem_get_playback_switch(hdl->elem, 0, &pbval)) < 0)
191
+	if (snd_mixer_selem_has_playback_switch(elem)) {
192
+		if ((err = snd_mixer_selem_get_playback_switch(elem, 0, &pbval)) < 0)
193
 			fprintf (stderr, "i3status: ALSA: playback_switch: %s\n", snd_strerror(err));
194
 		if (!pbval)  {
195
 			START_COLOR("color_degraded");
196
@@ -162,6 +108,9 @@ void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *
197
 		}
198
 	}
199
 
200
+	snd_mixer_close(m);
201
+	snd_mixer_selem_id_free(sid);
202
+
203
 	const char *walk = fmt;
204
 	for (; *walk != '\0'; walk++) {
205
 		if (*walk != '%') {