📄 pa_win_wdmks.c
字号:
{ if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has render alias\n",device)); hasAlias |= 1; /* Has render alias */ } } noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData); if(noError) { if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has capture alias\n",device)); hasAlias |= 2; /* Has capture alias */ } } if(!hasAlias) continue; /* This was not a valid capture or render audio device */ noError = SetupDiGetDeviceInterfaceDetail(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData); if( noError ) { /* Try to get the "friendly name" for this interface */ sizeFriendlyName = sizeof(friendlyName); /* Fix contributed by Ben Allison * Removed KEY_SET_VALUE from flags on following call * as its causes failure when running without admin rights * and it was not required */ hkey=SetupDiOpenDeviceInterfaceRegKey(handle,&interfaceData,0,KEY_QUERY_VALUE); if(hkey!=INVALID_HANDLE_VALUE) { noError = RegQueryValueEx(hkey,TEXT("FriendlyName"),0,&type,(BYTE*)friendlyName,&sizeFriendlyName); if( noError == ERROR_SUCCESS ) { PA_DEBUG(("Interface %d, Name: %s\n",device,friendlyName)); RegCloseKey(hkey); } else { friendlyName[0] = 0; } } newFilter = FilterNew(devInterfaceDetails->DevicePath,friendlyName,&result); if( result == paNoError ) { PA_DEBUG(("Filter created\n")); wdmHostApi->filters[slot] = newFilter; slot++; } else { PA_DEBUG(("Filter NOT created\n")); /* As there are now less filters than we initially thought * we must reduce the count by one */ wdmHostApi->filterCount--; } } } /* Clean up */ if(handle != NULL) SetupDiDestroyDeviceInfoList(handle); return paNoError;}PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ){ PaError result = paNoError; int i, deviceCount; PaWinWdmHostApiRepresentation *wdmHostApi; PaWinWdmDeviceInfo *deviceInfoArray; PaWinWdmFilter* pFilter; PaWinWdmDeviceInfo *wdmDeviceInfo; PaDeviceInfo *deviceInfo; PA_LOGE_; /* Attempt to load the KSUSER.DLL without which we cannot create pins We will unload this on termination */ if(DllKsUser == NULL) { DllKsUser = LoadLibrary(TEXT("ksuser.dll")); if(DllKsUser == NULL) goto error; } FunctionKsCreatePin = (KSCREATEPIN*)GetProcAddress(DllKsUser, "KsCreatePin"); if(FunctionKsCreatePin == NULL) goto error; wdmHostApi = (PaWinWdmHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinWdmHostApiRepresentation) ); if( !wdmHostApi ) { result = paInsufficientMemory; goto error; } wdmHostApi->allocations = PaUtil_CreateAllocationGroup(); if( !wdmHostApi->allocations ) { result = paInsufficientMemory; goto error; } result = BuildFilterList( wdmHostApi ); if( result != paNoError ) { goto error; } deviceCount = wdmHostApi->filterCount; *hostApi = &wdmHostApi->inheritedHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paWDMKS; (*hostApi)->info.name = "Windows WDM-KS"; (*hostApi)->info.defaultInputDevice = paNoDevice; (*hostApi)->info.defaultOutputDevice = paNoDevice; if( deviceCount > 0 ) { (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo*) * deviceCount ); if( !(*hostApi)->deviceInfos ) { result = paInsufficientMemory; goto error; } /* allocate all device info structs in a contiguous block */ deviceInfoArray = (PaWinWdmDeviceInfo*)PaUtil_GroupAllocateMemory( wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo) * deviceCount ); if( !deviceInfoArray ) { result = paInsufficientMemory; goto error; } for( i=0; i < deviceCount; ++i ) { wdmDeviceInfo = &deviceInfoArray[i]; deviceInfo = &wdmDeviceInfo->inheritedDeviceInfo; pFilter = wdmHostApi->filters[i]; if( pFilter == NULL ) continue; wdmDeviceInfo->filter = pFilter; deviceInfo->structVersion = 2; deviceInfo->hostApi = hostApiIndex; deviceInfo->name = (char*)pFilter->friendlyName; PA_DEBUG(("Device found name: %s\n",(char*)pFilter->friendlyName)); deviceInfo->maxInputChannels = pFilter->maxInputChannels; if(deviceInfo->maxInputChannels > 0) { /* Set the default input device to the first device we find with * more than zero input channels **/ if((*hostApi)->info.defaultInputDevice == paNoDevice) { (*hostApi)->info.defaultInputDevice = i; } } deviceInfo->maxOutputChannels = pFilter->maxOutputChannels; if(deviceInfo->maxOutputChannels > 0) { /* Set the default output device to the first device we find with * more than zero output channels **/ if((*hostApi)->info.defaultOutputDevice == paNoDevice) { (*hostApi)->info.defaultOutputDevice = i; } } /* These low values are not very useful because * a) The lowest latency we end up with can depend on many factors such * as the device buffer sizes/granularities, sample rate, channels and format * b) We cannot know the device buffer sizes until we try to open/use it at * a particular setting * So: we give 512x48000Hz frames as the default low input latency **/ deviceInfo->defaultLowInputLatency = (512.0/48000.0); deviceInfo->defaultLowOutputLatency = (512.0/48000.0); deviceInfo->defaultHighInputLatency = (4096.0/48000.0); deviceInfo->defaultHighOutputLatency = (4096.0/48000.0); deviceInfo->defaultSampleRate = (double)(pFilter->bestSampleRate); (*hostApi)->deviceInfos[i] = deviceInfo; } } (*hostApi)->info.deviceCount = deviceCount; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface( &wdmHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, GetStreamCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); PaUtil_InitializeStreamInterface( &wdmHostApi->blockingStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); PA_LOGL_; return result;error: if( DllKsUser != NULL ) { FreeLibrary( DllKsUser ); DllKsUser = NULL; } if( wdmHostApi ) { PaUtil_FreeMemory( wdmHostApi->filters ); if( wdmHostApi->allocations ) { PaUtil_FreeAllAllocations( wdmHostApi->allocations ); PaUtil_DestroyAllocationGroup( wdmHostApi->allocations ); } PaUtil_FreeMemory( wdmHostApi ); } PA_LOGL_; return result;}static void Terminate( struct PaUtilHostApiRepresentation *hostApi ){ PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; int i; PA_LOGE_; if( wdmHostApi->filters ) { for( i=0; i<wdmHostApi->filterCount; i++) { if( wdmHostApi->filters[i] != NULL ) { FilterFree( wdmHostApi->filters[i] ); wdmHostApi->filters[i] = NULL; } } } PaUtil_FreeMemory( wdmHostApi->filters ); if( wdmHostApi->allocations ) { PaUtil_FreeAllAllocations( wdmHostApi->allocations ); PaUtil_DestroyAllocationGroup( wdmHostApi->allocations ); } PaUtil_FreeMemory( wdmHostApi ); PA_LOGL_;}static void FillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount){ PA_LOGE_; PA_DEBUG(( "sampleFormat = %lx\n" , sampleFormat )); PA_DEBUG(( "sampleRate = %f\n" , sampleRate )); PA_DEBUG(( "chanelCount = %d\n", channelCount )); pwfext->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; pwfext->Format.nChannels = channelCount; pwfext->Format.nSamplesPerSec = (int)sampleRate; if(channelCount == 1) pwfext->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; else pwfext->dwChannelMask = KSAUDIO_SPEAKER_STEREO; if(sampleFormat == paFloat32) { pwfext->Format.nBlockAlign = channelCount * 4; pwfext->Format.wBitsPerSample = 32; pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); pwfext->Samples.wValidBitsPerSample = 32; pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; } else if(sampleFormat == paInt32) { pwfext->Format.nBlockAlign = channelCount * 4; pwfext->Format.wBitsPerSample = 32; pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); pwfext->Samples.wValidBitsPerSample = 32; pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else if(sampleFormat == paInt24) { pwfext->Format.nBlockAlign = channelCount * 3; pwfext->Format.wBitsPerSample = 24; pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); pwfext->Samples.wValidBitsPerSample = 24; pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else if(sampleFormat == paInt16) { pwfext->Format.nBlockAlign = channelCount * 2; pwfext->Format.wBitsPerSample = 16; pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); pwfext->Samples.wValidBitsPerSample = 16; pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } pwfext->Format.nAvgBytesPerSec = pwfext->Format.nSamplesPerSec * pwfext->Format.nBlockAlign; PA_LOGL_;}static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate ){ int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi; PaWinWdmFilter* pFilter; int result = paFormatIsSupported; WAVEFORMATEXTENSIBLE wfx; PA_LOGE_; if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ if( inputSampleFormat & paCustomFormat ) return paSampleFormatNotSupported; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that input device can support inputChannelCount */ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels ) return paInvalidChannelCount; /* validate inputStreamInfo */ if( inputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ /* Check that the input format is supported */ FillWFEXT(&wfx,paInt16,sampleRate,inputChannelCount); pFilter = wdmHostApi->filters[inputParameters->device]; result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx); if( result != paNoError ) { /* Try a WAVE_FORMAT_PCM instead */ wfx.Format.wFormatTag = WAVE_FORMAT_PCM; wfx.Format.cbSize = 0; wfx.Samples.wValidBitsPerSample = 0; wfx.dwChannelMask = 0; wfx.SubFormat = GUID_NULL; result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx); if( result != paNoError ) return result; } } else { inputChannelCount = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ if( outputSampleFormat & paCustomFormat ) return paSampleFormatNotSupported; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that output device can support outputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) return paInvalidChannelCount; /* validate outputStreamInfo */ if( outputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ /* Check that the output format is supported */ FillWFEXT(&wfx,paInt16,sampleRate,outputChannelCount); pFilter = wdmHostApi->filters[outputParameters->device]; result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx); if( result != paNoError ) { /* Try a WAVE_FORMAT_PCM instead */ wfx.Format.wFormatTag = WAVE_FORMAT_PCM; wfx.Format.cbSize = 0; wfx.Samples.wValidBitsPerSample = 0; wfx.dwChannelMask = 0; wfx.SubFormat = GUID_NULL; result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx); if( result != paNoError ) return result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -