factored out InitPaDeviceInfoFromAsioDriver function. skip device rather than failing entire init process if a single ASIO driver returns an error during init. This was happening with MOTU devices if the device wasn't present. See ticket #221
This commit is contained in:
parent
3dd3c9f5ce
commit
a51584e3b1
1 changed files with 152 additions and 123 deletions
|
|
@ -1019,6 +1019,149 @@ static ASIOSampleRate defaultSampleRateSearchOrder_[]
|
|||
192000.0, 16000.0, 12000.0, 11025.0, 9600.0, 8000.0 };
|
||||
|
||||
|
||||
static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asioHostApi,
|
||||
const char *driverName, int driverIndex,
|
||||
PaDeviceInfo *deviceInfo, PaAsioDeviceInfo *asioDeviceInfo )
|
||||
{
|
||||
PaError result = paNoError;
|
||||
|
||||
/* Due to the headless design of the ASIO API, drivers are free to write over data given to them (like M-Audio
|
||||
drivers f.i.). This is an attempt to overcome that. */
|
||||
union _tag_local {
|
||||
PaAsioDriverInfo info;
|
||||
char _padding[4096];
|
||||
} paAsioDriver;
|
||||
|
||||
asioDeviceInfo->asioChannelInfos = 0; /* we check this below to handle error cleanup */
|
||||
|
||||
result = LoadAsioDriver( asioHostApi, driverName, &paAsioDriver.info, asioHostApi->systemSpecific );
|
||||
if( result == paNoError )
|
||||
{
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", driverIndex,deviceInfo->name));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", driverIndex, paAsioDriver.info.inputChannelCount));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", driverIndex, paAsioDriver.info.outputChannelCount));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", driverIndex, paAsioDriver.info.bufferMinSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", driverIndex, paAsioDriver.info.bufferMaxSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", driverIndex, paAsioDriver.info.bufferPreferredSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", driverIndex, paAsioDriver.info.bufferGranularity));
|
||||
|
||||
deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount;
|
||||
deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount;
|
||||
|
||||
deviceInfo->defaultSampleRate = 0.;
|
||||
bool foundDefaultSampleRate = false;
|
||||
for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
|
||||
{
|
||||
ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
|
||||
if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
|
||||
{
|
||||
deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
|
||||
foundDefaultSampleRate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", driverIndex, deviceInfo->defaultSampleRate));
|
||||
|
||||
if( foundDefaultSampleRate ){
|
||||
|
||||
/* calculate default latency values from bufferPreferredSize
|
||||
for default low latency, and bufferMaxSize
|
||||
for default high latency.
|
||||
use the default sample rate to convert from samples to
|
||||
seconds. Without knowing what sample rate the user will
|
||||
use this is the best we can do.
|
||||
*/
|
||||
|
||||
double defaultLowLatency =
|
||||
paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate;
|
||||
|
||||
deviceInfo->defaultLowInputLatency = defaultLowLatency;
|
||||
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
|
||||
|
||||
double defaultHighLatency =
|
||||
paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate;
|
||||
|
||||
if( defaultHighLatency < defaultLowLatency )
|
||||
defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */
|
||||
|
||||
deviceInfo->defaultHighInputLatency = defaultHighLatency;
|
||||
deviceInfo->defaultHighOutputLatency = defaultHighLatency;
|
||||
|
||||
}else{
|
||||
|
||||
deviceInfo->defaultLowInputLatency = 0.;
|
||||
deviceInfo->defaultLowOutputLatency = 0.;
|
||||
deviceInfo->defaultHighInputLatency = 0.;
|
||||
deviceInfo->defaultHighOutputLatency = 0.;
|
||||
}
|
||||
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowInputLatency = %f\n", driverIndex, deviceInfo->defaultLowInputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowOutputLatency = %f\n", driverIndex, deviceInfo->defaultLowOutputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", driverIndex, deviceInfo->defaultHighInputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", driverIndex, deviceInfo->defaultHighOutputLatency));
|
||||
|
||||
asioDeviceInfo->minBufferSize = paAsioDriver.info.bufferMinSize;
|
||||
asioDeviceInfo->maxBufferSize = paAsioDriver.info.bufferMaxSize;
|
||||
asioDeviceInfo->preferredBufferSize = paAsioDriver.info.bufferPreferredSize;
|
||||
asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity;
|
||||
|
||||
|
||||
asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory(
|
||||
asioHostApi->allocations,
|
||||
sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels
|
||||
+ deviceInfo->maxOutputChannels) );
|
||||
if( !asioDeviceInfo->asioChannelInfos )
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error_unload;
|
||||
}
|
||||
|
||||
int a;
|
||||
|
||||
for( a=0; a < deviceInfo->maxInputChannels; ++a ){
|
||||
asioDeviceInfo->asioChannelInfos[a].channel = a;
|
||||
asioDeviceInfo->asioChannelInfos[a].isInput = ASIOTrue;
|
||||
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[a] );
|
||||
if( asioError != ASE_OK )
|
||||
{
|
||||
result = paUnanticipatedHostError;
|
||||
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
|
||||
goto error_unload;
|
||||
}
|
||||
}
|
||||
|
||||
for( a=0; a < deviceInfo->maxOutputChannels; ++a ){
|
||||
int b = deviceInfo->maxInputChannels + a;
|
||||
asioDeviceInfo->asioChannelInfos[b].channel = a;
|
||||
asioDeviceInfo->asioChannelInfos[b].isInput = ASIOFalse;
|
||||
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[b] );
|
||||
if( asioError != ASE_OK )
|
||||
{
|
||||
result = paUnanticipatedHostError;
|
||||
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
|
||||
goto error_unload;
|
||||
}
|
||||
}
|
||||
|
||||
/* unload the driver */
|
||||
UnloadAsioDriver();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
error_unload:
|
||||
UnloadAsioDriver();
|
||||
|
||||
if( asioDeviceInfo->asioChannelInfos ){
|
||||
PaUtil_GroupFreeMemory( asioHostApi->allocations, asioDeviceInfo->asioChannelInfos );
|
||||
asioDeviceInfo->asioChannelInfos = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* we look up IsDebuggerPresent at runtime incase it isn't present (on Win95 for example) */
|
||||
typedef BOOL (WINAPI *IsDebuggerPresentPtr)(VOID);
|
||||
IsDebuggerPresentPtr IsDebuggerPresent_ = 0;
|
||||
|
|
@ -1142,14 +1285,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
|
|||
|
||||
for( i=0; i < driverCount; ++i )
|
||||
{
|
||||
/* Due to the headless design of the ASIO API, drivers are free to write over data given to them (like M-Audio
|
||||
drivers f.i.). This is an attempt to overcome that. */
|
||||
union _tag_local {
|
||||
PaAsioDriverInfo info;
|
||||
char _padding[4096];
|
||||
} paAsioDriver;
|
||||
|
||||
|
||||
PA_DEBUG(("ASIO names[%d]:%s\n",i,names[i]));
|
||||
|
||||
// Since portaudio opens ALL ASIO drivers, and no one else does that,
|
||||
|
|
@ -1177,13 +1312,12 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
|
|||
if( strcmp(names[i], "ASIO Digidesign Driver") == 0 )
|
||||
{
|
||||
PA_DEBUG(("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n"));
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Attempt to load the asio driver... */
|
||||
if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriver.info, asioHostApi->systemSpecific ) == paNoError )
|
||||
/* Attempt to init device info from the asio driver... */
|
||||
{
|
||||
PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
|
||||
PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
|
||||
|
|
@ -1192,119 +1326,17 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
|
|||
deviceInfo->hostApi = hostApiIndex;
|
||||
|
||||
deviceInfo->name = names[i];
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d name = %s\n", i,deviceInfo->name));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d inputChannels = %d\n", i, paAsioDriver.info.inputChannelCount));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriver.info.outputChannelCount));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriver.info.bufferMinSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriver.info.bufferMaxSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriver.info.bufferPreferredSize));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriver.info.bufferGranularity));
|
||||
|
||||
deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount;
|
||||
deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount;
|
||||
|
||||
deviceInfo->defaultSampleRate = 0.;
|
||||
bool foundDefaultSampleRate = false;
|
||||
for( int j=0; j < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++j )
|
||||
if( InitPaDeviceInfoFromAsioDriver( asioHostApi, names[i], i, deviceInfo, asioDeviceInfo ) == paNoError )
|
||||
{
|
||||
ASIOError asioError = ASIOCanSampleRate( defaultSampleRateSearchOrder_[j] );
|
||||
if( asioError != ASE_NoClock && asioError != ASE_NotPresent )
|
||||
{
|
||||
deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[j];
|
||||
foundDefaultSampleRate = true;
|
||||
break;
|
||||
}
|
||||
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
|
||||
++(*hostApi)->info.deviceCount;
|
||||
}
|
||||
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultSampleRate = %f\n", i, deviceInfo->defaultSampleRate));
|
||||
|
||||
if( foundDefaultSampleRate ){
|
||||
|
||||
/* calculate default latency values from bufferPreferredSize
|
||||
for default low latency, and bufferMaxSize
|
||||
for default high latency.
|
||||
use the default sample rate to convert from samples to
|
||||
seconds. Without knowing what sample rate the user will
|
||||
use this is the best we can do.
|
||||
*/
|
||||
|
||||
double defaultLowLatency =
|
||||
paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate;
|
||||
|
||||
deviceInfo->defaultLowInputLatency = defaultLowLatency;
|
||||
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
|
||||
|
||||
double defaultHighLatency =
|
||||
paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate;
|
||||
|
||||
if( defaultHighLatency < defaultLowLatency )
|
||||
defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */
|
||||
|
||||
deviceInfo->defaultHighInputLatency = defaultHighLatency;
|
||||
deviceInfo->defaultHighOutputLatency = defaultHighLatency;
|
||||
|
||||
}else{
|
||||
|
||||
deviceInfo->defaultLowInputLatency = 0.;
|
||||
deviceInfo->defaultLowOutputLatency = 0.;
|
||||
deviceInfo->defaultHighInputLatency = 0.;
|
||||
deviceInfo->defaultHighOutputLatency = 0.;
|
||||
else
|
||||
{
|
||||
PA_DEBUG(("Skipping ASIO device:%s\n",names[i]));
|
||||
continue;
|
||||
}
|
||||
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowInputLatency = %f\n", i, deviceInfo->defaultLowInputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultLowOutputLatency = %f\n", i, deviceInfo->defaultLowOutputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighInputLatency = %f\n", i, deviceInfo->defaultHighInputLatency));
|
||||
PA_DEBUG(("PaAsio_Initialize: drv:%d defaultHighOutputLatency = %f\n", i, deviceInfo->defaultHighOutputLatency));
|
||||
|
||||
asioDeviceInfo->minBufferSize = paAsioDriver.info.bufferMinSize;
|
||||
asioDeviceInfo->maxBufferSize = paAsioDriver.info.bufferMaxSize;
|
||||
asioDeviceInfo->preferredBufferSize = paAsioDriver.info.bufferPreferredSize;
|
||||
asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity;
|
||||
|
||||
|
||||
asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory(
|
||||
asioHostApi->allocations,
|
||||
sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels
|
||||
+ deviceInfo->maxOutputChannels) );
|
||||
if( !asioDeviceInfo->asioChannelInfos )
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error_unload;
|
||||
}
|
||||
|
||||
int a;
|
||||
|
||||
for( a=0; a < deviceInfo->maxInputChannels; ++a ){
|
||||
asioDeviceInfo->asioChannelInfos[a].channel = a;
|
||||
asioDeviceInfo->asioChannelInfos[a].isInput = ASIOTrue;
|
||||
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[a] );
|
||||
if( asioError != ASE_OK )
|
||||
{
|
||||
result = paUnanticipatedHostError;
|
||||
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
|
||||
goto error_unload;
|
||||
}
|
||||
}
|
||||
|
||||
for( a=0; a < deviceInfo->maxOutputChannels; ++a ){
|
||||
int b = deviceInfo->maxInputChannels + a;
|
||||
asioDeviceInfo->asioChannelInfos[b].channel = a;
|
||||
asioDeviceInfo->asioChannelInfos[b].isInput = ASIOFalse;
|
||||
ASIOError asioError = ASIOGetChannelInfo( &asioDeviceInfo->asioChannelInfos[b] );
|
||||
if( asioError != ASE_OK )
|
||||
{
|
||||
result = paUnanticipatedHostError;
|
||||
PA_ASIO_SET_LAST_ASIO_ERROR( asioError );
|
||||
goto error_unload;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unload the driver */
|
||||
UnloadAsioDriver();
|
||||
|
||||
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
|
||||
++(*hostApi)->info.deviceCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1338,9 +1370,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
|
|||
|
||||
return result;
|
||||
|
||||
error_unload:
|
||||
UnloadAsioDriver();
|
||||
|
||||
error:
|
||||
if( asioHostApi )
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue