- 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:
dmitrykos 2010-07-23 10:04:03 +00:00
commit f2badb7725
4 changed files with 687 additions and 3 deletions

View file

@ -45,4 +45,6 @@ PaWasapi_GetDeviceDefaultFormat @56
PaWasapi_GetDeviceRole @57
PaWasapi_ThreadPriorityBoost @58
PaWasapi_ThreadPriorityRevert @59
PaWasapi_GetFramesPerHostBuffer @60
PaWasapi_GetFramesPerHostBuffer @60
PaWasapi_GetJackDescription @61
PaWasapi_GetJackCount @62

View file

@ -109,6 +109,70 @@ typedef enum 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 */
typedef enum PaWasapiThreadPriority
{
@ -124,6 +188,20 @@ typedef enum 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. */
typedef struct PaWasapiStreamInfo
{
@ -223,6 +301,31 @@ PaError PaWasapi_ThreadPriorityRevert( void *hTask );
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:

View file

@ -53,9 +53,10 @@
#define COBJMACROS
#include <Audioclient.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 <functiondiscoverykeys.h>
#include <devicetopology.h> // Used to get IKsJackDescription interface
#undef INITGUID
#endif
#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);
// "C8ADBD64-E71E-48a0-A4DE-185C395CD317"
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:
__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 );
@ -1422,7 +1429,7 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
// Get API
PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
if (paWasapi == NULL)
return ret;
return paNotInitialized;
// Get device index
ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
@ -3460,6 +3467,235 @@ PaError PaWasapi_ThreadPriorityRevert(void *hTask)
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)
{

343
test/patest_jack_wasapi.c Normal file
View 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;
}