PortAudio/portaudio

OSS: device cannot be selected correctly when SNDIO is enabled

tatsuki-makino opened this issue · 4 comments

Describe the bug
DeviceIndex and HostApiDeviceIndex are not used separately, so devices cannot be selected correctly if SNDIO, which is initialized before OSS, is enabled.

To Reproduce

  1. Allow one or more devices to be used with SNDIO.
  2. Build PortAudio with SNDIO and OSS enabled.
  3. Select OSS device in Audacity 3.4, etc.

Expected behavior
Sound is produced on the selected device.

Actual behavior
The number of devices in SNDIO will result in devices that cannot be used in OSS.

Desktop (please complete the following information):

  • OS: FreeBSD
  • OS Version 12.4-STABLE (It has been tested. All versions are affected.)
  • PortAudio version: 88ab584

Additional context
A workaround patch will be attached.
Adding an offset here would be consistent with the behavior of the other HostAPI without changing the software that is already running.
patch.txt

This may only be available to FreeBSD users in a reproducible environment.
Therefore, I have attached an image of the Audacity GUI that may be used to point out the problem.
screenshot

This sounds like a bug or misunderstanding in your client code (or in Audacity?). Certainly your patch is incorrect.

DeviceIndex is the global device index that is passed to Pa_OpenStream. It seems to me that you are passing a host-API-specific index to Pa_OpenStream when in-fact you should be passing a global device index.

If you still think that there is a bug please provide a test case that demonstrates the issue using the PortAudio public API.

The problem seems to occur somewhere in Pa_IsFormatSupported function.
Audacity (3.5.1) gives errors depending on the result, so I cut it out.
test.c.txt
When it is executed, the result is as follows:

[0:0]sndio
deviceCount: 1
defaultInputDevice: 0; defaultOutputDevice: 0
[ 0: 0]default
Pa_IsFormatSupported: (in) Success
Pa_IsFormatSupported: (out) Success
[1:1]OSS
deviceCount: 5
defaultInputDevice: 1; defaultOutputDevice: 1
[ 0: 1]/dev/dsp
Pa_IsFormatSupported: (in) Invalid device
Pa_IsFormatSupported: (out) Invalid device
[ 1: 2]/dev/dsp0
Pa_IsFormatSupported: (out) Success
[ 2: 3]/dev/dsp1
Pa_IsFormatSupported: (in) Device unavailable
Pa_IsFormatSupported: (out) Success
[ 3: 4]/dev/dsp2
Pa_IsFormatSupported: (in) Success
Pa_IsFormatSupported: (out) Success
[ 4: 5]/dev/dsp3
Pa_IsFormatSupported: (out) Success
[2:2]ALSA
deviceCount: 35
defaultInputDevice: 40; defaultOutputDevice: 40
[ 0: 6]sysdefault
Pa_IsFormatSupported: (in) Success
Pa_IsFormatSupported: (out) Success
[ 1: 7]front
Pa_IsFormatSupported: (out) Success
[ 2: 8]rear
Pa_IsFormatSupported: (out) Success
... Omitted below.

OSS gives an error that should not have occurred.
/dev/dsp is the same thing as /dev/dsp1, but it fails because it can't point to it correctly.
/dev/dsp0 is a device that cannot be captured, so the input side is not checked.
On the output side, it means that the check using /dev/dsp is successful.
/dev/dsp1 is a device that can capture and playback, so it checks both input and output, but because /dev/dsp0 is checked, the input side is treated as unavailable.

Around this point, the global device index has changed to a host-API-specific index, but I think it means that OSS host-API has used the changed value for a function that assumes that it will be used in a global device index.

It was my mistake to close it for a moment :)
This is the place to escape if any errors are found, but it already seems to be at the proper value by all the checks.
Therefore, I think it is just a matter of changing it like this.
patch.txt