📄 pa_win_ds.c
字号:
memset( &caps, 0, sizeof(caps) ); caps.dwSize = sizeof(caps); hr = IDirectSound_GetCaps( lpDirectSound, &caps ); if( hr != DS_OK ) { DBUG(("Cannot GetCaps() for DirectSound device %s. Result = 0x%x\n", name, hr )); deviceOK = FALSE; } else {#ifndef PA_NO_WMME if( caps.dwFlags & DSCAPS_EMULDRIVER ) { /* If WMME supported, then reject Emulated drivers because they are lousy. */ deviceOK = FALSE; }#endif if( deviceOK ) { deviceInfo->maxInputChannels = 0; /* Mono or stereo device? */ deviceInfo->maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; deviceInfo->defaultLowInputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultLowOutputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultHighInputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultHighOutputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultSampleRate = 0; /** @todo IMPLEMENT ME */ //printf( "min %d max %d\n", caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate ); // dwFlags | DSCAPS_CONTINUOUSRATE } } IDirectSound_Release( lpDirectSound ); } if( deviceOK ) { deviceInfo->name = name; if( lpGUID == NULL ) hostApi->info.defaultOutputDevice = hostApi->info.deviceCount; hostApi->info.deviceCount++; } return result;}/************************************************************************************** Extract capabilities from an input device, and add it to the device info list** if successful. This function assumes that there is enough room in the** device info list to accomodate all entries.**** The device will not be added to the device list if any errors are encountered.*/static PaError AddInputDeviceInfoFromDirectSoundCapture( PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID ){ PaUtilHostApiRepresentation *hostApi = &winDsHostApi->inheritedHostApiRep; PaDeviceInfo *deviceInfo = hostApi->deviceInfos[hostApi->info.deviceCount]; PaWinDsDeviceInfo *winDsDeviceInfo = &winDsHostApi->winDsDeviceInfos[hostApi->info.deviceCount]; HRESULT hr; LPDIRECTSOUNDCAPTURE lpDirectSoundCapture; DSCCAPS caps; int deviceOK = TRUE; PaError result = paNoError; /* Copy GUID to the device info structure. Set pointer. */ if( lpGUID == NULL ) { winDsDeviceInfo->lpGUID = NULL; } else { winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid; memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) ); } hr = dswDSoundEntryPoints.DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL ); /** try using CoCreateInstance because DirectSoundCreate was hanging under some circumstances - note this was probably related to the #define BOOL short bug which has now been fixed @todo delete this comment and the following code once we've ensured there is no bug. */ /* hr = CoCreateInstance( &CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSoundCapture, (void**)&lpDirectSoundCapture ); */ if( hr != DS_OK ) { DBUG(("Cannot create Capture for %s. Result = 0x%x\n", name, hr )); deviceOK = FALSE; } else { /* Query device characteristics. */ memset( &caps, 0, sizeof(caps) ); caps.dwSize = sizeof(caps); hr = IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps ); if( hr != DS_OK ) { DBUG(("Cannot GetCaps() for Capture device %s. Result = 0x%x\n", name, hr )); deviceOK = FALSE; } else {#ifndef PA_NO_WMME if( caps.dwFlags & DSCAPS_EMULDRIVER ) { /* If WMME supported, then reject Emulated drivers because they are lousy. */ deviceOK = FALSE; }#endif if( deviceOK ) { deviceInfo->maxInputChannels = caps.dwChannels; deviceInfo->maxOutputChannels = 0; deviceInfo->defaultLowInputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultLowOutputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultHighInputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultHighOutputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultSampleRate = 0; /** @todo IMPLEMENT ME */ } } IDirectSoundCapture_Release( lpDirectSoundCapture ); } if( deviceOK ) { deviceInfo->name = name; if( lpGUID == NULL ) hostApi->info.defaultInputDevice = hostApi->info.deviceCount; hostApi->info.deviceCount++; } return result;}/***********************************************************************************/PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ){ PaError result = paNoError; int i, deviceCount; PaWinDsHostApiRepresentation *winDsHostApi; DSDeviceNameAndGUIDVector inputNamesAndGUIDs, outputNamesAndGUIDs; PaDeviceInfo *deviceInfoArray; HRESULT hr = CoInitialize(NULL); /** @todo: should uninitialize too */ if( FAILED(hr) ){ return paUnanticipatedHostError; } /* initialise guid vectors so they can be safely deleted on error */ inputNamesAndGUIDs.items = NULL; outputNamesAndGUIDs.items = NULL; DSW_InitializeDSoundEntryPoints(); winDsHostApi = (PaWinDsHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinDsHostApiRepresentation) ); if( !winDsHostApi ) { result = paInsufficientMemory; goto error; } winDsHostApi->allocations = PaUtil_CreateAllocationGroup(); if( !winDsHostApi->allocations ) { result = paInsufficientMemory; goto error; } *hostApi = &winDsHostApi->inheritedHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paDirectSound; (*hostApi)->info.name = "Windows DirectSound"; (*hostApi)->info.deviceCount = 0; (*hostApi)->info.defaultInputDevice = paNoDevice; (*hostApi)->info.defaultOutputDevice = paNoDevice; /* DSound - enumerate devices to count them and to gather their GUIDs */ result = InitializeDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs, winDsHostApi->allocations ); if( result != paNoError ) goto error; result = InitializeDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs, winDsHostApi->allocations ); if( result != paNoError ) goto error; dswDSoundEntryPoints.DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&inputNamesAndGUIDs ); dswDSoundEntryPoints.DirectSoundEnumerate( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&outputNamesAndGUIDs ); if( inputNamesAndGUIDs.enumerationError != paNoError ) { result = inputNamesAndGUIDs.enumerationError; goto error; } if( outputNamesAndGUIDs.enumerationError != paNoError ) { result = outputNamesAndGUIDs.enumerationError; goto error; } deviceCount = inputNamesAndGUIDs.count + outputNamesAndGUIDs.count; if( deviceCount > 0 ) { /* allocate array for pointers to PaDeviceInfo structs */ (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( winDsHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount ); if( !(*hostApi)->deviceInfos ) { result = paInsufficientMemory; goto error; } /* allocate all PaDeviceInfo structs in a contiguous block */ deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( winDsHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount ); if( !deviceInfoArray ) { result = paInsufficientMemory; goto error; } /* allocate all DSound specific info structs in a contiguous block */ winDsHostApi->winDsDeviceInfos = (PaWinDsDeviceInfo*)PaUtil_GroupAllocateMemory( winDsHostApi->allocations, sizeof(PaWinDsDeviceInfo) * deviceCount ); if( !winDsHostApi->winDsDeviceInfos ) { result = paInsufficientMemory; goto error; } for( i=0; i < deviceCount; ++i ) { PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; deviceInfo->structVersion = 2; deviceInfo->hostApi = hostApiIndex; deviceInfo->name = 0; (*hostApi)->deviceInfos[i] = deviceInfo; } for( i=0; i< inputNamesAndGUIDs.count; ++i ) { result = AddInputDeviceInfoFromDirectSoundCapture( winDsHostApi, inputNamesAndGUIDs.items[i].name, inputNamesAndGUIDs.items[i].lpGUID ); if( result != paNoError ) goto error; } for( i=0; i< outputNamesAndGUIDs.count; ++i ) { result = AddOutputDeviceInfoFromDirectSound( winDsHostApi, outputNamesAndGUIDs.items[i].name, outputNamesAndGUIDs.items[i].lpGUID ); if( result != paNoError ) goto error; } } result = TerminateDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs ); if( result != paNoError ) goto error; result = TerminateDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs ); if( result != paNoError ) goto error; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface( &winDsHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, GetStreamCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); PaUtil_InitializeStreamInterface( &winDsHostApi->blockingStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); return result;error: if( winDsHostApi ) { if( winDsHostApi->allocations ) { PaUtil_FreeAllAllocations( winDsHostApi->allocations ); PaUtil_DestroyAllocationGroup( winDsHostApi->allocations ); } PaUtil_FreeMemory( winDsHostApi ); } TerminateDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs ); TerminateDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs ); return result;}/***********************************************************************************/static void Terminate( struct PaUtilHostApiRepresentation *hostApi ){ PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi; /* IMPLEMENT ME: - clean up any resources not handled by the allocation group */ if( winDsHostApi->allocations ) { PaUtil_FreeAllAllocations( winDsHostApi->allocations ); PaUtil_DestroyAllocationGroup( winDsHostApi->allocations ); } PaUtil_FreeMemory( winDsHostApi ); DSW_TerminateDSoundEntryPoints(); CoUninitialize();}/* Set minimal latency based on whether NT or Win95. * NT has higher latency. */static int PaWinDS_GetMinSystemLatency( void ){ int minLatencyMsec; /* Set minimal latency based on whether NT or other OS. * NT has higher latency. */ OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof( osvi ); GetVersionEx( &osvi ); DBUG(("PA - PlatformId = 0x%x\n", osvi.dwPlatformId )); DBUG(("PA - MajorVersion = 0x%x\n", osvi.dwMajorVersion )); DBUG(("PA - MinorVersion = 0x%x\n", osvi.dwMinorVersion )); /* Check for NT */ if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) ) { minLatencyMsec = PA_WIN_NT_LATENCY; } else if(osvi.dwMajorVersion >= 5) { minLatencyMsec = PA_WIN_WDM_LATENCY; } else { minLatencyMsec = PA_WIN_9X_LATENCY; } return minLatencyMsec;}/***********************************************************************************/static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate ){ int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* 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 */ } else { inputChannelCount = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that output device can support inputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -