diff options
author | Marvin Borner | 2019-03-05 01:09:01 +0100 |
---|---|---|
committer | Marvin Borner | 2019-03-05 01:09:01 +0100 |
commit | 55457187d18221e76bd12f0fb2cfab65c49b92fb (patch) | |
tree | 8db042d2d80710d54100c2709ad4332153ac848a /slstatus/components/volume.c |
Initial commit
Diffstat (limited to 'slstatus/components/volume.c')
-rw-r--r-- | slstatus/components/volume.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/slstatus/components/volume.c b/slstatus/components/volume.c new file mode 100644 index 0000000..61cec90 --- /dev/null +++ b/slstatus/components/volume.c @@ -0,0 +1,109 @@ +/* See LICENSE file for copyright and license details. */ +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include "../util.h" + +#if defined(__OpenBSD__) + #include <sys/audioio.h> + + const char * + vol_perc(const char *card) + { + static int cls = -1; + mixer_devinfo_t mdi; + mixer_ctrl_t mc; + int afd = -1, m = -1, v = -1; + + if ((afd = open(card, O_RDONLY)) < 0) { + warn("open '%s':", card); + return NULL; + } + + for (mdi.index = 0; cls == -1; mdi.index++) { + if (ioctl(afd, AUDIO_MIXER_DEVINFO, &mdi) < 0) { + warn("ioctl 'AUDIO_MIXER_DEVINFO':"); + close(afd); + return NULL; + } + if (mdi.type == AUDIO_MIXER_CLASS && + !strncmp(mdi.label.name, + AudioCoutputs, + MAX_AUDIO_DEV_LEN)) + cls = mdi.index; + } + for (mdi.index = 0; v == -1 || m == -1; mdi.index++) { + if (ioctl(afd, AUDIO_MIXER_DEVINFO, &mdi) < 0) { + warn("ioctl 'AUDIO_MIXER_DEVINFO':"); + close(afd); + return NULL; + } + if (mdi.mixer_class == cls && + ((mdi.type == AUDIO_MIXER_VALUE && + !strncmp(mdi.label.name, + AudioNmaster, + MAX_AUDIO_DEV_LEN)) || + (mdi.type == AUDIO_MIXER_ENUM && + !strncmp(mdi.label.name, + AudioNmute, + MAX_AUDIO_DEV_LEN)))) { + mc.dev = mdi.index, mc.type = mdi.type; + if (ioctl(afd, AUDIO_MIXER_READ, &mc) < 0) { + warn("ioctl 'AUDIO_MIXER_READ':"); + close(afd); + return NULL; + } + if (mc.type == AUDIO_MIXER_VALUE) + v = mc.un.value.num_channels == 1 ? + mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] : + (mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] > + mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] ? + mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] : + mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT]); + else if (mc.type == AUDIO_MIXER_ENUM) + m = mc.un.ord; + } + } + + close(afd); + + return bprintf("%d", m ? 0 : v * 100 / 255); + } +#else + #include <sys/soundcard.h> + + const char * + vol_perc(const char *card) + { + size_t i; + int v, afd, devmask; + char *vnames[] = SOUND_DEVICE_NAMES; + + if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { + warn("open '%s':", card); + return NULL; + } + + if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { + warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); + close(afd); + return NULL; + } + for (i = 0; i < LEN(vnames); i++) { + if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { + if (ioctl(afd, MIXER_READ(i), &v) < 0) { + warn("ioctl 'MIXER_READ(%ld)':", i); + close(afd); + return NULL; + } + } + } + + close(afd); + + return bprintf("%d", v & 0xff); + } +#endif |