diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2007-11-17 13:31:31 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2007-11-17 13:31:31 +0000 |
commit | 74358c6bd93ac2aaaab33ba78e8fc74dbaa9fc90 (patch) | |
tree | 5d3f7047433bfd2e3801e4a5a8c37a0ce6d04c95 /sys | |
parent | 23b840722e7956a5dc2650e520b907ed302fdfa2 (diff) |
use tables to determine the best control to use for play.gain, record.gain
and monitor_gain; this makes play.gain always usable as general purpose
volume knob even on devices that don't have outputs.master.
ok jakemsr@, deanna@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/audio.c | 110 |
1 files changed, 73 insertions, 37 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c index 204d1e209da..f1988319a37 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: audio.c,v 1.88 2007/10/28 13:27:05 ratchov Exp $ */ +/* $OpenBSD: audio.c,v 1.89 2007/11/17 13:31:30 ratchov Exp $ */ /* $NetBSD: audio.c,v 1.119 1999/11/09 16:50:47 augustss Exp $ */ /* @@ -169,9 +169,35 @@ static struct portname otable[] = { { AudioNline, AUDIO_LINE_OUT }, { 0 } }; +struct gainpref { + char *class, *device; +}; +static struct gainpref ipreftab[] = { + { AudioCinputs, AudioNvolume }, + { AudioCinputs, AudioNinput }, + { AudioCinputs, AudioNrecord }, + { AudioCrecord, AudioNvolume }, + { AudioCrecord, AudioNrecord }, + { NULL, NULL} +}; +static struct gainpref opreftab[] = { + { AudioCoutputs, AudioNoutput }, + { AudioCoutputs, AudioNdac }, + { AudioCinputs, AudioNdac }, + { AudioCoutputs, AudioNmaster }, + { NULL, NULL} +}; +static struct gainpref mpreftab[] = { + { AudioCoutputs, AudioNmonitor }, + { AudioCmonitor, AudioNmonitor }, + { NULL, NULL} +}; + +void au_gain_match(struct audio_softc *, struct gainpref *, + mixer_devinfo_t *, mixer_devinfo_t *, int *, int *); void au_check_ports(struct audio_softc *, struct au_mixer_ports *, - mixer_devinfo_t *, int, char *, char *, - struct portname *); + mixer_devinfo_t *, mixer_devinfo_t *, + char *, char *, struct portname *); int au_set_gain(struct audio_softc *, struct au_mixer_ports *, int, int); void au_get_gain(struct audio_softc *, struct au_mixer_ports *, @@ -236,8 +262,8 @@ audioattach(struct device *parent, struct device *self, void *aux) struct audio_hw_if *hwp = sa->hwif; void *hdlp = sa->hdl; int error; - mixer_devinfo_t mi; - int iclass, oclass, mclass; + mixer_devinfo_t mi, cl; + int ipref, opref, mpref; printf("\n"); @@ -295,7 +321,7 @@ audioattach(struct device *parent, struct device *self, void *aux) audio_init_ringbuffer(&sc->sc_pr); audio_calcwater(sc); - iclass = oclass = mclass = -1; + ipref = opref = mpref = -1; sc->sc_inports.index = -1; sc->sc_inports.nports = 0; sc->sc_inports.isenum = 0; @@ -310,31 +336,20 @@ audioattach(struct device *parent, struct device *self, void *aux) for(mi.index = 0; ; mi.index++) { if (hwp->query_devinfo(hdlp, &mi) != 0) break; - if (mi.type == AUDIO_MIXER_CLASS && - strcmp(mi.label.name, AudioCrecord) == 0) - iclass = mi.index; - if (mi.type == AUDIO_MIXER_CLASS && - strcmp(mi.label.name, AudioCmonitor) == 0) - mclass = mi.index; - if (mi.type == AUDIO_MIXER_CLASS && - strcmp(mi.label.name, AudioCoutputs) == 0) - oclass = mi.index; - } - for(mi.index = 0; ; mi.index++) { - if (hwp->query_devinfo(hdlp, &mi) != 0) - break; if (mi.type == AUDIO_MIXER_CLASS) continue; - au_check_ports(sc, &sc->sc_inports, &mi, iclass, - AudioNsource, AudioNrecord, itable); - au_check_ports(sc, &sc->sc_outports, &mi, oclass, - AudioNoutput, AudioNmaster, otable); - if (mi.mixer_class == mclass && - (strcmp(mi.label.name, AudioNmonitor) == 0)) - sc->sc_monitor_port = mi.index; - if ((sc->sc_monitor_port == -1) && (mi.mixer_class == oclass) && - (strcmp(mi.label.name, AudioNmonitor) == 0)) - sc->sc_monitor_port = mi.index; + cl.index = mi.mixer_class; + if (hwp->query_devinfo(hdlp, &cl) != 0) + continue; + + au_gain_match(sc, ipreftab, &cl, &mi, &sc->sc_inports.master, &ipref); + au_gain_match(sc, opreftab, &cl, &mi, &sc->sc_outports.master, &opref); + au_gain_match(sc, mpreftab, &cl, &mi, &sc->sc_monitor_port, &mpref); + + au_check_ports(sc, &sc->sc_inports, &cl, &mi, + AudioCrecord, AudioNsource, itable); + au_check_ports(sc, &sc->sc_outports, &cl, &mi, + AudioCoutputs, AudioNselect, otable); } DPRINTF(("audio_attach: inputs ports=0x%x, output ports=0x%x\n", sc->sc_inports.allports, sc->sc_outports.allports)); @@ -411,17 +426,13 @@ au_portof(struct audio_softc *sc, char *name) void au_check_ports(struct audio_softc *sc, struct au_mixer_ports *ports, - mixer_devinfo_t *mi, int cls, char *name, char *mname, struct portname *tbl) + mixer_devinfo_t *cl, mixer_devinfo_t *mi, char *cname, char *mname, + struct portname *tbl) { int i, j; - if (mi->mixer_class != cls) - return; - if (strcmp(mi->label.name, mname) == 0) { - ports->master = mi->index; - return; - } - if (strcmp(mi->label.name, name) != 0) + if (strcmp(cl->label.name, cname) != 0 || + strcmp(mi->label.name, mname) != 0) return; if (mi->type == AUDIO_MIXER_ENUM) { ports->index = mi->index; @@ -456,6 +467,31 @@ au_check_ports(struct audio_softc *sc, struct au_mixer_ports *ports, } /* + * check if the given (class, device) is better + * than the current setting (*index), if so, set the + * current setting. + */ +void +au_gain_match(struct audio_softc *sc, struct gainpref *tbl, + mixer_devinfo_t *cls, mixer_devinfo_t *dev, int *index, int *pref) +{ + int i; + + for (i = *pref + 1; tbl[i].class != NULL; i++) { + if (strcmp(tbl[i].class, cls->label.name) == 0 && + strcmp(tbl[i].device, dev->label.name) == 0) { + if (*pref < i) { + DPRINTF(("au_gain_match: found %s.%s\n", + cls->label.name, dev->label.name)); + *index = dev->index; + *pref = i; + } + break; + } + } +} + +/* * Called from hardware driver. This is where the MI audio driver gets * probed/attached to the hardware driver. */ |