cannam@89: #ifndef PA_WIN_WASAPI_H cannam@89: #define PA_WIN_WASAPI_H cannam@89: /* cannam@89: * $Id: $ cannam@89: * PortAudio Portable Real-Time Audio Library cannam@89: * DirectSound specific extensions cannam@89: * cannam@89: * Copyright (c) 1999-2007 Ross Bencina and Phil Burk cannam@89: * cannam@89: * Permission is hereby granted, free of charge, to any person obtaining cannam@89: * a copy of this software and associated documentation files cannam@89: * (the "Software"), to deal in the Software without restriction, cannam@89: * including without limitation the rights to use, copy, modify, merge, cannam@89: * publish, distribute, sublicense, and/or sell copies of the Software, cannam@89: * and to permit persons to whom the Software is furnished to do so, cannam@89: * subject to the following conditions: cannam@89: * cannam@89: * The above copyright notice and this permission notice shall be cannam@89: * included in all copies or substantial portions of the Software. cannam@89: * cannam@89: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, cannam@89: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF cannam@89: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. cannam@89: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR cannam@89: * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF cannam@89: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION cannam@89: * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cannam@89: */ cannam@89: cannam@89: /* cannam@89: * The text above constitutes the entire PortAudio license; however, cannam@89: * the PortAudio community also makes the following non-binding requests: cannam@89: * cannam@89: * Any person wishing to distribute modifications to the Software is cannam@89: * requested to send the modifications to the original developer so that cannam@89: * they can be incorporated into the canonical version. It is also cannam@89: * requested that these non-binding requests be included along with the cannam@89: * license above. cannam@89: */ cannam@89: cannam@89: /** @file cannam@89: @ingroup public_header cannam@89: @brief WASAPI-specific PortAudio API extension header file. cannam@89: */ cannam@89: cannam@89: #include "portaudio.h" cannam@89: #include "pa_win_waveformat.h" cannam@89: cannam@89: #ifdef __cplusplus cannam@89: extern "C" cannam@89: { cannam@89: #endif /* __cplusplus */ cannam@89: cannam@89: cannam@89: /* Setup flags */ cannam@89: typedef enum PaWasapiFlags cannam@89: { cannam@89: /* puts WASAPI into exclusive mode */ cannam@89: paWinWasapiExclusive = (1 << 0), cannam@89: cannam@89: /* allows to skip internal PA processing completely */ cannam@89: paWinWasapiRedirectHostProcessor = (1 << 1), cannam@89: cannam@89: /* assigns custom channel mask */ cannam@89: paWinWasapiUseChannelMask = (1 << 2), cannam@89: cannam@89: /* selects non-Event driven method of data read/write cannam@89: Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling cannam@89: method can only provide 15-20ms latency. */ cannam@89: paWinWasapiPolling = (1 << 3), cannam@89: cannam@89: /* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority cannam@89: is set to custom value. */ cannam@89: paWinWasapiThreadPriority = (1 << 4) cannam@89: } cannam@89: PaWasapiFlags; cannam@89: #define paWinWasapiExclusive (paWinWasapiExclusive) cannam@89: #define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor) cannam@89: #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask) cannam@89: #define paWinWasapiPolling (paWinWasapiPolling) cannam@89: #define paWinWasapiThreadPriority (paWinWasapiThreadPriority) cannam@89: cannam@89: cannam@89: /* Host processor. Allows to skip internal PA processing completely. cannam@89: You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member cannam@89: in order to have host processor redirected to your callback. cannam@89: Use with caution! inputFrames and outputFrames depend solely on final device setup. cannam@89: To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer. cannam@89: */ cannam@89: typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames, cannam@89: void *outputBuffer, long outputFrames, cannam@89: void *userData); cannam@89: cannam@89: /* Device role */ cannam@89: typedef enum PaWasapiDeviceRole cannam@89: { cannam@89: eRoleRemoteNetworkDevice = 0, cannam@89: eRoleSpeakers, cannam@89: eRoleLineLevel, cannam@89: eRoleHeadphones, cannam@89: eRoleMicrophone, cannam@89: eRoleHeadset, cannam@89: eRoleHandset, cannam@89: eRoleUnknownDigitalPassthrough, cannam@89: eRoleSPDIF, cannam@89: eRoleHDMI, cannam@89: eRoleUnknownFormFactor cannam@89: } cannam@89: PaWasapiDeviceRole; cannam@89: cannam@89: cannam@89: /* Jack connection type */ cannam@89: typedef enum PaWasapiJackConnectionType cannam@89: { cannam@89: eJackConnTypeUnknown, cannam@89: eJackConnType3Point5mm, cannam@89: eJackConnTypeQuarter, cannam@89: eJackConnTypeAtapiInternal, cannam@89: eJackConnTypeRCA, cannam@89: eJackConnTypeOptical, cannam@89: eJackConnTypeOtherDigital, cannam@89: eJackConnTypeOtherAnalog, cannam@89: eJackConnTypeMultichannelAnalogDIN, cannam@89: eJackConnTypeXlrProfessional, cannam@89: eJackConnTypeRJ11Modem, cannam@89: eJackConnTypeCombination cannam@89: } cannam@89: PaWasapiJackConnectionType; cannam@89: cannam@89: cannam@89: /* Jack geometric location */ cannam@89: typedef enum PaWasapiJackGeoLocation cannam@89: { cannam@89: eJackGeoLocUnk = 0, cannam@89: eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */ cannam@89: eJackGeoLocFront, cannam@89: eJackGeoLocLeft, cannam@89: eJackGeoLocRight, cannam@89: eJackGeoLocTop, cannam@89: eJackGeoLocBottom, cannam@89: eJackGeoLocRearPanel, cannam@89: eJackGeoLocRiser, cannam@89: eJackGeoLocInsideMobileLid, cannam@89: eJackGeoLocDrivebay, cannam@89: eJackGeoLocHDMI, cannam@89: eJackGeoLocOutsideMobileLid, cannam@89: eJackGeoLocATAPI, cannam@89: eJackGeoLocReserved5, cannam@89: eJackGeoLocReserved6, cannam@89: } cannam@89: PaWasapiJackGeoLocation; cannam@89: cannam@89: cannam@89: /* Jack general location */ cannam@89: typedef enum PaWasapiJackGenLocation cannam@89: { cannam@89: eJackGenLocPrimaryBox = 0, cannam@89: eJackGenLocInternal, cannam@89: eJackGenLocSeparate, cannam@89: eJackGenLocOther cannam@89: } cannam@89: PaWasapiJackGenLocation; cannam@89: cannam@89: cannam@89: /* Jack's type of port */ cannam@89: typedef enum PaWasapiJackPortConnection cannam@89: { cannam@89: eJackPortConnJack = 0, cannam@89: eJackPortConnIntegratedDevice, cannam@89: eJackPortConnBothIntegratedAndJack, cannam@89: eJackPortConnUnknown cannam@89: } cannam@89: PaWasapiJackPortConnection; cannam@89: cannam@89: cannam@89: /* Thread priority */ cannam@89: typedef enum PaWasapiThreadPriority cannam@89: { cannam@89: eThreadPriorityNone = 0, cannam@89: eThreadPriorityAudio, //!< Default for Shared mode. cannam@89: eThreadPriorityCapture, cannam@89: eThreadPriorityDistribution, cannam@89: eThreadPriorityGames, cannam@89: eThreadPriorityPlayback, cannam@89: eThreadPriorityProAudio, //!< Default for Exclusive mode. cannam@89: eThreadPriorityWindowManager cannam@89: } cannam@89: PaWasapiThreadPriority; cannam@89: cannam@89: cannam@89: /* Stream descriptor. */ cannam@89: typedef struct PaWasapiJackDescription cannam@89: { cannam@89: unsigned long channelMapping; cannam@89: unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */ cannam@89: PaWasapiJackConnectionType connectionType; cannam@89: PaWasapiJackGeoLocation geoLocation; cannam@89: PaWasapiJackGenLocation genLocation; cannam@89: PaWasapiJackPortConnection portConnection; cannam@89: unsigned int isConnected; cannam@89: } cannam@89: PaWasapiJackDescription; cannam@89: cannam@89: cannam@89: /* Stream descriptor. */ cannam@89: typedef struct PaWasapiStreamInfo cannam@89: { cannam@89: unsigned long size; /**< sizeof(PaWasapiStreamInfo) */ cannam@89: PaHostApiTypeId hostApiType; /**< paWASAPI */ cannam@89: unsigned long version; /**< 1 */ cannam@89: cannam@89: unsigned long flags; /**< collection of PaWasapiFlags */ cannam@89: cannam@89: /* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains cannam@89: paWinWasapiUseChannelMask this allows you to specify which speakers cannam@89: to address in a multichannel stream. Constants for channelMask cannam@89: are specified in pa_win_waveformat.h. Will be used only if cannam@89: paWinWasapiUseChannelMask flag is specified. cannam@89: */ cannam@89: PaWinWaveFormatChannelMask channelMask; cannam@89: cannam@89: /* Delivers raw data to callback obtained from GetBuffer() methods skipping cannam@89: internal PortAudio processing inventory completely. userData parameter will cannam@89: be the same that was passed to Pa_OpenStream method. Will be used only if cannam@89: paWinWasapiRedirectHostProcessor flag is specified. cannam@89: */ cannam@89: PaWasapiHostProcessorCallback hostProcessorOutput; cannam@89: PaWasapiHostProcessorCallback hostProcessorInput; cannam@89: cannam@89: /* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag cannam@89: is specified. cannam@89: cannam@89: Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode) cannam@89: you shall specify same value for threadPriority or othervise one of the values will be used cannam@89: to setup thread priority. cannam@89: */ cannam@89: PaWasapiThreadPriority threadPriority; cannam@89: } cannam@89: PaWasapiStreamInfo; cannam@89: cannam@89: cannam@89: /** Returns default sound format for device. Format is represented by PaWinWaveFormat or cannam@89: WAVEFORMATEXTENSIBLE structure. cannam@89: cannam@89: @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. cannam@89: @param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. cannam@89: @param nDevice Device index. cannam@89: cannam@89: @return Non-negative value indicating the number of bytes copied into format decriptor cannam@89: or, a PaErrorCode (which are always negative) if PortAudio is not initialized cannam@89: or an error is encountered. cannam@89: */ cannam@89: int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice ); cannam@89: cannam@89: cannam@89: /** Returns device role (PaWasapiDeviceRole enum). cannam@89: cannam@89: @param nDevice device index. cannam@89: cannam@89: @return Non-negative value indicating device role or, a PaErrorCode (which are always negative) cannam@89: if PortAudio is not initialized or an error is encountered. cannam@89: */ cannam@89: int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice ); cannam@89: cannam@89: cannam@89: /** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread cannam@89: which makes calls to Pa_WriteStream/Pa_ReadStream. cannam@89: cannam@89: @param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority cannam@89: method to revert thread priority to initial state. cannam@89: cannam@89: @param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying cannam@89: eThreadPriorityNone does nothing. cannam@89: cannam@89: @return Error code indicating success or failure. cannam@89: @see PaWasapi_RevertThreadPriority cannam@89: */ cannam@89: PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass ); cannam@89: cannam@89: cannam@89: /** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread cannam@89: which makes calls to Pa_WriteStream/Pa_ReadStream. cannam@89: cannam@89: @param hTask Task handle obtained by PaWasapi_BoostThreadPriority method. cannam@89: @return Error code indicating success or failure. cannam@89: @see PaWasapi_BoostThreadPriority cannam@89: */ cannam@89: PaError PaWasapi_ThreadPriorityRevert( void *hTask ); cannam@89: cannam@89: cannam@89: /** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which cannam@89: can be locked for operations. Use this method as helper to findout maximal values of cannam@89: inputFrames/outputFrames of PaWasapiHostProcessorCallback. cannam@89: cannam@89: @param pStream Pointer to PaStream to query. cannam@89: @param nInput Pointer to variable to receive number of input frames. Can be NULL. cannam@89: @param nOutput Pointer to variable to receive number of output frames. Can be NULL. cannam@89: @return Error code indicating success or failure. cannam@89: @see PaWasapiHostProcessorCallback cannam@89: */ cannam@89: PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput ); cannam@89: cannam@89: cannam@89: /** Get number of jacks associated with a WASAPI device. Use this method to determine if cannam@89: there are any jacks associated with the provided WASAPI device. Not all audio devices cannam@89: will support this capability. This is valid for both input and output devices. cannam@89: @param nDevice device index. cannam@89: @param jcount Number of jacks is returned in this variable cannam@89: @return Error code indicating success or failure cannam@89: @see PaWasapi_GetJackDescription cannam@89: */ cannam@89: PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount); cannam@89: cannam@89: cannam@89: /** Get the jack description associated with a WASAPI device and jack number cannam@89: Before this function is called, use PaWasapi_GetJackCount to determine the cannam@89: number of jacks associated with device. If jcount is greater than zero, then cannam@89: each jack from 0 to jcount can be queried with this function to get the jack cannam@89: description. cannam@89: @param nDevice device index. cannam@89: @param jindex Which jack to return information cannam@89: @param KSJACK_DESCRIPTION This structure filled in on success. cannam@89: @return Error code indicating success or failure cannam@89: @see PaWasapi_GetJackCount cannam@89: */ cannam@89: PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription); cannam@89: cannam@89: cannam@89: /* cannam@89: IMPORTANT: cannam@89: cannam@89: WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive cannam@89: share modes. cannam@89: cannam@89: Exclusive Mode: cannam@89: cannam@89: Exclusive mode allows to deliver audio data directly to hardware bypassing cannam@89: software mixing. cannam@89: Exclusive mode is specified by 'paWinWasapiExclusive' flag. cannam@89: cannam@89: Callback Interface: cannam@89: cannam@89: Provides best audio quality with low latency. Callback interface is implemented in cannam@89: two versions: cannam@89: cannam@89: 1) Event-Driven: cannam@89: This is the most powerful WASAPI implementation which provides glitch-free cannam@89: audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is cannam@89: 3 ms for HD Audio class audio chips. For the Shared mode latency can not be cannam@89: lower than 20 ms. cannam@89: cannam@89: 2) Poll-Driven: cannam@89: Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven cannam@89: and provides latency at around 10-13ms. Polling must be used to overcome a system bug cannam@89: under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply cannam@89: times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug cannam@89: does not exist in Vista x86 or Windows 7. cannam@89: Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects cannam@89: WOW64 bug and sets 'paWinWasapiPolling' automatically. cannam@89: cannam@89: Thread priority: cannam@89: cannam@89: Normally thread priority is set automatically and does not require modification. Although cannam@89: if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority' cannam@89: flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority cannam@89: enum. cannam@89: cannam@89: Blocking Interface: cannam@89: cannam@89: Blocking interface is implemented but due to above described Poll-Driven method can not cannam@89: deliver lowest possible latency. Specifying too low latency in Shared mode will result in cannam@89: distorted audio although Exclusive mode adds stability. cannam@89: cannam@89: Pa_IsFormatSupported: cannam@89: cannam@89: To check format with correct Share Mode (Exclusive/Shared) you must supply cannam@89: PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of cannam@89: PaStreamParameters::hostApiSpecificStreamInfo structure. cannam@89: cannam@89: Pa_OpenStream: cannam@89: cannam@89: To set desired Share Mode (Exclusive/Shared) you must supply cannam@89: PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of cannam@89: PaStreamParameters::hostApiSpecificStreamInfo structure. cannam@89: */ cannam@89: cannam@89: #ifdef __cplusplus cannam@89: } cannam@89: #endif /* __cplusplus */ cannam@89: cannam@89: #endif /* PA_WIN_WASAPI_H */