tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Audio volume setting: not working - sometimes?
>>> The primary gain control might not be the one currently responsible
>>> for output volume depending on the various DACs available.
>> Possibly - but audioctl's play.gain field _does_ work to control the
>> output volume. I had thought audioctl's play.gain was just a
>> different interface to the same thing [...]
> audioctl is primarily for manipulating /dev/sound, which persists
> these settings between opens, whereas /dev/audio doesn't. audioctl
> works by performing SETINFO on /dev/audioctl.
Right. This has nothing to do with the issue at hand. In the
problematic case, userland opens /dev/audio0 and tries to set the
playback gain (to 254). This setting is ignored, according to both the
resulting signal and audioctl -a (run while the application still has
/dev/audio0 open).
> If you need the "audio device parameters persist between opens"
> feature I'd recommend using /dev/sound instead.
Persistence between opens is neither wanted nor relevant.
Today I had the leisure to track this down. Building a kernel with
AUDIO_DEBUG and setting hw.audio0.debug to 2, I saw au_set_gain lines
indicating that the volume was getting changed as specified, only to be
immediately - as in, the next log line - changed back.
Turns out that, if you specify play.gain and play.balance in the same
AUDIO_SETINFO call, the former is ignored:
static int
audio_hw_setinfo(struct audio_softc *sc, const struct audio_info *newai,
struct audio_info *oldai)
{
u_int pgain;
...
/* Backup play.{gain,balance} */
if (SPECIFIED(newpi->gain) || SPECIFIED_CH(newpi->balance)) {
au_get_gain(sc, &sc->sc_outports, &pgain, &pbalance);
if (oldai) {
oldpi->gain = pgain;
oldpi->balance = pbalance;
}
}
/* Backup record.{gain,balance} */
if (SPECIFIED(newri->gain) || SPECIFIED_CH(newri->balance)) {
...
}
if (SPECIFIED(newpi->gain)) {
error = au_set_gain(sc, &sc->sc_outports,
newpi->gain, pbalance);
if (error) {
...
}
}
if (SPECIFIED(newri->gain)) {
...
}
if (SPECIFIED_CH(newpi->balance)) {
error = au_set_gain(sc, &sc->sc_outports,
pgain, newpi->balance);
Note that pgain is not changed between the "Backup play.{gain,balance}"
code and the last au_set_gain above, even if newpi->gain is specified.
Changing userland to call AUDIO_SETINFO twice, once with balance
specified and once with gain specified, is a workaround for my
purposes.
PR filed - kern/56308.
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse%rodents-montreal.org@localhost
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Home |
Main Index |
Thread Index |
Old Index