mirror of
https://git.FreeBSD.org/ports.git
synced 2025-01-07 06:40:06 +00:00
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
This commit is contained in:
parent
50ed7f091a
commit
52be91fb2f
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=475024
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
PORTNAME= portaudio
|
PORTNAME= portaudio
|
||||||
DISTVERSION= 19_20140130
|
DISTVERSION= 19_20140130
|
||||||
PORTREVISION= 7
|
PORTREVISION= 8
|
||||||
CATEGORIES= audio
|
CATEGORIES= audio
|
||||||
MASTER_SITES= http://www.portaudio.com/archives/
|
MASTER_SITES= http://www.portaudio.com/archives/
|
||||||
DISTNAME= pa_stable_v${DISTVERSION}
|
DISTNAME= pa_stable_v${DISTVERSION}
|
||||||
|
@ -61,11 +61,20 @@ typedef struct PaSndioHostApiRepresentation
|
|||||||
PaUtilStreamInterface callback;
|
PaUtilStreamInterface callback;
|
||||||
PaUtilStreamInterface blocking;
|
PaUtilStreamInterface blocking;
|
||||||
/*
|
/*
|
||||||
* sndio has no device discovery mechanism, so expose only
|
* sndio has no device discovery mechanism and PortAudio has
|
||||||
* the default device, the user will have a chance to change it
|
* no way of accepting raw device strings from users.
|
||||||
* using the environment variable
|
* 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
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
} PaSndioHostApiRepresentation;
|
} PaSndioHostApiRepresentation;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -248,6 +257,7 @@ OpenStream(struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
unsigned mode;
|
unsigned mode;
|
||||||
int inch, onch;
|
int inch, onch;
|
||||||
PaSampleFormat ifmt, ofmt, siofmt;
|
PaSampleFormat ifmt, ofmt, siofmt;
|
||||||
|
const char *dev;
|
||||||
|
|
||||||
DPR("OpenStream:\n");
|
DPR("OpenStream:\n");
|
||||||
|
|
||||||
@ -257,7 +267,7 @@ OpenStream(struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
sio_initpar(&par);
|
sio_initpar(&par);
|
||||||
|
|
||||||
if (outputPar && outputPar->channelCount > 0) {
|
if (outputPar && outputPar->channelCount > 0) {
|
||||||
if (outputPar->device != 0) {
|
if (outputPar->device >= sndioHostApi->base.info.deviceCount) {
|
||||||
DPR("OpenStream: %d: bad output device\n", outputPar->device);
|
DPR("OpenStream: %d: bad output device\n", outputPar->device);
|
||||||
return paInvalidDevice;
|
return paInvalidDevice;
|
||||||
}
|
}
|
||||||
@ -273,7 +283,7 @@ OpenStream(struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
mode |= SIO_PLAY;
|
mode |= SIO_PLAY;
|
||||||
}
|
}
|
||||||
if (inputPar && inputPar->channelCount > 0) {
|
if (inputPar && inputPar->channelCount > 0) {
|
||||||
if (inputPar->device != 0) {
|
if (inputPar->device >= sndioHostApi->base.info.deviceCount) {
|
||||||
DPR("OpenStream: %d: bad input device\n", inputPar->device);
|
DPR("OpenStream: %d: bad input device\n", inputPar->device);
|
||||||
return paInvalidDevice;
|
return paInvalidDevice;
|
||||||
}
|
}
|
||||||
@ -294,7 +304,14 @@ OpenStream(struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
|
|
||||||
DPR("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate);
|
DPR("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate);
|
||||||
|
|
||||||
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);
|
||||||
if (hdl == NULL)
|
if (hdl == NULL)
|
||||||
return paUnanticipatedHostError;
|
return paUnanticipatedHostError;
|
||||||
if (!sio_setpar(hdl, &par)) {
|
if (!sio_setpar(hdl, &par)) {
|
||||||
@ -636,16 +653,37 @@ IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi,
|
|||||||
static void
|
static void
|
||||||
Terminate(struct PaUtilHostApiRepresentation *hostApi)
|
Terminate(struct PaUtilHostApiRepresentation *hostApi)
|
||||||
{
|
{
|
||||||
|
PaSndioHostApiRepresentation *sndioHostApi;
|
||||||
|
sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
|
||||||
|
free(sndioHostApi->audiodevices);
|
||||||
PaUtil_FreeMemory(hostApi);
|
PaUtil_FreeMemory(hostApi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
PaError
|
PaError
|
||||||
PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
|
PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
|
||||||
{
|
{
|
||||||
PaSndioHostApiRepresentation *sndioHostApi;
|
PaSndioHostApiRepresentation *sndioHostApi;
|
||||||
PaDeviceInfo *info;
|
PaDeviceInfo *info;
|
||||||
struct sio_hdl *hdl;
|
struct sio_hdl *hdl;
|
||||||
|
char *audiodevices;
|
||||||
|
char *device;
|
||||||
|
size_t deviceCount;
|
||||||
|
|
||||||
DPR("PaSndio_Initialize: initializing...\n");
|
DPR("PaSndio_Initialize: initializing...\n");
|
||||||
|
|
||||||
/* unusable APIs should return paNoError and a NULL hostApi */
|
/* unusable APIs should return paNoError and a NULL hostApi */
|
||||||
@ -655,24 +693,38 @@ PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApi
|
|||||||
if (sndioHostApi == NULL)
|
if (sndioHostApi == NULL)
|
||||||
return paNoError;
|
return paNoError;
|
||||||
|
|
||||||
info = &sndioHostApi->default_info;
|
// Add default device
|
||||||
info->structVersion = 2;
|
info = &sndioHostApi->device_info[0];
|
||||||
info->name = "default";
|
InitDeviceInfo(info, hostApiIndex, SIO_DEVANY);
|
||||||
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;
|
|
||||||
sndioHostApi->infos[0] = info;
|
sndioHostApi->infos[0] = info;
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*hostApi = &sndioHostApi->base;
|
*hostApi = &sndioHostApi->base;
|
||||||
(*hostApi)->info.structVersion = 1;
|
(*hostApi)->info.structVersion = 1;
|
||||||
(*hostApi)->info.type = paSndio;
|
(*hostApi)->info.type = paSndio;
|
||||||
(*hostApi)->info.name = "sndio";
|
(*hostApi)->info.name = "sndio";
|
||||||
(*hostApi)->info.deviceCount = 1;
|
(*hostApi)->info.deviceCount = deviceCount;
|
||||||
(*hostApi)->info.defaultInputDevice = 0;
|
(*hostApi)->info.defaultInputDevice = 0;
|
||||||
(*hostApi)->info.defaultOutputDevice = 0;
|
(*hostApi)->info.defaultOutputDevice = 0;
|
||||||
(*hostApi)->deviceInfos = sndioHostApi->infos;
|
(*hostApi)->deviceInfos = sndioHostApi->infos;
|
||||||
|
Loading…
Reference in New Issue
Block a user