Hello,

I found portaudio for FreeBSD port supports multiple sndio devices at
https://svnweb.freebsd.org/ports/head/audio/portaudio/files/pa_sndio.c

The commit message is ----

audio/portaudio: Add support for enumerating multiple sndio devices

sndio has no device discovery mechanism and PortAudio has no way
of accepting raw device strings from users.  Normally we just expose
the default device (which can be changed via the AUDIODEVICE
environment variable).  This however means that we are stuck with
only one device at a time for playback/recording and would have to
restart applications (or the sndiod instance) to switch between
devices.

This is detrimental to the workflow in applications like Audacity
and makes them unusable in sndio only setups.

Add a new PA_SNDIO_AUDIODEVICES environment variables with which
users can specify and expose a list of 16 additional sndio devices
to applications using PortAudio.

Example:
PA_SNDIO_AUDIODEVICES=snd/0.monitor:snd@remote/0:rsnd/3

---- (end of citation)

I tried simply replace files/pa_sndio.c, it worked.
Here is the diff,

(we have to run sndio with "-f rsnd/0 -f rsnd/1" option to make multiple
sndio devices)

Index: Makefile
===================================================================
RCS file: /cvs/ports/audio/portaudio-svn/Makefile,v
retrieving revision 1.17
diff -r1.17 Makefile
9a10
> REVISION =            0
Index: files/pa_sndio.c
===================================================================
RCS file: /cvs/ports/audio/portaudio-svn/files/pa_sndio.c,v
retrieving revision 1.4
diff -r1.4 pa_sndio.c
64,66c64,72
<        * sndio has no device discovery mechanism, so expose only
<        * the default device, the user will have a chance to change it
<        * using the environment variable
---
>        * sndio has no device discovery mechanism and PortAudio has
>        * no way of accepting raw device strings from users.
>        * Normally we just expose the default device, which can be
>        * changed via the AUDIODEVICE environment variable, but we
>        * also allow specifying a list of up to 16 devices via the
>        * PA_SNDIO_AUDIODEVICES environment variable.
>        *
>        * Example:
>        * PA_SNDIO_AUDIODEVICES=default:snd/0.monitor:snd@remote/0
68c74,77
<       PaDeviceInfo *infos[1], default_info;
---
> #define PA_SNDIO_AUDIODEVICES_MAX     16
>       PaDeviceInfo device_info[PA_SNDIO_AUDIODEVICES_MAX];
>       PaDeviceInfo *infos[PA_SNDIO_AUDIODEVICES_MAX];
>       char *audiodevices;
250a260
>       const char *dev;
260c270
<               if (outputPar->device != 0) {
---
>               if (outputPar->device >= sndioHostApi->base.info.deviceCount) {
276c286
<               if (inputPar->device != 0) {
---
>               if (inputPar->device >= sndioHostApi->base.info.deviceCount) {
297c307,314
<       hdl = sio_open(SIO_DEVANY, mode, 0);
---
>       if (outputPar) {
>               dev = sndioHostApi->device_info[outputPar->device].name;
>       } else if (inputPar) {
>               dev = sndioHostApi->device_info[inputPar->device].name;
>       } else {
>               return paUnanticipatedHostError;
>       }
>       hdl = sio_open(dev, mode, 0);
638a656,658
>       PaSndioHostApiRepresentation *sndioHostApi;
>       sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
>       free(sndioHostApi->audiodevices);
641a662,676
> static void
> InitDeviceInfo(PaDeviceInfo *info, PaHostApiIndex hostApiIndex, const char 
> *name)
> {
>       info->structVersion = 2;
>       info->name = name;
>       info->hostApi = hostApiIndex;
>       info->maxInputChannels = 128;
>       info->maxOutputChannels = 128;
>       info->defaultLowInputLatency = 0.01;
>       info->defaultLowOutputLatency = 0.01;
>       info->defaultHighInputLatency = 0.5;
>       info->defaultHighOutputLatency = 0.5;
>       info->defaultSampleRate = 48000;
> }
> 
648c683,686
<       
---
>       char *audiodevices;
>       char *device;
>       size_t deviceCount;
> 
658,668c696,698
<       info = &sndioHostApi->default_info;
<       info->structVersion = 2;
<       info->name = "default";
<       info->hostApi = hostApiIndex;
<       info->maxInputChannels = 128;
<       info->maxOutputChannels = 128;
<       info->defaultLowInputLatency = 0.01;
<       info->defaultLowOutputLatency = 0.01;
<       info->defaultHighInputLatency = 0.5;
<       info->defaultHighOutputLatency = 0.5;
<       info->defaultSampleRate = 48000;
---
>       // Add default device
>       info = &sndioHostApi->device_info[0];
>       InitDeviceInfo(info, hostApiIndex, SIO_DEVANY);
670c700,722
<       
---
>       deviceCount = 1;
> 
>       // Add additional devices as specified in the PA_SNDIO_AUDIODEVICES
>       // environment variable as a colon separated list
>       sndioHostApi->audiodevices = NULL;
>       audiodevices = getenv("PA_SNDIO_AUDIODEVICES");
>       if (audiodevices != NULL) {
>               sndioHostApi->audiodevices = strdup(audiodevices);
>               if (sndioHostApi->audiodevices == NULL)
>                       return paNoError;
> 
>               audiodevices = sndioHostApi->audiodevices;
>               while ((device = strsep(&audiodevices, ":")) != NULL &&
>                       deviceCount < PA_SNDIO_AUDIODEVICES_MAX) {
>                       if (*device == '\0')
>                               continue;
>                       info = &sndioHostApi->device_info[deviceCount];
>                       InitDeviceInfo(info, hostApiIndex, device);
>                       sndioHostApi->infos[deviceCount] = info;
>                       deviceCount++;
>               }
>       }
> 
675c727
<       (*hostApi)->info.deviceCount = 1;
---
>       (*hostApi)->info.deviceCount = deviceCount;

-- 
SASANO Takayoshi (JG1UAA) <u...@mx5.nisiq.net>

Reply via email to