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 != '%') { |