Commit 70e3684d authored by robiwan's avatar robiwan

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


git-svn-id: https://subversion.assembla.com/svn/portaudio/portaudio/trunk@1924 0f58301d-fd10-0410-b4af-bbb618454e57
parent 7e7df88f
...@@ -7,6 +7,8 @@ PROJECT( portaudio ) ...@@ -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 ...@@ -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) ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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 @@ ...@@ -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 ...@@ -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); ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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: ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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, ...@@ -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, ...@@ -4266,7 +4340,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
} }