📄 pa_win_wdmks.c
字号:
filter->formats |= newPin->formats; } if(newPin->bestSampleRate > filter->bestSampleRate) { filter->bestSampleRate = newPin->bestSampleRate; } } } if(( filter->maxInputChannels == 0) && ( filter->maxOutputChannels == 0)) { /* No input or output... not valid */ valid = 0; } if( !valid ) { /* No valid pin was found on this filter so we destroy it */ result = paDeviceUnavailable; goto error; } /* Close the filter handle for now * It will be opened later when needed */ FilterRelease(filter); *error = paNoError; return filter;error: /* Error cleanup */ if( filter ) { for( pinId = 0; pinId < filter->pinCount; pinId++ ) PinFree(filter->pins[pinId]); PaUtil_FreeMemory( filter->pins ); if( filter->handle ) CloseHandle( filter->handle ); PaUtil_FreeMemory( filter ); } *error = result; return NULL;}/** * Free a previously created filter */static void FilterFree(PaWinWdmFilter* filter){ int pinId; PA_LOGL_; if( filter ) { for( pinId = 0; pinId < filter->pinCount; pinId++ ) PinFree(filter->pins[pinId]); PaUtil_FreeMemory( filter->pins ); if( filter->handle ) CloseHandle( filter->handle ); PaUtil_FreeMemory( filter ); } PA_LOGE_;}/** * Reopen the filter handle if necessary so it can be used **/static PaError FilterUse(PaWinWdmFilter* filter){ assert( filter ); PA_LOGE_; if( filter->handle == NULL ) { /* Open the filter */ filter->handle = CreateFile( filter->filterName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if( filter->handle == NULL ) { return paDeviceUnavailable; } } filter->usageCount++; PA_LOGL_; return paNoError;}/** * Release the filter handle if nobody is using it **/static void FilterRelease(PaWinWdmFilter* filter){ assert( filter ); assert( filter->usageCount > 0 ); PA_LOGE_; filter->usageCount--; if( filter->usageCount == 0 ) { if( filter->handle != NULL ) { CloseHandle( filter->handle ); filter->handle = NULL; } } PA_LOGL_;}/** * Create a render (playback) Pin using the supplied format **/static PaWinWdmPin* FilterCreateRenderPin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex, PaError* error){ PaError result; PaWinWdmPin* pin; assert( filter ); pin = FilterFindViableRenderPin(filter,wfex,&result); if(!pin) { goto error; } result = PinSetFormat(pin,wfex); if( result != paNoError ) { goto error; } result = PinInstantiate(pin); if( result != paNoError ) { goto error; } *error = paNoError; return pin;error: *error = result; return NULL;}/** * Find a pin that supports the given format **/static PaWinWdmPin* FilterFindViableRenderPin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex, PaError* error){ int pinId; PaWinWdmPin* pin; PaError result = paDeviceUnavailable; *error = paNoError; assert( filter ); for( pinId = 0; pinId<filter->pinCount; pinId++ ) { pin = filter->pins[pinId]; if( pin != NULL ) { if(( pin->dataFlow == KSPIN_DATAFLOW_IN ) && (( pin->communication == KSPIN_COMMUNICATION_SINK) || ( pin->communication == KSPIN_COMMUNICATION_BOTH))) { result = PinIsFormatSupported( pin, wfex ); if( result == paNoError ) { return pin; } } } } *error = result; return NULL;}/** * Check if there is a pin that should playback * with the supplied format **/static PaError FilterCanCreateRenderPin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex){ PaWinWdmPin* pin; PaError result; assert ( filter ); pin = FilterFindViableRenderPin(filter,wfex,&result); /* result will be paNoError if pin found * or else an error code indicating what is wrong with the format **/ return result;}/** * Create a capture (record) Pin using the supplied format **/static PaWinWdmPin* FilterCreateCapturePin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex, PaError* error){ PaError result; PaWinWdmPin* pin; assert( filter ); pin = FilterFindViableCapturePin(filter,wfex,&result); if(!pin) { goto error; } result = PinSetFormat(pin,wfex); if( result != paNoError ) { goto error; } result = PinInstantiate(pin); if( result != paNoError ) { goto error; } *error = paNoError; return pin;error: *error = result; return NULL;}/** * Find a capture pin that supports the given format **/static PaWinWdmPin* FilterFindViableCapturePin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex, PaError* error){ int pinId; PaWinWdmPin* pin; PaError result = paDeviceUnavailable; *error = paNoError; assert( filter ); for( pinId = 0; pinId<filter->pinCount; pinId++ ) { pin = filter->pins[pinId]; if( pin != NULL ) { if(( pin->dataFlow == KSPIN_DATAFLOW_OUT ) && (( pin->communication == KSPIN_COMMUNICATION_SINK) || ( pin->communication == KSPIN_COMMUNICATION_BOTH))) { result = PinIsFormatSupported( pin, wfex ); if( result == paNoError ) { return pin; } } } } *error = result; return NULL;}/** * Check if there is a pin that should playback * with the supplied format **/static PaError FilterCanCreateCapturePin(PaWinWdmFilter* filter, const WAVEFORMATEX* wfex){ PaWinWdmPin* pin; PaError result; assert ( filter ); pin = FilterFindViableCapturePin(filter,wfex,&result); /* result will be paNoError if pin found * or else an error code indicating what is wrong with the format **/ return result;}/** * Build the list of available filters */static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi){ PaError result = paNoError; HDEVINFO handle = NULL; int device; int invalidDevices; int slot; SP_DEVICE_INTERFACE_DATA interfaceData; SP_DEVICE_INTERFACE_DATA aliasData; SP_DEVINFO_DATA devInfoData; int noError; const int sizeInterface = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR)); unsigned char interfaceDetailsArray[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))]; SP_DEVICE_INTERFACE_DETAIL_DATA* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*)interfaceDetailsArray; TCHAR friendlyName[MAX_PATH]; HKEY hkey; DWORD sizeFriendlyName; DWORD type; PaWinWdmFilter* newFilter; GUID* category = (GUID*)&KSCATEGORY_AUDIO; GUID* alias_render = (GUID*)&KSCATEGORY_RENDER; GUID* alias_capture = (GUID*)&KSCATEGORY_CAPTURE; DWORD hasAlias; PA_LOGE_; devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); /* Open a handle to search for devices (filters) */ handle = SetupDiGetClassDevs(category,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if( handle == NULL ) { return paUnanticipatedHostError; } PA_DEBUG(("Setup called\n")); /* First let's count the number of devices so we can allocate a list */ invalidDevices = 0; for( device = 0;;device++ ) { interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); interfaceData.Reserved = 0; aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); aliasData.Reserved = 0; noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData); PA_DEBUG(("Enum called\n")); if( !noError ) break; /* No more devices */ /* Check this one has the render or capture alias */ hasAlias = 0; noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData); PA_DEBUG(("noError = %d\n",noError)); if(noError) { if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED))) { PA_DEBUG(("Device %d has render alias\n",device)); hasAlias |= 1; /* Has render alias */ } else { PA_DEBUG(("Device %d has no render alias\n",device)); } } 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 */ } else { PA_DEBUG(("Device %d has no capture alias\n",device)); } } if(!hasAlias) invalidDevices++; /* This was not a valid capture or render audio device */ } /* Remember how many there are */ wdmHostApi->filterCount = device-invalidDevices; PA_DEBUG(("Interfaces found: %d\n",device-invalidDevices)); /* Now allocate the list of pointers to devices */ wdmHostApi->filters = (PaWinWdmFilter**)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter*) * device ); if( !wdmHostApi->filters ) { if(handle != NULL) SetupDiDestroyDeviceInfoList(handle); return paInsufficientMemory; } /* Now create filter objects for each interface found */ slot = 0; for( device = 0;;device++ ) { interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); interfaceData.Reserved = 0; aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); aliasData.Reserved = 0; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInfoData.Reserved = 0; noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData); if( !noError ) break; /* No more devices */ /* Check this one has the render or capture alias */ hasAlias = 0; noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData); if(noError)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -