PaAsioHostApiRepresentation *asioHostApi;
PaAsioDeviceInfo *deviceInfoArray;
char **names;
- PaAsioDriverInfo paAsioDriverInfo;
-
asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) );
if( !asioHostApi )
{
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]));
/* Attempt to load the asio driver... */
- if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriverInfo, asioHostApi->systemSpecific ) == paNoError )
+ if( LoadAsioDriver( asioHostApi, names[i], &paAsioDriver.info, asioHostApi->systemSpecific ) == paNoError )
{
PaAsioDeviceInfo *asioDeviceInfo = &deviceInfoArray[ (*hostApi)->info.deviceCount ];
PaDeviceInfo *deviceInfo = &asioDeviceInfo->commonDeviceInfo;
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, paAsioDriverInfo.inputChannelCount));
- PA_DEBUG(("PaAsio_Initialize: drv:%d outputChannels = %d\n", i, paAsioDriverInfo.outputChannelCount));
- PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMinSize = %d\n", i, paAsioDriverInfo.bufferMinSize));
- PA_DEBUG(("PaAsio_Initialize: drv:%d bufferMaxSize = %d\n", i, paAsioDriverInfo.bufferMaxSize));
- PA_DEBUG(("PaAsio_Initialize: drv:%d bufferPreferredSize = %d\n", i, paAsioDriverInfo.bufferPreferredSize));
- PA_DEBUG(("PaAsio_Initialize: drv:%d bufferGranularity = %d\n", i, paAsioDriverInfo.bufferGranularity));
+ 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 = paAsioDriverInfo.inputChannelCount;
- deviceInfo->maxOutputChannels = paAsioDriverInfo.outputChannelCount;
+ deviceInfo->maxInputChannels = paAsioDriver.info.inputChannelCount;
+ deviceInfo->maxOutputChannels = paAsioDriver.info.outputChannelCount;
deviceInfo->defaultSampleRate = 0.;
bool foundDefaultSampleRate = false;
*/
double defaultLowLatency =
- paAsioDriverInfo.bufferPreferredSize / deviceInfo->defaultSampleRate;
+ paAsioDriver.info.bufferPreferredSize / deviceInfo->defaultSampleRate;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
double defaultHighLatency =
- paAsioDriverInfo.bufferMaxSize / deviceInfo->defaultSampleRate;
+ paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate;
if( defaultHighLatency < defaultLowLatency )
defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */
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 = paAsioDriverInfo.bufferMinSize;
- asioDeviceInfo->maxBufferSize = paAsioDriverInfo.bufferMaxSize;
- asioDeviceInfo->preferredBufferSize = paAsioDriverInfo.bufferPreferredSize;
- asioDeviceInfo->bufferGranularity = paAsioDriverInfo.bufferGranularity;
+ 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(
{
ULONG topoPinId = GetConnectedPin(pinId, (pin->dataFlow == KSPIN_DATAFLOW_IN), parentFilter, -1, NULL, NULL);
+ const wchar_t kInputName[] = L"Input";
+ const wchar_t kOutputName[] = L"Output";
if (topoPinId != KSFILTER_NODE)
{
/* Make sure pin gets a name here... */
if (wcslen(pin->friendlyName) == 0)
{
- wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? L"Output" : L"Input");
+ wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName);
#ifdef UNICODE
PA_DEBUG(("PinNew: Setting pin friendly name to '%s'\n", pin->friendlyName));
#else
/* Make sure we get a name for the pin */
if (wcslen(pin->friendlyName) == 0)
{
- wcscpy(pin->friendlyName, L"Input");
+ wcscpy(pin->friendlyName, kInputName);
}
#ifdef UNICODE
PA_DEBUG(("PinNew: Input friendly name '%s'\n", pin->friendlyName));
result = GetNameFromCategory(&category, TRUE, pin->inputs[i]->friendlyName, MAX_PATH);
if (result != paNoError)
{
- _snwprintf(pin->inputs[i]->friendlyName, MAX_PATH, L"Input %d", i + 1);
+ /* Only specify name, let name hash in ScanDeviceInfos fix postfix enumerators */
+ wcscpy(pin->inputs[i]->friendlyName, kInputName);
}
}
#ifdef UNICODE
{
PA_DEBUG(("PinNew: No topology pin id found. Bad...\n"));
/* No TOPO pin id ??? This is bad. Ok, so we just say it is an input or output... */
- if (pin->dataFlow == KSPIN_DATAFLOW_IN)
- {
- wcscpy(pin->friendlyName, L"Line Out");
- }
- else
- {
- wcscpy(pin->friendlyName, L"Line In");
- }
+ wcscpy(pin->friendlyName, (pin->dataFlow == KSPIN_DATAFLOW_IN) ? kOutputName : kInputName);
}
}
{
goto error;
}
- /* Reset the events as some devices SET the event on PinRead */
- ResetEvent(pInfo->stream->capture.packets[i].Signal.hEvent);
++pInfo->pending;
}
}
{
if (eventSignalled < captureEvents)
{
- timeStamp[0] = dwCurrentTime;
- info.stream->capture.pPin->fnEventHandler(&info, eventSignalled);
- /* Since we use the ring buffer, we can submit the buffers directly */
- if (!info.stream->streamStop)
+ if (info.stream->capture.pPin->fnEventHandler(&info, eventSignalled) == paNoError)
{
- result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail);
- if (result != paNoError)
+ timeStamp[0] = dwCurrentTime;
+
+ /* Since we use the ring buffer, we can submit the buffers directly */
+ if (!info.stream->streamStop)
{
- PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result));
- break;
+ result = info.stream->capture.pPin->fnSubmitHandler(&info, info.captureTail);
+ if (result != paNoError)
+ {
+ PA_HP_TRACE((info.stream->hLog, "Capture submit handler failed with result %d", result));
+ break;
+ }
+ }
+ ++info.captureTail;
+ /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop
+ handling working, so let that be processed anyways... */
+ if (info.stream->userOutputChannels > 0)
+ {
+ doProcessing = 0;
}
- }
- ++info.captureTail;
- /* If full-duplex, let _only_ render event trigger processing. We still need the stream stop
- handling working, so let that be processed anyways... */
- if (info.stream->userOutputChannels > 0)
- {
- doProcessing = 0;
}
}
else if (eventSignalled < renderEvents)
assert( eventIndex < pInfo->stream->capture.noOfPackets );
+ if (packet->Header.DataUsed == 0)
+ {
+ PA_HP_TRACE((pInfo->stream->hLog, ">>> Capture bogus event: idx=%u (DataUsed=%u)", eventIndex, packet->Header.DataUsed));
+
+ /* Bogus event, reset! This is to handle the behavior of this USB mic: http://shop.xtz.se/measurement-system/microphone-to-dirac-live-room-correction-suite
+ on startup of streaming, where it erroneously sets the event without the corresponding buffer being filled (DataUsed == 0) */
+ ResetEvent(packet->Signal.hEvent);
+ return -1;
+ }
+
pInfo->capturePackets[pInfo->captureHead & cPacketsArrayMask].packet = packet;
frameCount = PaUtil_WriteRingBuffer(&pInfo->stream->ringBuffer, packet->Header.Data, pInfo->stream->capture.framesPerBuffer);
assert(packet != 0);
PA_HP_TRACE((pInfo->stream->hLog, "Capture submit: %u", eventIndex));
packet->Header.DataUsed = 0; /* Reset for reuse */
- result = PinRead(pInfo->stream->capture.pPin->handle, packet);
- /* Reset event, as some drivers might not do so (or even set the event!!), resulting in a 100% CPU capture loop */
ResetEvent(packet->Signal.hEvent);
+ result = PinRead(pInfo->stream->capture.pPin->handle, packet);
++pInfo->pending;
return result;
}