- Certain drivers write over the available memory of PaAsioDriverInfo, now a padding area makes sure
  the stack doesn't get corrupted.
WDM-KS:
- Corrected capture event handling
This commit is contained in:
robiwan 2012-02-23 15:29:24 +00:00
commit 32e0080310
2 changed files with 58 additions and 47 deletions

View file

@ -1031,8 +1031,6 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
PaAsioHostApiRepresentation *asioHostApi;
PaAsioDeviceInfo *deviceInfoArray;
char **names;
PaAsioDriverInfo paAsioDriverInfo;
asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) );
if( !asioHostApi )
{
@ -1142,6 +1140,13 @@ 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]));
@ -1176,7 +1181,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
/* 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;
@ -1186,15 +1191,15 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
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;
@ -1222,13 +1227,13 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
*/
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 */
@ -1249,10 +1254,10 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex
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(

View file

@ -1532,6 +1532,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
{
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)
{
@ -1580,7 +1582,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
/* 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
@ -1798,7 +1800,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
/* 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));
@ -1875,7 +1877,8 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
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
@ -1903,14 +1906,7 @@ static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, Pa
{
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);
}
}
@ -5422,8 +5418,6 @@ static PaError PreparePinsForStart(PaProcessThreadInfo* pInfo)
{
goto error;
}
/* Reset the events as some devices SET the event on PinRead */
ResetEvent(pInfo->stream->capture.packets[i].Signal.hEvent);
++pInfo->pending;
}
}
@ -5903,24 +5897,27 @@ PA_THREAD_FUNC ProcessingThread(void* pParam)
{
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)
@ -6317,6 +6314,16 @@ static PaError PaPinCaptureEventHandler_WaveCyclic(PaProcessThreadInfo* pInfo, u
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);
@ -6335,9 +6342,8 @@ static PaError PaPinCaptureSubmitHandler_WaveCyclic(PaProcessThreadInfo* pInfo,
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;
}