- Define various new AFMT_*. These are not returned as supported
formats by SNDCTL_DSP_GETFMTS, because it would be very silly to
have Vorbis in the kernel.
- Implement PLAYTGT and RECSRC. For each NetBSD audio device
we only return one playback and recording source, "primary".
- Return preferred channel configuration in capabilities.
Either DSP_CH_STEREO, DSP_CH_MONO, or DSP_CH_MULTI
depending on the current hardware format.
- SNDCTL_DSP_HALT_* simply flushes the audio device.
some drivers (not hdaudio(4), but uaudio(4), eap(4), sb(4), various other
old cards) will return error if a AUDIO_MIXER_VALUE is requested and the
number of channels is not specified as input. this is not documented as
well as it should be, unfortunately.
These are no-ops (unimplemented) on both FreeBSD and Solaris
and the one piece of code I've found that uses it seems to assume the
call will fail so it should be safe to leave this returning EINVAL.
However, it does need the definitions to compile...
Both SNDCTL_DSP_SPEED and SNDCTL_DSP_CHANNELS support a special value
0 to "query the configured value without changing it". In our case,
this actually means setting and querying the hardware rate.
I don't know if OSSv3 or FreeBSD or other implementations also do this.
But it seems safe and sensible to support.
In OSSv4 these are supposed to avoid the wrapping problems with the
older GET(I|O)PTR ioctls but we don't quite get the same benefit here.
XXX: We could probably fake it by maintaining some state in-between calls.
One or two calls from this API were supported previously and have been
moved to the correct place.
Mapping the controls correctly is a difficult task. There is a define
hidden in the OSS headers that would allow an AUDIO_MIXER_SET control
to be represented perfectly, but it seems to _only_ exist there, and
no software supports it. So for now only one member of a set can be
set at a time - unfortunate. I've hidden code that should unlock
doing this the proper way under #notyet.
I'm not too happy with the way this code is managing file descriptors.
Currently it has to open a new fd for each ioctl due to OSSv4 deciding
to specify the device number in a structure rather than in the filename.
In the future, we could reuse the file descriptor if the correct one is
detected open.
This allows the mixer programs provided with the OSSv4 sources to compile
and work cleanly. I've observed problems with it failing to work on
secondary devices, and should investigate this later. There may be
a fd leak somewhere.
SNDCTL_DSP_COOKEDMODE simply always returns 1.
"Cooked mode" is a silly way the OSSv4 authors chose to refer to allowing
for reprocessed streams. The NetBSD kernel always performs format
conversion and it can't be turned off.
SNDCTL_DSP_GETERROR provides access to the read/write over/underrun
counters. There are other things it might return, but they don't make
sense for our implementation.
- Per OSSv4, make this ioctl work on the main mixer device.
Since the native NetBSD API uses queries on individual audio devices,
we have to reopen the correct audio device specified in the input to the
ioctl and fetch information from that.
- Correctly return whether the device is for playback, capture, or both.
- Return the full name of the device in the name field.
- The "handle" has to be a globally unique identifier. The closest thing
we have to that is device numbers, so use device numbers.
- Return reasonable values in min_rate/max_rate and min_channels/max_channels.
This should allow Mumble's device enumeration to work with a lot less
patching.
Problems in the previous code include returning values in the 0-255
range NetBSD uses instead of the 0-100 range OSSv4 expects, using
AUDIO_GETBUFINFO (which doesn't even return the mixer bits), and
not encoding channels as specified: "level=(left)|(right << 8)".
In reality, setting the gain in this way (through /dev/audio rather
than /dev/mixer) doesn't seem to work properly, and the mixer-set
value seems to be retained.
However, these changes at least ensure that the return values are
correct and the balance is set correctly.
I've only found one application using this API (audio/audacious), and
OSSv4 support in it is currently disabled precisely because it breaks
when it attempts to set the track volume using it.
The OSSv4 spec says we shouldn't really error if an invalid format is
chosen by an application. Things are especially likely to be confused
if we return MULAW, since in OSSv4 terms that means that's the native
hardware format. Instead, set and return the current hardware format
if an invalid format is chosen.
For the 24-bit sample formats, note that the NetBSD kernel currently
can't handle them in its default configuration, and will return an error
code if you attempt to use them. So, if an applicaton requests 24-bit PCM,
promote it to 32-bit PCM. According to the spec, this is valid and
applications should be checking the return value anyway.
In the Linux compat layer, we just use S16LE as a fallback. The OSSv3
headers that are still being shipped with Linux don't contain definitions
for fancier formats and we can reasonably expect all applications to
support S16LE.
From the perspective of reading the OSSv4 specification, NetBSD's
behaviour when an invalid sample rate is set makes no sense at all:
AUDIO_SETINFO simply returns an error code, and then we immediately
fall through to getting the sample rate, which is still set to the
legacy default of 8000 Hz.
Instead, what OSS applications generally expect is that they will be
able to receive the actual hardware sample rate. This is very, very
unlikely to be 8000 Hz on a modern machine.
No functional change when setting a sample rate between the supported
rates of 1000 and 192000 Hz. When a rate outside this range is requested,
the hardware rate is returned (on modern hardware, generally always 48000
Hz or a multiple of 48000 Hz).
- 'fragments' is the number of full free blocks and should not be
negative value.
- 'bytes' should not be rounded down.
It makes mpv work correctly (fixes a second half of kern/53028).
Reviewed by mlelstv@
picked up by gcc7's checker that the array size has not
been multipled by the member size.
here, we had 8 but should have had 8 * sizeof(int).
XXX: real bug - pullup-7, pullup-8