Introduction
Introduction Statistics Contact Development Disclaimer Help
mix.c - spoon - set dwm status
git clone git://git.codemadness.org/spoon
Log
Files
Refs
LICENSE
---
mix.c (5735B)
---
1 #include <err.h>
2 #include <stdio.h>
3
4 #include "util.h"
5
6 #ifdef __OpenBSD__
7 #include <errno.h>
8 #include <poll.h>
9 #include <sndio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #define MAX_CHANNELS 16
14
15 static struct sioctl_hdl *hdl = NULL;
16 static struct pollfd *pfds = NULL;
17
18 static struct {
19 unsigned int addr;
20 int val;
21 } channel[MAX_CHANNELS];
22 static size_t nchannels = 0;
23
24 static int
25 get_output(void)
26 {
27 size_t i;
28 int val;
29
30 if (nchannels == 0)
31 return 0;
32
33 val = 0;
34 for (i = 0; i < nchannels; i++)
35 val += channel[i].val;
36 return 100 * ((val / (double)nchannels) / 255.0);
37 }
38
39 static void
40 ondesc(void *arg, struct sioctl_desc *desc, int val)
41 {
42 size_t i;
43
44 if (desc == NULL)
45 return;
46
47 if (desc->type != SIOCTL_NUM ||
48 strcmp(desc->func, "level") != 0 ||
49 strcmp(desc->node0.name, "output") != 0)
50 return;
51
52 for (i = 0; i < nchannels; i++)
53 if (channel[i].addr == desc->addr)
54 break;
55
56 if (i < nchannels) {
57 channel[i].val = val;
58 return;
59 }
60
61 if (nchannels >= MAX_CHANNELS) {
62 warnx("too many channels");
63 return;
64 }
65 channel[i].addr = desc->addr;
66 channel[i].val = val;
67 nchannels++;
68 }
69
70 static void
71 onval(void *arg, unsigned int addr, unsigned int val)
72 {
73 size_t i;
74
75 for (i = 0; i < nchannels; i++)
76 if (channel[i].addr == addr) {
77 channel[i].val = val;
78 break;
79 }
80 }
81
82 static int
83 do_init(void)
84 {
85 hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
86 if (hdl == NULL) {
87 warnx("sioctl_open %s", SIO_DEVANY);
88 return 0;
89 }
90 if (!sioctl_ondesc(hdl, ondesc, NULL)) {
91 warnx("sioctl_ondesc");
92 sioctl_close(hdl);
93 return 0;
94 }
95 sioctl_onval(hdl, onval, NULL);
96
97 return 1;
98 }
99
100 static int
101 poll_peek(void)
102 {
103 int nfds, revents;
104
105 if (pfds == NULL) {
106 pfds = malloc(sizeof(struct pollfd) * sioctl_nfds(hdl));
107 if (pfds == NULL) {
108 warnx("out of memory");
109 goto out;
110 }
111 }
112
113 nfds = sioctl_pollfd(hdl, pfds, POLLIN);
114 if (nfds == 0)
115 return 1;
116 while (poll(pfds, nfds, 0) == -1)
117 if (errno != EINTR) {
118 warn("sioctl poll");
119 goto out;
120 }
121 revents = sioctl_revents(hdl, pfds);
122 if (revents & POLLHUP) {
123 warnx("sioctl disconnected");
124 goto out;
125 }
126
127 return 1;
128
129 out:
130 free(pfds);
131 pfds = NULL;
132 sioctl_close(hdl);
133
134 return 0;
135 }
136
137 int
138 mixread(void *arg, char *buf, size_t len)
139 {
140 static int init_done = 0;
141 struct pollfd *pfds;
142 int nfds;
143
144 if (!init_done) {
145 if (!do_init())
146 return -1;
147 init_done = 1;
148 }
149
150 init_done = poll_peek();
151 snprintf(buf, len, "%d%%", get_output());
152
153 return 0;
154 }
155 #elif __linux__ && !USE_TINYALSA
156 #include <alsa/asoundlib.h>
157
158 static int active;
159 static int master;
160
161 int
162 mixer_elem_cb(snd_mixer_elem_t *elem, unsigned int mask)
163 {
164 long min, max, vol;
165 int r;
166
167 r = snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_UNK…
168 if (r < 0) {
169 warnx("snd_mixer_selem_get_playback_switch: %s",
170 snd_strerror(r));
171 return -1;
172 }
173 DPRINTF_D(active);
174 r = snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
175 if (r < 0) {
176 warnx("snd_mixer_selem_get_playback_volume_range: %s",
177 snd_strerror(r));
178 return -1;
179 }
180 r = snd_mixer_selem_get_playback_volume(elem,
181 SND_MIXER_SCHN_UNKNOWN, &vol);
182 if (r < 0) {
183 warnx("snd_mixer_selem_get_playback_volume: %s",
184 snd_strerror(r));
185 return -1;
186 }
187 /* compute percentage */
188 vol -= min;
189 max -= min;
190 if (max == 0)
191 master = 0;
192 else
193 master = 100 * vol / max;
194 DPRINTF_D(master);
195 return 0;
196 }
197
198 int
199 mixread(void *arg, char *buf, size_t len)
200 {
201 snd_mixer_selem_id_t *id;
202 snd_mixer_elem_t *elem;
203 static snd_mixer_t *mixerp;
204 struct pollfd pfd[1];
205 int r;
206
207 snd_mixer_selem_id_alloca(&id);
208 snd_mixer_selem_id_set_name(id, "Master");
209 snd_mixer_selem_id_set_index(id, 0);
210
211 if (mixerp != NULL)
212 goto readvol;
213
214 r = snd_mixer_open(&mixerp, O_RDONLY);
215 if (r < 0) {
216 warnx("snd_mixer_open: %s", snd_strerror(r));
217 return -1;
218 }
219 r = snd_mixer_attach(mixerp, "default");
220 if (r < 0) {
221 warnx("snd_mixer_attach: %s", snd_strerror(r));
222 goto out;
223 }
224 r = snd_mixer_selem_register(mixerp, NULL, NULL);
225 if (r < 0) {
226 warnx("snd_mixer_selem_register: %s", snd_strerror(r));
227 goto out;
228 }
229 r = snd_mixer_load(mixerp);
230 if (r < 0) {
231 warnx("snd_mixer_load: %s", snd_strerror(r));
232 goto out;
233 }
234 elem = snd_mixer_find_selem(mixerp, id);
235 if (elem == NULL) {
236 warnx("could not find mixer element");
237 goto out;
238 }
239 snd_mixer_elem_set_callback(elem, mixer_elem_cb);
240 /* force the callback the first time around */
241 r = mixer_elem_cb(elem, 0);
242 if (r < 0)
243 goto out;
244 readvol:
245 r = snd_mixer_poll_descriptors(mixerp, pfd, LEN(pfd));
246 if (r < 0) {
247 warnx("snd_mixer_poll_descriptors: %s", snd_strerror(r));
248 goto out;
249 }
250 r = snd_mixer_handle_events(mixerp);
251 if (r < 0) {
252 warnx("snd_mixer_handle_events: %s", snd_strerror(r));
253 goto out;
254 }
255 if (active)
256 snprintf(buf, len, "%d%%", master);
257 else
258 snprintf(buf, len, "!%d%%", master);
259 return 0;
260 out:
261 snd_mixer_free(mixerp);
262 snd_mixer_close(mixerp);
263 mixerp = NULL;
264 return -1;
265 }
266 #elif __linux__ && USE_TINYALSA
267 #include <tinyalsa/asoundlib.h>
268
269 int
270 mixread(void *arg, char *buf, size_t len)
271 {
272 static struct mixer *mixer;
273 struct mixer_ctl *ctl;
274 int cur, max;
275
276 if (mixer == NULL && (mixer = mixer_open(0)) == NULL) {
277 warnx("mixer_open() failed");
278 return -1;
279 }
280
281 if ((ctl = mixer_get_ctl_by_name(mixer, "Master Playback Switch"…
282 == NULL) {
283 warnx("mixer_get_ctl_by_name() failed");
284 goto out;
285 }
286 if (!mixer_ctl_get_value(ctl, 0)) {
287 snprintf(buf, len, "mute");
288 return 0;
289 }
290
291 if ((ctl = mixer_get_ctl_by_name(mixer, "Master Playback Volume"…
292 == NULL) {
293 warnx("mixer_get_ctl_by_name() failed");
294 goto out;
295 }
296
297 cur = mixer_ctl_get_value(ctl, 0);
298 max = mixer_ctl_get_range_max(ctl);
299 snprintf(buf, len, "%d%%", cur * 100 / max);
300 return 0;
301
302 out:
303 mixer_close(mixer);
304 mixer = NULL;
305 return -1;
306 }
307 #endif
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.