Merge branch 'winrt' into 'master'
WASAPI: new API PaWasapi_SetStreamStateHandler(), header cleanup and minor fix Merged-on: https://assembla.com/code/portaudio/git/merge_requests/7129721
This commit is contained in:
commit
b7870b08f7
3 changed files with 362 additions and 203 deletions
|
|
@ -45,10 +45,12 @@ PaWasapi_GetAudioClient @56
|
|||
PaWasapi_UpdateDeviceList @57
|
||||
PaWasapi_GetDeviceCurrentFormat @58
|
||||
PaWasapi_GetDeviceDefaultFormat @59
|
||||
PaWasapi_GetDeviceRole @60
|
||||
PaWasapi_ThreadPriorityBoost @61
|
||||
PaWasapi_ThreadPriorityRevert @62
|
||||
PaWasapi_GetFramesPerHostBuffer @63
|
||||
PaWasapi_GetJackCount @64
|
||||
PaWasapi_GetJackDescription @65
|
||||
PaWasapi_SetDefaultInterfaceId @66
|
||||
PaWasapi_GetDeviceMixFormat @60
|
||||
PaWasapi_GetDeviceRole @61
|
||||
PaWasapi_ThreadPriorityBoost @62
|
||||
PaWasapi_ThreadPriorityRevert @63
|
||||
PaWasapi_GetFramesPerHostBuffer @64
|
||||
PaWasapi_GetJackCount @65
|
||||
PaWasapi_GetJackDescription @66
|
||||
PaWasapi_SetDefaultInterfaceId @67
|
||||
PaWasapi_SetStreamStateHandler @68
|
||||
|
|
@ -3,9 +3,11 @@
|
|||
/*
|
||||
* $Id: $
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* DirectSound specific extensions
|
||||
* WASAPI specific extensions
|
||||
*
|
||||
* Copyright (c) 1999-2007 Ross Bencina and Phil Burk
|
||||
* Copyright (c) 1999-2018 Ross Bencina and Phil Burk
|
||||
* Copyright (c) 2006-2010 David Viens
|
||||
* Copyright (c) 2010-2018 Dmitry Kostjuchenko
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
|
|
@ -28,13 +30,13 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
|
@ -52,7 +54,7 @@ extern "C"
|
|||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* Setup flags */
|
||||
/* Stream setup flags. */
|
||||
typedef enum PaWasapiFlags
|
||||
{
|
||||
/* put WASAPI into exclusive mode */
|
||||
|
|
@ -69,12 +71,12 @@ typedef enum PaWasapiFlags
|
|||
method can only provide 15-20ms latency. */
|
||||
paWinWasapiPolling = (1 << 3),
|
||||
|
||||
/* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
|
||||
/* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
|
||||
is set to a custom value */
|
||||
paWinWasapiThreadPriority = (1 << 4),
|
||||
|
||||
/* force explicit sample format and do not allow PA to select suitable working format, API will
|
||||
fail if provided sample format is not supported by audio hardware in Exclusive mode
|
||||
/* force explicit sample format and do not allow PA to select suitable working format, API will
|
||||
fail if provided sample format is not supported by audio hardware in Exclusive mode
|
||||
or system mixer in Shared mode */
|
||||
paWinWasapiExplicitSampleFormat = (1 << 5)
|
||||
}
|
||||
|
|
@ -87,15 +89,62 @@ PaWasapiFlags;
|
|||
#define paWinWasapiExplicitSampleFormat (paWinWasapiExplicitSampleFormat)
|
||||
|
||||
|
||||
/* Host processor. Allows to skip internal PA processing completely.
|
||||
You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member
|
||||
in order to have host processor redirected to your callback.
|
||||
Use with caution! inputFrames and outputFrames depend solely on final device setup.
|
||||
To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
|
||||
/* Stream state.
|
||||
|
||||
@note Multiple states can be united into a bitmask.
|
||||
@see PaWasapiStreamStateCallback, PaWasapi_SetStreamStateHandler
|
||||
*/
|
||||
typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
|
||||
void *outputBuffer, long outputFrames,
|
||||
void *userData);
|
||||
typedef enum PaWasapiStreamState
|
||||
{
|
||||
/* state change was caused by the error:
|
||||
|
||||
Example:
|
||||
1) If thread execution stopped due to AUDCLNT_E_RESOURCES_INVALIDATED then state
|
||||
value will contain paWasapiStreamStateError|paWasapiStreamStateThreadStop.
|
||||
*/
|
||||
paWasapiStreamStateError = (1 << 0),
|
||||
|
||||
/* processing thread is preparing to start execution */
|
||||
paWasapiStreamStateThreadPrepare = (1 << 1),
|
||||
|
||||
/* processing thread started execution (enters its loop) */
|
||||
paWasapiStreamStateThreadStart = (1 << 2),
|
||||
|
||||
/* processing thread stopped execution */
|
||||
paWasapiStreamStateThreadStop = (1 << 3)
|
||||
}
|
||||
PaWasapiStreamState;
|
||||
#define paWasapiStreamStateError (paWasapiStreamStateError)
|
||||
#define paWasapiStreamStateThreadPrepare (paWasapiStreamStateThreadPrepare)
|
||||
#define paWasapiStreamStateThreadStart (paWasapiStreamStateThreadStart)
|
||||
#define paWasapiStreamStateThreadStop (paWasapiStreamStateThreadStop)
|
||||
|
||||
|
||||
/* Host processor.
|
||||
|
||||
Allows to skip internal PA processing completely. paWinWasapiRedirectHostProcessor flag
|
||||
must be set to the PaWasapiStreamInfo::flags member in order to have host processor
|
||||
redirected to this callback.
|
||||
|
||||
Use with caution! inputFrames and outputFrames depend solely on final device setup.
|
||||
To query max values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
|
||||
*/
|
||||
typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
|
||||
void *outputBuffer, long outputFrames, void *userData);
|
||||
|
||||
|
||||
/* Stream state handler.
|
||||
|
||||
@param pStream Pointer to PaStream object.
|
||||
@param stateFlags State flags, a collection of values from PaWasapiStreamState enum.
|
||||
@param errorId Error id provided by system API (HRESULT).
|
||||
@param userData Pointer to user data.
|
||||
|
||||
@see PaWasapiStreamState
|
||||
*/
|
||||
typedef void (*PaWasapiStreamStateCallback) (PaStream *pStream, unsigned int stateFlags,
|
||||
unsigned int errorId, void *pUserData);
|
||||
|
||||
|
||||
/* Device role. */
|
||||
typedef enum PaWasapiDeviceRole
|
||||
|
|
@ -130,7 +179,7 @@ typedef enum PaWasapiJackConnectionType
|
|||
eJackConnTypeXlrProfessional,
|
||||
eJackConnTypeRJ11Modem,
|
||||
eJackConnTypeCombination
|
||||
}
|
||||
}
|
||||
PaWasapiJackConnectionType;
|
||||
|
||||
|
||||
|
|
@ -153,7 +202,7 @@ typedef enum PaWasapiJackGeoLocation
|
|||
eJackGeoLocATAPI,
|
||||
eJackGeoLocReserved5,
|
||||
eJackGeoLocReserved6,
|
||||
}
|
||||
}
|
||||
PaWasapiJackGeoLocation;
|
||||
|
||||
|
||||
|
|
@ -164,7 +213,7 @@ typedef enum PaWasapiJackGenLocation
|
|||
eJackGenLocInternal,
|
||||
eJackGenLocSeparate,
|
||||
eJackGenLocOther
|
||||
}
|
||||
}
|
||||
PaWasapiJackGenLocation;
|
||||
|
||||
|
||||
|
|
@ -175,7 +224,7 @@ typedef enum PaWasapiJackPortConnection
|
|||
eJackPortConnIntegratedDevice,
|
||||
eJackPortConnBothIntegratedAndJack,
|
||||
eJackPortConnUnknown
|
||||
}
|
||||
}
|
||||
PaWasapiJackPortConnection;
|
||||
|
||||
|
||||
|
|
@ -195,7 +244,7 @@ PaWasapiThreadPriority;
|
|||
|
||||
|
||||
/* Stream descriptor. */
|
||||
typedef struct PaWasapiJackDescription
|
||||
typedef struct PaWasapiJackDescription
|
||||
{
|
||||
unsigned long channelMapping;
|
||||
unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */
|
||||
|
|
@ -249,7 +298,7 @@ PaWasapiStreamOption;
|
|||
|
||||
|
||||
/* Stream descriptor. */
|
||||
typedef struct PaWasapiStreamInfo
|
||||
typedef struct PaWasapiStreamInfo
|
||||
{
|
||||
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
|
||||
PaHostApiTypeId hostApiType; /**< paWASAPI */
|
||||
|
|
@ -258,16 +307,16 @@ typedef struct PaWasapiStreamInfo
|
|||
unsigned long flags; /**< collection of PaWasapiFlags */
|
||||
|
||||
/** Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
|
||||
paWinWasapiUseChannelMask this allows you to specify which speakers
|
||||
paWinWasapiUseChannelMask this allows you to specify which speakers
|
||||
to address in a multichannel stream. Constants for channelMask
|
||||
are specified in pa_win_waveformat.h. Will be used only if
|
||||
are specified in pa_win_waveformat.h. Will be used only if
|
||||
paWinWasapiUseChannelMask flag is specified.
|
||||
*/
|
||||
PaWinWaveFormatChannelMask channelMask;
|
||||
|
||||
/** Delivers raw data to callback obtained from GetBuffer() methods skipping
|
||||
internal PortAudio processing inventory completely. userData parameter will
|
||||
be the same that was passed to Pa_OpenStream method. Will be used only if
|
||||
internal PortAudio processing inventory completely. userData parameter will
|
||||
be the same that was passed to Pa_OpenStream method. Will be used only if
|
||||
paWinWasapiRedirectHostProcessor flag is specified.
|
||||
*/
|
||||
PaWasapiHostProcessorCallback hostProcessorOutput;
|
||||
|
|
@ -293,13 +342,13 @@ typedef struct PaWasapiStreamInfo
|
|||
@version Available as of 19.6.0
|
||||
*/
|
||||
PaWasapiStreamOption streamOption;
|
||||
}
|
||||
}
|
||||
PaWasapiStreamInfo;
|
||||
|
||||
|
||||
/** Returns pointer to WASAPI's IAudioClient object of the stream.
|
||||
|
||||
@param pStream Pointer to PaStream.
|
||||
@param pStream Pointer to PaStream object.
|
||||
@param pAudioClient Pointer to pointer of IAudioClient.
|
||||
@param bOutput TRUE (1) for output stream, FALSE (0) for input stream.
|
||||
|
||||
|
|
@ -308,10 +357,11 @@ PaWasapiStreamInfo;
|
|||
PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput );
|
||||
|
||||
|
||||
/** Update device list.
|
||||
This function is available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined during compile time
|
||||
with maximum constant WASAPI device count (recommended value - 32).
|
||||
If PA_WASAPI_MAX_CONST_DEVICE_COUNT is set to 0 (or not defined) during compile time the implementation
|
||||
/** Update device list.
|
||||
|
||||
This function is available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined during compile time
|
||||
with maximum constant WASAPI device count (recommended value - 32).
|
||||
If PA_WASAPI_MAX_CONST_DEVICE_COUNT is set to 0 (or not defined) during compile time the implementation
|
||||
will not define PaWasapi_UpdateDeviceList() and thus updating device list can only be possible by calling
|
||||
Pa_Terminate() and then Pa_Initialize().
|
||||
|
||||
|
|
@ -320,115 +370,128 @@ PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOu
|
|||
PaError PaWasapi_UpdateDeviceList();
|
||||
|
||||
|
||||
/** Returns current audio format of the device assigned to the opened stream. Format is represented by
|
||||
PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. Use this function to reconfirm format if
|
||||
PA's processor is overriden and paWinWasapiRedirectHostProcessor flag is specified.
|
||||
/** Get current audio format of the device assigned to the opened stream.
|
||||
|
||||
@param pStream Pointer to PaStream.
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param bOutput TRUE (1) for output stream, FALSE (0) for input stream.
|
||||
Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
Use this function to reconfirm format if PA's processor is overriden and
|
||||
paWinWasapiRedirectHostProcessor flag is specified.
|
||||
|
||||
@param pStream Pointer to PaStream object.
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param bOutput TRUE (1) for output stream, FALSE (0) for input stream.
|
||||
|
||||
@return Non-negative value indicating the number of bytes copied into format decriptor
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or, a PaErrorCode (which is always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
*/
|
||||
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int nFormatSize, int bOutput );
|
||||
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput );
|
||||
|
||||
|
||||
/** Returns default audio format for device in Shared Mode. Format is represented by
|
||||
PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure and obtained by getting
|
||||
the device property with a PKEY_AudioEngine_DeviceFormat key.
|
||||
/** Get default audio format for the device in Shared Mode.
|
||||
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param nDevice Device index.
|
||||
Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure and obtained
|
||||
by getting the device property with a PKEY_AudioEngine_DeviceFormat key.
|
||||
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param device Device index.
|
||||
|
||||
@return Non-negative value indicating the number of bytes copied into format decriptor
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or, a PaErrorCode (which is always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
*/
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
|
||||
|
||||
|
||||
/** Returns mix audio format for device in Shared Mode. Format is represented by
|
||||
PaWinWaveFormat or WAVEFORMATEXTENSIBLE structureand obtained by
|
||||
/** Get mix audio format for the device in Shared Mode.
|
||||
|
||||
Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structureand obtained by
|
||||
IAudioClient::GetMixFormat.
|
||||
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param nDevice Device index.
|
||||
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param device Device index.
|
||||
|
||||
@return Non-negative value indicating the number of bytes copied into format decriptor
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or, a PaErrorCode (which is always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
*/
|
||||
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
|
||||
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
|
||||
|
||||
|
||||
/** Returns device role (PaWasapiDeviceRole enum).
|
||||
/** Get device role (PaWasapiDeviceRole enum).
|
||||
|
||||
@param nDevice Device index.
|
||||
@param device Device index.
|
||||
|
||||
@return Non-negative value indicating device role or, a PaErrorCode (which are always negative)
|
||||
@return Non-negative value indicating device role or, a PaErrorCode (which is always negative)
|
||||
if PortAudio is not initialized or an error is encountered.
|
||||
*/
|
||||
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
|
||||
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex device );
|
||||
|
||||
|
||||
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
|
||||
which makes calls to Pa_WriteStream/Pa_ReadStream.
|
||||
/** Boost thread priority of calling thread (MMCSS).
|
||||
|
||||
@param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
|
||||
method to revert thread priority to initial state.
|
||||
Use it for Blocking Interface only inside the thread which makes calls to Pa_WriteStream/Pa_ReadStream.
|
||||
|
||||
@param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying
|
||||
@param pTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
|
||||
method to revert thread priority to initial state.
|
||||
|
||||
@param priorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying
|
||||
eThreadPriorityNone does nothing.
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapi_RevertThreadPriority
|
||||
*/
|
||||
PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
|
||||
PaError PaWasapi_ThreadPriorityBoost( void **pTask, PaWasapiThreadPriority priorityClass );
|
||||
|
||||
|
||||
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
|
||||
which makes calls to Pa_WriteStream/Pa_ReadStream.
|
||||
/** Boost thread priority of calling thread (MMCSS).
|
||||
|
||||
Use it for Blocking Interface only inside the thread which makes calls to Pa_WriteStream/Pa_ReadStream.
|
||||
|
||||
@param pTask Task handle obtained by PaWasapi_BoostThreadPriority method.
|
||||
|
||||
@param hTask Task handle obtained by PaWasapi_BoostThreadPriority method.
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapi_BoostThreadPriority
|
||||
*/
|
||||
PaError PaWasapi_ThreadPriorityRevert( void *hTask );
|
||||
PaError PaWasapi_ThreadPriorityRevert( void *pTask );
|
||||
|
||||
|
||||
/** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which
|
||||
can be locked for operations. Use this method as helper to findout maximal values of
|
||||
inputFrames/outputFrames of PaWasapiHostProcessorCallback.
|
||||
/** Get number of frames per host buffer.
|
||||
|
||||
It is max value of frames of WASAPI buffer which can be locked for operations.
|
||||
Use this method as helper to findout max values of inputFrames/outputFrames
|
||||
of PaWasapiHostProcessorCallback.
|
||||
|
||||
@param pStream Pointer to PaStream object.
|
||||
@param pInput Pointer to variable to receive number of input frames. Can be NULL.
|
||||
@param pOutput Pointer to variable to receive number of output frames. Can be NULL.
|
||||
|
||||
@param pStream Pointer to PaStream to query.
|
||||
@param nInput Pointer to variable to receive number of input frames. Can be NULL.
|
||||
@param nOutput Pointer to variable to receive number of output frames. Can be NULL.
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapiHostProcessorCallback
|
||||
*/
|
||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
|
||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput );
|
||||
|
||||
|
||||
/** Get number of jacks associated with a WASAPI device. Use this method to determine if
|
||||
there are any jacks associated with the provided WASAPI device. Not all audio devices
|
||||
will support this capability. This is valid for both input and output devices.
|
||||
/** Get number of jacks associated with a WASAPI device.
|
||||
|
||||
Use this method to determine if there are any jacks associated with the provided WASAPI device.
|
||||
Not all audio devices will support this capability. This is valid for both input and output devices.
|
||||
|
||||
@note Not available on UWP platform.
|
||||
|
||||
@param nDevice device index.
|
||||
@param jcount Number of jacks is returned in this variable
|
||||
@return Error code indicating success or failure
|
||||
@param device Device index.
|
||||
@param pJackCount Pointer to variable to receive number of jacks.
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapi_GetJackDescription
|
||||
*/
|
||||
PaError PaWasapi_GetJackCount( PaDeviceIndex nDevice, int *jcount );
|
||||
PaError PaWasapi_GetJackCount( PaDeviceIndex device, int *pJackCount );
|
||||
|
||||
|
||||
/** Get the jack description associated with a WASAPI device and jack number
|
||||
/** Get the jack description associated with a WASAPI device and jack number.
|
||||
|
||||
Before this function is called, use PaWasapi_GetJackCount to determine the
|
||||
number of jacks associated with device. If jcount is greater than zero, then
|
||||
each jack from 0 to jcount can be queried with this function to get the jack
|
||||
|
|
@ -436,19 +499,21 @@ PaError PaWasapi_GetJackCount( PaDeviceIndex nDevice, int *jcount );
|
|||
|
||||
@note Not available on UWP platform.
|
||||
|
||||
@param nDevice device index.
|
||||
@param jindex Which jack to return information
|
||||
@param device Device index.
|
||||
@param jackIndex Jack index.
|
||||
@param pJackDescription Pointer to PaWasapiJackDescription.
|
||||
@return Error code indicating success or failure
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapi_GetJackCount
|
||||
*/
|
||||
PaError PaWasapi_GetJackDescription( PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription );
|
||||
PaError PaWasapi_GetJackDescription( PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription );
|
||||
|
||||
|
||||
/** Set default interface Id.
|
||||
By default PA implementation will use DEVINTERFACE_AUDIO_RENDER and
|
||||
DEVINTERFACE_AUDIO_CAPTURE if device Id is not provided explicitly. These default Ids
|
||||
will not allow to use Exclusive mode on UWP platform and thus you must provide
|
||||
|
||||
By default PA implementation will use DEVINTERFACE_AUDIO_RENDER and
|
||||
DEVINTERFACE_AUDIO_CAPTURE if device Id is not provided explicitly. These default Ids
|
||||
will not allow to use Exclusive mode on UWP platform and thus you must provide
|
||||
device Id explicitly via this API before calling Pa_OpenStream().
|
||||
Device Ids on UWP platform are obtainable via
|
||||
Windows::Media::Devices::MediaDevice::GetDefaultAudioRenderId() or
|
||||
|
|
@ -459,18 +524,30 @@ PaError PaWasapi_GetJackDescription( PaDeviceIndex nDevice, int jindex, PaWasapi
|
|||
@param pId Interface Id, pointer to the 16-bit Unicode string (WCHAR). If NULL then device Id
|
||||
will be reset to the default, e.g. DEVINTERFACE_AUDIO_RENDER or DEVINTERFACE_AUDIO_CAPTURE.
|
||||
@param bOutput TRUE (1) for output (render), FALSE (0) for input (capture).
|
||||
|
||||
@return Error code indicating success or failure. Will return paIncompatibleStreamHostApi if PA is not compiled
|
||||
for UWP platform. If Id is longer than 4096 characters paBufferTooBig will be returned.
|
||||
*/
|
||||
PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput );
|
||||
|
||||
|
||||
/** Set stream state handler.
|
||||
|
||||
@param pStream Pointer to PaStream object.
|
||||
@param fnStateHandler Pointer to state handling function.
|
||||
@param pUserData Pointer to user data.
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
*/
|
||||
PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData );
|
||||
|
||||
|
||||
/*
|
||||
IMPORTANT:
|
||||
|
||||
WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive
|
||||
share modes.
|
||||
|
||||
share modes.
|
||||
|
||||
Exclusive Mode:
|
||||
|
||||
Exclusive mode allows to deliver audio data directly to hardware bypassing
|
||||
|
|
@ -479,20 +556,20 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput );
|
|||
|
||||
Callback Interface:
|
||||
|
||||
Provides best audio quality with low latency. Callback interface is implemented in
|
||||
Provides best audio quality with low latency. Callback interface is implemented in
|
||||
two versions:
|
||||
|
||||
1) Event-Driven:
|
||||
This is the most powerful WASAPI implementation which provides glitch-free
|
||||
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
|
||||
3 ms for HD Audio class audio chips. For the Shared mode latency can not be
|
||||
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
|
||||
3 ms for HD Audio class audio chips. For the Shared mode latency can not be
|
||||
lower than 20 ms.
|
||||
|
||||
2) Poll-Driven:
|
||||
Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven
|
||||
and provides latency at around 10-13ms. Polling must be used to overcome a system bug
|
||||
under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply
|
||||
times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug
|
||||
under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply
|
||||
times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug
|
||||
does not exist in Vista x86 or Windows 7.
|
||||
Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects
|
||||
WOW64 bug and sets 'paWinWasapiPolling' automatically.
|
||||
|
|
@ -501,44 +578,51 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput );
|
|||
|
||||
Normally thread priority is set automatically and does not require modification. Although
|
||||
if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
|
||||
flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
|
||||
flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
|
||||
enum.
|
||||
|
||||
Blocking Interface:
|
||||
|
||||
Blocking interface is implemented but due to above described Poll-Driven method can not
|
||||
deliver lowest possible latency. Specifying too low latency in Shared mode will result in
|
||||
deliver lowest possible latency. Specifying too low latency in Shared mode will result in
|
||||
distorted audio although Exclusive mode adds stability.
|
||||
|
||||
8.24 format:
|
||||
|
||||
If paCustomFormat is specified as sample format then the implementation will understand it
|
||||
If paCustomFormat is specified as sample format then the implementation will understand it
|
||||
as valid 24-bits inside 32-bit container (e.g. wBitsPerSample = 32, Samples.wValidBitsPerSample = 24).
|
||||
|
||||
By using paCustomFormat there will be small optimization when samples are be copied
|
||||
with Copy_24_To_24 by PA processor instead of conversion from packed 3-byte (24-bit) data
|
||||
|
||||
By using paCustomFormat there will be small optimization when samples are be copied
|
||||
with Copy_24_To_24 by PA processor instead of conversion from packed 3-byte (24-bit) data
|
||||
with Int24_To_Int32.
|
||||
|
||||
Pa_IsFormatSupported:
|
||||
|
||||
To check format with correct Share Mode (Exclusive/Shared) you must supply PaWasapiStreamInfo
|
||||
with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo
|
||||
structure.
|
||||
|
||||
If paWinWasapiExplicitSampleFormat flag is provided then implementation will not try to select
|
||||
suitable close format and will return an error instead of paFormatIsSupported. By specifying
|
||||
paWinWasapiExplicitSampleFormat flag it is possible to find out what sample formats are
|
||||
To check format with correct Share Mode (Exclusive/Shared) you must supply PaWasapiStreamInfo
|
||||
with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo
|
||||
structure.
|
||||
|
||||
If paWinWasapiExplicitSampleFormat flag is provided then implementation will not try to select
|
||||
suitable close format and will return an error instead of paFormatIsSupported. By specifying
|
||||
paWinWasapiExplicitSampleFormat flag it is possible to find out what sample formats are
|
||||
supported by Exclusive or Shared modes.
|
||||
|
||||
Pa_OpenStream:
|
||||
|
||||
To set desired Share Mode (Exclusive/Shared) you must supply
|
||||
PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
|
||||
PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
|
||||
PaStreamParameters::hostApiSpecificStreamInfo structure.
|
||||
|
||||
Coding style for parameters and structure members of the public API:
|
||||
|
||||
1) bXXX - boolean, [1 (TRUE), 0 (FALSE)]
|
||||
2) pXXX - pointer
|
||||
3) fnXXX - pointer to function
|
||||
4) structure members are never prefixed with a type distinguisher
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PA_WIN_WASAPI_H */
|
||||
#endif /* PA_WIN_WASAPI_H */
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
/*
|
||||
* Portable Audio I/O Library WASAPI implementation
|
||||
* Copyright (c) 2006-2010 David Viens, Dmitry Kostjuchenko
|
||||
* Copyright (c) 2006-2010 David Viens
|
||||
* Copyright (c) 2010-2018 Dmitry Kostjuchenko
|
||||
*
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
|
||||
* Copyright (c) 1999-2018 Ross Bencina, Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
|
|
@ -292,6 +293,10 @@ PA_THREAD_FUNC ProcThreadPoll(void *param);
|
|||
|
||||
#define MAX_STR_LEN 512
|
||||
|
||||
#ifdef PA_WINRT
|
||||
#define PA_WASAPI_DEVICE_ID_LEN 4096
|
||||
#endif
|
||||
|
||||
enum { S_INPUT = 0, S_OUTPUT = 1, S_COUNT = 2, S_FULLDUPLEX = 0 };
|
||||
|
||||
// Number of packets which compose single contignous buffer. With trial and error it was calculated
|
||||
|
|
@ -339,12 +344,6 @@ FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
|
|||
FAvSetMmThreadPriority pAvSetMmThreadPriority = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef PA_WINRT
|
||||
#define PA_WASAPI_DEVICE_ID_LEN 4096
|
||||
static OLECHAR g_DefaultRenderId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
|
||||
static OLECHAR g_DefaultCaptureId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
|
||||
#endif
|
||||
|
||||
#define _GetProc(fun, type, name) { \
|
||||
fun = (type) GetProcAddress(hDInputDLL,name); \
|
||||
if (fun == NULL) { \
|
||||
|
|
@ -452,15 +451,15 @@ typedef struct
|
|||
|
||||
PaWinUtilComInitializationResult comInitializationResult;
|
||||
|
||||
//this is the REAL number of devices, whether they are usefull to PA or not!
|
||||
// this is the REAL number of devices, whether they are usefull to PA or not!
|
||||
UINT32 deviceCount;
|
||||
|
||||
WCHAR defaultRenderer [MAX_STR_LEN];
|
||||
WCHAR defaultCapturer [MAX_STR_LEN];
|
||||
WCHAR defaultRenderer[MAX_STR_LEN];
|
||||
WCHAR defaultCapturer[MAX_STR_LEN];
|
||||
|
||||
PaWasapiDeviceInfo *devInfo;
|
||||
|
||||
// Is true when WOW64 Vista/7 Workaround is needed
|
||||
// is TRUE when WOW64 Vista/7 Workaround is needed
|
||||
BOOL useWOW64Workaround;
|
||||
}
|
||||
PaWasapiHostApiRepresentation;
|
||||
|
|
@ -584,6 +583,10 @@ typedef struct PaWasapiStream
|
|||
|
||||
// Thread priority level
|
||||
PaWasapiThreadPriority nThreadPriority;
|
||||
|
||||
// State handler
|
||||
PaWasapiStreamStateCallback fnStateHandler;
|
||||
void *pStateHandlerUserData;
|
||||
}
|
||||
PaWasapiStream;
|
||||
|
||||
|
|
@ -606,6 +609,10 @@ static void PaWasapi_FreeMemory(void *ptr);
|
|||
static PaSampleFormat WaveToPaFormat(const WAVEFORMATEXTENSIBLE *fmtext);
|
||||
|
||||
// Local statics
|
||||
#ifdef PA_WINRT
|
||||
static OLECHAR g_DefaultRenderId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
|
||||
static OLECHAR g_DefaultCaptureId[PA_WASAPI_DEVICE_ID_LEN] = { 0 };
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#define LogHostError(HRES) __LogHostError(HRES, __FUNCTION__, __FILE__, __LINE__)
|
||||
|
|
@ -851,7 +858,7 @@ static UINT32 ALIGN_FWD(UINT32 v, UINT32 align)
|
|||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// Get next value power of 2
|
||||
UINT32 ALIGN_NEXT_POW2(UINT32 v)
|
||||
static UINT32 ALIGN_NEXT_POW2(UINT32 v)
|
||||
{
|
||||
UINT32 v2 = 1;
|
||||
while (v > (v2 <<= 1)) { }
|
||||
|
|
@ -1583,6 +1590,18 @@ static DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static void NotifyStateChanged(PaWasapiStream *stream, UINT32 flags, HRESULT hr)
|
||||
{
|
||||
if (stream->fnStateHandler == NULL)
|
||||
return;
|
||||
|
||||
if (FAILED(hr))
|
||||
flags |= paWasapiStreamStateError;
|
||||
|
||||
stream->fnStateHandler((PaStream *)stream, flags, hr, stream->pStateHandlerUserData);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostApiIndex hostApiIndex)
|
||||
{
|
||||
|
|
@ -1684,7 +1703,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
|
|||
}
|
||||
#endif
|
||||
|
||||
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_AllocateMemory(sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
||||
paWasapi->devInfo = (PaWasapiDeviceInfo *)PaUtil_GroupAllocateMemory(
|
||||
paWasapi->allocations, sizeof(PaWasapiDeviceInfo) * paWasapi->deviceCount);
|
||||
if (paWasapi->devInfo == NULL)
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
|
|
@ -2013,7 +2033,7 @@ error:
|
|||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
|
||||
{
|
||||
PaError result = paInternalError;
|
||||
PaError result;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
|
|
@ -2032,10 +2052,12 @@ PaError PaWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
|
|||
}
|
||||
memset(paWasapi, 0, sizeof(PaWasapiHostApiRepresentation)); /* ensure all fields are zeroed. especially paWasapi->allocations */
|
||||
|
||||
// Initialize COM subsystem
|
||||
result = PaWinUtil_CoInitialize(paWASAPI, &paWasapi->comInitializationResult);
|
||||
if (result != paNoError)
|
||||
goto error;
|
||||
|
||||
// Create memory group
|
||||
paWasapi->allocations = PaUtil_CreateAllocationGroup();
|
||||
if (paWasapi->allocations == NULL)
|
||||
{
|
||||
|
|
@ -2091,15 +2113,20 @@ static void ReleaseWasapiDeviceInfoList( PaWasapiHostApiRepresentation *paWasapi
|
|||
{
|
||||
UINT32 i;
|
||||
|
||||
// Release device info bound objects and device info itself
|
||||
// Release device info bound objects
|
||||
for (i = 0; i < paWasapi->deviceCount; ++i)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
SAFE_RELEASE(paWasapi->devInfo[i].device);
|
||||
#endif
|
||||
}
|
||||
PaUtil_FreeMemory(paWasapi->devInfo);
|
||||
|
||||
// Free device info
|
||||
if (paWasapi->allocations != NULL)
|
||||
PaUtil_GroupFreeMemory(paWasapi->allocations, paWasapi->devInfo);
|
||||
|
||||
// Be ready for a device list reinitialization and if its creation is failed pointers must not be dangling
|
||||
paWasapi->devInfo = NULL;
|
||||
paWasapi->deviceCount = 0;
|
||||
}
|
||||
|
||||
|
|
@ -2110,16 +2137,20 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
|
|||
if (paWasapi == NULL)
|
||||
return;
|
||||
|
||||
// Release device list
|
||||
ReleaseWasapiDeviceInfoList(paWasapi);
|
||||
|
||||
// Free allocations and memory group itself
|
||||
if (paWasapi->allocations != NULL)
|
||||
{
|
||||
PaUtil_FreeAllAllocations(paWasapi->allocations);
|
||||
PaUtil_DestroyAllocationGroup(paWasapi->allocations);
|
||||
}
|
||||
|
||||
PaWinUtil_CoUninitialize( paWASAPI, &paWasapi->comInitializationResult );
|
||||
// Release COM subsystem
|
||||
PaWinUtil_CoUninitialize(paWASAPI, &paWasapi->comInitializationResult);
|
||||
|
||||
// Free API representation
|
||||
PaUtil_FreeMemory(paWasapi);
|
||||
|
||||
// Close AVRT
|
||||
|
|
@ -2127,18 +2158,19 @@ static void Terminate( PaUtilHostApiRepresentation *hostApi )
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
static PaWasapiHostApiRepresentation *_GetHostApi(PaError *_error)
|
||||
static PaWasapiHostApiRepresentation *_GetHostApi(PaError *ret)
|
||||
{
|
||||
PaError error;
|
||||
|
||||
PaUtilHostApiRepresentation *pApi;
|
||||
|
||||
if ((error = PaUtil_GetHostApiRepresentation(&pApi, paWASAPI)) != paNoError)
|
||||
{
|
||||
if (_error != NULL)
|
||||
(*_error) = error;
|
||||
if (ret != NULL)
|
||||
(*ret) = error;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (PaWasapiHostApiRepresentation *)pApi;
|
||||
}
|
||||
|
||||
|
|
@ -2153,7 +2185,11 @@ static PaError UpdateDeviceList()
|
|||
// Get API
|
||||
hostApi = (PaUtilHostApiRepresentation *)(paWasapi = _GetHostApi(&ret));
|
||||
if (paWasapi == NULL)
|
||||
return ret;
|
||||
return paNotInitialized;
|
||||
|
||||
// Make sure initialized properly
|
||||
if (paWasapi->allocations == NULL)
|
||||
return paNotInitialized;
|
||||
|
||||
// Release WASAPI internal device info list
|
||||
ReleaseWasapiDeviceInfoList(paWasapi);
|
||||
|
|
@ -2168,6 +2204,8 @@ static PaError UpdateDeviceList()
|
|||
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos[0]);
|
||||
PaUtil_GroupFreeMemory(paWasapi->allocations, hostApi->deviceInfos);
|
||||
|
||||
// Be ready for a device list reinitialization and if its creation is failed pointers must not be dangling
|
||||
hostApi->deviceInfos = NULL;
|
||||
hostApi->info.deviceCount = 0;
|
||||
hostApi->info.defaultInputDevice = paNoDevice;
|
||||
hostApi->info.defaultOutputDevice = paNoDevice;
|
||||
|
|
@ -2189,7 +2227,7 @@ PaError PaWasapi_UpdateDeviceList()
|
|||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int nFormatSize, int bOutput )
|
||||
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput )
|
||||
{
|
||||
UINT32 size;
|
||||
WAVEFORMATEXTENSIBLE *format;
|
||||
|
|
@ -2200,14 +2238,14 @@ int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned
|
|||
|
||||
format = (bOutput == TRUE ? &stream->out.wavex : &stream->in.wavex);
|
||||
|
||||
size = min(nFormatSize, (UINT32)sizeof(*format));
|
||||
size = min(formatSize, (UINT32)sizeof(*format));
|
||||
memcpy(pFormat, format, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device )
|
||||
{
|
||||
PaError ret;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
|
|
@ -2216,7 +2254,7 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
|
|||
|
||||
if (pFormat == NULL)
|
||||
return paBadBufferPtr;
|
||||
if (nFormatSize <= 0)
|
||||
if (formatSize <= 0)
|
||||
return paBufferTooSmall;
|
||||
|
||||
// Get API
|
||||
|
|
@ -2225,7 +2263,7 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
|
|||
return ret;
|
||||
|
||||
// Get device index
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
|
||||
if (ret != paNoError)
|
||||
return ret;
|
||||
|
||||
|
|
@ -2233,14 +2271,14 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
|
|||
if ((UINT32)index >= paWasapi->deviceCount)
|
||||
return paInvalidDevice;
|
||||
|
||||
size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].DefaultFormat));
|
||||
size = min(formatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].DefaultFormat));
|
||||
memcpy(pFormat, &paWasapi->devInfo[ index ].DefaultFormat, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
|
||||
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device )
|
||||
{
|
||||
PaError ret;
|
||||
PaWasapiHostApiRepresentation *paWasapi;
|
||||
|
|
@ -2249,7 +2287,7 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
|
|||
|
||||
if (pFormat == NULL)
|
||||
return paBadBufferPtr;
|
||||
if (nFormatSize <= 0)
|
||||
if (formatSize <= 0)
|
||||
return paBufferTooSmall;
|
||||
|
||||
// Get API
|
||||
|
|
@ -2258,7 +2296,7 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
|
|||
return ret;
|
||||
|
||||
// Get device index
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
|
||||
if (ret != paNoError)
|
||||
return ret;
|
||||
|
||||
|
|
@ -2266,14 +2304,14 @@ int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDevi
|
|||
if ((UINT32)index >= paWasapi->deviceCount)
|
||||
return paInvalidDevice;
|
||||
|
||||
size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].MixFormat));
|
||||
size = min(formatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].MixFormat));
|
||||
memcpy(pFormat, &paWasapi->devInfo[ index ].MixFormat, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
|
||||
int PaWasapi_GetDeviceRole( PaDeviceIndex device )
|
||||
{
|
||||
PaError ret;
|
||||
PaDeviceIndex index;
|
||||
|
|
@ -2284,7 +2322,7 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
|
|||
return paNotInitialized;
|
||||
|
||||
// Get device index
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
|
||||
if (ret != paNoError)
|
||||
return ret;
|
||||
|
||||
|
|
@ -2296,17 +2334,17 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput )
|
||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
|
||||
{
|
||||
PaWasapiStream *stream = (PaWasapiStream *)pStream;
|
||||
if (stream == NULL)
|
||||
return paBadStreamPtr;
|
||||
|
||||
if (nInput != NULL)
|
||||
(*nInput) = stream->in.framesPerHostCallback;
|
||||
if (pInput != NULL)
|
||||
(*pInput) = stream->in.framesPerHostCallback;
|
||||
|
||||
if (nOutput != NULL)
|
||||
(*nOutput) = stream->out.framesPerHostCallback;
|
||||
if (pOutput != NULL)
|
||||
(*pOutput) = stream->out.framesPerHostCallback;
|
||||
|
||||
return paNoError;
|
||||
}
|
||||
|
|
@ -4849,19 +4887,19 @@ static void MMCSS_deactivate(HANDLE hTask)
|
|||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass)
|
||||
PaError PaWasapi_ThreadPriorityBoost(void **pTask, PaWasapiThreadPriority priorityClass)
|
||||
{
|
||||
HANDLE task;
|
||||
PaError ret;
|
||||
|
||||
if (hTask == NULL)
|
||||
if (pTask == NULL)
|
||||
return paUnanticipatedHostError;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
if ((ret = MMCSS_activate(nPriorityClass, &task)) != paNoError)
|
||||
if ((ret = MMCSS_activate(priorityClass, &task)) != paNoError)
|
||||
return ret;
|
||||
#else
|
||||
switch (nPriorityClass)
|
||||
switch (priorityClass)
|
||||
{
|
||||
case eThreadPriorityAudio:
|
||||
case eThreadPriorityProAudio: {
|
||||
|
|
@ -4885,21 +4923,21 @@ PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPrior
|
|||
}
|
||||
#endif
|
||||
|
||||
(*hTask) = task;
|
||||
(*pTask) = task;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_ThreadPriorityRevert(void *hTask)
|
||||
PaError PaWasapi_ThreadPriorityRevert(void *pTask)
|
||||
{
|
||||
if (hTask == NULL)
|
||||
if (pTask == NULL)
|
||||
return paUnanticipatedHostError;
|
||||
|
||||
#ifndef PA_WINRT
|
||||
MMCSS_deactivate((HANDLE)hTask);
|
||||
MMCSS_deactivate((HANDLE)pTask);
|
||||
#else
|
||||
// Revert previous priority by removing 0x80000000 mask
|
||||
if (SetThreadPriority(GetCurrentThread(), (int)((intptr_t)hTask & ~0x80000000)) == FALSE)
|
||||
if (SetThreadPriority(GetCurrentThread(), (int)((intptr_t)pTask & ~0x80000000)) == FALSE)
|
||||
return paUnanticipatedHostError;
|
||||
#endif
|
||||
|
||||
|
|
@ -4910,7 +4948,7 @@ PaError PaWasapi_ThreadPriorityRevert(void *hTask)
|
|||
// Described at:
|
||||
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
|
||||
|
||||
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
|
||||
PaError PaWasapi_GetJackCount(PaDeviceIndex device, int *pJackCount)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
PaError ret;
|
||||
|
|
@ -4927,47 +4965,50 @@ PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
|
|||
if (paWasapi == NULL)
|
||||
return paNotInitialized;
|
||||
|
||||
// Get device index.
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||
if (pJackCount == NULL)
|
||||
return paUnanticipatedHostError;
|
||||
|
||||
// Get device index
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
|
||||
if (ret != paNoError)
|
||||
return ret;
|
||||
|
||||
// Validate index.
|
||||
// Validate index
|
||||
if ((UINT32)index >= paWasapi->deviceCount)
|
||||
return paInvalidDevice;
|
||||
|
||||
// Get the endpoint device's IDeviceTopology interface.
|
||||
// Get the endpoint device's IDeviceTopology interface
|
||||
hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,
|
||||
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// The device topology for an endpoint device always contains just one connector (connector number 0).
|
||||
// The device topology for an endpoint device always contains just one connector (connector number 0)
|
||||
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Step across the connection to the jack on the adapter.
|
||||
// Step across the connection to the jack on the adapter
|
||||
hr = IConnector_GetConnectedTo(pConnFrom, &pConnTo);
|
||||
if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
|
||||
{
|
||||
// The adapter device is not currently active.
|
||||
// The adapter device is not currently active
|
||||
hr = E_NOINTERFACE;
|
||||
}
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Get the connector's IPart interface.
|
||||
// Get the connector's IPart interface
|
||||
hr = IConnector_QueryInterface(pConnTo, &pa_IID_IPart, (void**)&pPart);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Activate the connector's IKsJackDescription interface.
|
||||
// Activate the connector's IKsJackDescription interface
|
||||
hr = IPart_Activate(pPart, CLSCTX_INPROC_SERVER, &pa_IID_IKsJackDescription, (void**)&pJackDesc);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Return jack count for this device.
|
||||
// Return jack count for this device
|
||||
hr = IKsJackDescription_GetJackCount(pJackDesc, &jackCount);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Set.
|
||||
(*jcount) = jackCount;
|
||||
(*pJackCount) = jackCount;
|
||||
|
||||
// Ok.
|
||||
ret = paNoError;
|
||||
|
|
@ -4983,8 +5024,8 @@ error:
|
|||
LogHostError(hr);
|
||||
return paNoError;
|
||||
#else
|
||||
(void)nDevice;
|
||||
(void)jcount;
|
||||
(void)device;
|
||||
(void)pJackCount;
|
||||
return paUnanticipatedHostError;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -5082,7 +5123,7 @@ static PaWasapiJackPortConnection _ConvertJackPortConnectionWASAPIToPA(int portC
|
|||
// Described at:
|
||||
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
|
||||
|
||||
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription)
|
||||
PaError PaWasapi_GetJackDescription(PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription)
|
||||
{
|
||||
#ifndef PA_WINRT
|
||||
PaError ret;
|
||||
|
|
@ -5099,46 +5140,46 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ
|
|||
if (paWasapi == NULL)
|
||||
return paNotInitialized;
|
||||
|
||||
// Get device index.
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||
// Get device index
|
||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, device, &paWasapi->inheritedHostApiRep);
|
||||
if (ret != paNoError)
|
||||
return ret;
|
||||
|
||||
// Validate index.
|
||||
// Validate index
|
||||
if ((UINT32)index >= paWasapi->deviceCount)
|
||||
return paInvalidDevice;
|
||||
|
||||
// Get the endpoint device's IDeviceTopology interface.
|
||||
// Get the endpoint device's IDeviceTopology interface
|
||||
hr = IMMDevice_Activate(paWasapi->devInfo[index].device, &pa_IID_IDeviceTopology,
|
||||
CLSCTX_INPROC_SERVER, NULL, (void**)&pDeviceTopology);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// The device topology for an endpoint device always contains just one connector (connector number 0).
|
||||
// The device topology for an endpoint device always contains just one connector (connector number 0)
|
||||
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Step across the connection to the jack on the adapter.
|
||||
// Step across the connection to the jack on the adapter
|
||||
hr = IConnector_GetConnectedTo(pConnFrom, &pConnTo);
|
||||
if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
|
||||
{
|
||||
// The adapter device is not currently active.
|
||||
// The adapter device is not currently active
|
||||
hr = E_NOINTERFACE;
|
||||
}
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Get the connector's IPart interface.
|
||||
// Get the connector's IPart interface
|
||||
hr = IConnector_QueryInterface(pConnTo, &pa_IID_IPart, (void**)&pPart);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Activate the connector's IKsJackDescription interface.
|
||||
// Activate the connector's IKsJackDescription interface
|
||||
hr = IPart_Activate(pPart, CLSCTX_INPROC_SERVER, &pa_IID_IKsJackDescription, (void**)&pJackDesc);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Test to return jack description struct for index 0.
|
||||
hr = IKsJackDescription_GetJackDescription(pJackDesc, jindex, &jack);
|
||||
// Test to return jack description struct for index 0
|
||||
hr = IKsJackDescription_GetJackDescription(pJackDesc, jackIndex, &jack);
|
||||
IF_FAILED_JUMP(hr, error);
|
||||
|
||||
// Convert WASAPI values to PA format.
|
||||
// Convert WASAPI values to PA format
|
||||
pJackDescription->channelMapping = jack.ChannelMapping;
|
||||
pJackDescription->color = jack.Color;
|
||||
pJackDescription->connectionType = _ConvertJackConnectionTypeWASAPIToPA(jack.ConnectionType);
|
||||
|
|
@ -5147,7 +5188,7 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ
|
|||
pJackDescription->isConnected = jack.IsConnected;
|
||||
pJackDescription->portConnection = _ConvertJackPortConnectionWASAPIToPA(jack.PortConnection);
|
||||
|
||||
// Ok.
|
||||
// Ok
|
||||
ret = paNoError;
|
||||
|
||||
error:
|
||||
|
|
@ -5162,8 +5203,8 @@ error:
|
|||
return ret;
|
||||
|
||||
#else
|
||||
(void)nDevice;
|
||||
(void)jindex;
|
||||
(void)device;
|
||||
(void)jackIndex;
|
||||
(void)pJackDescription;
|
||||
return paUnanticipatedHostError;
|
||||
#endif
|
||||
|
|
@ -5188,11 +5229,12 @@ PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOut
|
|||
PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
|
||||
{
|
||||
#ifdef PA_WINRT
|
||||
int i;
|
||||
|
||||
// Validate Id length
|
||||
if (pId != NULL)
|
||||
{
|
||||
for (int i = 0; pId[i] != 0; ++i)
|
||||
for (i = 0; pId[i] != 0; ++i)
|
||||
{
|
||||
if (i >= PA_WASAPI_DEVICE_ID_LEN)
|
||||
return paBufferTooBig;
|
||||
|
|
@ -5205,7 +5247,7 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
|
|||
memset(g_DefaultRenderId, 0, sizeof(g_DefaultRenderId));
|
||||
if (pId != NULL)
|
||||
{
|
||||
for (int i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultRenderId)); ++i)
|
||||
for (i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultRenderId)); ++i)
|
||||
g_DefaultRenderId[i] = pId[i];
|
||||
}
|
||||
}
|
||||
|
|
@ -5214,7 +5256,7 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
|
|||
memset(g_DefaultCaptureId, 0, sizeof(g_DefaultCaptureId));
|
||||
if (pId != NULL)
|
||||
{
|
||||
for (int i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultCaptureId)); ++i)
|
||||
for (i = 0; (pId[i] != 0) && (i < STATIC_ARRAY_SIZE(g_DefaultCaptureId)); ++i)
|
||||
g_DefaultCaptureId[i] = pId[i];
|
||||
}
|
||||
}
|
||||
|
|
@ -5226,6 +5268,19 @@ PaError PaWasapi_SetDefaultInterfaceId( unsigned short *pId, int bOutput )
|
|||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData )
|
||||
{
|
||||
PaWasapiStream *stream = (PaWasapiStream *)pStream;
|
||||
if (stream == NULL)
|
||||
return paBadStreamPtr;
|
||||
|
||||
stream->fnStateHandler = fnStateHandler;
|
||||
stream->pStateHandlerUserData = pUserData;
|
||||
|
||||
return paNoError;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
HRESULT _PollGetOutputFramesAvailable(PaWasapiStream *stream, UINT32 *available)
|
||||
{
|
||||
|
|
@ -5453,6 +5508,9 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
|
|||
BOOL bWaitAllEvents = FALSE;
|
||||
BOOL bThreadComInitialized = FALSE;
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadPrepare, ERROR_SUCCESS);
|
||||
|
||||
/*
|
||||
If COM is already initialized CoInitialize will either return
|
||||
FALSE, or RPC_E_CHANGED_MODE if it was initialized in a different
|
||||
|
|
@ -5565,6 +5623,9 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
|
|||
// Notify: thread started
|
||||
SetEvent(stream->hThreadStart);
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadStart, ERROR_SUCCESS);
|
||||
|
||||
// Processing Loop
|
||||
for (;;)
|
||||
{
|
||||
|
|
@ -5632,6 +5693,9 @@ thread_end:
|
|||
// Notify: thread exited
|
||||
SetEvent(stream->hThreadExit);
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadStop, hr);
|
||||
|
||||
return 0;
|
||||
|
||||
thread_error:
|
||||
|
|
@ -5660,6 +5724,9 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
|
|||
|
||||
BOOL bThreadComInitialized = FALSE;
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadPrepare, ERROR_SUCCESS);
|
||||
|
||||
/*
|
||||
If COM is already initialized CoInitialize will either return
|
||||
FALSE, or RPC_E_CHANGED_MODE if it was initialized in a different
|
||||
|
|
@ -5802,6 +5869,9 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
|
|||
// Notify: thread started
|
||||
SetEvent(stream->hThreadStart);
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadStart, ERROR_SUCCESS);
|
||||
|
||||
if (!PA_WASAPI__IS_FULLDUPLEX(stream))
|
||||
{
|
||||
// Processing Loop
|
||||
|
|
@ -6157,6 +6227,9 @@ thread_end:
|
|||
// Notify: thread exited
|
||||
SetEvent(stream->hThreadExit);
|
||||
|
||||
// Notify: state
|
||||
NotifyStateChanged(stream, paWasapiStreamStateThreadStop, hr);
|
||||
|
||||
return 0;
|
||||
|
||||
thread_error:
|
||||
|
|
|
|||
Loading…
Reference in a new issue