[BACK]Return to mixerctl.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mixerctl

Annotation of src/usr.bin/mixerctl/mixerctl.c, Revision 1.1

1.1     ! provos      1: /*     $NetBSD: mixerctl.c,v 1.9 1997/10/19 07:46:04 augustss Exp $    */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997 The NetBSD Foundation, Inc.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Author: Lennart Augustsson, with some code and ideas from Chuck Cranor.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *        This product includes software developed by the NetBSD
        !            20:  *        Foundation, Inc. and its contributors.
        !            21:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            22:  *    contributors may be used to endorse or promote products derived
        !            23:  *    from this software without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            26:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            35:  * POSSIBILITY OF SUCH DAMAGE.
        !            36:  */
        !            37: #include <stdio.h>
        !            38: #include <stdlib.h>
        !            39: #include <fcntl.h>
        !            40: #include <err.h>
        !            41: #include <unistd.h>
        !            42: #include <string.h>
        !            43: #include <sys/types.h>
        !            44: #include <sys/ioctl.h>
        !            45: #include <sys/audioio.h>
        !            46:
        !            47: char *catstr __P((char *p, char *q));
        !            48: struct field *findfield __P((char *name));
        !            49: void prfield __P((struct field *p, char *sep, int prvalset));
        !            50: int rdfield __P((struct field *p, char *q));
        !            51: int main(int argc, char **argv);
        !            52:
        !            53: FILE *out = stdout;
        !            54:
        !            55: char *prog;
        !            56:
        !            57: struct field {
        !            58:        char *name;
        !            59:        mixer_ctrl_t *valp;
        !            60:        mixer_devinfo_t *infp;
        !            61:        char changed;
        !            62: } *fields, *rfields;
        !            63:
        !            64: mixer_ctrl_t *values;
        !            65: mixer_devinfo_t *infos;
        !            66:
        !            67: char *
        !            68: catstr(p, q)
        !            69:        char *p;
        !            70:         char *q;
        !            71: {
        !            72:        char *r = malloc(strlen(p) + strlen(q) + 2);
        !            73:        strcpy(r, p);
        !            74:        strcat(r, ".");
        !            75:        strcat(r, q);
        !            76:        return r;
        !            77: }
        !            78:
        !            79: struct field *
        !            80: findfield(name)
        !            81:        char *name;
        !            82: {
        !            83:        int i;
        !            84:        for(i = 0; fields[i].name; i++)
        !            85:                if (strcmp(fields[i].name, name) == 0)
        !            86:                        return &fields[i];
        !            87:        return 0;
        !            88: }
        !            89:
        !            90: void
        !            91: prfield(p, sep, prvalset)
        !            92:        struct field *p;
        !            93:         char *sep;
        !            94:         int prvalset;
        !            95: {
        !            96:        mixer_ctrl_t *m;
        !            97:        int i, n;
        !            98:
        !            99:        if (sep)
        !           100:                fprintf(out, "%s%s", p->name, sep);
        !           101:        m = p->valp;
        !           102:        switch(m->type) {
        !           103:        case AUDIO_MIXER_ENUM:
        !           104:                for(i = 0; i < p->infp->un.e.num_mem; i++)
        !           105:                        if (p->infp->un.e.member[i].ord == m->un.ord)
        !           106:                                fprintf(out, "%s",
        !           107:                                        p->infp->un.e.member[i].label.name);
        !           108:                if (prvalset) {
        !           109:                        fprintf(out, "  [ ");
        !           110:                        for(i = 0; i < p->infp->un.e.num_mem; i++)
        !           111:                                fprintf(out, "%s ", p->infp->un.e.member[i].label.name);
        !           112:                        fprintf(out, "]");
        !           113:                }
        !           114:                break;
        !           115:        case AUDIO_MIXER_SET:
        !           116:                for(n = i = 0; i < p->infp->un.s.num_mem; i++)
        !           117:                        if (m->un.mask & p->infp->un.s.member[i].mask)
        !           118:                                fprintf(out, "%s%s", n++ ? "," : "",
        !           119:                                        p->infp->un.s.member[i].label.name);
        !           120:                if (prvalset) {
        !           121:                        fprintf(out, "  { ");
        !           122:                        for(i = 0; i < p->infp->un.s.num_mem; i++)
        !           123:                                fprintf(out, "%s ", p->infp->un.s.member[i].label.name);
        !           124:                        fprintf(out, "}");
        !           125:                }
        !           126:                break;
        !           127:        case AUDIO_MIXER_VALUE:
        !           128:                if (m->un.value.num_channels == 1)
        !           129:                        fprintf(out, "%d", m->un.value.level[0]);
        !           130:                else
        !           131:                        fprintf(out, "%d,%d", m->un.value.level[0],
        !           132:                               m->un.value.level[1]);
        !           133:                if (prvalset)
        !           134:                        fprintf(out, " %s", p->infp->un.v.units.name);
        !           135:                break;
        !           136:        default:
        !           137:                printf("\n");
        !           138:                errx(1, "Invalid format.");
        !           139:        }
        !           140: }
        !           141:
        !           142: int
        !           143: rdfield(p, q)
        !           144:        struct field *p;
        !           145:         char *q;
        !           146: {
        !           147:        mixer_ctrl_t *m;
        !           148:        int v, v0, v1, mask;
        !           149:        int i;
        !           150:        char *s;
        !           151:
        !           152:        m = p->valp;
        !           153:        switch(m->type) {
        !           154:        case AUDIO_MIXER_ENUM:
        !           155:                for(i = 0; i < p->infp->un.e.num_mem; i++)
        !           156:                        if (strcmp(p->infp->un.e.member[i].label.name, q) == 0)
        !           157:                                break;
        !           158:                if (i < p->infp->un.e.num_mem)
        !           159:                        m->un.ord = p->infp->un.e.member[i].ord;
        !           160:                else {
        !           161:                        warnx("Bad enum value %s", q);
        !           162:                        return 0;
        !           163:                }
        !           164:                break;
        !           165:        case AUDIO_MIXER_SET:
        !           166:                mask = 0;
        !           167:                for(v = 0; q && *q; q = s) {
        !           168:                        s = strchr(q, ',');
        !           169:                        if (s)
        !           170:                                *s++ = 0;
        !           171:                        for(i = 0; i < p->infp->un.s.num_mem; i++)
        !           172:                                if (strcmp(p->infp->un.s.member[i].label.name, q) == 0)
        !           173:                                        break;
        !           174:                        if (i < p->infp->un.s.num_mem) {
        !           175:                                mask |= p->infp->un.s.member[i].mask;
        !           176:                        } else {
        !           177:                                warnx("Bad set value %s", q);
        !           178:                                return 0;
        !           179:                        }
        !           180:                }
        !           181:                m->un.mask = mask;
        !           182:                break;
        !           183:        case AUDIO_MIXER_VALUE:
        !           184:                if (m->un.value.num_channels == 1) {
        !           185:                        if (sscanf(q, "%d", &v) == 1) {
        !           186:                                m->un.value.level[0] = v;
        !           187:                        } else {
        !           188:                                warnx("Bad number %s", q);
        !           189:                                return 0;
        !           190:                        }
        !           191:                } else {
        !           192:                        if (sscanf(q, "%d,%d", &v0, &v1) == 2) {
        !           193:                                m->un.value.level[0] = v0;
        !           194:                                m->un.value.level[1] = v1;
        !           195:                        } else if (sscanf(q, "%d", &v) == 1) {
        !           196:                                m->un.value.level[0] = m->un.value.level[1] = v;
        !           197:                        } else {
        !           198:                                warnx("Bad numbers %s", q);
        !           199:                                return 0;
        !           200:                        }
        !           201:                }
        !           202:                break;
        !           203:        default:
        !           204:                errx(1, "Invalid format.");
        !           205:        }
        !           206:        p->changed = 1;
        !           207:        return 1;
        !           208: }
        !           209:
        !           210: int
        !           211: main(argc, argv)
        !           212:        int argc;
        !           213:         char **argv;
        !           214: {
        !           215:        int fd, i, j, ch, pos;
        !           216:        int aflag = 0, wflag = 0, vflag = 0;
        !           217:        char *file = "/dev/mixer";
        !           218:        char *sep = "=";
        !           219:        mixer_devinfo_t dinfo;
        !           220:        mixer_ctrl_t val;
        !           221:        int ndev;
        !           222:
        !           223:        prog = *argv;
        !           224:
        !           225:        while ((ch = getopt(argc, argv, "af:nvw")) != -1) {
        !           226:                switch(ch) {
        !           227:                case 'a':
        !           228:                        aflag++;
        !           229:                        break;
        !           230:                case 'w':
        !           231:                        wflag++;
        !           232:                        break;
        !           233:                case 'v':
        !           234:                        vflag++;
        !           235:                        break;
        !           236:                case 'n':
        !           237:                        sep = 0;
        !           238:                        break;
        !           239:                case 'f':
        !           240:                        file = optarg;
        !           241:                        break;
        !           242:                case '?':
        !           243:                default:
        !           244:                usage:
        !           245:                fprintf(out, "%s [-f file] [-v] [-n] name ...\n", prog);
        !           246:                fprintf(out, "%s [-f file] [-v] [-n] -w name=value ...\n", prog);
        !           247:                fprintf(out, "%s [-f file] [-v] [-n] -a\n", prog);
        !           248:                exit(0);
        !           249:                }
        !           250:        }
        !           251:        argc -= optind;
        !           252:        argv += optind;
        !           253:
        !           254:        fd = open(file, O_RDWR);
        !           255:        if (fd < 0)
        !           256:                err(1, "%s", file);
        !           257:
        !           258:        for(ndev = 0; ; ndev++) {
        !           259:                dinfo.index = ndev;
        !           260:                if (ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo) < 0)
        !           261:                        break;
        !           262:        }
        !           263:        rfields = calloc(ndev, sizeof *rfields);
        !           264:        fields = calloc(ndev, sizeof *fields);
        !           265:        infos = calloc(ndev, sizeof *infos);
        !           266:        values = calloc(ndev, sizeof *values);
        !           267:
        !           268:        for(i = 0; i < ndev; i++) {
        !           269:                infos[i].index = i;
        !           270:                ioctl(fd, AUDIO_MIXER_DEVINFO, &infos[i]);
        !           271:        }
        !           272:
        !           273:        for(i = 0; i < ndev; i++) {
        !           274:                rfields[i].name = infos[i].label.name;
        !           275:                rfields[i].valp = &values[i];
        !           276:                rfields[i].infp = &infos[i];
        !           277:        }
        !           278:
        !           279:        for(i = 0; i < ndev; i++) {
        !           280:                values[i].dev = i;
        !           281:                values[i].type = infos[i].type;
        !           282:                if (infos[i].type != AUDIO_MIXER_CLASS) {
        !           283:                        values[i].un.value.num_channels = 2;
        !           284:                        if (ioctl(fd, AUDIO_MIXER_READ, &values[i]) < 0) {
        !           285:                                values[i].un.value.num_channels = 1;
        !           286:                                if (ioctl(fd, AUDIO_MIXER_READ, &values[i]) < 0)
        !           287:                                        err(1, "AUDIO_MIXER_READ");
        !           288:                        }
        !           289:                }
        !           290:        }
        !           291:
        !           292:        for(j = i = 0; i < ndev; i++) {
        !           293:                if (infos[i].type != AUDIO_MIXER_CLASS &&
        !           294:                    infos[i].type != -1) {
        !           295:                        fields[j++] = rfields[i];
        !           296:                        for(pos = infos[i].next; pos != AUDIO_MIXER_LAST;
        !           297:                            pos = infos[pos].next) {
        !           298:                                fields[j] = rfields[pos];
        !           299:                                fields[j].name = catstr(rfields[i].name,
        !           300:                                                        infos[pos].label.name);
        !           301:                                infos[pos].type = -1;
        !           302:                                j++;
        !           303:                        }
        !           304:                }
        !           305:        }
        !           306:
        !           307:        for(i = 0; i < j; i++) {
        !           308:                int cls = fields[i].infp->mixer_class;
        !           309:                if (cls >= 0 && cls < ndev)
        !           310:                        fields[i].name = catstr(infos[cls].label.name,
        !           311:                                                fields[i].name);
        !           312:        }
        !           313:
        !           314:        if (argc == 0 && aflag && !wflag) {
        !           315:                for(i = 0; fields[i].name; i++) {
        !           316:                        prfield(&fields[i], sep, vflag);
        !           317:                        fprintf(out, "\n");
        !           318:                }
        !           319:        } else if (argc > 0 && !aflag) {
        !           320:                struct field *p;
        !           321:                if (wflag) {
        !           322:                        while(argc--) {
        !           323:                                char *q;
        !           324:
        !           325:                                q = strchr(*argv, '=');
        !           326:                                if (q) {
        !           327:                                        *q++ = 0;
        !           328:                                        p = findfield(*argv);
        !           329:                                        if (p == 0)
        !           330:                                                warnx("field %s does not exist", *argv);
        !           331:                                        else {
        !           332:                                                val = *p->valp;
        !           333:                                                if (rdfield(p, q)) {
        !           334:                                                        if (ioctl(fd, AUDIO_MIXER_WRITE, p->valp) < 0)
        !           335:                                                                warn("AUDIO_MIXER_WRITE");
        !           336:                                                        else if (sep) {
        !           337:                                                                *p->valp = val;
        !           338:                                                                prfield(p, ": ", 0);
        !           339:                                                                ioctl(fd, AUDIO_MIXER_READ, p->valp);
        !           340:                                                                printf(" -> ");
        !           341:                                                                prfield(p, 0, 0);
        !           342:                                                                printf("\n");
        !           343:                                                        }
        !           344:                                                }
        !           345:                                        }
        !           346:                                } else {
        !           347:                                        warnx("No `=' in %s", *argv);
        !           348:                                }
        !           349:                                argv++;
        !           350:                        }
        !           351:                } else {
        !           352:                        while(argc--) {
        !           353:                                p = findfield(*argv);
        !           354:                                if (p == 0)
        !           355:                                        warnx("field %s does not exist", *argv);
        !           356:                                else
        !           357:                                        prfield(p, sep, vflag), fprintf(out, "\n");
        !           358:                                argv++;
        !           359:                        }
        !           360:                }
        !           361:        } else
        !           362:                goto usage;
        !           363:        exit(0);
        !           364: }