Introduction
Introduction Statistics Contact Development Disclaimer Help
volume.c - slstatus - status monitor
git clone git://git.suckless.org/slstatus
Log
Files
Refs
README
LICENSE
---
volume.c (4319B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/ioctl.h>
6 #include <unistd.h>
7
8 #include "../slstatus.h"
9 #include "../util.h"
10
11 #if defined(__OpenBSD__) | defined(__FreeBSD__)
12 #include <poll.h>
13 #include <sndio.h>
14 #include <stdlib.h>
15 #include <sys/queue.h>
16
17 struct control {
18 LIST_ENTRY(control) next;
19 unsigned int addr;
20 #define CTRL_NONE 0
21 #define CTRL_LEVEL 1
22 #define CTRL_MUTE 2
23 unsigned int type;
24 unsigned int maxval;
25 unsigned int val;
26 };
27
28 static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(con…
29 static struct pollfd *pfds;
30 static struct sioctl_hdl *hdl;
31 static int initialized;
32
33 /*
34 * Call-back to obtain the description of all audio controls.
35 */
36 static void
37 ondesc(void *unused, struct sioctl_desc *desc, int val)
38 {
39 struct control *c, *ctmp;
40 unsigned int type = CTRL_NONE;
41
42 if (desc == NULL)
43 return;
44
45 /* Delete existing audio control with the same address. …
46 LIST_FOREACH_SAFE(c, &controls, next, ctmp) {
47 if (desc->addr == c->addr) {
48 LIST_REMOVE(c, next);
49 free(c);
50 break;
51 }
52 }
53
54 /* Only match output.level and output.mute audio control…
55 if (desc->group[0] != 0 ||
56 strcmp(desc->node0.name, "output") != 0)
57 return;
58 if (desc->type == SIOCTL_NUM &&
59 strcmp(desc->func, "level") == 0)
60 type = CTRL_LEVEL;
61 else if (desc->type == SIOCTL_SW &&
62 strcmp(desc->func, "mute") == 0)
63 type = CTRL_MUTE;
64 else
65 return;
66
67 c = malloc(sizeof(struct control));
68 if (c == NULL) {
69 warn("sndio: failed to allocate audio control\n"…
70 return;
71 }
72
73 c->addr = desc->addr;
74 c->type = type;
75 c->maxval = desc->maxval;
76 c->val = val;
77 LIST_INSERT_HEAD(&controls, c, next);
78 }
79
80 /*
81 * Call-back invoked whenever an audio control changes.
82 */
83 static void
84 onval(void *unused, unsigned int addr, unsigned int val)
85 {
86 struct control *c;
87
88 LIST_FOREACH(c, &controls, next) {
89 if (c->addr == addr)
90 break;
91 }
92 c->val = val;
93 }
94
95 static void
96 cleanup(void)
97 {
98 struct control *c;
99
100 if (hdl) {
101 sioctl_close(hdl);
102 hdl = NULL;
103 }
104
105 free(pfds);
106 pfds = NULL;
107
108 while (!LIST_EMPTY(&controls)) {
109 c = LIST_FIRST(&controls);
110 LIST_REMOVE(c, next);
111 free(c);
112 }
113 }
114
115 static int
116 init(void)
117 {
118 hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
119 if (hdl == NULL) {
120 warn("sndio: cannot open device");
121 goto failed;
122 }
123
124 if (!sioctl_ondesc(hdl, ondesc, NULL)) {
125 warn("sndio: cannot set control description call…
126 goto failed;
127 }
128
129 if (!sioctl_onval(hdl, onval, NULL)) {
130 warn("sndio: cannot set control values call-back…
131 goto failed;
132 }
133
134 pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd));
135 if (pfds == NULL) {
136 warn("sndio: cannot allocate pollfd structures");
137 goto failed;
138 }
139
140 return 1;
141 failed:
142 cleanup();
143 return 0;
144 }
145
146 const char *
147 vol_perc(const char *unused)
148 {
149 struct control *c;
150 int n, v, value;
151
152 if (!initialized)
153 initialized = init();
154
155 if (hdl == NULL)
156 return NULL;
157
158 n = sioctl_pollfd(hdl, pfds, POLLIN);
159 if (n > 0) {
160 n = poll(pfds, n, 0);
161 if (n > 0) {
162 if (sioctl_revents(hdl, pfds) & POLLHUP)…
163 warn("sndio: disconnected");
164 cleanup();
165 initialized = 0;
166 return NULL;
167 }
168 }
169 }
170
171 value = 100;
172 LIST_FOREACH(c, &controls, next) {
173 if (c->type == CTRL_MUTE && c->val == 1)
174 value = 0;
175 else if (c->type == CTRL_LEVEL) {
176 v = (c->val * 100 + c->maxval / 2) / c->…
177 /* For multiple channels return the mini…
178 if (v < value)
179 value = v;
180 }
181 }
182
183 return bprintf("%d", value);
184 }
185 #else
186 #include <sys/soundcard.h>
187
188 const char *
189 vol_perc(const char *card)
190 {
191 size_t i;
192 int v, afd, devmask;
193 char *vnames[] = SOUND_DEVICE_NAMES;
194
195 if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) {
196 warn("open '%s':", card);
197 return NULL;
198 }
199
200 if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) …
201 warn("ioctl 'SOUND_MIXER_READ_DEVMASK':");
202 close(afd);
203 return NULL;
204 }
205 for (i = 0; i < LEN(vnames); i++) {
206 if (devmask & (1 << i) && !strcmp("vol", vnames[…
207 if (ioctl(afd, MIXER_READ(i), &v) < 0) {
208 warn("ioctl 'MIXER_READ(%ld)':",…
209 close(afd);
210 return NULL;
211 }
212 }
213 }
214
215 close(afd);
216
217 return bprintf("%d", v & 0xff);
218 }
219 #endif
You are viewing proxied material from suckless.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.