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
The ioctl definitions and accompanying structures were
taken from FreeBSD's soundcard.h, hopefully providing
some binary compatibility.
The ioctls are as follows:
SNDCTL_SYSINFO: Returns a structure containing
details about the audio device.
SNDCTL_ENGINEINFO - SNDCTL_AUDIOINFO: Returns a
structure with playback/recording
characteristics.
SNDCTL_DSP_GETPLAYVOL, SNDCTL_DSP_SETPLAYVOL,
SNDCTL_DSP_GETRECVOL, SNDCTL_DSP_SETRECVOL:
Retrieves/Sets Playback/Recording volume.
SNDCTL_DSP_SKIP - SNDCTL_DSP_SILENCE: These ioctls
were intended to manipulate the underlying
audio buffer skip or insert silence. These
return EINVAL.
SOUND_VERSION is unchanged, but is definable, It will be
changed when the mixer OSSv4 ioctls are written.
Addresses PR 46611
This commit was approved by wiz@.