Subject: lib/34822: libossaudio ignores mixer class
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <svs+pr@grep.ru>
List: netbsd-bugs
Date: 10/15/2006 01:00:00
>Number: 34822
>Category: lib
>Synopsis: libossaudio ignores mixer class
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Oct 15 01:00:00 +0000 2006
>Originator: svs+pr@grep.ru
>Release: NetBSD 3.0.1_STABLE
>Organization:
>Environment:
>Description:
If an audio driver uses 'record.master' to control record gain
(see PR 34821), libossaudio (and compat/ossaudio) may map it to
SOUND_MIXER_VOLUME, which is wrong.
>How-To-Repeat:
>Fix:
--- lib/libossaudio/ossaudio.c 1 Jun 2005 11:22:18 -0000 1.20
+++ lib/libossaudio/ossaudio.c 14 Oct 2006 22:17:21 -0000
@@ -456,7 +456,8 @@
int done;
dev_t dev;
int16_t devmap[SOUND_MIXER_NRDEVICES],
- rdevmap[NETBSD_MAXDEVS];
+ rdevmap[NETBSD_MAXDEVS],
+ mclass[4];
char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN];
int enum2opaque[NETBSD_MAXDEVS];
u_long devmask, recmask, stereomask;
@@ -509,6 +510,11 @@
return (m);
}
+#define _MIXER_CLASS_INPUTS 0
+#define _MIXER_CLASS_OUTPUTS 1
+#define _MIXER_CLASS_RECORD 2
+#define _MIXER_CLASS_MONITOR 3
+
/*
* Collect the audio device information to allow faster
* emulation of the Linux mixer ioctls. Cache the information
@@ -521,30 +527,27 @@
mixer_devinfo_t mi;
int i, j, e;
static struct {
- char *name;
+ int class;
+ const char *name;
int code;
} *dp, devs[] = {
- { AudioNmicrophone, SOUND_MIXER_MIC },
- { AudioNline, SOUND_MIXER_LINE },
- { AudioNcd, SOUND_MIXER_CD },
- { AudioNdac, SOUND_MIXER_PCM },
- { AudioNaux, SOUND_MIXER_LINE1 },
- { AudioNrecord, SOUND_MIXER_IMIX },
- { AudioNmaster, SOUND_MIXER_VOLUME },
- { AudioNtreble, SOUND_MIXER_TREBLE },
- { AudioNbass, SOUND_MIXER_BASS },
- { AudioNspeaker, SOUND_MIXER_SPEAKER },
-/* { AudioNheadphone, ?? },*/
- { AudioNoutput, SOUND_MIXER_OGAIN },
- { AudioNinput, SOUND_MIXER_IGAIN },
-/* { AudioNmaster, SOUND_MIXER_SPEAKER },*/
-/* { AudioNstereo, ?? },*/
-/* { AudioNmono, ?? },*/
- { AudioNfmsynth, SOUND_MIXER_SYNTH },
-/* { AudioNwave, SOUND_MIXER_PCM },*/
- { AudioNmidi, SOUND_MIXER_SYNTH },
-/* { AudioNmixerout, ?? },*/
- { 0, -1 }
+ { _MIXER_CLASS_INPUTS, AudioNmicrophone, SOUND_MIXER_MIC },
+ { _MIXER_CLASS_INPUTS, AudioNline, SOUND_MIXER_LINE },
+ { _MIXER_CLASS_INPUTS, AudioNcd, SOUND_MIXER_CD },
+ { _MIXER_CLASS_INPUTS, AudioNdac, SOUND_MIXER_PCM },
+ { _MIXER_CLASS_INPUTS, AudioNaux, SOUND_MIXER_LINE1 },
+ { _MIXER_CLASS_INPUTS, AudioNspeaker, SOUND_MIXER_SPEAKER },
+ { _MIXER_CLASS_INPUTS, AudioNfmsynth, SOUND_MIXER_SYNTH },
+ { _MIXER_CLASS_INPUTS, AudioNmidi, SOUND_MIXER_SYNTH },
+ { _MIXER_CLASS_MONITOR, AudioNmaster, SOUND_MIXER_VOLUME },
+ { _MIXER_CLASS_OUTPUTS, AudioNmaster, SOUND_MIXER_VOLUME },
+ { _MIXER_CLASS_OUTPUTS, AudioNtreble, SOUND_MIXER_TREBLE },
+ { _MIXER_CLASS_OUTPUTS, AudioNbass, SOUND_MIXER_BASS },
+ { _MIXER_CLASS_RECORD, AudioNmaster, SOUND_MIXER_IMIX },
+ { _MIXER_CLASS_RECORD, AudioNrecord, SOUND_MIXER_IMIX },
+ { _MIXER_CLASS_RECORD, AudioNoutput, SOUND_MIXER_OGAIN },
+ { _MIXER_CLASS_RECORD, AudioNinput, SOUND_MIXER_IGAIN },
+ { 0, 0, -1 }
};
static struct audiodevinfo devcache = { 0 };
struct audiodevinfo *di = &devcache;
@@ -577,16 +580,33 @@
mi.index = i;
if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
break;
+ if (mi.type == AUDIO_MIXER_CLASS) {
+ if (strcmp(mi.label.name, AudioCinputs) == 0)
+ di->mclass[_MIXER_CLASS_INPUTS] = i;
+ if (strcmp(mi.label.name, AudioCoutputs) == 0)
+ di->mclass[_MIXER_CLASS_OUTPUTS] = i;
+ if (strcmp(mi.label.name, AudioCmonitor) == 0)
+ di->mclass[_MIXER_CLASS_MONITOR] = i;
+ if (strcmp(mi.label.name, AudioCrecord) == 0)
+ di->mclass[_MIXER_CLASS_RECORD] = i;
+ }
+ }
+ for(i = 0; i < NETBSD_MAXDEVS; i++) {
+ mi.index = i;
+ if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
+ break;
switch(mi.type) {
case AUDIO_MIXER_VALUE:
for(dp = devs; dp->name; dp++) {
- if (strcmp(dp->name, mi.label.name) == 0)
+ if (strcmp(dp->name, mi.label.name) == 0
+ && di->mclass[dp->class] == mi.mixer_class)
break;
dlen = strlen(dp->name);
mlen = strlen(mi.label.name);
if (dlen < mlen
&& mi.label.name[mlen-dlen-1] == '.'
- && strcmp(dp->name, mi.label.name + mlen - dlen) == 0)
+ && strcmp(dp->name, mi.label.name + mlen - dlen) == 0
+ && di->mclass[dp->class] == mi.mixer_class)
break;
}
if (dp->code >= 0) {
--- sys/compat/ossaudio/ossaudio.c 3 Sep 2006 20:58:26 -0000 1.53
+++ sys/compat/ossaudio/ossaudio.c 14 Oct 2006 23:18:05 -0000
@@ -536,7 +536,8 @@
int done;
dev_t dev;
int16_t devmap[OSS_SOUND_MIXER_NRDEVICES],
- rdevmap[NETBSD_MAXDEVS];
+ rdevmap[NETBSD_MAXDEVS],
+ mclass[4];
char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN];
int enum2opaque[NETBSD_MAXDEVS];
u_long devmask, recmask, stereomask;
@@ -588,6 +589,11 @@
return (m);
}
+#define _MIXER_CLASS_INPUTS 0
+#define _MIXER_CLASS_OUTPUTS 1
+#define _MIXER_CLASS_RECORD 2
+#define _MIXER_CLASS_MONITOR 3
+
/*
* Collect the audio device information to allow faster
* emulation of the Linux mixer ioctls. Cache the information
@@ -602,30 +608,27 @@
mixer_devinfo_t mi;
int i, j, e;
static const struct {
+ int class;
const char *name;
int code;
} *dp, devs[] = {
- { AudioNmicrophone, OSS_SOUND_MIXER_MIC },
- { AudioNline, OSS_SOUND_MIXER_LINE },
- { AudioNcd, OSS_SOUND_MIXER_CD },
- { AudioNdac, OSS_SOUND_MIXER_PCM },
- { AudioNaux, OSS_SOUND_MIXER_LINE1 },
- { AudioNrecord, OSS_SOUND_MIXER_IMIX },
- { AudioNmaster, OSS_SOUND_MIXER_VOLUME },
- { AudioNtreble, OSS_SOUND_MIXER_TREBLE },
- { AudioNbass, OSS_SOUND_MIXER_BASS },
- { AudioNspeaker, OSS_SOUND_MIXER_SPEAKER },
-/* { AudioNheadphone, ?? },*/
- { AudioNoutput, OSS_SOUND_MIXER_OGAIN },
- { AudioNinput, OSS_SOUND_MIXER_IGAIN },
-/* { AudioNmaster, OSS_SOUND_MIXER_SPEAKER },*/
-/* { AudioNstereo, ?? },*/
-/* { AudioNmono, ?? },*/
- { AudioNfmsynth, OSS_SOUND_MIXER_SYNTH },
-/* { AudioNwave, OSS_SOUND_MIXER_PCM },*/
- { AudioNmidi, OSS_SOUND_MIXER_SYNTH },
-/* { AudioNmixerout, ?? },*/
- { 0, -1 }
+ { _MIXER_CLASS_INPUTS, AudioNmicrophone, OSS_SOUND_MIXER_MIC },
+ { _MIXER_CLASS_INPUTS, AudioNline, OSS_SOUND_MIXER_LINE },
+ { _MIXER_CLASS_INPUTS, AudioNcd, OSS_SOUND_MIXER_CD },
+ { _MIXER_CLASS_INPUTS, AudioNdac, OSS_SOUND_MIXER_PCM },
+ { _MIXER_CLASS_INPUTS, AudioNaux, OSS_SOUND_MIXER_LINE1 },
+ { _MIXER_CLASS_INPUTS, AudioNspeaker, OSS_SOUND_MIXER_SPEAKER },
+ { _MIXER_CLASS_INPUTS, AudioNfmsynth, OSS_SOUND_MIXER_SYNTH },
+ { _MIXER_CLASS_INPUTS, AudioNmidi, OSS_SOUND_MIXER_SYNTH },
+ { _MIXER_CLASS_MONITOR, AudioNmaster, OSS_SOUND_MIXER_VOLUME },
+ { _MIXER_CLASS_OUTPUTS, AudioNmaster, OSS_SOUND_MIXER_VOLUME },
+ { _MIXER_CLASS_OUTPUTS, AudioNtreble, OSS_SOUND_MIXER_TREBLE },
+ { _MIXER_CLASS_OUTPUTS, AudioNbass, OSS_SOUND_MIXER_BASS },
+ { _MIXER_CLASS_RECORD, AudioNmaster, OSS_SOUND_MIXER_IMIX },
+ { _MIXER_CLASS_RECORD, AudioNrecord, OSS_SOUND_MIXER_IMIX },
+ { _MIXER_CLASS_RECORD, AudioNoutput, OSS_SOUND_MIXER_OGAIN },
+ { _MIXER_CLASS_RECORD, AudioNinput, OSS_SOUND_MIXER_IGAIN },
+ { 0, 0, -1 }
};
int (*ioctlf)(struct file *, u_long, void *, struct lwp *) =
fp->f_ops->fo_ioctl;
@@ -665,16 +668,33 @@
mi.index = i;
if (ioctlf(fp, AUDIO_MIXER_DEVINFO, (caddr_t)&mi, l) < 0)
break;
+ if (mi.type == AUDIO_MIXER_CLASS) {
+ if (strcmp(mi.label.name, AudioCinputs) == 0)
+ di->mclass[_MIXER_CLASS_INPUTS] = i;
+ if (strcmp(mi.label.name, AudioCoutputs) == 0)
+ di->mclass[_MIXER_CLASS_OUTPUTS] = i;
+ if (strcmp(mi.label.name, AudioCmonitor) == 0)
+ di->mclass[_MIXER_CLASS_MONITOR] = i;
+ if (strcmp(mi.label.name, AudioCrecord) == 0)
+ di->mclass[_MIXER_CLASS_RECORD] = i;
+ }
+ }
+ for(i = 0; i < NETBSD_MAXDEVS; i++) {
+ mi.index = i;
+ if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
+ break;
switch(mi.type) {
case AUDIO_MIXER_VALUE:
for(dp = devs; dp->name; dp++) {
- if (strcmp(dp->name, mi.label.name) == 0)
+ if (strcmp(dp->name, mi.label.name) == 0
+ && di->mclass[dp->class] == mi.mixer_class)
break;
dlen = strlen(dp->name);
mlen = strlen(mi.label.name);
if (dlen < mlen
&& mi.label.name[mlen-dlen-1] == '.'
- && strcmp(dp->name, mi.label.name + mlen - dlen) == 0)
+ && strcmp(dp->name, mi.label.name + mlen - dlen) == 0
+ && di->mclass[dp->class] == mi.mixer_class)
break;
}
if (dp->code >= 0) {
>Unformatted: