Xinqi Bao's Git
1 /* See LICENSE file for copyright and license details. */
10 #if defined(__OpenBSD__)
11 #include <sys/queue.h>
17 LIST_ENTRY(control
) next
;
27 static LIST_HEAD(, control
) controls
= LIST_HEAD_INITIALIZER(controls
);
28 static struct pollfd
*pfds
;
29 static struct sioctl_hdl
*hdl
;
30 static int initialized
;
33 * Call-back to obtain the description of all audio controls.
36 ondesc(void *unused
, struct sioctl_desc
*desc
, int val
)
38 struct control
*c
, *ctmp
;
39 unsigned int type
= CTRL_NONE
;
44 /* Delete existing audio control with the same address. */
45 LIST_FOREACH_SAFE(c
, &controls
, next
, ctmp
) {
46 if (desc
->addr
== c
->addr
) {
53 /* Only match output.level and output.mute audio controls. */
54 if (desc
->group
[0] != 0 ||
55 strcmp(desc
->node0
.name
, "output") != 0)
57 if (desc
->type
== SIOCTL_NUM
&&
58 strcmp(desc
->func
, "level") == 0)
60 else if (desc
->type
== SIOCTL_SW
&&
61 strcmp(desc
->func
, "mute") == 0)
66 c
= malloc(sizeof(struct control
));
68 warn("sndio: failed to allocate audio control\n");
74 c
->maxval
= desc
->maxval
;
76 LIST_INSERT_HEAD(&controls
, c
, next
);
80 * Call-back invoked whenever an audio control changes.
83 onval(void *unused
, unsigned int addr
, unsigned int val
)
87 LIST_FOREACH(c
, &controls
, next
) {
107 while (!LIST_EMPTY(&controls
)) {
108 c
= LIST_FIRST(&controls
);
109 LIST_REMOVE(c
, next
);
117 hdl
= sioctl_open(SIO_DEVANY
, SIOCTL_READ
, 0);
119 warn("sndio: cannot open device");
123 if (!sioctl_ondesc(hdl
, ondesc
, NULL
)) {
124 warn("sndio: cannot set control description call-back");
128 if (!sioctl_onval(hdl
, onval
, NULL
)) {
129 warn("sndio: cannot set control values call-back");
133 pfds
= calloc(sioctl_nfds(hdl
), sizeof(struct pollfd
));
135 warn("sndio: cannot allocate pollfd structures");
146 vol_perc(const char *unused
)
152 initialized
= init();
157 n
= sioctl_pollfd(hdl
, pfds
, POLLIN
);
159 n
= poll(pfds
, n
, 0);
161 if (sioctl_revents(hdl
, pfds
) & POLLHUP
) {
162 warn("sndio: disconnected");
170 LIST_FOREACH(c
, &controls
, next
) {
171 if (c
->type
== CTRL_MUTE
&& c
->val
== 1)
173 else if (c
->type
== CTRL_LEVEL
) {
174 v
= (c
->val
* 100 + c
->maxval
/ 2) / c
->maxval
;
175 /* For multiple channels return the minimum. */
181 return bprintf("%d", value
);
184 #include <sys/soundcard.h>
187 vol_perc(const char *card
)
191 char *vnames
[] = SOUND_DEVICE_NAMES
;
193 if ((afd
= open(card
, O_RDONLY
| O_NONBLOCK
)) < 0) {
194 warn("open '%s':", card
);
198 if (ioctl(afd
, (int)SOUND_MIXER_READ_DEVMASK
, &devmask
) < 0) {
199 warn("ioctl 'SOUND_MIXER_READ_DEVMASK':");
203 for (i
= 0; i
< LEN(vnames
); i
++) {
204 if (devmask
& (1 << i
) && !strcmp("vol", vnames
[i
])) {
205 if (ioctl(afd
, MIXER_READ(i
), &v
) < 0) {
206 warn("ioctl 'MIXER_READ(%ld)':", i
);
215 return bprintf("%d", v
& 0xff);