version 1.8, 2002/05/29 18:33:39 |
version 1.9, 2002/12/03 22:27:42 |
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGE. |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
|
/* |
|
* mixerctl(1) - a program to control audio mixing. |
|
*/ |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
|
void prfield(struct field *p, char *sep, int prvalset); |
void prfield(struct field *p, char *sep, int prvalset); |
int rdfield(struct field *p, char *q); |
int rdfield(struct field *p, char *q); |
int main(int argc, char **argv); |
int main(int argc, char **argv); |
|
void usage(void); |
|
|
FILE *out = stdout; |
FILE *out = stdout; |
|
|
char *prog; |
|
|
|
struct field { |
struct field { |
char *name; |
char *name; |
mixer_ctrl_t *valp; |
mixer_ctrl_t *valp; |
|
|
mixer_devinfo_t *infos; |
mixer_devinfo_t *infos; |
|
|
char * |
char * |
catstr(p, q) |
catstr(char *p, char *q) |
char *p; |
|
char *q; |
|
{ |
{ |
int len; |
int len; |
char *r; |
char *r; |
|
|
len = strlen(p) + 1 + strlen(q) + 1; |
len = strlen(p) + 1 + strlen(q) + 1; |
r = malloc(len); |
if ((r = malloc(len)) == NULL) |
|
err(1, "malloc()"); |
strlcpy(r, p, len); |
strlcpy(r, p, len); |
strlcat(r, ".", len); |
strlcat(r, ".", len); |
strlcat(r, q, len); |
strlcat(r, q, len); |
return r; |
return (r); |
} |
} |
|
|
struct field * |
struct field * |
findfield(name) |
findfield(char *name) |
char *name; |
|
{ |
{ |
int i; |
int i; |
for(i = 0; fields[i].name; i++) |
for(i = 0; fields[i].name; i++) |
if (strcmp(fields[i].name, name) == 0) |
if (strcmp(fields[i].name, name) == 0) |
return &fields[i]; |
return &fields[i]; |
return 0; |
return (0); |
} |
} |
|
|
void |
void |
prfield(p, sep, prvalset) |
prfield(struct field *p, char *sep, int prvalset) |
struct field *p; |
|
char *sep; |
|
int prvalset; |
|
{ |
{ |
mixer_ctrl_t *m; |
mixer_ctrl_t *m; |
int i, n; |
int i, n; |
|
|
fprintf(out, " %s", p->infp->un.v.units.name); |
fprintf(out, " %s", p->infp->un.v.units.name); |
break; |
break; |
default: |
default: |
printf("\n"); |
|
errx(1, "Invalid format."); |
errx(1, "Invalid format."); |
} |
} |
} |
} |
|
|
int |
int |
rdfield(p, q) |
rdfield(struct field *p, char *q) |
struct field *p; |
|
char *q; |
|
{ |
{ |
mixer_ctrl_t *m; |
mixer_ctrl_t *m; |
int v, v0, v1, mask; |
int v, v0, v1, mask; |
|
|
break; |
break; |
if (i < p->infp->un.e.num_mem) |
if (i < p->infp->un.e.num_mem) |
m->un.ord = p->infp->un.e.member[i].ord; |
m->un.ord = p->infp->un.e.member[i].ord; |
else { |
else |
warnx("Bad enum value %s", q); |
errx(1, "Bad enum value %s", q); |
return 0; |
|
} |
|
break; |
break; |
case AUDIO_MIXER_SET: |
case AUDIO_MIXER_SET: |
mask = 0; |
mask = 0; |
for(v = 0; q && *q; q = s) { |
for(v = 0; q && *q; q = s) { |
s = strchr(q, ','); |
if (s = strchr(q, ',')) |
if (s) |
|
*s++ = 0; |
*s++ = 0; |
for (i = 0; i < p->infp->un.s.num_mem; i++) |
for (i = 0; i < p->infp->un.s.num_mem; i++) |
if (strcmp(p->infp->un.s.member[i].label.name, q) == 0) |
if (strcmp(p->infp->un.s.member[i].label.name, q) == 0) |
break; |
break; |
if (i < p->infp->un.s.num_mem) { |
if (i < p->infp->un.s.num_mem) |
mask |= p->infp->un.s.member[i].mask; |
mask |= p->infp->un.s.member[i].mask; |
} else { |
else |
warnx("Bad set value %s", q); |
errx(1, "Bad set value %s", q); |
return 0; |
|
} |
|
} |
} |
m->un.mask = mask; |
m->un.mask = mask; |
break; |
break; |
|
|
m->un.value.level[0] = v; |
m->un.value.level[0] = v; |
break; |
break; |
} |
} |
} else { |
} else |
warnx("Bad number %s", q); |
errx(1, "Bad number %s", q); |
return 0; |
|
} |
|
} else { |
} else { |
if (sscanf(q, "%d,%d", &v0, &v1) == 2) { |
if (sscanf(q, "%d,%d", &v0, &v1) == 2) { |
switch (*q) { |
switch (*q) { |
|
|
m->un.value.level[1] += v; |
m->un.value.level[1] += v; |
break; |
break; |
default: |
default: |
m->un.value.level[0] = |
m->un.value.level[0] = v; |
m->un.value.level[1] = v; |
m->un.value.level[1] = v; |
break; |
break; |
} |
} |
} else { |
} else |
warnx("Bad numbers %s", q); |
errx(1, "Bad numbers %s", q); |
return 0; |
|
} |
|
} |
} |
break; |
break; |
default: |
default: |
errx(1, "Invalid format."); |
errx(1, "Invalid format."); |
} |
} |
p->changed = 1; |
p->changed = 1; |
return 1; |
return (1); |
} |
} |
|
|
int |
int |
main(argc, argv) |
main(int argc, char **argv) |
int argc; |
|
char **argv; |
|
{ |
{ |
int fd, i, j, ch, pos; |
int fd, i, j, ch, pos; |
int aflag = 0, wflag = 0, vflag = 0; |
int aflag = 0, wflag = 0, vflag = 0; |
|
|
char *sep = "="; |
char *sep = "="; |
mixer_devinfo_t dinfo; |
mixer_devinfo_t dinfo; |
mixer_ctrl_t val; |
mixer_ctrl_t val; |
int ndev; |
int ndev = 0; |
|
|
file = getenv("MIXERDEVICE"); |
if ((file = getenv("MIXERDEVICE")) == 0 || *file == '\0') |
if (file == 0) |
file = "/dev/mixer"; |
file = "/dev/mixer"; |
|
|
|
prog = *argv; |
|
|
|
while ((ch = getopt(argc, argv, "af:nvw")) != -1) { |
while ((ch = getopt(argc, argv, "af:nvw")) != -1) { |
switch(ch) { |
switch(ch) { |
case 'a': |
case 'a': |
|
|
break; |
break; |
case '?': |
case '?': |
default: |
default: |
usage: |
usage(); |
fprintf(out, "%s [-f file] [-v] [-n] name ...\n", prog); |
|
fprintf(out, "%s [-f file] [-v] [-n] -w name=value ...\n", prog); |
|
fprintf(out, "%s [-f file] [-v] [-n] -a\n", prog); |
|
exit(0); |
|
} |
} |
} |
} |
argc -= optind; |
argc -= optind; |
argv += optind; |
argv += optind; |
|
|
fd = open(file, wflag? O_RDWR : O_RDONLY); |
if ((fd = open(file, wflag ? O_RDWR : O_RDONLY)) < 0) |
if (fd < 0) |
|
err(1, "%s", file); |
err(1, "%s", file); |
|
|
for(ndev = 0; ; ndev++) { |
for(;;) { |
dinfo.index = ndev; |
dinfo.index = ndev++; |
if (ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo) < 0) |
if (ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo) < 0) |
break; |
break; |
} |
} |
|
|
if (ndev == 0) |
if (!ndev) |
errx(1, "no mixer devices configured"); |
errx(1, "no mixer devices configured"); |
|
|
rfields = calloc(ndev, sizeof *rfields); |
if ((rfields = calloc(ndev, sizeof *rfields)) == NULL || |
fields = calloc(ndev, sizeof *fields); |
(fields = calloc(ndev, sizeof *fields)) == NULL || |
infos = calloc(ndev, sizeof *infos); |
(infos = calloc(ndev, sizeof *infos)) == NULL || |
values = calloc(ndev, sizeof *values); |
(values = calloc(ndev, sizeof *values)) == NULL) |
|
err(1, "calloc()"); |
|
|
for(i = 0; i < ndev; i++) { |
for(i = 0; i < ndev; i++) { |
infos[i].index = i; |
infos[i].index = i; |
|
|
fields[i].name); |
fields[i].name); |
} |
} |
|
|
if (argc == 0 && aflag && !wflag) { |
if (!argc && aflag && !wflag) { |
for(i = 0; fields[i].name; i++) { |
for(i = 0; fields[i].name; i++) { |
prfield(&fields[i], sep, vflag); |
prfield(&fields[i], sep, vflag); |
fprintf(out, "\n"); |
fprintf(out, "\n"); |
|
|
while(argc--) { |
while(argc--) { |
char *q; |
char *q; |
|
|
q = strchr(*argv, '='); |
if (q = strchr(*argv, '=')) { |
if (q) { |
|
*q++ = 0; |
*q++ = 0; |
p = findfield(*argv); |
p = findfield(*argv); |
if (p == 0) |
if (p == 0) |
|
|
} |
} |
} |
} |
} |
} |
} else { |
} else |
warnx("No `=' in %s", *argv); |
warnx("No `=' in %s", *argv); |
} |
|
argv++; |
argv++; |
} |
} |
} else { |
} else { |
|
|
} |
} |
} |
} |
} else |
} else |
goto usage; |
usage(); |
exit(0); |
exit(0); |
|
} |
|
|
|
void |
|
usage(void) |
|
{ |
|
extern char *__progname; /* from crt0.o */ |
|
|
|
fprintf(stderr, |
|
"usage: %s [-f file] [-n] [-v] name ...\n" |
|
" %s [-f file] [-n] [-v] -w name=value ...\n" |
|
" %s [-f file] [-n] [-v] -a\n", __progname, |
|
__progname, __progname); |
|
|
|
exit(1); |
} |
} |