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_ThreadPriorityBoost @58
|
||||
PaWasapi_ThreadPriorityRevert @59
|
||||
PaWasapi_GetFramesPerHostBuffer @60
|
||||
PaWasapi_GetFramesPerHostBuffer @60
|
||||
PaWasapi_GetJackDescription @61
|
||||
PaWasapi_GetJackCount @62
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
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