#include #include #include #include #include static void die(const char *errmsg) { fputs(errmsg, stderr); exit(EXIT_FAILURE); } static snd_mixer_t *alsainit(const char *card) { snd_mixer_t *handle; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); return handle; } static void alsaclose(snd_mixer_t *handle) { snd_mixer_close(handle); } static snd_mixer_elem_t *alsamixer(snd_mixer_t *handle, const char *mixer) { snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, mixer); return snd_mixer_find_selem(handle, sid); } static int ismuted(snd_mixer_elem_t *mixer) { int on; snd_mixer_selem_get_playback_switch(mixer, SND_MIXER_SCHN_MONO, &on); return !on; } static int getvol(snd_mixer_elem_t *mixer) { long vol, min, max; snd_mixer_selem_get_playback_volume_range(mixer, &min, &max); snd_mixer_selem_get_playback_volume(mixer, SND_MIXER_SCHN_MONO, &vol); vol = vol < max ? (vol > min ? vol : min) : max; return vol * 100.0 / max + 0.5; } static char *gettime() { static char timestr[60]; time_t rawtime; time(&rawtime); strftime(timestr, sizeof(timestr), "%d %B %H:%M", localtime(&rawtime)); return timestr; } int main(int argc, char *argv[]) { char buf[100]; static Display *dpy; snd_mixer_t *alsa; snd_mixer_elem_t *mixer; if (!(dpy = XOpenDisplay(NULL))) die("dstatus: cannot open display \n"); if (!(alsa = alsainit("default"))) die("dstatus: cannot initialize alsa\n"); if (!(mixer = alsamixer(alsa, "Master"))) die("dstatus: cannot get mixer\n"); while (1) { snprintf(buf, sizeof(buf), "%s | %d%%%s", gettime(), getvol(mixer), ismuted(mixer) ? " [off]" : ""); XStoreName(dpy, DefaultRootWindow(dpy), buf); XSync(dpy, False); snd_mixer_wait(alsa, 10000); snd_mixer_handle_events(alsa); } alsaclose(alsa); XCloseDisplay(dpy); return 0; }