Merge branch 'master' into hotplug
This commit is contained in:
commit
46f97c7c20
5 changed files with 504 additions and 121 deletions
|
|
@ -27,26 +27,26 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* The text above constitutes the entire PortAudio license; however,
|
||||
* The text above constitutes the entire PortAudio license; however,
|
||||
* the PortAudio community also makes the following non-binding requests:
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version. It is also
|
||||
* requested that these non-binding requests be included along with the
|
||||
* they can be incorporated into the canonical version. It is also
|
||||
* requested that these non-binding requests be included along with the
|
||||
* license above.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@ingroup common_src
|
||||
|
||||
@brief Implements PortAudio API functions defined in portaudio.h, checks
|
||||
@brief Implements PortAudio API functions defined in portaudio.h, checks
|
||||
some errors, delegates platform-specific behavior to host API implementations.
|
||||
|
||||
Implements the functions defined in the PortAudio API (portaudio.h),
|
||||
validates some parameters and checks for state inconsistencies before
|
||||
forwarding API requests to specific Host API implementations (via the
|
||||
interface declared in pa_hostapi.h), and Streams (via the interface
|
||||
|
||||
Implements the functions defined in the PortAudio API (portaudio.h),
|
||||
validates some parameters and checks for state inconsistencies before
|
||||
forwarding API requests to specific Host API implementations (via the
|
||||
interface declared in pa_hostapi.h), and Streams (via the interface
|
||||
declared in pa_stream.h).
|
||||
|
||||
This file manages initialization and termination of Host API
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
/**
|
||||
* This is a combination of paVersionMajor, paVersionMinor and paVersionSubMinor.
|
||||
* It will always increase so that version numbers can be compared as integers to
|
||||
* It will always increase so that version numbers can be compared as integers to
|
||||
* see which is later.
|
||||
*/
|
||||
#define paVersion paMakeVersionNumber(paVersionMajor, paVersionMinor, paVersionSubMinor)
|
||||
|
|
@ -125,11 +125,11 @@ const char* Pa_GetVersionText( void )
|
|||
}
|
||||
|
||||
static PaVersionInfo versionInfo_ = {
|
||||
.versionMajor = paVersionMajor,
|
||||
.versionMinor = paVersionMinor,
|
||||
.versionSubMinor = paVersionSubMinor,
|
||||
.versionControlRevision = TOSTRING(PA_SVN_REVISION),
|
||||
.versionText = PA_VERSION_TEXT_
|
||||
/*.versionMajor =*/ paVersionMajor,
|
||||
/*.versionMinor =*/ paVersionMinor,
|
||||
/*.versionSubMinor =*/ paVersionSubMinor,
|
||||
/*.versionControlRevision =*/ TOSTRING(PA_SVN_REVISION),
|
||||
/*.versionText =*/ PA_VERSION_TEXT_
|
||||
};
|
||||
|
||||
const PaVersionInfo* Pa_GetVersionInfo()
|
||||
|
|
@ -213,7 +213,7 @@ static PaError InitializeHostApis( void )
|
|||
if( !hostApis_ )
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
goto error;
|
||||
}
|
||||
|
||||
hostApisCount_ = 0;
|
||||
|
|
@ -239,11 +239,11 @@ static PaError InitializeHostApis( void )
|
|||
assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
|
||||
assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
|
||||
|
||||
/* the first successfully initialized host API with a default input *or*
|
||||
/* the first successfully initialized host API with a default input *or*
|
||||
output device is used as the default host API.
|
||||
*/
|
||||
if( (defaultHostApiIndex_ == -1) &&
|
||||
( hostApi->info.defaultInputDevice != paNoDevice
|
||||
( hostApi->info.defaultInputDevice != paNoDevice
|
||||
|| hostApi->info.defaultOutputDevice != paNoDevice ) )
|
||||
{
|
||||
defaultHostApiIndex_ = hostApisCount_;
|
||||
|
|
@ -281,7 +281,7 @@ error:
|
|||
<device> belongs and returns it. if <hostSpecificDeviceIndex> is
|
||||
non-null, the host specific device index is returned in it.
|
||||
returns -1 if <device> is out of range.
|
||||
|
||||
|
||||
*/
|
||||
static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
|
||||
{
|
||||
|
|
@ -371,7 +371,7 @@ PaError Pa_Initialize( void )
|
|||
{
|
||||
PA_VALIDATE_TYPE_SIZES;
|
||||
PA_VALIDATE_ENDIANNESS;
|
||||
|
||||
|
||||
PaUtil_InitializeClock();
|
||||
PaUtil_ResetTraceMessages();
|
||||
|
||||
|
|
@ -463,11 +463,11 @@ const char *Pa_GetErrorText( PaError errorCode )
|
|||
case paCanNotWriteToAnInputOnlyStream: result = "Can't write to an input only stream"; break;
|
||||
case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break;
|
||||
case paBadBufferPtr: result = "Bad buffer pointer"; break;
|
||||
default:
|
||||
default:
|
||||
if( errorCode > 0 )
|
||||
result = "Invalid error code (value greater than zero)";
|
||||
result = "Invalid error code (value greater than zero)";
|
||||
else
|
||||
result = "Invalid error code";
|
||||
result = "Invalid error code";
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -478,7 +478,7 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
|
|||
{
|
||||
PaHostApiIndex result;
|
||||
int i;
|
||||
|
||||
|
||||
PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiTypeIdToHostApiIndex" );
|
||||
PA_LOGAPI(("\tPaHostApiTypeId type: %d\n", type ));
|
||||
|
||||
|
|
@ -489,14 +489,14 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
|
|||
else
|
||||
{
|
||||
result = paHostApiNotFound;
|
||||
|
||||
|
||||
for( i=0; i < hostApisCount_; ++i )
|
||||
{
|
||||
if( hostApis_[i]->info.type == type )
|
||||
{
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +511,7 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho
|
|||
{
|
||||
PaError result;
|
||||
int i;
|
||||
|
||||
|
||||
if( !PA_IS_INITIALISED_ )
|
||||
{
|
||||
result = paNotInitialized;
|
||||
|
|
@ -519,7 +519,7 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho
|
|||
else
|
||||
{
|
||||
result = paHostApiNotFound;
|
||||
|
||||
|
||||
for( i=0; i < hostApisCount_; ++i )
|
||||
{
|
||||
if( hostApis_[i]->info.type == type )
|
||||
|
|
@ -540,7 +540,7 @@ PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
|
|||
{
|
||||
PaError result;
|
||||
PaDeviceIndex x;
|
||||
|
||||
|
||||
x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
|
||||
|
||||
if( x < 0 || x >= hostApi->info.deviceCount )
|
||||
|
|
@ -625,7 +625,7 @@ const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
|
|||
else if( hostApi < 0 || hostApi >= hostApisCount_ )
|
||||
{
|
||||
info = NULL;
|
||||
|
||||
|
||||
PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
|
||||
PA_LOGAPI(("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n" ));
|
||||
|
||||
|
|
@ -734,7 +734,7 @@ PaDeviceIndex Pa_GetDefaultOutputDevice( void )
|
|||
{
|
||||
PaHostApiIndex hostApi;
|
||||
PaDeviceIndex result;
|
||||
|
||||
|
||||
PA_LOGAPI_ENTER( "Pa_GetDefaultOutputDevice" );
|
||||
|
||||
hostApi = Pa_GetDefaultHostApi();
|
||||
|
|
@ -964,7 +964,7 @@ static int SampleFormatIsValid( PaSampleFormat format )
|
|||
ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
|
||||
conform to the expected values as described below. This function is
|
||||
also designed to be used with the proposed Pa_IsFormatSupported() function.
|
||||
|
||||
|
||||
There are basically two types of validation that could be performed:
|
||||
Generic conformance validation, and device capability mismatch
|
||||
validation. This function performs only generic conformance validation.
|
||||
|
|
@ -973,21 +973,21 @@ static int SampleFormatIsValid( PaSampleFormat format )
|
|||
combinations of parameters - for example, even if the sampleRate
|
||||
seems ok, it might not be for a duplex stream - we have no way of
|
||||
checking this in an API-neutral way, so we don't try.
|
||||
|
||||
|
||||
On success the function returns PaNoError and fills in hostApi,
|
||||
hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
|
||||
the function returns an error code indicating the first encountered
|
||||
parameter error.
|
||||
|
||||
|
||||
|
||||
|
||||
If ValidateOpenStreamParameters() returns paNoError, the following
|
||||
assertions are guaranteed to be true.
|
||||
|
||||
|
||||
- at least one of inputParameters & outputParmeters is valid (not NULL)
|
||||
|
||||
- if inputParameters & outputParameters are both valid, that
|
||||
inputParameters->device & outputParameters->device both use the same host api
|
||||
|
||||
|
||||
PaDeviceIndex inputParameters->device
|
||||
- is within range (0 to Pa_GetDeviceCount-1) Or:
|
||||
- is paUseHostApiSpecificDeviceSpecification and
|
||||
|
|
@ -997,30 +997,30 @@ static int SampleFormatIsValid( PaSampleFormat format )
|
|||
int inputParameters->channelCount
|
||||
- if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
|
||||
- upper bound is NOT validated against device capabilities
|
||||
|
||||
|
||||
PaSampleFormat inputParameters->sampleFormat
|
||||
- is one of the sample formats defined in portaudio.h
|
||||
|
||||
void *inputParameters->hostApiSpecificStreamInfo
|
||||
- if supplied its hostApi field matches the input device's host Api
|
||||
|
||||
|
||||
PaDeviceIndex outputParmeters->device
|
||||
- is within range (0 to Pa_GetDeviceCount-1)
|
||||
|
||||
|
||||
int outputParmeters->channelCount
|
||||
- if inputDevice is valid, channelCount is > 0
|
||||
- upper bound is NOT validated against device capabilities
|
||||
|
||||
|
||||
PaSampleFormat outputParmeters->sampleFormat
|
||||
- is one of the sample formats defined in portaudio.h
|
||||
|
||||
|
||||
void *outputParmeters->hostApiSpecificStreamInfo
|
||||
- if supplied its hostApi field matches the output device's host Api
|
||||
|
||||
|
||||
double sampleRate
|
||||
- is not an 'absurd' rate (less than 1000. or greater than 384000.)
|
||||
- sampleRate is NOT validated against device capabilities
|
||||
|
||||
|
||||
PaStreamFlags streamFlags
|
||||
- unused platform neutral flags are zero
|
||||
- paNeverDropInput is only used for full-duplex callback streams with
|
||||
|
|
@ -1147,7 +1147,7 @@ static PaError ValidateOpenStreamParameters(
|
|||
!= (*hostApi)->info.type )
|
||||
return paIncompatibleHostApiSpecificStreamInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (inputParameters != NULL) && (outputParameters != NULL) )
|
||||
{
|
||||
|
|
@ -1156,8 +1156,8 @@ static PaError ValidateOpenStreamParameters(
|
|||
return paBadIODeviceCombination;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Check for absurd sample rates. */
|
||||
if( (sampleRate < 1000.0) || (sampleRate > 384000.0) )
|
||||
return paInvalidSampleRate;
|
||||
|
|
@ -1179,7 +1179,7 @@ static PaError ValidateOpenStreamParameters(
|
|||
if( framesPerBuffer != paFramesPerBufferUnspecified )
|
||||
return paInvalidFlag;
|
||||
}
|
||||
|
||||
|
||||
return paNoError;
|
||||
}
|
||||
|
||||
|
|
@ -1219,7 +1219,7 @@ PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
|
|||
PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
|
||||
PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
|
||||
}
|
||||
|
||||
|
||||
PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
|
||||
#endif
|
||||
|
||||
|
|
@ -1242,7 +1242,7 @@ PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
|
|||
PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( inputParameters )
|
||||
{
|
||||
|
|
@ -1329,7 +1329,7 @@ PaError Pa_OpenStream( PaStream** stream,
|
|||
PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
|
||||
PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
|
||||
}
|
||||
|
||||
|
||||
PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
|
||||
PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
|
||||
PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags ));
|
||||
|
|
@ -1376,7 +1376,7 @@ PaError Pa_OpenStream( PaStream** stream,
|
|||
PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( inputParameters )
|
||||
{
|
||||
|
|
@ -1450,8 +1450,8 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
|
|||
{
|
||||
hostApiInputParameters.device = Pa_GetDefaultInputDevice();
|
||||
if( hostApiInputParameters.device == paNoDevice )
|
||||
return paDeviceUnavailable;
|
||||
|
||||
return paDeviceUnavailable;
|
||||
|
||||
hostApiInputParameters.channelCount = inputChannelCount;
|
||||
hostApiInputParameters.sampleFormat = sampleFormat;
|
||||
/* defaultHighInputLatency is used below instead of
|
||||
|
|
@ -1459,7 +1459,7 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
|
|||
stream to work reliably than it is for it to work with the lowest
|
||||
latency.
|
||||
*/
|
||||
hostApiInputParameters.suggestedLatency =
|
||||
hostApiInputParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
|
||||
hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
hostApiInputParametersPtr = &hostApiInputParameters;
|
||||
|
|
@ -1473,7 +1473,7 @@ PaError Pa_OpenDefaultStream( PaStream** stream,
|
|||
{
|
||||
hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
if( hostApiOutputParameters.device == paNoDevice )
|
||||
return paDeviceUnavailable;
|
||||
return paDeviceUnavailable;
|
||||
|
||||
hostApiOutputParameters.channelCount = outputChannelCount;
|
||||
hostApiOutputParameters.sampleFormat = sampleFormat;
|
||||
|
|
@ -1857,7 +1857,7 @@ PaError Pa_WriteStream( PaStream* stream,
|
|||
else if( result == 1 )
|
||||
{
|
||||
result = paStreamIsStopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,12 +42,18 @@
|
|||
@note pa_wasapi currently requires minimum VC 2005, and the latest Vista SDK
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // exclude rare headers
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <assert.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
// WinRT
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
#define PA_WINRT
|
||||
#define INITGUID
|
||||
#endif
|
||||
|
||||
// WASAPI
|
||||
#include <mmreg.h> // must be before other Wasapi headers
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#include <Avrt.h>
|
||||
|
|
@ -61,9 +67,9 @@
|
|||
#undef INITGUID
|
||||
#endif
|
||||
#ifndef __MWERKS__
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#endif /* __MWERKS__ */
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
#include "pa_util.h"
|
||||
#include "pa_allocation.h"
|
||||
|
|
@ -74,10 +80,9 @@
|
|||
#include "pa_win_wasapi.h"
|
||||
#include "pa_debugprint.h"
|
||||
#include "pa_ringbuffer.h"
|
||||
|
||||
#include "pa_win_coinitialize.h"
|
||||
|
||||
#ifndef NTDDI_VERSION
|
||||
#if !defined(NTDDI_VERSION)
|
||||
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
|
|
@ -160,6 +165,38 @@
|
|||
|
||||
#endif // NTDDI_VERSION
|
||||
|
||||
// Missing declarations for WinRT
|
||||
#ifdef PA_WINRT
|
||||
|
||||
#define DEVICE_STATE_ACTIVE 0x00000001
|
||||
|
||||
typedef enum _EDataFlow
|
||||
{
|
||||
eRender = 0,
|
||||
eCapture = ( eRender + 1 ) ,
|
||||
eAll = ( eCapture + 1 ) ,
|
||||
EDataFlow_enum_count = ( eAll + 1 )
|
||||
}
|
||||
EDataFlow;
|
||||
|
||||
typedef enum _EndpointFormFactor
|
||||
{
|
||||
RemoteNetworkDevice = 0,
|
||||
Speakers = ( RemoteNetworkDevice + 1 ) ,
|
||||
LineLevel = ( Speakers + 1 ) ,
|
||||
Headphones = ( LineLevel + 1 ) ,
|
||||
Microphone = ( Headphones + 1 ) ,
|
||||
Headset = ( Microphone + 1 ) ,
|
||||
Handset = ( Headset + 1 ) ,
|
||||
UnknownDigitalPassthrough = ( Handset + 1 ) ,
|
||||
SPDIF = ( UnknownDigitalPassthrough + 1 ) ,
|
||||
HDMI = ( SPDIF + 1 ) ,
|
||||
UnknownFormFactor = ( HDMI + 1 )
|
||||
}
|
||||
EndpointFormFactor;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef GUID_SECT
|
||||
#define GUID_SECT
|
||||
#endif
|
||||
|
|
@ -192,6 +229,7 @@ PA_DEFINE_IID(IDeviceTopology, 2A07407E, 6497, 4A18, 97, 87, 32, f7, 9b, d0
|
|||
PA_DEFINE_IID(IPart, AE2DE0E4, 5BCA, 4F2D, aa, 46, 5d, 13, f8, fd, b3, a9);
|
||||
// *4509F757-2D46-4637-8E62-CE7DB944F57B*
|
||||
PA_DEFINE_IID(IKsJackDescription, 4509F757, 2D46, 4637, 8e, 62, ce, 7d, b9, 44, f5, 7b);
|
||||
|
||||
// Media formats:
|
||||
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
|
||||
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_ADPCM, 0x00000002, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
|
||||
|
|
@ -272,13 +310,13 @@ enum { WASAPI_PACKETS_PER_INPUT_BUFFER = 6 };
|
|||
typedef void (*MixMonoToStereoF) (void *__to, void *__from, UINT32 count);
|
||||
|
||||
// AVRT is the new "multimedia schedulling stuff"
|
||||
#ifndef PA_WINRT
|
||||
typedef BOOL (WINAPI *FAvRtCreateThreadOrderingGroup) (PHANDLE,PLARGE_INTEGER,GUID*,PLARGE_INTEGER);
|
||||
typedef BOOL (WINAPI *FAvRtDeleteThreadOrderingGroup) (HANDLE);
|
||||
typedef BOOL (WINAPI *FAvRtWaitOnThreadOrderingGroup) (HANDLE);
|
||||
typedef HANDLE (WINAPI *FAvSetMmThreadCharacteristics) (LPCSTR,LPDWORD);
|
||||
typedef BOOL (WINAPI *FAvRevertMmThreadCharacteristics)(HANDLE);
|
||||
typedef BOOL (WINAPI *FAvSetMmThreadPriority) (HANDLE,AVRT_PRIORITY);
|
||||
|
||||
static HMODULE hDInputDLL = 0;
|
||||
FAvRtCreateThreadOrderingGroup pAvRtCreateThreadOrderingGroup = NULL;
|
||||
FAvRtDeleteThreadOrderingGroup pAvRtDeleteThreadOrderingGroup = NULL;
|
||||
|
|
@ -286,6 +324,7 @@ FAvRtWaitOnThreadOrderingGroup pAvRtWaitOnThreadOrderingGroup = NULL;
|
|||
FAvSetMmThreadCharacteristics pAvSetMmThreadCharacteristics = NULL;
|
||||
FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
|
||||
FAvSetMmThreadPriority pAvSetMmThreadPriority = NULL;
|
||||
#endif
|
||||
|
||||
#define _GetProc(fun, type, name) { \
|
||||
fun = (type) GetProcAddress(hDInputDLL,name); \
|
||||
|
|
@ -351,7 +390,9 @@ static signed long GetStreamWriteAvailable( PaStream* stream );
|
|||
typedef struct PaWasapiDeviceInfo
|
||||
{
|
||||
// Device
|
||||
#ifndef PA_WINRT
|
||||
IMMDevice *device;
|
||||
#endif
|
||||
|
||||
// from GetId
|
||||
WCHAR szDeviceID[MAX_STR_LEN];
|
||||
|
|
@ -359,20 +400,17 @@ typedef struct PaWasapiDeviceInfo
|
|||
// from GetState
|
||||
DWORD state;
|
||||
|
||||
// Fields filled from IMMEndpoint'sGetDataFlow
|
||||
EDataFlow flow;
|
||||
|
||||
// Fields filled from IAudioDevice (_prior_ to Initialize)
|
||||
// from GetDevicePeriod(
|
||||
REFERENCE_TIME DefaultDevicePeriod;
|
||||
REFERENCE_TIME MinimumDevicePeriod;
|
||||
|
||||
// from GetMixFormat
|
||||
// WAVEFORMATEX *MixFormat;//needs to be CoTaskMemFree'd after use!
|
||||
|
||||
// Default format (setup through Control Panel by user)
|
||||
WAVEFORMATEXTENSIBLE DefaultFormat;
|
||||
|
||||
// Fields filled from IMMEndpoint'sGetDataFlow
|
||||
EDataFlow flow;
|
||||
|
||||
// Formfactor
|
||||
EndpointFormFactor formFactor;
|
||||
}
|
||||
|
|
@ -393,7 +431,9 @@ typedef struct
|
|||
PaWinUtilComInitializationResult comInitializationResult;
|
||||
|
||||
//in case we later need the synch
|
||||
#ifndef PA_WINRT
|
||||
IMMDeviceEnumerator *enumerator;
|
||||
#endif
|
||||
|
||||
//this is the REAL number of devices, whether they are usefull to PA or not!
|
||||
UINT32 deviceCount;
|
||||
|
|
@ -428,7 +468,9 @@ PaWasapiAudioClientParams;
|
|||
typedef struct PaWasapiSubStream
|
||||
{
|
||||
IAudioClient *clientParent;
|
||||
#ifndef PA_WINRT
|
||||
IStream *clientStream;
|
||||
#endif
|
||||
IAudioClient *clientProc;
|
||||
|
||||
WAVEFORMATEXTENSIBLE wavex;
|
||||
|
|
@ -478,14 +520,18 @@ typedef struct PaWasapiStream
|
|||
// input
|
||||
PaWasapiSubStream in;
|
||||
IAudioCaptureClient *captureClientParent;
|
||||
#ifndef PA_WINRT
|
||||
IStream *captureClientStream;
|
||||
#endif
|
||||
IAudioCaptureClient *captureClient;
|
||||
IAudioEndpointVolume *inVol;
|
||||
|
||||
// output
|
||||
PaWasapiSubStream out;
|
||||
IAudioRenderClient *renderClientParent;
|
||||
#ifndef PA_WINRT
|
||||
IStream *renderClientStream;
|
||||
#endif
|
||||
IAudioRenderClient *renderClient;
|
||||
IAudioEndpointVolume *outVol;
|
||||
|
||||
|
|
@ -766,6 +812,7 @@ static UINT32 AlignFramesPerBuffer(UINT32 nFrames, UINT32 nSamplesPerSec, UINT32
|
|||
|
||||
long frame_bytes = nFrames * nBlockAlign;
|
||||
long packets;
|
||||
(void)nSamplesPerSec;
|
||||
|
||||
// align to packet size
|
||||
frame_bytes = pAlignFunc(frame_bytes, HDA_PACKET_SIZE); // use ALIGN_FWD if bigger but safer period is more desired
|
||||
|
|
@ -812,6 +859,7 @@ static UINT32 GetFramesSleepTimeMicroseconds(UINT32 nFrames, UINT32 nSamplesPerS
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifndef PA_WINRT
|
||||
static BOOL SetupAVRT()
|
||||
{
|
||||
hDInputDLL = LoadLibraryA("avrt.dll");
|
||||
|
|
@ -832,18 +880,23 @@ static BOOL SetupAVRT()
|
|||
pAvRevertMmThreadCharacteristics &&
|
||||
pAvSetMmThreadPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static void CloseAVRT()
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
if (hDInputDLL != NULL)
|
||||
FreeLibrary(hDInputDLL);
|
||||
hDInputDLL = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static BOOL IsWow64()
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx
|
||||
|
||||
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
|
||||
|
|
@ -865,6 +918,12 @@ static BOOL IsWow64()
|
|||
return FALSE;
|
||||
|
||||
return bIsWow64;
|
||||
|
||||
#else
|
||||
|
||||
return FALSE;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -880,6 +939,7 @@ typedef enum EWindowsVersion
|
|||
}
|
||||
EWindowsVersion;
|
||||
// Alternative way for checking Windows version (allows to check version on Windows 8.1 and up)
|
||||
#ifndef PA_WINRT
|
||||
static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
typedef ULONGLONG (NTAPI *LPFN_VERSETCONDITIONMASK)(ULONGLONG ConditionMask, DWORD TypeMask, BYTE Condition);
|
||||
|
|
@ -909,9 +969,11 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO
|
|||
|
||||
return (fnVerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE);
|
||||
}
|
||||
#endif
|
||||
// Get Windows version
|
||||
static EWindowsVersion GetWindowsVersion()
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
static EWindowsVersion version = WINDOWS_UNKNOWN;
|
||||
|
||||
if (version == WINDOWS_UNKNOWN)
|
||||
|
|
@ -996,6 +1058,9 @@ static EWindowsVersion GetWindowsVersion()
|
|||
}
|
||||
|
||||
return version;
|
||||
#else
|
||||
return WINDOWS_8_SERVER2012;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -1167,6 +1232,180 @@ static MixMonoToStereoF _GetMonoToStereoMixer(PaSampleFormat format, EMixerDir d
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifdef PA_WINRT
|
||||
typedef struct PaActivateAudioInterfaceCompletionHandler
|
||||
{
|
||||
IActivateAudioInterfaceCompletionHandler parent;
|
||||
volatile LONG refs;
|
||||
volatile LONG done;
|
||||
struct
|
||||
{
|
||||
HRESULT hr;
|
||||
IAudioClient *client;
|
||||
}
|
||||
out;
|
||||
}
|
||||
PaActivateAudioInterfaceCompletionHandler;
|
||||
|
||||
static HRESULT (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_QueryInterface)(
|
||||
IActivateAudioInterfaceCompletionHandler *This, REFIID riid, void **ppvObject)
|
||||
{
|
||||
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
|
||||
|
||||
// From MSDN:
|
||||
// "The IAgileObject interface is a marker interface that indicates that an object
|
||||
// is free threaded and can be called from any apartment."
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IAgileObject))
|
||||
{
|
||||
handler->parent.lpVtbl->AddRef((IActivateAudioInterfaceCompletionHandler *)handler);
|
||||
(*ppvObject) = handler;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
static ULONG (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_AddRef)(
|
||||
IActivateAudioInterfaceCompletionHandler *This)
|
||||
{
|
||||
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
|
||||
|
||||
return InterlockedIncrement(&handler->refs);
|
||||
}
|
||||
|
||||
static ULONG (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_Release)(
|
||||
IActivateAudioInterfaceCompletionHandler *This)
|
||||
{
|
||||
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
|
||||
ULONG refs;
|
||||
|
||||
if ((refs = InterlockedDecrement(&handler->refs)) == 0)
|
||||
{
|
||||
PaUtil_FreeMemory(handler->parent.lpVtbl);
|
||||
PaUtil_FreeMemory(handler);
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
static HRESULT (STDMETHODCALLTYPE PaActivateAudioInterfaceCompletionHandler_ActivateCompleted)(
|
||||
IActivateAudioInterfaceCompletionHandler *This, IActivateAudioInterfaceAsyncOperation *activateOperation)
|
||||
{
|
||||
PaActivateAudioInterfaceCompletionHandler *handler = (PaActivateAudioInterfaceCompletionHandler *)This;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hrActivateResult = S_OK;
|
||||
IUnknown *punkAudioInterface = NULL;
|
||||
|
||||
// Check for a successful activation result
|
||||
hr = activateOperation->lpVtbl->GetActivateResult(activateOperation, &hrActivateResult, &punkAudioInterface);
|
||||
if (SUCCEEDED(hr) && SUCCEEDED(hrActivateResult))
|
||||
{
|
||||
// Get the pointer for the Audio Client
|
||||
punkAudioInterface->lpVtbl->QueryInterface(punkAudioInterface, GetAudioClientIID(), &handler->out.client);
|
||||
if (handler->out.client == NULL)
|
||||
hrActivateResult = E_FAIL;
|
||||
}
|
||||
SAFE_RELEASE(punkAudioInterface);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
handler->out.hr = hrActivateResult;
|
||||
else
|
||||
handler->out.hr = hr;
|
||||
|
||||
// Got client object, stop busy waiting in ActivateAudioInterface_WINRT
|
||||
InterlockedExchange(&handler->done, TRUE);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static IActivateAudioInterfaceCompletionHandler *CreateActivateAudioInterfaceCompletionHandler()
|
||||
{
|
||||
PaActivateAudioInterfaceCompletionHandler *handler = PaUtil_AllocateMemory(sizeof(PaActivateAudioInterfaceCompletionHandler));
|
||||
ZeroMemory(handler, sizeof(*handler));
|
||||
handler->parent.lpVtbl = PaUtil_AllocateMemory(sizeof(*handler->parent.lpVtbl));
|
||||
handler->parent.lpVtbl->QueryInterface = &PaActivateAudioInterfaceCompletionHandler_QueryInterface;
|
||||
handler->parent.lpVtbl->AddRef = &PaActivateAudioInterfaceCompletionHandler_AddRef;
|
||||
handler->parent.lpVtbl->Release = &PaActivateAudioInterfaceCompletionHandler_Release;
|
||||
handler->parent.lpVtbl->ActivateCompleted = &PaActivateAudioInterfaceCompletionHandler_ActivateCompleted;
|
||||
handler->refs = 1;
|
||||
return (IActivateAudioInterfaceCompletionHandler *)handler;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifdef PA_WINRT
|
||||
static HRESULT ActivateAudioInterface_WINRT(const PaWasapiDeviceInfo *deviceInfo, IAudioClient **client)
|
||||
{
|
||||
#define PA_WASAPI_DEVICE_PATH_LEN 64
|
||||
|
||||
PaError result = paNoError;
|
||||
HRESULT hr = S_OK;
|
||||
IActivateAudioInterfaceAsyncOperation *asyncOp = NULL;
|
||||
IActivateAudioInterfaceCompletionHandler *handler = CreateActivateAudioInterfaceCompletionHandler();
|
||||
PaActivateAudioInterfaceCompletionHandler *handlerImpl = (PaActivateAudioInterfaceCompletionHandler *)handler;
|
||||
OLECHAR devicePath[PA_WASAPI_DEVICE_PATH_LEN] = { 0 };
|
||||
|
||||
// Get device path in form L"{DEVICE_GUID}"
|
||||
switch (deviceInfo->flow)
|
||||
{
|
||||
case eRender:
|
||||
StringFromGUID2(&DEVINTERFACE_AUDIO_RENDER, devicePath, PA_WASAPI_DEVICE_PATH_LEN - 1);
|
||||
break;
|
||||
case eCapture:
|
||||
StringFromGUID2(&DEVINTERFACE_AUDIO_CAPTURE, devicePath, PA_WASAPI_DEVICE_PATH_LEN - 1);
|
||||
break;
|
||||
default:
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// Async operation will call back to IActivateAudioInterfaceCompletionHandler::ActivateCompleted
|
||||
// which must be an agile interface implementation
|
||||
hr = ActivateAudioInterfaceAsync(devicePath, GetAudioClientIID(), NULL, handler, &asyncOp);
|
||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
|
||||
// Wait in busy loop for async operation to complete
|
||||
// Use Interlocked API here to ensure that ->done variable is read every time through the loop
|
||||
while (SUCCEEDED(hr) && !InterlockedOr(&handlerImpl->done, 0))
|
||||
{
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
(*client) = handlerImpl->out.client;
|
||||
hr = handlerImpl->out.hr;
|
||||
|
||||
error:
|
||||
|
||||
SAFE_RELEASE(asyncOp);
|
||||
SAFE_RELEASE(handler);
|
||||
|
||||
return hr;
|
||||
|
||||
#undef PA_WASAPI_DEVICE_PATH_LEN
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static HRESULT ActivateAudioInterface(const PaWasapiDeviceInfo *deviceInfo, IAudioClient **client)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
return IMMDevice_Activate(deviceInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void **)client);
|
||||
#else
|
||||
return ActivateAudioInterface_WINRT(deviceInfo, client);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifdef PA_WINRT
|
||||
static DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
|
||||
{
|
||||
SetEvent(hObjectToSignal);
|
||||
return WaitForSingleObjectEx(hObjectToWaitOn, dwMilliseconds, bAlertable);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||
{
|
||||
|
|
@ -1174,14 +1413,20 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
PaDeviceInfo *deviceInfoArray;
|
||||
HRESULT hr = S_OK;
|
||||
IMMDeviceCollection* pEndPoints = NULL;
|
||||
UINT i;
|
||||
#ifndef PA_WINRT
|
||||
IMMDeviceCollection* pEndPoints = NULL;
|
||||
#else
|
||||
WAVEFORMATEX *mixFormat;
|
||||
#endif
|
||||
|
||||
#ifndef PA_WINRT
|
||||
if (!SetupAVRT())
|
||||
{
|
||||
PRINT(("WASAPI: No AVRT! (not VISTA?)"));
|
||||
return paNoError;
|
||||
}
|
||||
#endif
|
||||
|
||||
paWasapi = (PaWasapiHostApiRepresentation *)PaUtil_AllocateMemory( sizeof(PaWasapiHostApiRepresentation) );
|
||||
if (paWasapi == NULL)
|
||||
|
|
@ -1213,6 +1458,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
(*hostApi)->info.defaultInputDevice = paNoDevice;
|
||||
(*hostApi)->info.defaultOutputDevice = paNoDevice;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
paWasapi->enumerator = NULL;
|
||||
hr = CoCreateInstance(&pa_CLSID_IMMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER,
|
||||
&pa_IID_IMMDeviceEnumerator, (void **)&paWasapi->enumerator);
|
||||
|
|
@ -1282,6 +1528,10 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
|
||||
#else
|
||||
paWasapi->deviceCount = 2;
|
||||
#endif
|
||||
|
||||
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
||||
if (paWasapi->devInfo == NULL)
|
||||
{
|
||||
|
|
@ -1312,7 +1562,6 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
{
|
||||
DWORD state = 0;
|
||||
PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
|
||||
deviceInfo->structVersion = 3;
|
||||
deviceInfo->hostApi = hostApiIndex;
|
||||
|
|
@ -1320,6 +1569,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
PA_DEBUG(("WASAPI: device idx: %02d\n", i));
|
||||
PA_DEBUG(("WASAPI: ---------------\n"));
|
||||
|
||||
#ifndef PA_WINRT
|
||||
hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
|
|
@ -1352,7 +1602,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
if (paWasapi->devInfo[i].state != DEVICE_STATE_ACTIVE)
|
||||
{
|
||||
PRINT(("WASAPI device: %d is not currently available (state:%d)\n",i,state));
|
||||
PRINT(("WASAPI device: %d is not currently available (state:%d)\n", i, paWasapi->devInfo[i].state));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -1379,9 +1629,9 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
goto error;
|
||||
}
|
||||
if (value.pwszVal)
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.pwszVal, (int)wcslen(value.pwszVal), deviceName, MAX_STR_LEN-1, 0, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.pwszVal, (int)wcslen(value.pwszVal), deviceName, MAX_STR_LEN - 1, 0, 0);
|
||||
else
|
||||
_snprintf(deviceName, MAX_STR_LEN-1, "baddev%d", i);
|
||||
_snprintf(deviceName, MAX_STR_LEN - 1, "baddev%d", i);
|
||||
deviceInfo->name = deviceName;
|
||||
PropVariantClear(&value);
|
||||
PA_DEBUG(("WASAPI:%d| name[%s]\n", i, deviceInfo->name));
|
||||
|
|
@ -1424,8 +1674,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
|
||||
SAFE_RELEASE(pProperty);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Endpoint data
|
||||
{
|
||||
IMMEndpoint *endpoint = NULL;
|
||||
|
|
@ -1436,18 +1685,25 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
SAFE_RELEASE(endpoint);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Getting a temporary IAudioClient for more fields
|
||||
// we make sure NOT to call Initialize yet!
|
||||
{
|
||||
IAudioClient *tmpClient = NULL;
|
||||
#ifdef PA_WINRT
|
||||
// Set flow as ActivateAudioInterface depends on it and selects corresponding
|
||||
// direction for the Audio Client
|
||||
paWasapi->devInfo[i].flow = (i == 0 ? eRender : eCapture);
|
||||
#endif
|
||||
|
||||
hr = IMMDevice_Activate(paWasapi->devInfo[i].device, GetAudioClientIID(),
|
||||
CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);
|
||||
// Create temp Audio Client instance to query additional details
|
||||
IAudioClient *tmpClient = NULL;
|
||||
hr = ActivateAudioInterface(&paWasapi->devInfo[i], &tmpClient);
|
||||
// We need to set the result to a value otherwise we will return paNoError
|
||||
// [IF_FAILED_JUMP(hResult, error);]
|
||||
IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
|
||||
|
||||
// Get latency
|
||||
hr = IAudioClient_GetDevicePeriod(tmpClient,
|
||||
&paWasapi->devInfo[i].DefaultDevicePeriod,
|
||||
&paWasapi->devInfo[i].MinimumDevicePeriod);
|
||||
|
|
@ -1462,10 +1718,42 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
// ignore error, let continue further without failing with paInternalError
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
#ifdef PA_WINRT
|
||||
// Get mix format which will treat as default device format
|
||||
hr = IAudioClient_GetMixFormat(tmpClient, &mixFormat);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Default device
|
||||
if (i == 0)
|
||||
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
|
||||
else
|
||||
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
|
||||
|
||||
//hr = tmpClient->GetMixFormat(&paWasapi->devInfo[i].MixFormat);
|
||||
// State
|
||||
paWasapi->devInfo[i].state = DEVICE_STATE_ACTIVE;
|
||||
|
||||
// Release client
|
||||
// Default format
|
||||
memcpy(&paWasapi->devInfo[i].DefaultFormat, mixFormat, min(sizeof(paWasapi->devInfo[i].DefaultFormat), sizeof(*mixFormat)));
|
||||
CoTaskMemFree(mixFormat);
|
||||
|
||||
// Form-factor
|
||||
paWasapi->devInfo[i].formFactor = UnknownFormFactor;
|
||||
|
||||
// Name
|
||||
deviceInfo->name = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1);
|
||||
if (deviceInfo->name == NULL)
|
||||
{
|
||||
SAFE_RELEASE(tmpClient);
|
||||
result = paInsufficientMemory;
|
||||
goto error;
|
||||
}
|
||||
_snprintf((char *)deviceInfo->name, MAX_STR_LEN - 1, "WASAPI_%s:%d", (i == 0 ? "Output" : "Input"), i);
|
||||
PA_DEBUG(("WASAPI:%d| name[%s]\n", i, deviceInfo->name));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Release tmp client
|
||||
SAFE_RELEASE(tmpClient);
|
||||
|
||||
if (hr != S_OK)
|
||||
|
|
@ -1479,7 +1767,7 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we can now fill in portaudio device data
|
||||
deviceInfo->maxInputChannels = 0;
|
||||
deviceInfo->maxOutputChannels = 0;
|
||||
|
|
@ -1537,7 +1825,9 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
// findout if platform workaround is required
|
||||
paWasapi->useWOW64Workaround = UseWOW64Workaround();
|
||||
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
#endif
|
||||
|
||||
PRINT(("WASAPI: initialized ok\n"));
|
||||
|
||||
|
|
@ -1547,7 +1837,9 @@ error:
|
|||
|
||||
PRINT(("WASAPI: failed %s error[%d|%s]\n", __FUNCTION__, result, Pa_GetErrorText(result)));
|
||||
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(pEndPoints);
|
||||
#endif
|
||||
|
||||
Terminate((PaUtilHostApiRepresentation *)paWasapi);
|
||||
|
||||
|
|
@ -1568,15 +1860,19 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
|
|||
return;
|
||||
|
||||
// Release IMMDeviceEnumerator
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(paWasapi->enumerator);
|
||||
#endif
|
||||
|
||||
// Release device info bound objects and device info itself
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
{
|
||||
PaWasapiDeviceInfo *info = &paWasapi->devInfo[i];
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(info->device);
|
||||
|
||||
//if (info->MixFormat)
|
||||
// CoTaskMemFree(info->MixFormat);
|
||||
#else
|
||||
(void)info;
|
||||
#endif
|
||||
}
|
||||
PaUtil_FreeMemory(paWasapi->devInfo);
|
||||
|
||||
|
|
@ -1835,25 +2131,25 @@ static PaError MakeWaveFormatFromParams(WAVEFORMATEXTENSIBLE *wavex, const PaStr
|
|||
{
|
||||
switch (params->channelCount)
|
||||
{
|
||||
case 1: wavex->dwChannelMask = KSAUDIO_SPEAKER_MONO; break;
|
||||
case 2: wavex->dwChannelMask = KSAUDIO_SPEAKER_STEREO; break;
|
||||
case 3: wavex->dwChannelMask = KSAUDIO_SPEAKER_STEREO|SPEAKER_LOW_FREQUENCY; break;
|
||||
case 4: wavex->dwChannelMask = KSAUDIO_SPEAKER_QUAD; break;
|
||||
case 5: wavex->dwChannelMask = KSAUDIO_SPEAKER_QUAD|SPEAKER_LOW_FREQUENCY; break;
|
||||
#ifdef KSAUDIO_SPEAKER_5POINT1_SURROUND
|
||||
case 6: wavex->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND; break;
|
||||
case 1: wavex->dwChannelMask = PAWIN_SPEAKER_MONO; break;
|
||||
case 2: wavex->dwChannelMask = PAWIN_SPEAKER_STEREO; break;
|
||||
case 3: wavex->dwChannelMask = PAWIN_SPEAKER_STEREO|SPEAKER_LOW_FREQUENCY; break;
|
||||
case 4: wavex->dwChannelMask = PAWIN_SPEAKER_QUAD; break;
|
||||
case 5: wavex->dwChannelMask = PAWIN_SPEAKER_QUAD|SPEAKER_LOW_FREQUENCY; break;
|
||||
#ifdef PAWIN_SPEAKER_5POINT1_SURROUND
|
||||
case 6: wavex->dwChannelMask = PAWIN_SPEAKER_5POINT1_SURROUND; break;
|
||||
#else
|
||||
case 6: wavex->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break;
|
||||
case 6: wavex->dwChannelMask = PAWIN_SPEAKER_5POINT1; break;
|
||||
#endif
|
||||
#ifdef KSAUDIO_SPEAKER_5POINT1_SURROUND
|
||||
case 7: wavex->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND|SPEAKER_BACK_CENTER; break;
|
||||
#ifdef PAWIN_SPEAKER_5POINT1_SURROUND
|
||||
case 7: wavex->dwChannelMask = PAWIN_SPEAKER_5POINT1_SURROUND|SPEAKER_BACK_CENTER; break;
|
||||
#else
|
||||
case 7: wavex->dwChannelMask = KSAUDIO_SPEAKER_5POINT1|SPEAKER_BACK_CENTER; break;
|
||||
case 7: wavex->dwChannelMask = PAWIN_SPEAKER_5POINT1|SPEAKER_BACK_CENTER; break;
|
||||
#endif
|
||||
#ifdef KSAUDIO_SPEAKER_7POINT1_SURROUND
|
||||
case 8: wavex->dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND; break;
|
||||
#ifdef PAWIN_SPEAKER_7POINT1_SURROUND
|
||||
case 8: wavex->dwChannelMask = PAWIN_SPEAKER_7POINT1_SURROUND; break;
|
||||
#else
|
||||
case 8: wavex->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break;
|
||||
case 8: wavex->dwChannelMask = PAWIN_SPEAKER_7POINT1; break;
|
||||
#endif
|
||||
|
||||
default: wavex->dwChannelMask = 0;
|
||||
|
|
@ -1874,9 +2170,9 @@ static PaError MakeWaveFormatFromParams(WAVEFORMATEXTENSIBLE *wavex, const PaStr
|
|||
pwfext->Format.nChannels = (WORD)channelCount;
|
||||
pwfext->Format.nSamplesPerSec = (DWORD)sampleRate;
|
||||
if(channelCount == 1)
|
||||
pwfext->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT;
|
||||
pwfext->dwChannelMask = PAWIN_SPEAKER_DIRECTOUT;
|
||||
else
|
||||
pwfext->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
|
||||
pwfext->dwChannelMask = PAWIN_SPEAKER_STEREO;
|
||||
if(sampleFormat == paFloat32)
|
||||
{
|
||||
pwfext->Format.nBlockAlign = (WORD)(channelCount * 4);
|
||||
|
|
@ -1921,6 +2217,7 @@ static PaError GetClosestFormat(IAudioClient *myClient, double sampleRate,
|
|||
WAVEFORMATEX *sharedClosestMatch = NULL;
|
||||
HRESULT hr = !S_OK;
|
||||
PaStreamParameters params = (*_params);
|
||||
(void)output;
|
||||
|
||||
/* It was not noticed that 24-bit Input producing no output while device accepts this format.
|
||||
To fix this issue let's ask for 32-bits and let PA converters convert host 32-bit data
|
||||
|
|
@ -2159,8 +2456,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
|
|||
if (inputStreamInfo && (inputStreamInfo->flags & paWinWasapiExclusive))
|
||||
shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
||||
|
||||
hr = IMMDevice_Activate(paWasapi->devInfo[inputParameters->device].device,
|
||||
GetAudioClientIID(), CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);
|
||||
hr = ActivateAudioInterface(&paWasapi->devInfo[inputParameters->device], &tmpClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LogHostError(hr);
|
||||
|
|
@ -2185,8 +2481,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
|
|||
if (outputStreamInfo && (outputStreamInfo->flags & paWinWasapiExclusive))
|
||||
shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
||||
|
||||
hr = IMMDevice_Activate(paWasapi->devInfo[outputParameters->device].device,
|
||||
GetAudioClientIID(), CLSCTX_INPROC_SERVER, NULL, (void **)&tmpClient);
|
||||
hr = ActivateAudioInterface(&paWasapi->devInfo[outputParameters->device], &tmpClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LogHostError(hr);
|
||||
|
|
@ -2264,7 +2559,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||
const PaStreamParameters *params = &pSub->params.stream_params;
|
||||
UINT32 framesPerLatency = pSub->params.frames_per_buffer;
|
||||
double sampleRate = pSub->params.sample_rate;
|
||||
BOOL blocking = pSub->params.blocking;
|
||||
//BOOL blocking = pSub->params.blocking;
|
||||
BOOL fullDuplex = pSub->params.full_duplex;
|
||||
|
||||
const UINT32 userFramesPerBuffer = framesPerLatency;
|
||||
|
|
@ -2286,7 +2581,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||
}
|
||||
|
||||
// Get the audio client
|
||||
hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void **)&audioClient);
|
||||
hr = ActivateAudioInterface(pInfo, &audioClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
(*pa_error) = paInsufficientMemory;
|
||||
|
|
@ -2500,7 +2795,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||
SAFE_RELEASE(audioClient);
|
||||
|
||||
// Create a new audio client
|
||||
hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);
|
||||
hr = ActivateAudioInterface(pInfo, &audioClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
(*pa_error) = paInsufficientMemory;
|
||||
|
|
@ -2531,7 +2826,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||
SAFE_RELEASE(audioClient);
|
||||
|
||||
// Create a new audio client
|
||||
hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);
|
||||
hr = ActivateAudioInterface(pInfo, &audioClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
(*pa_error) = paInsufficientMemory;
|
||||
|
|
@ -2571,7 +2866,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
|
|||
SAFE_RELEASE(audioClient);
|
||||
|
||||
// Create a new audio client
|
||||
hr = IMMDevice_Activate(pInfo->device, GetAudioClientIID(), CLSCTX_ALL, NULL, (void**)&audioClient);
|
||||
hr = ActivateAudioInterface(pInfo, &audioClient);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
(*pa_error) = paInsufficientMemory;
|
||||
|
|
@ -3254,6 +3549,7 @@ static PaError CloseStream( PaStream* s )
|
|||
// ------------------------------------------------------------------------------------------
|
||||
HRESULT UnmarshalSubStreamComPointers(PaWasapiSubStream *substream)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
HRESULT hResult = S_OK;
|
||||
HRESULT hFirstBadResult = S_OK;
|
||||
substream->clientProc = NULL;
|
||||
|
|
@ -3267,11 +3563,17 @@ HRESULT UnmarshalSubStreamComPointers(PaWasapiSubStream *substream)
|
|||
}
|
||||
|
||||
return hFirstBadResult;
|
||||
|
||||
#else
|
||||
(void)substream;
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
HRESULT UnmarshalStreamComPointers(PaWasapiStream *stream)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
HRESULT hResult = S_OK;
|
||||
HRESULT hFirstBadResult = S_OK;
|
||||
stream->captureClient = NULL;
|
||||
|
|
@ -3316,6 +3618,33 @@ HRESULT UnmarshalStreamComPointers(PaWasapiStream *stream)
|
|||
}
|
||||
|
||||
return hFirstBadResult;
|
||||
#else
|
||||
if (stream->in.clientParent != NULL)
|
||||
{
|
||||
stream->in.clientProc = stream->in.clientParent;
|
||||
IAudioClient_AddRef(stream->in.clientParent);
|
||||
}
|
||||
|
||||
if (stream->out.clientParent != NULL)
|
||||
{
|
||||
stream->out.clientProc = stream->out.clientParent;
|
||||
IAudioClient_AddRef(stream->out.clientParent);
|
||||
}
|
||||
|
||||
if (stream->renderClientParent != NULL)
|
||||
{
|
||||
stream->renderClient = stream->renderClientParent;
|
||||
IAudioRenderClient_AddRef(stream->renderClientParent);
|
||||
}
|
||||
|
||||
if (stream->captureClientParent != NULL)
|
||||
{
|
||||
stream->captureClient = stream->captureClientParent;
|
||||
IAudioCaptureClient_AddRef(stream->captureClientParent);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
|
@ -3339,6 +3668,7 @@ void ReleaseUnmarshaledComPointers(PaWasapiStream *stream)
|
|||
// ------------------------------------------------------------------------------------------
|
||||
HRESULT MarshalSubStreamComPointers(PaWasapiSubStream *substream)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
HRESULT hResult;
|
||||
substream->clientStream = NULL;
|
||||
|
||||
|
|
@ -3355,11 +3685,16 @@ marshal_sub_error:
|
|||
UnmarshalSubStreamComPointers(substream);
|
||||
ReleaseUnmarshaledSubComPointers(substream);
|
||||
return hResult;
|
||||
#else
|
||||
(void)substream;
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
HRESULT MarshalStreamComPointers(PaWasapiStream *stream)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
HRESULT hResult = S_OK;
|
||||
stream->captureClientStream = NULL;
|
||||
stream->in.clientStream = NULL;
|
||||
|
|
@ -3400,6 +3735,10 @@ marshal_error:
|
|||
UnmarshalStreamComPointers(stream);
|
||||
ReleaseUnmarshaledComPointers(stream);
|
||||
return hResult;
|
||||
#else
|
||||
(void)stream;
|
||||
return S_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -4084,6 +4423,7 @@ static void WaspiHostProcessingLoop( void *inputBuffer, long inputFrames,
|
|||
// ------------------------------------------------------------------------------------------
|
||||
HANDLE MMCSS_activate(const char *name)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
DWORD task_idx = 0;
|
||||
HANDLE hTask = pAvSetMmThreadCharacteristics(name, &task_idx);
|
||||
if (hTask == NULL)
|
||||
|
|
@ -4105,6 +4445,10 @@ HANDLE MMCSS_activate(const char *name)
|
|||
}
|
||||
|
||||
return hTask;
|
||||
#else
|
||||
(void)name;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -4113,10 +4457,12 @@ void MMCSS_deactivate(HANDLE hTask)
|
|||
if (!hTask)
|
||||
return;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
if (pAvRevertMmThreadCharacteristics(hTask) == FALSE)
|
||||
{
|
||||
PRINT(("WASAPI: AvRevertMmThreadCharacteristics failed!\n"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -4166,6 +4512,7 @@ PaError PaWasapi_ThreadPriorityRevert(void *hTask)
|
|||
|
||||
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
PaError ret;
|
||||
HRESULT hr = S_OK;
|
||||
PaDeviceIndex index;
|
||||
|
|
@ -4235,9 +4582,15 @@ error:
|
|||
|
||||
LogHostError(hr);
|
||||
return paNoError;
|
||||
#else
|
||||
(void)nDevice;
|
||||
(void)jcount;
|
||||
return paUnanticipatedHostError;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifndef PA_WINRT
|
||||
static PaWasapiJackConnectionType ConvertJackConnectionTypeWASAPIToPA(int connType)
|
||||
{
|
||||
switch (connType)
|
||||
|
|
@ -4261,8 +4614,10 @@ static PaWasapiJackConnectionType ConvertJackConnectionTypeWASAPIToPA(int connTy
|
|||
}
|
||||
return eJackConnTypeUnknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifndef PA_WINRT
|
||||
static PaWasapiJackGeoLocation ConvertJackGeoLocationWASAPIToPA(int geoLoc)
|
||||
{
|
||||
switch (geoLoc)
|
||||
|
|
@ -4287,8 +4642,10 @@ static PaWasapiJackGeoLocation ConvertJackGeoLocationWASAPIToPA(int geoLoc)
|
|||
}
|
||||
return eJackGeoLocUnk;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifndef PA_WINRT
|
||||
static PaWasapiJackGenLocation ConvertJackGenLocationWASAPIToPA(int genLoc)
|
||||
{
|
||||
switch (genLoc)
|
||||
|
|
@ -4304,8 +4661,10 @@ static PaWasapiJackGenLocation ConvertJackGenLocationWASAPIToPA(int genLoc)
|
|||
}
|
||||
return eJackGenLocPrimaryBox;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#ifndef PA_WINRT
|
||||
static PaWasapiJackPortConnection ConvertJackPortConnectionWASAPIToPA(int portConn)
|
||||
{
|
||||
switch (portConn)
|
||||
|
|
@ -4317,6 +4676,7 @@ static PaWasapiJackPortConnection ConvertJackPortConnectionWASAPIToPA(int portCo
|
|||
}
|
||||
return eJackPortConnJack;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// Described at:
|
||||
|
|
@ -4324,6 +4684,7 @@ static PaWasapiJackPortConnection ConvertJackPortConnectionWASAPIToPA(int portCo
|
|||
|
||||
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
PaError ret;
|
||||
HRESULT hr = S_OK;
|
||||
PaDeviceIndex index;
|
||||
|
|
@ -4399,6 +4760,13 @@ error:
|
|||
|
||||
LogHostError(hr);
|
||||
return ret;
|
||||
|
||||
#else
|
||||
(void)nDevice;
|
||||
(void)jindex;
|
||||
(void)pJackDescription;
|
||||
return paUnanticipatedHostError;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
|
@ -4623,7 +4991,7 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
|
|||
if (FAILED(hr) && (hr != RPC_E_CHANGED_MODE))
|
||||
{
|
||||
PRINT(("WASAPI: failed ProcThreadEvent CoInitialize"));
|
||||
return paUnanticipatedHostError;
|
||||
return (UINT32)paUnanticipatedHostError;
|
||||
}
|
||||
if (hr != RPC_E_CHANGED_MODE)
|
||||
bThreadComInitialized = TRUE;
|
||||
|
|
@ -4830,7 +5198,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
|
|||
if (FAILED(hr) && (hr != RPC_E_CHANGED_MODE))
|
||||
{
|
||||
PRINT(("WASAPI: failed ProcThreadPoll CoInitialize"));
|
||||
return paUnanticipatedHostError;
|
||||
return (UINT32)paUnanticipatedHostError;
|
||||
}
|
||||
if (hr != RPC_E_CHANGED_MODE)
|
||||
bThreadComInitialized = TRUE;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
#include "pa_win_coinitialize.h"
|
||||
|
||||
|
||||
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
|
||||
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) /* MSC version 6 and above */
|
||||
#pragma comment( lib, "ole32.lib" )
|
||||
#endif
|
||||
|
||||
|
|
@ -76,7 +76,11 @@ PaError PaWinUtil_CoInitialize( PaHostApiTypeId hostApiType, PaWinUtilComInitial
|
|||
RPC_E_CHANGED_MODE was returned.
|
||||
*/
|
||||
|
||||
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_APP)
|
||||
hr = CoInitialize(0); /* use legacy-safe equivalent to CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) */
|
||||
#else
|
||||
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
#endif
|
||||
if( FAILED(hr) && hr != RPC_E_CHANGED_MODE )
|
||||
{
|
||||
PA_DEBUG(("CoInitialize(0) failed. hr=%d\n", hr));
|
||||
|
|
|
|||
|
|
@ -44,14 +44,17 @@
|
|||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> /* for timeGetTime() */
|
||||
|
||||
#include "pa_util.h"
|
||||
|
||||
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
|
||||
#pragma comment( lib, "winmm.lib" )
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
#include <sys/timeb.h> /* for _ftime_s() */
|
||||
#else
|
||||
#include <mmsystem.h> /* for timeGetTime() */
|
||||
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) && !defined(_WIN32_WCE) /* MSC version 6 and above */
|
||||
#pragma comment( lib, "winmm.lib" )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "pa_util.h"
|
||||
|
||||
/*
|
||||
Track memory allocations to avoid leaks.
|
||||
|
|
@ -144,8 +147,12 @@ double PaUtil_GetTime( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifndef UNDER_CE
|
||||
#ifndef UNDER_CE
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
return GetTickCount64() * .001;
|
||||
#else
|
||||
return timeGetTime() * .001;
|
||||
#endif
|
||||
#else
|
||||
return GetTickCount() * .001;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
#include <mmreg.h> /* for WAVEFORMATEX */
|
||||
#endif
|
||||
|
||||
#include "portaudio.h"
|
||||
#include "pa_win_waveformat.h"
|
||||
|
|
@ -47,6 +50,7 @@
|
|||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
#endif
|
||||
|
||||
|
||||
static GUID pawin_ksDataFormatSubtypeGuidBase =
|
||||
{ (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue