CMake: Added PA_WDMKS_NO_KSGUID_LIB to WDMKS and solution folders
WDMKS: Support for default device (see caveat for input devices though in ScanDeviceInfos)
Added possibility to set channel mask
This commit is contained in:
parent
c8cc50d6d1
commit
4aa340a57e
6 changed files with 192 additions and 54 deletions
|
|
@ -7,6 +7,8 @@ PROJECT( portaudio )
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||||
|
|
||||||
|
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
OPTION(PA_CONFIG_LIB_OUTPUT_PATH "Make sure that output paths are kept neat" OFF)
|
OPTION(PA_CONFIG_LIB_OUTPUT_PATH "Make sure that output paths are kept neat" OFF)
|
||||||
IF(CMAKE_CL_64)
|
IF(CMAKE_CL_64)
|
||||||
SET(TARGET_POSTFIX x64)
|
SET(TARGET_POSTFIX x64)
|
||||||
|
|
@ -173,6 +175,7 @@ SOURCE_GROUP("hostapi\\wasapi" FILES
|
||||||
ENDIF(PA_USE_WASAPI)
|
ENDIF(PA_USE_WASAPI)
|
||||||
|
|
||||||
IF(PA_USE_WDMKS)
|
IF(PA_USE_WDMKS)
|
||||||
|
ADD_DEFINITIONS(-DPA_WDMKS_NO_KSGUID_LIB)
|
||||||
|
|
||||||
SET(PA_WDMKS_INCLUDES
|
SET(PA_WDMKS_INCLUDES
|
||||||
include/pa_win_wdmks.h
|
include/pa_win_wdmks.h
|
||||||
|
|
@ -328,8 +331,10 @@ IF(PA_USE_WDMKS)
|
||||||
TARGET_LINK_LIBRARIES(portaudio setupapi)
|
TARGET_LINK_LIBRARIES(portaudio setupapi)
|
||||||
ENDIF(PA_USE_WDMKS)
|
ENDIF(PA_USE_WDMKS)
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio_${TARGET_POSTFIX})
|
SET_TARGET_PROPERTIES(portaudio PROPERTIES OUTPUT_NAME portaudio_${TARGET_POSTFIX}
|
||||||
SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio_static_${TARGET_POSTFIX})
|
FOLDER "Portaudio")
|
||||||
|
SET_TARGET_PROPERTIES(portaudio_static PROPERTIES OUTPUT_NAME portaudio_static_${TARGET_POSTFIX}
|
||||||
|
FOLDER "Portaudio")
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
OPTION(PA_BUILD_TESTS "Include test projects" OFF)
|
OPTION(PA_BUILD_TESTS "Include test projects" OFF)
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,19 @@
|
||||||
MACRO(ADD_EXAMPLE appl_name)
|
MACRO(ADD_EXAMPLE appl_name)
|
||||||
ADD_EXECUTABLE(${appl_name} "${appl_name}.c")
|
ADD_EXECUTABLE(${appl_name} "${appl_name}.c")
|
||||||
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
||||||
|
SET_TARGET_PROPERTIES(${appl_name}
|
||||||
|
PROPERTIES
|
||||||
|
FOLDER "Examples C"
|
||||||
|
)
|
||||||
ENDMACRO(ADD_EXAMPLE)
|
ENDMACRO(ADD_EXAMPLE)
|
||||||
|
|
||||||
MACRO(ADD_EXAMPLE_CPP appl_name)
|
MACRO(ADD_EXAMPLE_CPP appl_name)
|
||||||
ADD_EXECUTABLE(${appl_name} "${appl_name}.cpp")
|
ADD_EXECUTABLE(${appl_name} "${appl_name}.cpp")
|
||||||
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
||||||
|
SET_TARGET_PROPERTIES(${appl_name}
|
||||||
|
PROPERTIES
|
||||||
|
FOLDER "Examples C++"
|
||||||
|
)
|
||||||
ENDMACRO(ADD_EXAMPLE_CPP)
|
ENDMACRO(ADD_EXAMPLE_CPP)
|
||||||
|
|
||||||
ADD_EXAMPLE(pa_devs)
|
ADD_EXAMPLE(pa_devs)
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,12 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(index);
|
||||||
|
if (pInfo != 0)
|
||||||
|
{
|
||||||
|
printf("Output device name: '%s'\r", pInfo->name);
|
||||||
|
}
|
||||||
|
|
||||||
outputParameters.channelCount = 2; /* stereo output */
|
outputParameters.channelCount = 2; /* stereo output */
|
||||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
||||||
|
|
@ -88,7 +94,7 @@ public:
|
||||||
NULL, /* no input */
|
NULL, /* no input */
|
||||||
&outputParameters,
|
&outputParameters,
|
||||||
SAMPLE_RATE,
|
SAMPLE_RATE,
|
||||||
FRAMES_PER_BUFFER,
|
paFramesPerBufferUnspecified,
|
||||||
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||||
&Sine::paCallback,
|
&Sine::paCallback,
|
||||||
this /* Using 'this' for userData so we can cast to Sine* in paCallback method */
|
this /* Using 'this' for userData so we can cast to Sine* in paCallback method */
|
||||||
|
|
@ -212,18 +218,38 @@ private:
|
||||||
char message[20];
|
char message[20];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScopedPaHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScopedPaHandler()
|
||||||
|
: _result(Pa_Initialize())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~ScopedPaHandler()
|
||||||
|
{
|
||||||
|
if (_result == paNoError)
|
||||||
|
{
|
||||||
|
Pa_Terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PaError result() const { return _result; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PaError _result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
int main(void);
|
int main(void);
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
PaError err;
|
|
||||||
Sine sine;
|
Sine sine;
|
||||||
|
|
||||||
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||||
|
|
||||||
err = Pa_Initialize();
|
ScopedPaHandler paInit;
|
||||||
if( err != paNoError ) goto error;
|
if( paInit.result() != paNoError ) goto error;
|
||||||
|
|
||||||
if (sine.open(Pa_GetDefaultOutputDevice()))
|
if (sine.open(Pa_GetDefaultOutputDevice()))
|
||||||
{
|
{
|
||||||
|
|
@ -238,15 +264,12 @@ int main(void)
|
||||||
sine.close();
|
sine.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pa_Terminate();
|
|
||||||
printf("Test finished.\n");
|
printf("Test finished.\n");
|
||||||
|
return paNoError;
|
||||||
return err;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Pa_Terminate();
|
|
||||||
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||||
fprintf( stderr, "Error number: %d\n", err );
|
fprintf( stderr, "Error number: %d\n", paInit.result() );
|
||||||
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( paInit.result() ) );
|
||||||
return err;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,29 @@
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* Setup flags */
|
||||||
|
typedef enum PaWinWDMKSFlags
|
||||||
|
{
|
||||||
|
/* Makes WDMKS use the supplied latency figures instead of relying on the frame size reported
|
||||||
|
by the WaveCyclic device. Use at own risk! */
|
||||||
|
paWinWDMKSOverrideFramesize = (1 << 0),
|
||||||
|
|
||||||
|
/* Makes WDMKS (output stream) use the given channelMask instead of the default */
|
||||||
|
paWinWDMKSUseGivenChannelMask = (1 << 1),
|
||||||
|
|
||||||
|
} PaWinWDMKSFlags;
|
||||||
|
|
||||||
typedef struct PaWinWDMKSInfo{
|
typedef struct PaWinWDMKSInfo{
|
||||||
unsigned long size; /**< sizeof(PaWinWDMKSInfo) */
|
unsigned long size; /**< sizeof(PaWinWDMKSInfo) */
|
||||||
PaHostApiTypeId hostApiType; /**< paWDMKS */
|
PaHostApiTypeId hostApiType; /**< paWDMKS */
|
||||||
unsigned long version; /**< 1 */
|
unsigned long version; /**< 1 */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
/* The number of packets to use for WaveCyclic devices, range is [2, 8]. Set to zero for default value of 2. */
|
/* The number of packets to use for WaveCyclic devices, range is [2, 8]. Set to zero for default value of 2. */
|
||||||
unsigned noOfPackets;
|
unsigned noOfPackets;
|
||||||
|
/* If paWinWDMKSUseGivenChannelMask bit is set in flags, use this as channelMask instead of default */
|
||||||
|
unsigned channelMask;
|
||||||
} PaWinWDMKSInfo;
|
} PaWinWDMKSInfo;
|
||||||
|
|
||||||
typedef enum PaWDMKSType
|
typedef enum PaWDMKSType
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,13 @@ of a device for the duration of active stream using those devices
|
||||||
|
|
||||||
#include "pa_win_wdmks.h"
|
#include "pa_win_wdmks.h"
|
||||||
|
|
||||||
|
#ifndef DRV_QUERYDEVICEINTERFACE
|
||||||
|
#define DRV_QUERYDEVICEINTERFACE (DRV_RESERVED + 12)
|
||||||
|
#endif
|
||||||
|
#ifndef DRV_QUERYDEVICEINTERFACESIZE
|
||||||
|
#define DRV_QUERYDEVICEINTERFACESIZE (DRV_RESERVED + 13)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
|
@ -506,8 +513,9 @@ static PaError PinRegisterPositionRegister(PaWinWdmPin* pPin);
|
||||||
static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
|
static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
|
||||||
static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
|
static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle);
|
||||||
static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay);
|
static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChipsetDelay, ULONG* pCodecDelay);
|
||||||
static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition);
|
static PaError PinGetAudioPositionMemoryMapped(PaWinWdmPin* pPin, ULONG* pPosition);
|
||||||
static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition);
|
static PaError PinGetAudioPositionViaIOCTLRead(PaWinWdmPin* pPin, ULONG* pPosition);
|
||||||
|
static PaError PinGetAudioPositionViaIOCTLWrite(PaWinWdmPin* pPin, ULONG* pPosition);
|
||||||
|
|
||||||
/* Filter management functions */
|
/* Filter management functions */
|
||||||
static PaWinWdmFilter* FilterNew(PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error);
|
static PaWinWdmFilter* FilterNew(PaWDMKSType type, DWORD devNode, const wchar_t* filterName, const wchar_t* friendlyName, PaError* error);
|
||||||
|
|
@ -2221,12 +2229,7 @@ static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format
|
||||||
|
|
||||||
if (pFormatExt != 0)
|
if (pFormatExt != 0)
|
||||||
{
|
{
|
||||||
if ( dataRange->MinimumBitsPerSample > pFormatExt->Samples.wValidBitsPerSample )
|
if (!IsBitsWithinRange(dataRange, pFormatExt->Samples.wValidBitsPerSample))
|
||||||
{
|
|
||||||
result = paSampleFormatNotSupported;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( dataRange->MaximumBitsPerSample < pFormatExt->Samples.wValidBitsPerSample )
|
|
||||||
{
|
{
|
||||||
result = paSampleFormatNotSupported;
|
result = paSampleFormatNotSupported;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2234,26 +2237,14 @@ static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( dataRange->MinimumBitsPerSample > format->wBitsPerSample )
|
if (!IsBitsWithinRange(dataRange, format->wBitsPerSample))
|
||||||
{
|
|
||||||
result = paSampleFormatNotSupported;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( dataRange->MaximumBitsPerSample < format->wBitsPerSample )
|
|
||||||
{
|
{
|
||||||
result = paSampleFormatNotSupported;
|
result = paSampleFormatNotSupported;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dataRange->MinimumSampleFrequency > format->nSamplesPerSec )
|
if (!IsFrequencyWithinRange(dataRange, format->nSamplesPerSec))
|
||||||
{
|
|
||||||
result = paInvalidSampleRate;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( dataRange->MaximumSampleFrequency < format->nSamplesPerSec )
|
|
||||||
{
|
{
|
||||||
result = paInvalidSampleRate;
|
result = paInvalidSampleRate;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2466,7 +2457,7 @@ static PaError PinRegisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle)
|
||||||
prop.NotificationEvent = handle;
|
prop.NotificationEvent = handle;
|
||||||
prop.Property.Set = KSPROPSETID_RtAudio;
|
prop.Property.Set = KSPROPSETID_RtAudio;
|
||||||
prop.Property.Id = KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT;
|
prop.Property.Id = KSPROPERTY_RTAUDIO_REGISTER_NOTIFICATION_EVENT;
|
||||||
prop.Property.Flags = KSPROPERTY_TYPE_GET;
|
prop.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
|
||||||
result = WdmSyncIoctl(pPin->handle,
|
result = WdmSyncIoctl(pPin->handle,
|
||||||
IOCTL_KS_PROPERTY,
|
IOCTL_KS_PROPERTY,
|
||||||
|
|
@ -2497,7 +2488,7 @@ static PaError PinUnregisterNotificationHandle(PaWinWdmPin* pPin, HANDLE handle)
|
||||||
prop.NotificationEvent = handle;
|
prop.NotificationEvent = handle;
|
||||||
prop.Property.Set = KSPROPSETID_RtAudio;
|
prop.Property.Set = KSPROPSETID_RtAudio;
|
||||||
prop.Property.Id = KSPROPERTY_RTAUDIO_UNREGISTER_NOTIFICATION_EVENT;
|
prop.Property.Id = KSPROPERTY_RTAUDIO_UNREGISTER_NOTIFICATION_EVENT;
|
||||||
prop.Property.Flags = KSPROPERTY_TYPE_GET;
|
prop.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
|
||||||
result = WdmSyncIoctl(pPin->handle,
|
result = WdmSyncIoctl(pPin->handle,
|
||||||
IOCTL_KS_PROPERTY,
|
IOCTL_KS_PROPERTY,
|
||||||
|
|
@ -2552,14 +2543,14 @@ static PaError PinGetHwLatency(PaWinWdmPin* pPin, ULONG* pFifoSize, ULONG* pChip
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This one is used for WaveRT */
|
/* This one is used for WaveRT */
|
||||||
static PaError PinGetAudioPositionDirect(PaWinWdmPin* pPin, ULONG* pPosition)
|
static PaError PinGetAudioPositionMemoryMapped(PaWinWdmPin* pPin, ULONG* pPosition)
|
||||||
{
|
{
|
||||||
*pPosition = (*pPin->positionRegister);
|
*pPosition = (*pPin->positionRegister);
|
||||||
return paNoError;
|
return paNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This one also, but in case the driver hasn't implemented memory mapped access to the position register */
|
/* This one also, but in case the driver hasn't implemented memory mapped access to the position register */
|
||||||
static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition)
|
static PaError PinGetAudioPositionViaIOCTLRead(PaWinWdmPin* pPin, ULONG* pPosition)
|
||||||
{
|
{
|
||||||
PaError result = paNoError;
|
PaError result = paNoError;
|
||||||
KSPROPERTY propIn;
|
KSPROPERTY propIn;
|
||||||
|
|
@ -2583,7 +2574,41 @@ static PaError PinGetAudioPositionViaIOCTL(PaWinWdmPin* pPin, ULONG* pPosition)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PA_DEBUG(("Failed to get audio position!\n"));
|
PA_DEBUG(("Failed to get audio play position!\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
PA_LOGL_;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This one also, but in case the driver hasn't implemented memory mapped access to the position register */
|
||||||
|
static PaError PinGetAudioPositionViaIOCTLWrite(PaWinWdmPin* pPin, ULONG* pPosition)
|
||||||
|
{
|
||||||
|
PaError result = paNoError;
|
||||||
|
KSPROPERTY propIn;
|
||||||
|
KSAUDIO_POSITION propOut;
|
||||||
|
|
||||||
|
PA_LOGE_;
|
||||||
|
|
||||||
|
propIn.Set = KSPROPSETID_Audio;
|
||||||
|
propIn.Id = KSPROPERTY_AUDIO_POSITION;
|
||||||
|
propIn.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
|
result = WdmSyncIoctl(pPin->handle,
|
||||||
|
IOCTL_KS_PROPERTY,
|
||||||
|
&propIn, sizeof(KSPROPERTY),
|
||||||
|
&propOut, sizeof(KSAUDIO_POSITION),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (result == paNoError)
|
||||||
|
{
|
||||||
|
*pPosition = (ULONG)(propOut.WriteOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PA_DEBUG(("Failed to get audio write position!\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_LOGL_;
|
PA_LOGL_;
|
||||||
|
|
@ -2800,7 +2825,6 @@ error:
|
||||||
*/
|
*/
|
||||||
static void FilterFree(PaWinWdmFilter* filter)
|
static void FilterFree(PaWinWdmFilter* filter)
|
||||||
{
|
{
|
||||||
int pinId;
|
|
||||||
PA_LOGL_;
|
PA_LOGL_;
|
||||||
if( filter )
|
if( filter )
|
||||||
{
|
{
|
||||||
|
|
@ -2810,13 +2834,14 @@ static void FilterFree(PaWinWdmFilter* filter)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->topologyFilter)
|
if ( filter->topologyFilter )
|
||||||
{
|
{
|
||||||
FilterFree(filter->topologyFilter);
|
FilterFree(filter->topologyFilter);
|
||||||
filter->topologyFilter = 0;
|
filter->topologyFilter = 0;
|
||||||
}
|
}
|
||||||
if ( filter->pins )
|
if ( filter->pins )
|
||||||
{
|
{
|
||||||
|
int pinId;
|
||||||
for( pinId = 0; pinId < filter->pinCount; pinId++ )
|
for( pinId = 0; pinId < filter->pinCount; pinId++ )
|
||||||
PinFree(filter->pins[pinId]);
|
PinFree(filter->pins[pinId]);
|
||||||
PaUtil_FreeMemory( filter->pins );
|
PaUtil_FreeMemory( filter->pins );
|
||||||
|
|
@ -3374,6 +3399,10 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
|
||||||
int filterCount = 0;
|
int filterCount = 0;
|
||||||
int totalDeviceCount = 0;
|
int totalDeviceCount = 0;
|
||||||
int idxDevice = 0;
|
int idxDevice = 0;
|
||||||
|
DWORD defaultInDevPathSize = 0;
|
||||||
|
DWORD defaultOutDevPathSize = 0;
|
||||||
|
wchar_t* defaultInDevPath = 0;
|
||||||
|
wchar_t* defaultOutDevPath = 0;
|
||||||
|
|
||||||
ppFilters = BuildFilterList( &filterCount, &totalDeviceCount, &result );
|
ppFilters = BuildFilterList( &filterCount, &totalDeviceCount, &result );
|
||||||
if( result != paNoError )
|
if( result != paNoError )
|
||||||
|
|
@ -3381,11 +3410,24 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get hold of default device paths for capture & playback
|
||||||
|
if( waveInMessage(0, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&defaultInDevPathSize, 0 ) == MMSYSERR_NOERROR )
|
||||||
|
{
|
||||||
|
defaultInDevPath = (wchar_t *)PaUtil_AllocateMemory((defaultInDevPathSize + 1) * sizeof(wchar_t));
|
||||||
|
waveInMessage(0, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)defaultInDevPath, defaultInDevPathSize);
|
||||||
|
}
|
||||||
|
if( waveOutMessage(0, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&defaultOutDevPathSize, 0 ) == MMSYSERR_NOERROR )
|
||||||
|
{
|
||||||
|
defaultOutDevPath = (wchar_t *)PaUtil_AllocateMemory((defaultOutDevPathSize + 1) * sizeof(wchar_t));
|
||||||
|
waveOutMessage(0, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)defaultOutDevPath, defaultOutDevPathSize);
|
||||||
|
}
|
||||||
|
|
||||||
if( totalDeviceCount > 0 )
|
if( totalDeviceCount > 0 )
|
||||||
{
|
{
|
||||||
PaWinWdmDeviceInfo *deviceInfoArray = 0;
|
PaWinWdmDeviceInfo *deviceInfoArray = 0;
|
||||||
int idxFilter;
|
int idxFilter;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned devIsDefaultIn = 0, devIsDefaultOut = 0;
|
||||||
|
|
||||||
/* Allocate the out param for all the info we need */
|
/* Allocate the out param for all the info we need */
|
||||||
outArgument = (PaWinWDMScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
|
outArgument = (PaWinWDMScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
|
||||||
|
|
@ -3440,6 +3482,9 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devIsDefaultIn = (defaultInDevPath && (_wcsicmp(pFilter->devInfo.filterPath, defaultInDevPath) == 0));
|
||||||
|
devIsDefaultOut = (defaultOutDevPath && (_wcsicmp(pFilter->devInfo.filterPath, defaultOutDevPath) == 0));
|
||||||
|
|
||||||
for (i = 0; i < pFilter->pinCount; ++i)
|
for (i = 0; i < pFilter->pinCount; ++i)
|
||||||
{
|
{
|
||||||
unsigned m;
|
unsigned m;
|
||||||
|
|
@ -3501,14 +3546,19 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
|
||||||
/* Convert wide char string to utf-8 */
|
/* Convert wide char string to utf-8 */
|
||||||
WideCharToMultiByte(CP_UTF8, 0, localCompositeName, -1, wdmDeviceInfo->compositeName, MAX_PATH, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, localCompositeName, -1, wdmDeviceInfo->compositeName, MAX_PATH, NULL, NULL);
|
||||||
|
|
||||||
/* NB! WDM/KS has no concept of a full-duplex device, each pin is either an input or and output */
|
/* NB! WDM/KS has no concept of a full-duplex device, each pin is either an input or an output */
|
||||||
if (isInput)
|
if (isInput)
|
||||||
{
|
{
|
||||||
/* INPUT ! */
|
/* INPUT ! */
|
||||||
deviceInfo->maxInputChannels = pin->maxChannels;
|
deviceInfo->maxInputChannels = pin->maxChannels;
|
||||||
deviceInfo->maxOutputChannels = 0;
|
deviceInfo->maxOutputChannels = 0;
|
||||||
|
|
||||||
if (outArgument->defaultInputDevice == paNoDevice)
|
/* RoBi NB: Due to the fact that input audio endpoints in Vista (& later OSs) can be the same device, but with
|
||||||
|
different input mux settings, there might be a discrepancy between the default input device chosen, and
|
||||||
|
that which will be used by Portaudio. Not much to do about that unfortunately.
|
||||||
|
*/
|
||||||
|
if ((defaultInDevPath == 0 || devIsDefaultIn) &&
|
||||||
|
outArgument->defaultInputDevice == paNoDevice)
|
||||||
{
|
{
|
||||||
outArgument->defaultInputDevice = idxDevice;
|
outArgument->defaultInputDevice = idxDevice;
|
||||||
}
|
}
|
||||||
|
|
@ -3519,7 +3569,8 @@ static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaH
|
||||||
deviceInfo->maxInputChannels = 0;
|
deviceInfo->maxInputChannels = 0;
|
||||||
deviceInfo->maxOutputChannels = pin->maxChannels;
|
deviceInfo->maxOutputChannels = pin->maxChannels;
|
||||||
|
|
||||||
if (outArgument->defaultOutputDevice == paNoDevice)
|
if ((defaultOutDevPath == 0 || devIsDefaultOut) &&
|
||||||
|
outArgument->defaultOutputDevice == paNoDevice)
|
||||||
{
|
{
|
||||||
outArgument->defaultOutputDevice = idxDevice;
|
outArgument->defaultOutputDevice = idxDevice;
|
||||||
}
|
}
|
||||||
|
|
@ -4159,7 +4210,8 @@ static unsigned NextPowerOf2(unsigned val)
|
||||||
|
|
||||||
static PaError ValidateSpecificStreamParameters(
|
static PaError ValidateSpecificStreamParameters(
|
||||||
const PaStreamParameters *streamParameters,
|
const PaStreamParameters *streamParameters,
|
||||||
const PaWinWDMKSInfo *streamInfo)
|
const PaWinWDMKSInfo *streamInfo,
|
||||||
|
unsigned isInput)
|
||||||
{
|
{
|
||||||
if( streamInfo )
|
if( streamInfo )
|
||||||
{
|
{
|
||||||
|
|
@ -4170,6 +4222,12 @@ static PaError ValidateSpecificStreamParameters(
|
||||||
return paIncompatibleHostApiSpecificStreamInfo;
|
return paIncompatibleHostApiSpecificStreamInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!!(streamInfo->flags & ~(paWinWDMKSOverrideFramesize | paWinWDMKSUseGivenChannelMask)))
|
||||||
|
{
|
||||||
|
PA_DEBUG(("Stream parameters: non supported flags set"));
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo;
|
||||||
|
}
|
||||||
|
|
||||||
if (streamInfo->noOfPackets != 0 &&
|
if (streamInfo->noOfPackets != 0 &&
|
||||||
(streamInfo->noOfPackets < 2 || streamInfo->noOfPackets > 8))
|
(streamInfo->noOfPackets < 2 || streamInfo->noOfPackets > 8))
|
||||||
{
|
{
|
||||||
|
|
@ -4177,6 +4235,21 @@ static PaError ValidateSpecificStreamParameters(
|
||||||
return paIncompatibleHostApiSpecificStreamInfo;
|
return paIncompatibleHostApiSpecificStreamInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streamInfo->flags & paWinWDMKSUseGivenChannelMask)
|
||||||
|
{
|
||||||
|
if (isInput)
|
||||||
|
{
|
||||||
|
PA_DEBUG(("Stream parameters: Channels mask setting not supported for input stream"));
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streamInfo->channelMask & PAWIN_SPEAKER_RESERVED)
|
||||||
|
{
|
||||||
|
PA_DEBUG(("Stream parameters: Given channels mask 0x%08X not supported", streamInfo->channelMask));
|
||||||
|
return paIncompatibleHostApiSpecificStreamInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return paNoError;
|
return paNoError;
|
||||||
|
|
@ -4184,6 +4257,7 @@ static PaError ValidateSpecificStreamParameters(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
|
/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
|
||||||
|
|
||||||
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
|
|
@ -4231,7 +4305,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate inputStreamInfo */
|
/* validate inputStreamInfo */
|
||||||
result = ValidateSpecificStreamParameters(inputParameters, inputParameters->hostApiSpecificStreamInfo);
|
result = ValidateSpecificStreamParameters(inputParameters, inputParameters->hostApiSpecificStreamInfo, 1 );
|
||||||
if(result != paNoError)
|
if(result != paNoError)
|
||||||
{
|
{
|
||||||
PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (in)");
|
PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (in)");
|
||||||
|
|
@ -4266,7 +4340,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate outputStreamInfo */
|
/* validate outputStreamInfo */
|
||||||
result = ValidateSpecificStreamParameters( outputParameters, outputParameters->hostApiSpecificStreamInfo );
|
result = ValidateSpecificStreamParameters( outputParameters, outputParameters->hostApiSpecificStreamInfo, 0 );
|
||||||
if (result != paNoError)
|
if (result != paNoError)
|
||||||
{
|
{
|
||||||
PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (out)");
|
PaWinWDM_SetLastErrorInfo(result, "Host API stream info not supported (out)");
|
||||||
|
|
@ -4471,8 +4545,16 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
PaWinWdmFilter* pFilter;
|
PaWinWdmFilter* pFilter;
|
||||||
PaWinWdmDeviceInfo* pDeviceInfo;
|
PaWinWdmDeviceInfo* pDeviceInfo;
|
||||||
PaWinWdmPin* pPin;
|
PaWinWdmPin* pPin;
|
||||||
|
PaWinWDMKSInfo* pInfo = (PaWinWDMKSInfo*)(outputParameters->hostApiSpecificStreamInfo);
|
||||||
unsigned validBitsPerSample = 0;
|
unsigned validBitsPerSample = 0;
|
||||||
PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userOutputChannels );
|
PaWinWaveFormatChannelMask channelMask = PaWin_DefaultChannelMask( userOutputChannels );
|
||||||
|
if (pInfo && (pInfo->flags & paWinWDMKSUseGivenChannelMask))
|
||||||
|
{
|
||||||
|
PA_DEBUG(("Using channelMask 0x%08X instead of default 0x%08X\n",
|
||||||
|
pInfo->channelMask,
|
||||||
|
channelMask));
|
||||||
|
channelMask = pInfo->channelMask;
|
||||||
|
}
|
||||||
|
|
||||||
result = paSampleFormatNotSupported;
|
result = paSampleFormatNotSupported;
|
||||||
pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device];
|
pDeviceInfo = (PaWinWdmDeviceInfo*)wdmHostApi->inheritedHostApiRep.deviceInfos[outputParameters->device];
|
||||||
|
|
@ -4960,8 +5042,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
if (result != paNoError)
|
if (result != paNoError)
|
||||||
{
|
{
|
||||||
unsigned long pos = 0xdeadc0de;
|
unsigned long pos = 0xdeadc0de;
|
||||||
PA_DEBUG(("Failed to register capture position register, using PinGetAudioPositionViaIOCTL\n"));
|
PA_DEBUG(("Failed to register capture position register, using PinGetAudioPositionViaIOCTLWrite\n"));
|
||||||
stream->capture.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL;
|
stream->capture.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTLWrite;
|
||||||
/* Test position function */
|
/* Test position function */
|
||||||
result = (stream->capture.pPin->fnAudioPosition)(stream->capture.pPin, &pos);
|
result = (stream->capture.pPin->fnAudioPosition)(stream->capture.pPin, &pos);
|
||||||
if (result != paNoError || pos != 0x0)
|
if (result != paNoError || pos != 0x0)
|
||||||
|
|
@ -4974,7 +5056,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream->capture.pPin->fnAudioPosition = PinGetAudioPositionDirect;
|
stream->capture.pPin->fnAudioPosition = PinGetAudioPositionMemoryMapped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -5082,8 +5164,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
if (result != paNoError)
|
if (result != paNoError)
|
||||||
{
|
{
|
||||||
unsigned long pos = 0xdeadc0de;
|
unsigned long pos = 0xdeadc0de;
|
||||||
PA_DEBUG(("Failed to register rendering position register, using PinGetAudioPositionViaIOCTL\n"));
|
PA_DEBUG(("Failed to register rendering position register, using PinGetAudioPositionViaIOCTLRead\n"));
|
||||||
stream->render.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTL;
|
stream->render.pPin->fnAudioPosition = PinGetAudioPositionViaIOCTLRead;
|
||||||
/* Test position function */
|
/* Test position function */
|
||||||
result = (stream->render.pPin->fnAudioPosition)(stream->render.pPin, &pos);
|
result = (stream->render.pPin->fnAudioPosition)(stream->render.pPin, &pos);
|
||||||
if (result != paNoError || pos != 0x0)
|
if (result != paNoError || pos != 0x0)
|
||||||
|
|
@ -5096,7 +5178,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream->render.pPin->fnAudioPosition = PinGetAudioPositionDirect;
|
stream->render.pPin->fnAudioPosition = PinGetAudioPositionMemoryMapped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
MACRO(ADD_TEST appl_name)
|
MACRO(ADD_TEST appl_name)
|
||||||
ADD_EXECUTABLE(${appl_name} "${appl_name}.c")
|
ADD_EXECUTABLE(${appl_name} "${appl_name}.c")
|
||||||
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
|
||||||
|
SET_TARGET_PROPERTIES(${appl_name}
|
||||||
|
PROPERTIES
|
||||||
|
FOLDER "Test"
|
||||||
|
)
|
||||||
ENDMACRO(ADD_TEST)
|
ENDMACRO(ADD_TEST)
|
||||||
|
|
||||||
ADD_TEST(patest_longsine)
|
ADD_TEST(patest_longsine)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue