/* * 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; }