From e1eccedf0b08ae0ee49ae71efcbdcefc7107682b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 31 May 2016 15:56:22 +0200 Subject: Initial commit. --- Makefile | 21 +++++++++ mixnotify.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 Makefile create mode 100644 mixnotify.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..91e2718 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -fPIC -g +LDFLAGS = -lasound + +TARGET = mixnotify + +OBJS = mixnotify.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + cc ${LDFLAGS} -o $@ $(OBJS) + +%.o: %.c + cc $(CFLAGS) -MMD -MF $(@:.o=.d) -MT $@ -c -o $@ $< + +clean: + -rm -f *.o *.d $(TARGET) + +-include $(OBJS:.o=.d) + +.PHONY: clean diff --git a/mixnotify.c b/mixnotify.c new file mode 100644 index 0000000..734ffc0 --- /dev/null +++ b/mixnotify.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016 Anton Khirnov + * + * mixnotify is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * mixnotify is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with mixnotify. If not, see . + */ + +#include + +#include +#include + +typedef struct MixerPrivate { + snd_mixer_elem_t *elem; +} MixerPrivate; + +static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask) +{ + MixerPrivate *s = snd_mixer_elem_get_callback_private(elem); + long val, min, max; + int ret; + + if (!(mask & SND_CTL_EVENT_MASK_VALUE)) + return 0; + + ret = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_UNKNOWN, &val); + if (ret < 0) { + fprintf(stderr, "Error getting element volume: %d (%s)\n"); + return ret; + } + + ret = snd_mixer_selem_get_playback_volume_range(elem, &min, &max); + if (ret < 0) { + fprintf(stderr, "Error getting element volume range: %d (%s)\n", + ret, snd_strerror(ret)); + return ret; + } + + fprintf(stdout, "%ld %ld %ld\n", val, min, max); + fflush(stdout); + + return 0; +} + +int main(int argc, const char **argv) +{ + static const char *ctl_name = "default"; + static const char *elem_name = "Master"; + + MixerPrivate priv = { NULL }; + + snd_mixer_t *mixer = NULL; + snd_mixer_elem_t *elem; + int ret; + + if (argc > 1) + ctl_name = argv[1]; + if (argc > 2) + elem_name = argv[2]; + + fprintf(stderr, "Using CTL: %s\n", ctl_name); + fprintf(stderr, "Using mixer element: %s\n", elem_name); + + ret = snd_mixer_open(&mixer, 0); + if (ret < 0) { + fprintf(stderr, "Error opening a new mixer: %d (%s)\n", + ret, snd_strerror(ret)); + return -1; + } + + ret = snd_mixer_attach(mixer, ctl_name); + if (ret < 0) { + fprintf(stderr, "Error attachng a HCTL '%s' to the mixer: %d (%s)\n", + ctl_name, ret, snd_strerror(ret)); + ret = -1; + goto fail; + } + + ret = snd_mixer_selem_register(mixer, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Error registering simple element class: %d (%s)\n", + ctl_name, ret, snd_strerror(ret)); + ret = -1; + goto fail; + } + + ret = snd_mixer_load(mixer); + if (ret < 0) { + fprintf(stderr, "Error loading mixer elements: %d (%s)\n", + ret, snd_strerror(ret)); + ret = -1; + goto fail; + } + + for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) { + snd_mixer_elem_type_t type = snd_mixer_elem_get_type(elem); + + if (type == SND_MIXER_ELEM_SIMPLE && + !strcmp(snd_mixer_selem_get_name(elem), elem_name)) + break; + } + if (!elem) { + fprintf(stderr, "Mixer element '%s' not found\n", elem_name); + ret = -1; + goto fail; + } + + snd_mixer_elem_set_callback_private(elem, &priv); + snd_mixer_elem_set_callback(elem, elem_callback); + + while (!(ret = snd_mixer_wait(mixer, -1))) { + ret = snd_mixer_handle_events(mixer); + if (ret < 0) { + fprintf(stderr, "Error handling events: %d (%s)\n", + ret, snd_strerror(ret)); + ret = -1; + goto fail; + } + } + if (ret < 0) { + fprintf(stderr, "Error waiting for mixer events: %d (%s)\n", + ret, snd_strerror(ret)); + ret = -1; + goto fail; + } + +fail: + snd_mixer_close(mixer); + + return ret; +} -- cgit v1.2.3