wasapi:
- added functionality to enumerate jacks and their description - added example which demonstrates jacks enumeration technique Thanks Reid Bishop for providing the idea for this extended functionality and patch with implementation.
This commit is contained in:
parent
e540964ffc
commit
f2badb7725
4 changed files with 687 additions and 3 deletions
|
|
@ -45,4 +45,6 @@ PaWasapi_GetDeviceDefaultFormat @56
|
||||||
PaWasapi_GetDeviceRole @57
|
PaWasapi_GetDeviceRole @57
|
||||||
PaWasapi_ThreadPriorityBoost @58
|
PaWasapi_ThreadPriorityBoost @58
|
||||||
PaWasapi_ThreadPriorityRevert @59
|
PaWasapi_ThreadPriorityRevert @59
|
||||||
PaWasapi_GetFramesPerHostBuffer @60
|
PaWasapi_GetFramesPerHostBuffer @60
|
||||||
|
PaWasapi_GetJackDescription @61
|
||||||
|
PaWasapi_GetJackCount @62
|
||||||
|
|
@ -109,6 +109,70 @@ typedef enum PaWasapiDeviceRole
|
||||||
PaWasapiDeviceRole;
|
PaWasapiDeviceRole;
|
||||||
|
|
||||||
|
|
||||||
|
/* Jack connection type */
|
||||||
|
typedef enum PaWasapiJackConnectionType
|
||||||
|
{
|
||||||
|
eJackConnTypeUnknown,
|
||||||
|
eJackConnType3Point5mm,
|
||||||
|
eJackConnTypeQuarter,
|
||||||
|
eJackConnTypeAtapiInternal,
|
||||||
|
eJackConnTypeRCA,
|
||||||
|
eJackConnTypeOptical,
|
||||||
|
eJackConnTypeOtherDigital,
|
||||||
|
eJackConnTypeOtherAnalog,
|
||||||
|
eJackConnTypeMultichannelAnalogDIN,
|
||||||
|
eJackConnTypeXlrProfessional,
|
||||||
|
eJackConnTypeRJ11Modem,
|
||||||
|
eJackConnTypeCombination
|
||||||
|
}
|
||||||
|
PaWasapiJackConnectionType;
|
||||||
|
|
||||||
|
|
||||||
|
/* Jack geometric location */
|
||||||
|
typedef enum PaWasapiJackGeoLocation
|
||||||
|
{
|
||||||
|
eJackGeoLocUnk = 0,
|
||||||
|
eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
|
||||||
|
eJackGeoLocFront,
|
||||||
|
eJackGeoLocLeft,
|
||||||
|
eJackGeoLocRight,
|
||||||
|
eJackGeoLocTop,
|
||||||
|
eJackGeoLocBottom,
|
||||||
|
eJackGeoLocRearPanel,
|
||||||
|
eJackGeoLocRiser,
|
||||||
|
eJackGeoLocInsideMobileLid,
|
||||||
|
eJackGeoLocDrivebay,
|
||||||
|
eJackGeoLocHDMI,
|
||||||
|
eJackGeoLocOutsideMobileLid,
|
||||||
|
eJackGeoLocATAPI,
|
||||||
|
eJackGeoLocReserved5,
|
||||||
|
eJackGeoLocReserved6,
|
||||||
|
}
|
||||||
|
PaWasapiJackGeoLocation;
|
||||||
|
|
||||||
|
|
||||||
|
/* Jack general location */
|
||||||
|
typedef enum PaWasapiJackGenLocation
|
||||||
|
{
|
||||||
|
eJackGenLocPrimaryBox = 0,
|
||||||
|
eJackGenLocInternal,
|
||||||
|
eJackGenLocSeparate,
|
||||||
|
eJackGenLocOther
|
||||||
|
}
|
||||||
|
PaWasapiJackGenLocation;
|
||||||
|
|
||||||
|
|
||||||
|
/* Jack's type of port */
|
||||||
|
typedef enum PaWasapiJackPortConnection
|
||||||
|
{
|
||||||
|
eJackPortConnJack = 0,
|
||||||
|
eJackPortConnIntegratedDevice,
|
||||||
|
eJackPortConnBothIntegratedAndJack,
|
||||||
|
eJackPortConnUnknown
|
||||||
|
}
|
||||||
|
PaWasapiJackPortConnection;
|
||||||
|
|
||||||
|
|
||||||
/* Thread priority */
|
/* Thread priority */
|
||||||
typedef enum PaWasapiThreadPriority
|
typedef enum PaWasapiThreadPriority
|
||||||
{
|
{
|
||||||
|
|
@ -124,6 +188,20 @@ typedef enum PaWasapiThreadPriority
|
||||||
PaWasapiThreadPriority;
|
PaWasapiThreadPriority;
|
||||||
|
|
||||||
|
|
||||||
|
/* Stream descriptor. */
|
||||||
|
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))) */
|
||||||
|
PaWasapiJackConnectionType connectionType;
|
||||||
|
PaWasapiJackGeoLocation geoLocation;
|
||||||
|
PaWasapiJackGenLocation genLocation;
|
||||||
|
PaWasapiJackPortConnection portConnection;
|
||||||
|
unsigned int isConnected;
|
||||||
|
}
|
||||||
|
PaWasapiJackDescription;
|
||||||
|
|
||||||
|
|
||||||
/* Stream descriptor. */
|
/* Stream descriptor. */
|
||||||
typedef struct PaWasapiStreamInfo
|
typedef struct PaWasapiStreamInfo
|
||||||
{
|
{
|
||||||
|
|
@ -223,6 +301,31 @@ PaError PaWasapi_ThreadPriorityRevert( void *hTask );
|
||||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
|
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
|
||||||
|
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
@param nDevice device index.
|
||||||
|
@param jcount Number of jacks is returned in this variable
|
||||||
|
@return Error code indicating success or failure
|
||||||
|
@see PaWasapi_GetJackDescription
|
||||||
|
*/
|
||||||
|
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
|
||||||
|
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
description.
|
||||||
|
@param nDevice device index.
|
||||||
|
@param jindex Which jack to return information
|
||||||
|
@param KSJACK_DESCRIPTION This structure filled in on success.
|
||||||
|
@return Error code indicating success or failure
|
||||||
|
@see PaWasapi_GetJackCount
|
||||||
|
*/
|
||||||
|
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IMPORTANT:
|
IMPORTANT:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,10 @@
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#include <Audioclient.h>
|
#include <Audioclient.h>
|
||||||
#include <endpointvolume.h>
|
#include <endpointvolume.h>
|
||||||
#define INITGUID //<< avoid additional linkage of static libs, uneeded code will be optimized out
|
#define INITGUID // Avoid additional linkage of static libs, excessive code will be optimized out by the compiler
|
||||||
#include <mmdeviceapi.h>
|
#include <mmdeviceapi.h>
|
||||||
#include <functiondiscoverykeys.h>
|
#include <functiondiscoverykeys.h>
|
||||||
|
#include <devicetopology.h> // Used to get IKsJackDescription interface
|
||||||
#undef INITGUID
|
#undef INITGUID
|
||||||
#endif
|
#endif
|
||||||
#ifndef __MWERKS__
|
#ifndef __MWERKS__
|
||||||
|
|
@ -275,6 +276,12 @@ PA_DEFINE_CLSID(IMMDeviceEnumerator,bcde0395, e52f, 467c, 8e, 3d, c4, 57, 92, 91
|
||||||
PA_DEFINE_IID(IAudioRenderClient, f294acfc, 3146, 4483, a7, bf, ad, dc, a7, c2, 60, e2);
|
PA_DEFINE_IID(IAudioRenderClient, f294acfc, 3146, 4483, a7, bf, ad, dc, a7, c2, 60, e2);
|
||||||
// "C8ADBD64-E71E-48a0-A4DE-185C395CD317"
|
// "C8ADBD64-E71E-48a0-A4DE-185C395CD317"
|
||||||
PA_DEFINE_IID(IAudioCaptureClient, c8adbd64, e71e, 48a0, a4, de, 18, 5c, 39, 5c, d3, 17);
|
PA_DEFINE_IID(IAudioCaptureClient, c8adbd64, e71e, 48a0, a4, de, 18, 5c, 39, 5c, d3, 17);
|
||||||
|
// *2A07407E-6497-4A18-9787-32F79BD0D98F* Or this??
|
||||||
|
PA_DEFINE_IID(IDeviceTopology, 2A07407E, 6497, 4A18, 97, 87, 32, f7, 9b, d0, d9, 8f);
|
||||||
|
// *AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9*
|
||||||
|
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:
|
// Media formats:
|
||||||
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
|
__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 );
|
__DEFINE_GUID(pa_KSDATAFORMAT_SUBTYPE_ADPCM, 0x00000002, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
|
||||||
|
|
@ -1422,7 +1429,7 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
|
||||||
// Get API
|
// Get API
|
||||||
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
|
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
|
||||||
if (paWasapi == NULL)
|
if (paWasapi == NULL)
|
||||||
return ret;
|
return paNotInitialized;
|
||||||
|
|
||||||
// Get device index
|
// Get device index
|
||||||
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||||
|
|
@ -3460,6 +3467,235 @@ PaError PaWasapi_ThreadPriorityRevert(void *hTask)
|
||||||
return paNoError;
|
return paNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
// Described at:
|
||||||
|
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
|
||||||
|
|
||||||
|
PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount)
|
||||||
|
{
|
||||||
|
PaError ret;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
PaDeviceIndex index;
|
||||||
|
IDeviceTopology *pDeviceTopology = NULL;
|
||||||
|
IConnector *pConnFrom = NULL;
|
||||||
|
IConnector *pConnTo = NULL;
|
||||||
|
IPart *pPart = NULL;
|
||||||
|
IKsJackDescription *pJackDesc = NULL;
|
||||||
|
UINT jackCount = 0;
|
||||||
|
|
||||||
|
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
|
||||||
|
if (paWasapi == NULL)
|
||||||
|
return paNotInitialized;
|
||||||
|
|
||||||
|
// Get device index.
|
||||||
|
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||||
|
if (ret != paNoError)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// Validate index.
|
||||||
|
if ((UINT32)index >= paWasapi->deviceCount)
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
// 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).
|
||||||
|
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
hr = E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
hr = IPart_Activate(pPart, CLSCTX_INPROC_SERVER, &pa_IID_IKsJackDescription, (void**)&pJackDesc);
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// Return jack count for this device.
|
||||||
|
hr = IKsJackDescription_GetJackCount(pJackDesc, &jackCount);
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// Set.
|
||||||
|
(*jcount) = jackCount;
|
||||||
|
|
||||||
|
// Ok.
|
||||||
|
ret = paNoError;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
SAFE_RELEASE(pDeviceTopology);
|
||||||
|
SAFE_RELEASE(pConnFrom);
|
||||||
|
SAFE_RELEASE(pConnTo);
|
||||||
|
SAFE_RELEASE(pPart);
|
||||||
|
SAFE_RELEASE(pJackDesc);
|
||||||
|
|
||||||
|
LogHostError(hr);
|
||||||
|
return paNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
static PaWasapiJackConnectionType ConvertJackConnectionTypeWASAPIToPA(int connType)
|
||||||
|
{
|
||||||
|
switch (connType)
|
||||||
|
{
|
||||||
|
case eConnTypeUnknown: return eJackConnTypeUnknown;
|
||||||
|
case eConnType3Point5mm: return eJackConnType3Point5mm;
|
||||||
|
case eConnTypeQuarter: return eJackConnTypeQuarter;
|
||||||
|
case eConnTypeAtapiInternal: return eJackConnTypeAtapiInternal;
|
||||||
|
case eConnTypeRCA: return eJackConnTypeRCA;
|
||||||
|
case eConnTypeOptical: return eJackConnTypeOptical;
|
||||||
|
case eConnTypeOtherDigital: return eJackConnTypeOtherDigital;
|
||||||
|
case eConnTypeOtherAnalog: return eJackConnTypeOtherAnalog;
|
||||||
|
case eConnTypeMultichannelAnalogDIN: return eJackConnTypeMultichannelAnalogDIN;
|
||||||
|
case eConnTypeXlrProfessional: return eJackConnTypeXlrProfessional;
|
||||||
|
case eConnTypeRJ11Modem: return eJackConnTypeRJ11Modem;
|
||||||
|
case eConnTypeCombination: return eJackConnTypeCombination;
|
||||||
|
}
|
||||||
|
return eJackConnTypeUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
static PaWasapiJackGeoLocation ConvertJackGeoLocationWASAPIToPA(int geoLoc)
|
||||||
|
{
|
||||||
|
switch (geoLoc)
|
||||||
|
{
|
||||||
|
case eGeoLocRear: return eJackGeoLocRear;
|
||||||
|
case eGeoLocFront: return eJackGeoLocFront;
|
||||||
|
case eGeoLocLeft: return eJackGeoLocLeft;
|
||||||
|
case eGeoLocRight: return eJackGeoLocRight;
|
||||||
|
case eGeoLocTop: return eJackGeoLocTop;
|
||||||
|
case eGeoLocBottom: return eJackGeoLocBottom;
|
||||||
|
case eGeoLocRearPanel: return eJackGeoLocRearPanel;
|
||||||
|
case eGeoLocRiser: return eJackGeoLocRiser;
|
||||||
|
case eGeoLocInsideMobileLid: return eJackGeoLocInsideMobileLid;
|
||||||
|
case eGeoLocDrivebay: return eJackGeoLocDrivebay;
|
||||||
|
case eGeoLocHDMI: return eJackGeoLocHDMI;
|
||||||
|
case eGeoLocOutsideMobileLid: return eJackGeoLocOutsideMobileLid;
|
||||||
|
case eGeoLocATAPI: return eJackGeoLocATAPI;
|
||||||
|
}
|
||||||
|
return eJackGeoLocUnk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
static PaWasapiJackGenLocation ConvertJackGenLocationWASAPIToPA(int genLoc)
|
||||||
|
{
|
||||||
|
switch (genLoc)
|
||||||
|
{
|
||||||
|
case eGenLocPrimaryBox: return eJackGenLocPrimaryBox;
|
||||||
|
case eGenLocInternal: return eJackGenLocInternal;
|
||||||
|
case eGenLocSeparate: return eJackGenLocSeparate;
|
||||||
|
case eGenLocOther: return eJackGenLocOther;
|
||||||
|
}
|
||||||
|
return eJackGenLocPrimaryBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
static PaWasapiJackPortConnection ConvertJackPortConnectionWASAPIToPA(int portConn)
|
||||||
|
{
|
||||||
|
switch (portConn)
|
||||||
|
{
|
||||||
|
case ePortConnJack: return eJackPortConnJack;
|
||||||
|
case ePortConnIntegratedDevice: return eJackPortConnIntegratedDevice;
|
||||||
|
case ePortConnBothIntegratedAndJack:return eJackPortConnBothIntegratedAndJack;
|
||||||
|
case ePortConnUnknown: return eJackPortConnUnknown;
|
||||||
|
}
|
||||||
|
return eJackPortConnJack;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------
|
||||||
|
// Described at:
|
||||||
|
// http://msdn.microsoft.com/en-us/library/dd371387(v=VS.85).aspx
|
||||||
|
|
||||||
|
PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription)
|
||||||
|
{
|
||||||
|
PaError ret;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
PaDeviceIndex index;
|
||||||
|
IDeviceTopology *pDeviceTopology = NULL;
|
||||||
|
IConnector *pConnFrom = NULL;
|
||||||
|
IConnector *pConnTo = NULL;
|
||||||
|
IPart *pPart = NULL;
|
||||||
|
IKsJackDescription *pJackDesc = NULL;
|
||||||
|
KSJACK_DESCRIPTION jack = { 0 };
|
||||||
|
|
||||||
|
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
|
||||||
|
if (paWasapi == NULL)
|
||||||
|
return paNotInitialized;
|
||||||
|
|
||||||
|
// Get device index.
|
||||||
|
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
|
||||||
|
if (ret != paNoError)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// Validate index.
|
||||||
|
if ((UINT32)index >= paWasapi->deviceCount)
|
||||||
|
return paInvalidDevice;
|
||||||
|
|
||||||
|
// 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).
|
||||||
|
hr = IDeviceTopology_GetConnector(pDeviceTopology, 0, &pConnFrom);
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
hr = E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
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);
|
||||||
|
IF_FAILED_JUMP(hr, error);
|
||||||
|
|
||||||
|
// Convert WASAPI values to PA format.
|
||||||
|
pJackDescription->channelMapping = jack.ChannelMapping;
|
||||||
|
pJackDescription->color = jack.Color;
|
||||||
|
pJackDescription->connectionType = ConvertJackConnectionTypeWASAPIToPA(jack.ConnectionType);
|
||||||
|
pJackDescription->genLocation = ConvertJackGenLocationWASAPIToPA(jack.GenLocation);
|
||||||
|
pJackDescription->geoLocation = ConvertJackGeoLocationWASAPIToPA(jack.GeoLocation);
|
||||||
|
pJackDescription->isConnected = jack.IsConnected;
|
||||||
|
pJackDescription->portConnection = ConvertJackPortConnectionWASAPIToPA(jack.PortConnection);
|
||||||
|
|
||||||
|
// Ok.
|
||||||
|
ret = paNoError;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
SAFE_RELEASE(pDeviceTopology);
|
||||||
|
SAFE_RELEASE(pConnFrom);
|
||||||
|
SAFE_RELEASE(pConnTo);
|
||||||
|
SAFE_RELEASE(pPart);
|
||||||
|
SAFE_RELEASE(pJackDesc);
|
||||||
|
|
||||||
|
LogHostError(hr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor *processor, UINT32 frames)
|
static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor *processor, UINT32 frames)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
343
test/patest_jack_wasapi.c
Normal file
343
test/patest_jack_wasapi.c
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
/** @file pa_test_jack_wasapi.c
|
||||||
|
@ingroup test_src
|
||||||
|
@brief Print out jack information for WASAPI endpoints
|
||||||
|
@author Reid Bishop <rbish@attglobal.net>
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* $Id: pa_test_jack_wasapi.c 1368 2008-03-01 00:38:27Z rbishop $
|
||||||
|
*
|
||||||
|
* This program uses the PortAudio Portable Audio Library.
|
||||||
|
* For more information see: http://www.portaudio.com/
|
||||||
|
* Copyright (c) 1999-2010 Ross Bencina and Phil Burk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files
|
||||||
|
* (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||||
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||||
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* license above.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "portaudio.h"
|
||||||
|
#include "pa_win_wasapi.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to determine if a given enum is present in mask variable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int IsInMask(int val, int val2)
|
||||||
|
{
|
||||||
|
return ((val & val2) == val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine enumerates through the ChannelMapping for the IJackDescription
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void EnumIJackChannels(int channelMapping)
|
||||||
|
{
|
||||||
|
printf("Channel Mapping: ");
|
||||||
|
if(channelMapping == PAWIN_SPEAKER_DIRECTOUT)
|
||||||
|
{
|
||||||
|
printf("DIRECTOUT\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_LEFT))
|
||||||
|
printf("FRONT_LEFT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_RIGHT))
|
||||||
|
printf("FRONT_RIGHT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_CENTER))
|
||||||
|
printf("FRONT_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_LOW_FREQUENCY))
|
||||||
|
printf("LOW_FREQUENCY, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_BACK_LEFT))
|
||||||
|
printf("BACK_LEFT, ");
|
||||||
|
if(IsInMask(channelMapping,PAWIN_SPEAKER_BACK_RIGHT))
|
||||||
|
printf("BACK_RIGHT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER))
|
||||||
|
printf("FRONT_LEFT_OF_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER))
|
||||||
|
printf("FRONT_RIGHT_OF_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_BACK_CENTER))
|
||||||
|
printf("BACK_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping,PAWIN_SPEAKER_SIDE_LEFT))
|
||||||
|
printf("SIDE_LEFT, ");
|
||||||
|
if(IsInMask(channelMapping,PAWIN_SPEAKER_SIDE_RIGHT))
|
||||||
|
printf("SIDE_RIGHT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_CENTER))
|
||||||
|
printf("TOP_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_LEFT))
|
||||||
|
printf("TOP_FRONT_LEFT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_CENTER))
|
||||||
|
printf("TOP_FRONT_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_RIGHT))
|
||||||
|
printf("TOP_FRONT_RIGHT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_LEFT))
|
||||||
|
printf("TOP_BACK_LEFT, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_CENTER))
|
||||||
|
printf("TOP_BACK_CENTER, ");
|
||||||
|
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_RIGHT))
|
||||||
|
printf("TOP_BACK_RIGHT, ");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine enumerates through the Jack Connection Types enums for IJackDescription
|
||||||
|
*/
|
||||||
|
static void EnumIJackConnectionType(int cType)
|
||||||
|
{
|
||||||
|
printf("Connection Type: ");
|
||||||
|
switch(cType)
|
||||||
|
{
|
||||||
|
case eJackConnTypeUnknown:
|
||||||
|
printf("eJackConnTypeUnknown");
|
||||||
|
break;
|
||||||
|
case eJackConnType3Point5mm:
|
||||||
|
printf("eJackConnType3Point5mm");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeQuarter:
|
||||||
|
printf("eJackConnTypeQuarter");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeAtapiInternal:
|
||||||
|
printf("eJackConnTypeAtapiInternal");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeRCA:
|
||||||
|
printf("eJackConnTypeRCA");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeOptical:
|
||||||
|
printf("eJackConnTypeOptical");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeOtherDigital:
|
||||||
|
printf("eJackConnTypeOtherDigital");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeOtherAnalog:
|
||||||
|
printf("eJackConnTypeOtherAnalog");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeMultichannelAnalogDIN:
|
||||||
|
printf("eJackConnTypeMultichannelAnalogDIN");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeXlrProfessional:
|
||||||
|
printf("eJackConnTypeXlrProfessional");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeRJ11Modem:
|
||||||
|
printf("eJackConnTypeRJ11Modem");
|
||||||
|
break;
|
||||||
|
case eJackConnTypeCombination:
|
||||||
|
printf("eJackConnTypeCombination");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine enumerates through the GeoLocation enums for the IJackDescription
|
||||||
|
*/
|
||||||
|
static void EnumIJackGeoLocation(int iVal)
|
||||||
|
{
|
||||||
|
printf("Geometric Location: ");
|
||||||
|
switch(iVal)
|
||||||
|
{
|
||||||
|
case eJackGeoLocRear:
|
||||||
|
printf("eJackGeoLocRear");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocFront:
|
||||||
|
printf("eJackGeoLocFront");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocLeft:
|
||||||
|
printf("eJackGeoLocLeft");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocRight:
|
||||||
|
printf("eJackGeoLocRight");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocTop:
|
||||||
|
printf("eJackGeoLocTop");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocBottom:
|
||||||
|
printf("eJackGeoLocBottom");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocRearPanel:
|
||||||
|
printf("eJackGeoLocRearPanel");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocRiser:
|
||||||
|
printf("eJackGeoLocRiser");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocInsideMobileLid:
|
||||||
|
printf("eJackGeoLocInsideMobileLid");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocDrivebay:
|
||||||
|
printf("eJackGeoLocDrivebay");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocHDMI:
|
||||||
|
printf("eJackGeoLocHDMI");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocOutsideMobileLid:
|
||||||
|
printf("eJackGeoLocOutsideMobileLid");
|
||||||
|
break;
|
||||||
|
case eJackGeoLocATAPI:
|
||||||
|
printf("eJackGeoLocATAPI");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine enumerates through the GenLocation enums for the IJackDescription
|
||||||
|
*/
|
||||||
|
static void EnumIJackGenLocation(int iVal)
|
||||||
|
{
|
||||||
|
printf("General Location: ");
|
||||||
|
switch(iVal)
|
||||||
|
{
|
||||||
|
case eJackGenLocPrimaryBox:
|
||||||
|
printf("eJackGenLocPrimaryBox");
|
||||||
|
break;
|
||||||
|
case eJackGenLocInternal:
|
||||||
|
printf("eJackGenLocInternal");
|
||||||
|
break;
|
||||||
|
case eJackGenLocSeparate:
|
||||||
|
printf("eJackGenLocSeparate");
|
||||||
|
break;
|
||||||
|
case eJackGenLocOther:
|
||||||
|
printf("eJackGenLocOther");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine enumerates through the PortConnection enums for the IJackDescription
|
||||||
|
*/
|
||||||
|
static void EnumIJackPortConnection(int iVal)
|
||||||
|
{
|
||||||
|
printf("Port Type: ");
|
||||||
|
switch(iVal)
|
||||||
|
{
|
||||||
|
case eJackPortConnJack:
|
||||||
|
printf("eJackPortConnJack");
|
||||||
|
break;
|
||||||
|
case eJackPortConnIntegratedDevice:
|
||||||
|
printf("eJackPortConnIntegratedDevice");
|
||||||
|
break;
|
||||||
|
case eJackPortConnBothIntegratedAndJack:
|
||||||
|
printf("eJackPortConnBothIntegratedAndJack");
|
||||||
|
break;
|
||||||
|
case eJackPortConnUnknown:
|
||||||
|
printf("eJackPortConnUnknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine retrieves and parses the KSJACK_DESCRIPTION structure for
|
||||||
|
* the provided device ID.
|
||||||
|
*/
|
||||||
|
static PaError GetJackInformation(int deviceId)
|
||||||
|
{
|
||||||
|
PaError err;
|
||||||
|
int i;
|
||||||
|
int jackCount = 0;
|
||||||
|
PaWasapiJackDescription jackDesc;
|
||||||
|
|
||||||
|
err = PaWasapi_GetJackCount(deviceId, &jackCount);
|
||||||
|
if( err != paNoError ) return err;
|
||||||
|
|
||||||
|
fprintf( stderr,"Number of Jacks: %d \n", jackCount );
|
||||||
|
|
||||||
|
for( i = 0; i<jackCount; i++ )
|
||||||
|
{
|
||||||
|
fprintf( stderr,"Jack #%d:\n", i );
|
||||||
|
|
||||||
|
err = PaWasapi_GetJackDescription(deviceId, i, &jackDesc);
|
||||||
|
if( err != paNoError )
|
||||||
|
{
|
||||||
|
fprintf( stderr,"Failed getting description." );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Is connected: %s\n",(jackDesc.isConnected)?"true":"false");
|
||||||
|
EnumIJackChannels(jackDesc.channelMapping);
|
||||||
|
EnumIJackConnectionType(jackDesc.connectionType);
|
||||||
|
EnumIJackGeoLocation(jackDesc.geoLocation);
|
||||||
|
EnumIJackGenLocation(jackDesc.genLocation);
|
||||||
|
EnumIJackPortConnection(jackDesc.portConnection);
|
||||||
|
printf("Jack Color: 0x%06X\n", jackDesc.color);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
int main(void);
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
PaError err;
|
||||||
|
const PaDeviceInfo *device;
|
||||||
|
int i;
|
||||||
|
int jackCount = 0;
|
||||||
|
int isInput = 0;
|
||||||
|
|
||||||
|
printf("PortAudio Test: WASAPI Jack Configuratin");
|
||||||
|
err = Pa_Initialize();
|
||||||
|
if( err != paNoError ) goto error;
|
||||||
|
|
||||||
|
/* Find all WASAPI devices */
|
||||||
|
for( i = 0; i < Pa_GetDeviceCount(); ++i )
|
||||||
|
{
|
||||||
|
device = Pa_GetDeviceInfo(i);
|
||||||
|
if( Pa_GetDeviceInfo(i)->hostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI) )
|
||||||
|
{
|
||||||
|
if( device->maxOutputChannels == 0 )
|
||||||
|
{
|
||||||
|
isInput = 1;
|
||||||
|
}
|
||||||
|
printf("------------------------------------------\n");
|
||||||
|
printf("Device: %s",device->name);
|
||||||
|
if(isInput)
|
||||||
|
printf(" (Input) %d Channels\n",device->maxInputChannels);
|
||||||
|
else
|
||||||
|
printf(" (Output) %d Channels\n",device->maxOutputChannels);
|
||||||
|
// Try to see if this WASAPI device can provide Jack information
|
||||||
|
err = GetJackInformation(i);
|
||||||
|
if( err != paNoError ) goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pa_Terminate();
|
||||||
|
printf("Test finished.\n");
|
||||||
|
return err;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Pa_Terminate();
|
||||||
|
fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
||||||
|
fprintf( stderr, "Error number: %d\n", err );
|
||||||
|
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
||||||
|
return err;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue