From 1e958d6853cce034de62628e941fc8852b906b27 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 28 Aug 2015 08:59:59 +0200 Subject: [PATCH] move the mixer api to a dedicated "mixer" branch --- sndioctl/Makefile.in | 53 --- sndioctl/sndioctl.1 | 156 -------- sndioctl/sndioctl.c | 926 ------------------------------------------- xvolkeys/Makefile.in | 52 --- xvolkeys/xvolkeys.1 | 54 --- xvolkeys/xvolkeys.c | 319 --------------- 6 files changed, 1560 deletions(-) delete mode 100644 sndioctl/Makefile.in delete mode 100644 sndioctl/sndioctl.1 delete mode 100644 sndioctl/sndioctl.c delete mode 100644 xvolkeys/Makefile.in delete mode 100644 xvolkeys/xvolkeys.1 delete mode 100644 xvolkeys/xvolkeys.c diff --git a/sndioctl/Makefile.in b/sndioctl/Makefile.in deleted file mode 100644 index 463cf2b..0000000 --- a/sndioctl/Makefile.in +++ /dev/null @@ -1,53 +0,0 @@ -# extra includes paths (-I options) -INCLUDE = -I../libsndio -I../bsd-compat - -# extra libraries paths (-L options) -LIB = -L../libsndio - -# extra defines (-D options) -DEFS = -DDEBUG @defs@ - -# extra libraries (-l options) -LDADD = -lsndio @ldadd@ - -# variables defined on configure script command line (if any) -@vars@ - -# -# binaries, documentation, man pages and examples will be installed in -# ${BIN_DIR}, ${MAN1_DIR} -# -BIN_DIR = @bindir@ -MAN1_DIR = @mandir@/man1 - -# -# programs to build -# -PROG = sndioctl -MAN1 = sndioctl.1 - -all: ${PROG} ${MAN1} - -install: - mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR} - cp sndioctl ${DESTDIR}${BIN_DIR} - cp sndioctl.1 ${DESTDIR}${MAN1_DIR} - -uninstall: - cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG} - cd ${DESTDIR}${MAN1_DIR} && rm -f ${MAN1} - -clean: - rm -f -- *.o sndioctl - -# ---------------------------------------------------------- dependencies --- - -OBJS = sndioctl.o - -sndioctl: ${OBJS} - ${CC} ${LDFLAGS} ${LIB} -o sndioctl ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $< - -sndioctl.o: sndioctl.c diff --git a/sndioctl/sndioctl.1 b/sndioctl/sndioctl.1 deleted file mode 100644 index a189bb1..0000000 --- a/sndioctl/sndioctl.1 +++ /dev/null @@ -1,156 +0,0 @@ -.\" $OpenBSD$ -.\" -.\" Copyright (c) 2007 Alexandre Ratchov -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate: April 8 2011 $ -.Dt SNDIOCTL 1 -.Os -.Sh NAME -.Nm sndioctl -.Nd control audio mixer parameters -.Sh SYNOPSIS -.Nm -.Bk -words -.Op Fl iv -.Op Fl f Ar device -.Op Ar command ... -.Ek -.Nm -.Bk -words -.Fl d -.Ek -.Sh DESCRIPTION -The -.Nm -utility can display or change mixer parameters of -.Xr sndio 7 -audio devices. -The options are as follows: -.Bl -tag -width Ds -.It Fl d -Dump the raw list of available parameters and exit. -Useful to debug device drivers or programs using the -.Xr siomix_open 3 -interface. -.It Fl f Ar device -Use this -.Xr sndio 7 -mixer device. -.It Fl m -Monitor and display mixer changes. -.It Fl n -Don't hide program names associated to audio streams (by -default they are displayed as comments). -.It Fl i -Display characteristics of requested parameters -instead of their values. -.It Fl v -Enable verbose mode, a.k.a. multi-channel mode. -By default parameters affecting different channels -of the same stream are disguised as a single mono -parameter to hide details that are not essential. -.El -.Pp -If no commands are specified all valid parameters are displayed on -.Em stdout . -Unless -.Fl d -or -.Fl i -are used, displayed parameters are valid commands. -The set of available controls depends on the mixer device. -.Pp -Commands use the following two formats to display and set -parameters respectively: -.Pp -.Dl . -.Dl .= -.Pp -On the left-hand side, the affected substream is specified -by the stream name followed by an optional -channel range. -Examples of left-hand side terms: -.Pp -.Dl spkr.level -.Dl spkr[2-5].level -.Dl spkr[6].level -.Pp -There are three parameter types: numbers, selectors and vectors. -.Pp -Numbers are specified in decimal and follow the same semantics -as MIDI controllers. -Values are in the 0..127 range and 64 is the neutral state (if applicable). -Two-state controls (switches) take any value in the 0..63 range or -in the 64..127 range typically to the -.Em off -and -.Em on -states respectively. -.Pp -If a decimal is prefixed by the plus (minus) sign then -the given value is added to (subtracted from) the -current value of the control. -If -.Qq \&! -is used instead of a number, then the switch is toggled. -Examples: -.Pp -.Dl spkr.level=85 -.Dl spkr[4-5].level=+10 -.Dl spkr.mute=0 -.Dl spkr.mute=! -.Pp -.Pp Selectors -Selector values are substreams; they are specified -as the stream name followed by an optional channel -range. -If no channel range is specified, the same -range as the stream specified on the left-hand side is used. -For instance the following are equivalent: -.Pp -.Dl record[1].source=mic -.Dl record[1].source=mic[1] -.Pp -.Pp Vectors -Vectors are arrays of numbers. -Values are specified as comma-separated components. -Each component is a substream, followed by -a colon, followed by a number. -If the colon and the number are omitted, then 127 is -assumed. -If a component is missing, then 0 is assumed. -Example: -.Pp -.Dl monitor.mix=play:120,linein:85 -.Dl record.source=mic,linein -.Pp -Numbers are specified as discussed above. -Note that a vector of switches is equivalent to -a list. -.Sh SEE ALSO -.Xr siomix_open 3 -.Sh EXAMPLES -The following will set all -.Ar level -parameters that control the -.Ar spkr -stream to zero. -.Pp -.Dl $ sndioctl spkr.level=0 -.Pp -The following commands are equivalent: -.Pp -.Dl $ sndioctl record[0].source=mic[0] record[1].source=mic[1] -.Dl $ sndioctl record.source=mic diff --git a/sndioctl/sndioctl.c b/sndioctl/sndioctl.c deleted file mode 100644 index 4961b7c..0000000 --- a/sndioctl/sndioctl.c +++ /dev/null @@ -1,926 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2007-2011 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include - -#define IS_IDENT(c) (((c) >= 'a' && (c) <= 'z') || \ - ((c) >= 'A' && (c) <= 'Z') || \ - ((c) >= '0' && (c) <= '9') || \ - ((c) == '_')) - -struct info { - struct info *next; - struct siomix_desc desc; - unsigned ctladdr; -#define MODE_IGNORE 0 /* ignore this value */ -#define MODE_PRINT 1 /* print-only, don't change value */ -#define MODE_SET 2 /* set to newval value */ -#define MODE_ADD 3 /* increase current value by newval */ -#define MODE_SUB 4 /* decrease current value by newval */ -#define MODE_TOGGLE 5 /* toggle current value */ - unsigned mode; - int curval, newval; -}; - -int cmpdesc(struct siomix_desc *, struct siomix_desc *); -int isdiag(struct info *); -struct info *selpos(struct info *); -struct info *vecent(struct info *, char *, char *); -struct info *nextgrp(struct info *); -struct info *nextpar(struct info *); -struct info *firstent(struct info *, char *); -struct info *nextent(struct info *, int); -int matchpar(struct info *, char *, char *); -int matchent(struct info *, char *, char *); -int ismono(struct info *); -void print_chan(struct siomix_chan *, int); -void print_desc(struct info *, int); -void print_val(struct info *, int); -void print_par(struct info *, int); -int parse_name(char **, char *); -int parse_dec(char **, unsigned *); -int parse_chan(char **, char *, char *); -int parse_modeval(char **, int *, unsigned *); -void dump(void); -int cmd(char *); -void commit(void); -void list(void); -void ondesc(void *, struct siomix_desc *, int); -void onctl(void *, unsigned, unsigned); - -struct siomix_hdl *hdl; -struct info *infolist; -int n_flag = 0, i_flag = 0, v_flag = 0, m_flag = 0; - -/* - * compare two siomix_desc structures, used to sort infolist - */ -int -cmpdesc(struct siomix_desc *d1, struct siomix_desc *d2) -{ - int res; - - res = strcmp(d1->chan0.str, d2->chan0.str); - if (res != 0) - return res; - res = d1->type - d2->type; - if (res != 0) - return res; - res = strcmp(d1->func, d2->func); - if (res != 0) - return res; - res = strcmp(d1->chan0.opt, d2->chan0.opt); - if (d1->type == SIOMIX_VEC || - d1->type == SIOMIX_LIST) { - if (res != 0) - return res; - res = strcmp(d1->chan1.str, d2->chan1.str); - if (res != 0) - return res; - res = strcmp(d1->chan1.opt, d2->chan1.opt); - } - return res; -} - -/* - * return true of the selector or vector entry is diagonal - */ -int -isdiag(struct info *e) -{ - if (strlen(e->desc.chan0.opt) == 0 || - strlen(e->desc.chan1.opt) == 0) - return 1; - return strcmp(e->desc.chan1.opt, e->desc.chan0.opt) == 0; -} - -/* - * find the value of the given selector parameter - */ -struct info * -selpos(struct info *i) -{ - while (i != NULL) { - if (i->curval) - return i; - i = i->next; - } - fprintf(stderr, "selpos: not found, bogus mixer\n"); - abort(); -} - -/* - * find the selector or vector entry with the given name and channels - */ -struct info * -vecent(struct info *i, char *vstr, char *vopt) -{ - while (i != NULL) { - if ((strcmp(i->desc.chan1.str, vstr) == 0) && - (strlen(vopt) == 0 || strcmp(i->desc.chan1.opt, vopt) == 0)) - break; - i = i->next; - } - return i; -} - -/* - * find the next parameter group - */ -struct info * -nextgrp(struct info *i) -{ - char *str, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - return i; - } - return NULL; -} - -/* - * find the next parameter of the same group - */ -struct info * -nextpar(struct info *i) -{ - char *str, *opt, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - opt = i->desc.chan0.opt; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - break; - if (strcmp(i->desc.chan0.opt, opt) != 0) - return i; - } - return NULL; -} - -/* - * return the first structure having of a selector or vector group - */ -struct info * -firstent(struct info *g, char *vstr) -{ - char *astr, *func; - struct info *i; - - astr = g->desc.chan0.str; - func = g->desc.func; - for (i = g; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, astr) != 0 || - strcmp(i->desc.func, func) != 0) - break; - if (!isdiag(i)) - continue; - if (strcmp(i->desc.chan1.str, vstr) == 0) - return i; - } - return NULL; -} - -/* - * find the next entry of the given selector or vector, if the mono flag - * is set then the whole group is searched and off-diagonal entries are - * skipped - */ -struct info * -nextent(struct info *i, int mono) -{ - char *str, *opt, *func; - - func = i->desc.func; - str = i->desc.chan0.str; - opt = i->desc.chan0.opt; - for (i = i->next; i != NULL; i = i->next) { - if (strcmp(i->desc.chan0.str, str) != 0 || - strcmp(i->desc.func, func) != 0) - return NULL; - if (mono) - return i; - if (strcmp(i->desc.chan0.opt, opt) == 0) - return i; - } - return NULL; -} - -/* - * return true if parameter matches the given name and channel range - */ -int -matchpar(struct info *i, char *astr, char *aopt) -{ - if (strcmp(i->desc.chan0.str, astr) != 0) - return 0; - if (strlen(aopt) == 0) - return 1; - else if (strlen(i->desc.chan0.opt) == 0) { - fprintf(stderr, "opt used for parameter with no opt\n"); - exit(1); - } - return strcmp(i->desc.chan0.opt, aopt) == 0; -} - -/* - * return true if selector or vector entry matches the given name and - * channel range - */ -int -matchent(struct info *i, char *vstr, char *vopt) -{ - if (strcmp(i->desc.chan1.str, vstr) != 0) - return 0; - if (strlen(vopt) == 0) - return 1; - else if (strlen(i->desc.chan1.opt) == 0) { - fprintf(stderr, "opt used for parameter with no opt\n"); - exit(1); - } - return strcmp(i->desc.chan1.opt, vopt) == 0; -} - -/* - * return true if the given group can be represented as a signle mono - * parameter - */ -int -ismono(struct info *g) -{ - struct info *p1, *p2; - struct info *e1, *e2; - - p1 = g; - switch (g->desc.type) { - case SIOMIX_LABEL: - break; - case SIOMIX_NUM: - case SIOMIX_SW: - for (p2 = g; p2 != NULL; p2 = nextpar(p2)) { - if (p2->curval != p1->curval) - return 0; - } - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - for (p2 = g; p2 != NULL; p2 = nextpar(p2)) { - for (e2 = p2; e2 != NULL; e2 = nextent(e2, 0)) { - if (!isdiag(e2)) { - if (e2->curval != 0) - return 0; - } else { - e1 = vecent(p1, - e2->desc.chan1.str, - p1->desc.chan0.opt); - if (e1 == NULL) - continue; - if (e1->curval != e2->curval) - return 0; - } - } - } - break; - } - return 1; -} - -/* - * print a sub-stream, eg. "spkr[4-7]" - */ -void -print_chan(struct siomix_chan *c, int mono) -{ - printf("%s", c->str); - if (!mono && strlen(c->opt) > 0) { - printf("[%s]", c->opt); - } -} - -/* - * print info about the parameter - */ -void -print_desc(struct info *p, int mono) -{ - struct info *e; - int more; - - switch (p->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - printf("*"); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - more = 0; - for (e = p; e != NULL; e = nextent(e, mono)) { - if (mono) { - if (!isdiag(e)) - continue; - if (e != firstent(p, e->desc.chan1.str)) - continue; - } - if (more) - printf(","); - print_chan(&e->desc.chan1, mono); - printf(":*"); - more = 1; - } - } -} - -/* - * print parameter value - */ -void -print_val(struct info *p, int mono) -{ - struct info *e; - int more; - - switch (p->desc.type) { - case SIOMIX_LABEL: - printf("%s", p->desc.chan1.str); - //print_chan(&e->desc.chan1, mono); - break; - case SIOMIX_NUM: - case SIOMIX_SW: - printf("%u", p->curval); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - more = 0; - for (e = p; e != NULL; e = nextent(e, mono)) { - if (mono) { - if (!isdiag(e)) - continue; - if (e != firstent(p, e->desc.chan1.str)) - continue; - } - if (more) - printf(","); - print_chan(&e->desc.chan1, mono); - printf(":%u", e->curval); - more = 1; - } - } -} - -/* - * print ``='' string (including '\n') - */ -void -print_par(struct info *p, int mono) -{ - struct info *i; - int more; - - print_chan(&p->desc.chan0, mono); - printf(".%s=", p->desc.func); - if (i_flag) - print_desc(p, mono); - else - print_val(p, mono); - - /* append a comment with the labels (if any) */ - if (!n_flag && p->desc.type != SIOMIX_LABEL) { - more = 0; - for (i = infolist; i != NULL; i = i->next) { - if (i->desc.type != SIOMIX_LABEL) - continue; - if (strcmp(i->desc.chan0.str, p->desc.chan0.str) == 0 && - strcmp(i->desc.chan0.opt, p->desc.chan0.opt) == 0) { - if (!more) { - printf("\t#"); - more = 1; - } - printf(" %s=%s", i->desc.func, i->desc.chan1.str); - } - } - } - printf("\n"); -} - -/* - * parse a stream name or parameter name - */ -int -parse_name(char **line, char *name) -{ - char *p = *line; - unsigned len = 0; - - if (!IS_IDENT(*p)) { - fprintf(stderr, "letter/digit expected near '%s'\n", p); - return 0; - } - while (IS_IDENT(*p)) { - if (len >= SIOMIX_NAMEMAX - 1) { - name[SIOMIX_NAMEMAX - 1] = '\0'; - fprintf(stderr, "%s...: too long\n", name); - return 0; - } - name[len++] = *p; - p++; - } - name[len] = '\0'; - *line = p; - return 1; -} - -/* - * parse a decimal number - */ -int -parse_dec(char **line, unsigned *num) -{ - char *p = *line; - unsigned val = 0; - - if (*p < '0' || *p > '9') { - fprintf(stderr, "number expected near '%s'\n", p); - return 0; - } - while (*p >= '0' && *p <= '9') { - val = 10 * val + (*p - '0'); - if (val > SIOMIX_INTMAX) { - fprintf(stderr, "integer too large\n"); - return 0; - } - p++; - } - *num = val; - *line = p; - return 1; -} - -/* - * parse a sub-stream, eg. "spkr[4-7]" - */ -int -parse_chan(char **line, char *str, char *opt) -{ - char *p = *line; - - if (!parse_name(&p, str)) - return 0; - if (*p != '[') { - *opt = 0; - *line = p; - return 1; - } - p++; - if (!parse_name(&p, opt)) - return 0; - if (*p != ']') { - fprintf(stderr, "']' expected near '%s'\n", p); - return 0; - } - p++; - *line = p; - return 1; -} - -/* - * parse a decimal prefixed by the optional mode - */ -int -parse_modeval(char **line, int *rmode, unsigned *rval) -{ - char *p = *line; - unsigned mode; - - switch (*p) { - case '+': - mode = MODE_ADD; - p++; - break; - case '-': - mode = MODE_SUB; - p++; - break; - case '!': - mode = MODE_TOGGLE; - p++; - break; - default: - mode = MODE_SET; - } - if (mode != MODE_TOGGLE) { - if (!parse_dec(&p, rval)) - return 0; - } - *line = p; - *rmode = mode; - return 1; -} - -/* - * dump the whole mixer, useful for debugging - */ -void -dump(void) -{ - struct info *i; - - for (i = infolist; i != NULL; i = i->next) { - printf("%03u:", i->ctladdr); - print_chan(&i->desc.chan0, 0); - printf(".%s", i->desc.func); - printf("="); - switch (i->desc.type) { - case SIOMIX_LABEL: - print_chan(&i->desc.chan1, 0); - break; - case SIOMIX_NUM: - case SIOMIX_SW: - printf("* (%u)", i->curval); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - print_chan(&i->desc.chan1, 0); - printf(":* (%u)", i->curval); - } - printf("\n"); - } -} - -/* - * parse and execute a command ``[=]'' - */ -int -cmd(char *line) -{ - char *pos = line; - struct info *i, *e, *g; - char func[SIOMIX_NAMEMAX], astr[SIOMIX_NAMEMAX], vstr[SIOMIX_NAMEMAX]; - char aopt[SIOMIX_NAMEMAX], vopt[SIOMIX_NAMEMAX]; - unsigned val, npar = 0, nent = 0; - int comma, mode; - - if (!parse_chan(&pos, astr, aopt)) - return 0; - if (*pos != '.') { - fprintf(stderr, "'.' expected near '%s'\n", pos); - return 0; - } - pos++; - if (!parse_name(&pos, func)) - return 0; - for (g = infolist;; g = g->next) { - if (g == NULL) { - fprintf(stderr, "%s.%s: no such group\n", astr, func); - return 0; - } - if (strcmp(g->desc.func, func) == 0 && - strcmp(g->desc.chan0.str, astr) == 0) - break; - } - g->mode = MODE_PRINT; - if (*pos != '=') { - if (*pos != '\0') { - fprintf(stderr, "junk at end of command\n"); - return 0; - } - return 1; - } - pos++; - if (i_flag) { - printf("can't set values in info mode\n"); - return 0; - } - npar = 0; - switch (g->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - if (!parse_modeval(&pos, &mode, &val)) - return 0; - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - i->mode = mode; - i->newval = val; - npar++; - } - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - for (e = i; e != NULL; e = nextent(e, 0)) { - e->newval = 0; - e->mode = MODE_SET; - } - npar++; - } - comma = 0; - for (;;) { - if (*pos == '\0') - break; - if (comma) { - if (*pos != ',') - break; - pos++; - } - if (!parse_chan(&pos, vstr, vopt)) - return 0; - if (*pos == ':') { - pos++; - if (!parse_modeval(&pos, &mode, &val)) - return 0; - } else { - val = SIOMIX_INTMAX; - mode = MODE_SET; - } - nent = 0; - for (i = g; i != NULL; i = nextpar(i)) { - if (!matchpar(i, astr, aopt)) - continue; - for (e = i; e != NULL; e = nextent(e, 0)) { - if (matchent(e, vstr, vopt)) { - e->newval = val; - e->mode = mode; - nent++; - } - } - } - if (nent == 0) { - fprintf(stderr, "%s[%s]: invalid value\n", vstr, vopt); - print_par(g, 0); - exit(1); - } - comma = 1; - } - } - if (npar == 0) { - fprintf(stderr, "%s: invalid parameter\n", line); - exit(1); - } - if (*pos != '\0') { - printf("%s: junk at end of command\n", pos); - exit(1); - } - return 1; -} - -/* - * write on the mixer device entries with the ``set'' flag - */ -void -commit(void) -{ - struct info *i; - int val; - - for (i = infolist; i != NULL; i = i->next) { - val = 0xdeadbeef; - switch (i->mode) { - case MODE_IGNORE: - case MODE_PRINT: - continue; - case MODE_SET: - val = i->newval; - break; - case MODE_ADD: - val = i->curval + i->newval; - if (val > SIOMIX_INTMAX) - val = SIOMIX_INTMAX; - break; - case MODE_SUB: - val = i->curval - i->newval; - if (val < 0) - val = 0; - break; - case MODE_TOGGLE: - val = (i->curval >= SIOMIX_HALF) ? 0 : SIOMIX_INTMAX; - } - switch (i->desc.type) { - case SIOMIX_NUM: - case SIOMIX_SW: - siomix_setctl(hdl, i->ctladdr, val); - break; - case SIOMIX_VEC: - case SIOMIX_LIST: - siomix_setctl(hdl, i->ctladdr, val); - } - i->curval = val; - } -} - -/* - * print all parameters - */ -void -list(void) -{ - struct info *p, *g; - - for (g = infolist; g != NULL; g = nextgrp(g)) { - if (g->mode == MODE_IGNORE) - continue; - if (i_flag) { - if (v_flag) { - for (p = g; p != NULL; p = nextpar(p)) - print_par(p, 0); - } else - print_par(g, 1); - } else { - if (v_flag || !ismono(g)) { - for (p = g; p != NULL; p = nextpar(p)) - print_par(p, 0); - } else - print_par(g, 1); - } - } -} - -/* - * register a new knob/button, called from the poll() loop. this may be - * called when label string changes, in which case we update the - * existing label widged rather than inserting a new one. - */ -void -ondesc(void *arg, struct siomix_desc *d, int curval) -{ - struct info *i, **pi; - int cmp; - - if (d == NULL) - return; - - /* - * find the right position to insert the new widget - */ - for (pi = &infolist; (i = *pi) != NULL; pi = &i->next) { - cmp = cmpdesc(d, &i->desc); - if (cmp == 0) { - /* label is updated */ - if (i->desc.type == SIOMIX_LABEL) { - memcpy(i->desc.chan1.str, d->chan1.str, - SIOMIX_NAMEMAX); - print_par(i, 0); - return; - } - fprintf(stderr, "fatal: duplicate mixer knob:\n"); - print_par(i, 0); - exit(1); - } - if (cmp < 0) - break; - } - i = malloc(sizeof(struct info)); - if (i == NULL) { - perror("malloc"); - exit(1); - } - i->desc = *d; - i->ctladdr = d->addr; - i->curval = i->newval = curval; - i->mode = MODE_IGNORE; - i->next = *pi; - *pi = i; -} - -/* - * update a knob/button state, called from the poll() loop - */ -void -onctl(void *arg, unsigned addr, unsigned val) -{ - struct info *i; - - if (v_flag >= 1) - fprintf(stderr, "onctl (%d, %d)\n", addr, val); - for (i = infolist; i != NULL; i = i->next) { - if (i->ctladdr != addr) - continue; - i->curval = val; - print_par(i, 0); - } -} - -int -main(int argc, char **argv) -{ - char *devname = SIOMIX_DEVANY; - int i, c, d_flag = 0; - struct info *g; - struct pollfd *pfds; - int nfds, revents; - - while ((c = getopt(argc, argv, "df:imnv")) != -1) { - switch (c) { - case 'd': - d_flag = 1; - break; - case 'f': - devname = optarg; - break; - case 'i': - i_flag = 1; - break; - case 'm': - m_flag = 1; - break; - case 'n': - n_flag = 1; - break; - case 'v': - v_flag = 1; - break; - default: - fprintf(stderr, "usage: sndioctl " - "[-dimnv] [-f device] [command ...]\n"); - exit(1); - } - } - argc -= optind; - argv += optind; - - hdl = siomix_open(devname, SIOMIX_READ | SIOMIX_WRITE, 0); - if (hdl == NULL) { - fprintf(stderr, "%s: can't open mixer device\n", devname); - exit(1); - } - if (!siomix_ondesc(hdl, ondesc, NULL)) { - fprintf(stderr, "%s: can't get mixer description\n", devname); - exit(1); - } - siomix_onctl(hdl, onctl, NULL); - - if (d_flag) { - if (argc > 0) { - fprintf(stderr, - "commands are not allowed with -d option\n"); - exit(1); - } - dump(); - } else { - if (argc == 0) { - for (g = infolist; g != NULL; g = nextgrp(g)) { - if (g->desc.type == SIOMIX_LABEL && !n_flag) - continue; - g->mode = MODE_PRINT; - } - } else { - for (i = 0; i < argc; i++) { - if (!cmd(argv[i])) - return 1; - } - } - commit(); - list(); - } - if (m_flag) { - pfds = malloc(sizeof(struct pollfd) * siomix_nfds(hdl)); - if (pfds == NULL) { - perror("malloc"); - exit(1); - } - for (;;) { - nfds = siomix_pollfd(hdl, pfds, POLLIN); - if (nfds == 0) - break; - while (poll(pfds, nfds, -1) < 0) { - if (errno != EINTR) { - perror("poll"); - exit(1); - } - } - revents = siomix_revents(hdl, pfds); - if (revents & POLLHUP) { - fprintf(stderr, "disconnected\n"); - break; - } - } - free(pfds); - } - siomix_close(hdl); - return 0; -} diff --git a/xvolkeys/Makefile.in b/xvolkeys/Makefile.in deleted file mode 100644 index 3e977f5..0000000 --- a/xvolkeys/Makefile.in +++ /dev/null @@ -1,52 +0,0 @@ -# extra includes paths (-I options) -INCLUDE = -I/usr/X11R6/include -I../libsndio -I../bsd-compat - -# extra libraries paths (-L options) -LIB = -L/usr/X11R6/lib -L../libsndio - -# extra defines (-D options) -DEFS = -DDEBUG @defs@ - -# extra libraries (-l options) -LDADD = -lX11 -lsndio @ldadd@ - -# variables defined on configure script command line (if any) -@vars@ - -# -# binaries, documentation, man pages and examples will be installed in -# ${BIN_DIR}, ${MAN1_DIR} -# -BIN_DIR = @bindir@ -MAN1_DIR = @mandir@/man1 - -# -# programs to build -# -PROG = xvolkeys - -all: ${PROG} - -install: - mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR} - cp ${PROG} ${DESTDIR}${BIN_DIR} - cp ${PROG:=.1} ${DESTDIR}${MAN1_DIR} - -uninstall: - cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG} - cd ${DESTDIR}${MAN1_DIR} && rm -f ${PROG:=.1} - -clean: - rm -f -- *.o xvolkeys - -# ---------------------------------------------------------- dependencies --- - -OBJS = xvolkeys.o - -xvolkeys: ${OBJS} - ${CC} ${LDFLAGS} ${LIB} -o xvolkeys ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $< - -xvolkeys.o: xvolkeys.c diff --git a/xvolkeys/xvolkeys.1 b/xvolkeys/xvolkeys.1 deleted file mode 100644 index f9c510f..0000000 --- a/xvolkeys/xvolkeys.1 +++ /dev/null @@ -1,54 +0,0 @@ -.\" $OpenBSD$ -.\" -.\" Copyright (c) 2014 Alexandre Ratchov -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate$ -.Dt XVOLKEYS 1 -.Os -.Sh NAME -.Nm xvolkeys -.Nd hot-keys in X to control sndiod master volume -.Sh SYNOPSIS -.Nm xvolkeys -.Op Fl D -.Op Fl v -.Op Fl f Ar device -.Sh DESCRIPTION -The -.Nm -increments or -decrements the -.Xr sndiod 1 -master volume whenever the "+" and "-" keys -are pressed while the Control and Alt keys are held down. -It is meant to be started as background process by -.Xr xinit 1 -or -.Xr xdm 1 -session startup scripts. -It exits when X session terminates. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl D -Daemonize. -.It Fl f Ar device -Audio device to control volume of. -.It Fl v -Increase log verbosity. -.El -.Sh SEE ALSO -.Xr sndiod 1 -.Xr sndio 7 diff --git a/xvolkeys/xvolkeys.c b/xvolkeys/xvolkeys.c deleted file mode 100644 index d0c7b27..0000000 --- a/xvolkeys/xvolkeys.c +++ /dev/null @@ -1,319 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2014 Alexandre Ratchov - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * X keysyms to increment / decrement volume: + and - - */ -#define KEY_INC XK_plus -#define KEY_DEC XK_minus - -/* - * modifiers: Alt + Ctrl - */ -#define MODMASK (Mod1Mask | ControlMask) - -/* - * volume increment - */ -#define VOL_INC 9 - -char *dev_name; -struct pollfd pfds[16]; -struct siomix_hdl *hdl; -unsigned int master_addr, master_val = SIOMIX_INTMAX; -int master_found = 0; -int verbose; - -/* - * X bits - */ -Display *dpy; -KeyCode inc_code, dec_code; -KeySym *inc_map, *dec_map; - -/* - * new control - */ -static void -mixer_ondesc(void *unused, struct siomix_desc *desc, int val) -{ - if (desc == NULL) - return; - if (master_found) - return; - if (strcmp(desc->chan0.str, "sndiod0") == 0 && - strcmp(desc->func, "level") == 0) { - master_found = 1; - master_addr = desc->addr; - master_val = val; - if (verbose) - fprintf(stderr, "%s: master at addr %u, value = %u\n", - dev_name, master_addr, master_val); - } -} - -/* - * control value changed - */ -static void -mixer_onctl(void *unused, unsigned int addr, unsigned int val) -{ - if (addr == master_addr) { - if (verbose) - fprintf(stderr, "master changed %u -> %u\n", master_val, val); - master_val = val; - } -} - -/* - * if there's an error, close connection to sndiod - */ -static void -mixer_disconnect(void) -{ - if (!siomix_eof(hdl)) - return; - if (verbose) - fprintf(stderr, "%s: mixer device disconnected\n", dev_name); - siomix_close(hdl); - hdl = NULL; -} - -/* - * connect to sndiod - */ -static int -mixer_connect(void) -{ - if (hdl != NULL) - return 1; - hdl = siomix_open(dev_name, SIOMIX_READ | SIOMIX_WRITE, 0); - if (hdl == NULL) { - if (verbose) - fprintf(stderr, "%s: couldn't open mixer device\n", - dev_name); - return 0; - } - master_found = 0; - siomix_ondesc(hdl, mixer_ondesc, NULL); - siomix_onctl(hdl, mixer_onctl, NULL); - if (!master_found) - fprintf(stderr, "%s: warning, couldn't find master control\n", - dev_name); - return 1; -} - -/* - * send master volume message and to the server - */ -static void -mixer_incrvol(int incr) -{ - int vol; - - if (!mixer_connect()) - return; - vol = master_val + incr; - if (vol > SIOMIX_INTMAX) - vol = SIOMIX_INTMAX; - if (vol < 0) - vol = 0; - if (master_val != (unsigned int)vol) { - master_val = vol; - if (hdl && master_found) { - if (verbose) { - fprintf(stderr, "%s: setting volume to %d\n", - dev_name, vol); - } - siomix_setctl(hdl, master_addr, master_val); - mixer_disconnect(); - } - } -} - -/* - * register hot-keys in X - */ -static void -grab_keys(void) -{ - unsigned int i, scr, nscr; - int nret; - - if (verbose) - fprintf(stderr, "grabbing keys\n"); - inc_code = XKeysymToKeycode(dpy, KEY_INC); - inc_map = XGetKeyboardMapping(dpy, inc_code, 1, &nret); - if (nret <= ShiftMask) { - fprintf(stderr, "couldn't get keymap for '+' key\n"); - exit(1); - } - - dec_code = XKeysymToKeycode(dpy, KEY_DEC); - dec_map = XGetKeyboardMapping(dpy, dec_code, 1, &nret); - if (nret <= ShiftMask) { - fprintf(stderr, "couldn't get keymap for '-' key\n"); - exit(1); - } - - nscr = ScreenCount(dpy); - for (i = 0; i <= 0xff; i++) { - if ((i & MODMASK) != 0) - continue; - for (scr = 0; scr != nscr; scr++) { - - XGrabKey(dpy, inc_code, i | MODMASK, - RootWindow(dpy, scr), 1, - GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, dec_code, i | MODMASK, - RootWindow(dpy, scr), 1, - GrabModeAsync, GrabModeAsync); - } - } -} - -/* - * unregister hot-keys - */ -static void -ungrab_keys(void) -{ - unsigned int scr, nscr; - - if (verbose) - fprintf(stderr, "ungrabbing keys\n"); - - XFree(inc_map); - XFree(dec_map); - - nscr = ScreenCount(dpy); - for (scr = 0; scr != nscr; scr++) - XUngrabKey(dpy, AnyKey, AnyModifier, RootWindow(dpy, scr)); -} - -int -main(int argc, char **argv) -{ - int scr; - XEvent xev; - int c, nfds; - int background, revents; - - /* - * parse command line options - */ - dev_name = SIOMIX_DEVANY; - verbose = 0; - background = 0; - while ((c = getopt(argc, argv, "Df:q:v")) != -1) { - switch (c) { - case 'D': - background = 1; - break; - case 'v': - verbose++; - break; - - case 'q': /* compat */ - case 'f': - dev_name = optarg; - break; - default: - goto bad_usage; - } - } - argc -= optind; - argv += optind; - if (argc > 0) { - bad_usage: - fprintf(stderr, "usage: xvolkeys [-Dv] [-f device]\n"); - } - - dpy = XOpenDisplay(NULL); - if (dpy == 0) { - fprintf(stderr, "Couldn't open display\n"); - exit(1); - } - - /* mask non-key events for each screan */ - for (scr = 0; scr != ScreenCount(dpy); scr++) - XSelectInput(dpy, RootWindow(dpy, scr), KeyPress); - - (void)mixer_connect(); - - grab_keys(); - - if (background) { - verbose = 0; - if (daemon(0, 0) < 0) { - perror("daemon"); - exit(1); - } - } - - while (1) { - while (XPending(dpy)) { - XNextEvent(dpy, &xev); - if (xev.type == MappingNotify) { - if (xev.xmapping.request != MappingKeyboard) - continue; - if (verbose) - fprintf(stderr, "keyboard remapped\n"); - ungrab_keys(); - grab_keys(); - } - if (xev.type != KeyPress) - continue; - if (xev.xkey.keycode == inc_code && - inc_map[xev.xkey.state & ShiftMask] == KEY_INC) { - mixer_incrvol(VOL_INC); - } else if (xev.xkey.keycode == dec_code && - dec_map[xev.xkey.state & ShiftMask] == KEY_DEC) { - mixer_incrvol(-VOL_INC); - } - } - nfds = (hdl != NULL) ? siomix_pollfd(hdl, pfds, 0) : 0; - pfds[nfds].fd = ConnectionNumber(dpy); - pfds[nfds].events = POLLIN; - while (poll(pfds, nfds + 1, -1) < 0 && errno == EINTR) - ; /* nothing */ - if (hdl) { - revents = siomix_revents(hdl, pfds); - if (revents & POLLHUP) - mixer_disconnect(); - else if (revents & POLLIN) { - /* what */ - } - } - } - XFree(inc_map); - XFree(dec_map); - XCloseDisplay(dpy); - if (hdl) - siomix_close(hdl); - return 0; -}