I need to get the Jack Information of the Audio Device in MS Windows 7 using C# , C++ or any .NET framework.
I checked NAudio framework but seems is impossible to use it in this case. Also those links are not usefull https://msdn.microsoft.com/en-us/library/windows/desktop/dd370793(v=vs.85).aspx and https://msdn.microsoft.com/en-us/library/windows/desktop/dd370812(v=vs.85).aspx.
And this approach doesn't help as well.
ManagementObjectSearcher objSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_SoundDevice");
ManagementObjectCollection objCollection = objSearcher.Get();
foreach (ManagementObject obj in objCollection)
{
foreach (PropertyData property in obj.Properties)
{
Debug.WriteLine(String.Format("{0}:{1}", property.Name, property.Value));
}
}
Any clue how to get this info or at least some MSDN refernece to that property?
P.S. Here is C++ code to obtaim similar properties of Audio Device that I use but cannot get how to get Jack Information
#pragma once
#include "Mmdeviceapi.h"
#include "PolicyConfig.h"
#include "Propidl.h"
#include "NotificationClient.h"
#include "AudioDevice.h"
namespace AudioDeviceUtil {
ref class MmDeviceApiWrapper
{
public:
MmDeviceApiWrapper(void)
{
//.Net threads are coinitialized...
//CoInitializeEx(NULL, COINIT_MULTITHREADED);
notificationRegistered = false;
audioDeviceNotificationHelper = gcnew AudioDeviceNotificationHelper();
pNotifyClient = NULL;
}
virtual ~MmDeviceApiWrapper(void)
{
//CoUninitialize();
if (notificationRegistered)
RegisterForNotification(false);
}
static property AudioDeviceNotificationHelper^ AudioDeviceNotification
{
AudioDeviceNotificationHelper^ get()
{
return audioDeviceNotificationHelper;
}
};
static property bool IsRegisteredForNotification
{
bool get()
{
return notificationRegistered;
}
}
// Enumerates playback device list and marks the default device by the appropriate flag
static System::Collections::Generic::List<AudioDevice^>^ GetPlaybackDeviceList()
{
System::Collections::Generic::List<AudioDevice^>^ playbackDevices =
gcnew System::Collections::Generic::List<AudioDevice^>();
HRESULT hr = S_OK;//CoInitialize(NULL);
HRESULT hr2 = S_OK;
//HRESULT hr3 = S_OK;
if (SUCCEEDED(hr))
{
IMMDeviceEnumerator *pEnum = NULL;
// Create a multimedia device enumerator.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum);
if (SUCCEEDED(hr))
{
IMMDevice *pDevice;
IMMDeviceCollection *pDevices;
LPWSTR wstrDefaultID = L"";
// Enumerate the output devices.
hr = pEnum->EnumAudioEndpoints(eRender,
DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED | DEVICE_STATE_DISABLED, &pDevices);
if (SUCCEEDED(hr))
{
HRESULT hrDef = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
if (SUCCEEDED(hrDef))
{
hrDef = pDevice->GetId(&wstrDefaultID);
}
System::Diagnostics::Trace::WriteLineIf(!SUCCEEDED(hrDef),
System::String::Format("[MmDeviceApiWrapper] GetDefaultAudioEndPoint failed: {0:X}", hr), "Error");
}
if (SUCCEEDED(hr))
{
UINT count;
pDevices->GetCount(&count);
if (SUCCEEDED(hr))
{
for (unsigned int i = 0; i < count; i++)
{
hr = pDevices->Item(i, &pDevice);
if (SUCCEEDED(hr))
{
LPWSTR wstrID = NULL;
DWORD dwState = 0;
hr = pDevice->GetId(&wstrID);
hr2 = pDevice->GetState(&dwState);
if (SUCCEEDED(hr) && SUCCEEDED(hr2))
{
IPropertyStore *pStore;
hr = pDevice->OpenPropertyStore(STGM_READ, &pStore);
if (SUCCEEDED(hr))
{
//PROPVARIANT jackSubType;
//PropVariantInit(&jackSubType);
//hr3 = pStore->GetValue(PKEY_Device_JackSubType, &jackSubType);
//
PROPVARIANT friendlyName;
PropVariantInit(&friendlyName);
hr = pStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
if (SUCCEEDED(hr))
{
System::String^ name = gcnew System::String(friendlyName.pwszVal);
playbackDevices->Add(gcnew AudioDevice(gcnew System::String(wstrID),
name, (AudioDeviceStateType)dwState, 0 == wcscmp(wstrID, wstrDefaultID)));
PropVariantClear(&friendlyName);
}
/*if (SUCCEEDED(hr3))
{
PropVariantClear(&jackSubType);
}*/
pStore->Release();
}
}
System::Diagnostics::Trace::WriteLineIf(!(SUCCEEDED(hr) && SUCCEEDED(hr2)),
System::String::Format("[MmDeviceApiWrapper] GetID or GetState failed: {0:X}", hr), "Error");
pDevice->Release();
}
}
}
pDevices->Release();
}
pEnum->Release();
}
}
System::Diagnostics::Trace::WriteLineIf(!(SUCCEEDED(hr) && SUCCEEDED(hr2)),
System::String::Format("[MmDeviceApiWrapper] Error: GetPlaybackDeviceList failed: {0:X}, {1:X}", hr, hr2), "Error");
//CoUninitialize();
return playbackDevices;
}
// Get default playback device on the system
static AudioDevice^ GetDefaultPlaybackDevice()
{
AudioDevice^ defaultPlaybackDevice = nullptr;
HRESULT hr = S_OK;//CoInitialize(NULL);
//HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr2 = S_OK;
if (SUCCEEDED(hr))
{
IMMDeviceEnumerator *pEnum = NULL;
// Create a multimedia device enumerator.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum);
if (SUCCEEDED(hr))
{
IMMDevice *pDevice;
// Enumerate the output devices.
hr = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
LPWSTR wstrID = NULL;
hr = pDevice->GetId(&wstrID);
DWORD dwState = 0;
hr2 = pDevice->GetState(&dwState);
if (SUCCEEDED(hr) && SUCCEEDED(hr2))
{
IPropertyStore *pStore;
hr = pDevice->OpenPropertyStore(STGM_READ, &pStore);
if (SUCCEEDED(hr))
{
PROPVARIANT friendlyName;
PropVariantInit(&friendlyName);
hr = pStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
if (SUCCEEDED(hr))
{
defaultPlaybackDevice = gcnew AudioDevice(
gcnew System::String(friendlyName.pwszVal), gcnew System::String(wstrID),
(AudioDeviceStateType)dwState, true);
}
PropVariantClear(&friendlyName);
}
pStore->Release();
}
pDevice->Release();
}
}
System::Diagnostics::Trace::WriteLineIf(!(SUCCEEDED(hr) && SUCCEEDED(hr2)),
System::String::Format("[MmDeviceApiWrapper] Error: GetDefaultPlaybackDevice failed: {0:X}, {1:X}", hr, hr2), "Error");
//CoUninitialize();
return defaultPlaybackDevice;
}
// Set default playback device on the system
// returns true if succeeded.
static bool SetDefaultPlaybackDevice(LPCWSTR devIDString)
{
IPolicyConfigVista *pPolicyConfig;
ERole reserved = eConsole;
HRESULT hr = CoCreateInstance(__uuidof(CPolicyConfigVistaClient),
NULL, CLSCTX_ALL, __uuidof(IPolicyConfigVista), (LPVOID *)&pPolicyConfig);
System::Diagnostics::Trace::WriteLineIf(!SUCCEEDED(hr),
System::String::Format("[MmDeviceApiWrapper] SetDefaultPlaybackDevice CoCreate failed: {0:X}", hr), "Error");
if (SUCCEEDED(hr))
{
System::Diagnostics::Trace::WriteLine(
System::String::Format("[MmDeviceApiWrapper] SetDefaultPlaybackDevice to devId {0}", gcnew System::String(devIDString)), "Information");
hr = pPolicyConfig->SetDefaultEndpoint(devIDString, reserved);
System::Diagnostics::Trace::WriteLineIf(SUCCEEDED(hr),
System::String::Format("[MmDeviceApiWrapper] SetDefaultPlaybackDevice SetDefEndPoint succeeded."), "Information");
System::Diagnostics::Trace::WriteLineIf(!SUCCEEDED(hr),
System::String::Format("[MmDeviceApiWrapper] SetDefaultPlaybackDevice SetDefEndPoint failed: {0:X}", hr), "Error");
pPolicyConfig->Release();
}
return SUCCEEDED(hr);
}
static bool RegisterForNotification()
{
if(!notificationRegistered)
{
pNotifyClient = new CMMNotificationClient(audioDeviceNotificationHelper);
notificationRegistered = RegisterForNotification(true);
}
return notificationRegistered;
}
static bool UnRegisterForNotification()
{
if(notificationRegistered && pNotifyClient)
{
notificationRegistered = !RegisterForNotification(false);
SAFE_DELETE(pNotifyClient);
return notificationRegistered;
}
else
{
return false;
}
}
private:
static AudioDeviceNotificationHelper^ audioDeviceNotificationHelper;
static bool notificationRegistered;
static CMMNotificationClient* pNotifyClient;
// Registered or unregister for notification.
// The clients can use the event of the A
// returns true if succeeded.
static bool RegisterForNotification(bool registerForNotification)
{
HRESULT hr = S_OK;//CoInitialize(NULL);
if (SUCCEEDED(hr))
{
IMMDeviceEnumerator *pEnum = NULL;
// Create a multimedia device enumerator.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum);
if (SUCCEEDED(hr))
{
IMMNotificationClient* pNotify = (IMMNotificationClient*)(pNotifyClient);
if(!registerForNotification)
{
hr = pEnum->UnregisterEndpointNotificationCallback(pNotify);
}
else
{
hr = pEnum->RegisterEndpointNotificationCallback(pNotify);
}
System::Diagnostics::Trace::WriteLineIf(SUCCEEDED(hr),
System::String::Format("[MmDeviceApiWrapper] {0}Register for notification succeeded.",
registerForNotification ? "" : "Un" ), "Information");
System::Diagnostics::Trace::WriteLineIf(!SUCCEEDED(hr),
System::String::Format("[MmDeviceApiWrapper] Error: {0}Register for notification not succeded! Code: {1}",
registerForNotification ? "" : "Un" ,
(hr == E_POINTER ? "E_POINTER" :
(hr == E_OUTOFMEMORY ? "E_OUTOFMEMORY" :
(hr == E_NOTFOUND ? "E_NOTFOUND" : "NOT_DEFINED")))), "Error");
}
pEnum->Release();
}
//CoUninitialize();
return SUCCEEDED(hr);
}
};
}
To get jack information, you need to use the DeviceTopology API.
This API defines an IKsJackDescription interface that will give you jack connectors information. Here is a sample console app that displays this information on a machine for all render devices:
int main()
{
HRESULT hr = S_OK;
CoInitialize(NULL);
CComPtr<IMMDeviceEnumerator> enumerator;
hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (SUCCEEDED(hr))
{
CComPtr<IMMDeviceCollection> devices;
hr = enumerator->EnumAudioEndpoints(EDataFlow::eRender, DEVICE_STATEMASK_ALL, &devices);
if (SUCCEEDED(hr))
{
UINT count = 0;
devices->GetCount(&count);
for (int i = 0; i < count; i++)
{
CComPtr<IMMDevice> device;
hr = devices->Item(i, &device);
if (SUCCEEDED(hr))
{
CComPtr<IPropertyStore> store;
hr = device->OpenPropertyStore(STGM_READ, &store);
if (SUCCEEDED(hr))
{
PROPVARIANT pv;
PropVariantInit(&pv);
hr = store->GetValue(PKEY_Device_FriendlyName, &pv);
if (SUCCEEDED(hr))
{
PWSTR p;
PSFormatForDisplayAlloc(PKEY_Device_FriendlyName, pv, PDFF_DEFAULT, &p);
wprintf(L"name: '%s'\n", p);
CoTaskMemFree(p);
}
PropVariantClear(&pv);
}
CComPtr<IDeviceTopology> topology;
hr = device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&topology);
if (SUCCEEDED(hr))
{
CComPtr<IConnector> connector;
hr = topology->GetConnector(0, &connector);
if (SUCCEEDED(hr))
{
CComPtr<IConnector> connectedTo;
hr = connector->GetConnectedTo(&connectedTo);
if (SUCCEEDED(hr))
{
CComPtr<IPart> part;
hr = connectedTo->QueryInterface(&part);
if (SUCCEEDED(hr))
{
CComPtr<IKsJackDescription> jack;
hr = part->Activate(CLSCTX_ALL, IID_PPV_ARGS(&jack));
if (SUCCEEDED(hr))
{
UINT jackCount = 0;
jack->GetJackCount(&jackCount);
for (int j = 0; j < jackCount; j++)
{
KSJACK_DESCRIPTION desc = { 0 };
jack->GetJackDescription(j, &desc);
wprintf(L" jack[%i] channel mapping: %i\n", j, desc.ChannelMapping);
wprintf(L" jack[%i] connection type: %i\n", j, desc.ConnectionType);
wprintf(L" jack[%i] is connected: %i\n", j, desc.IsConnected);
wprintf(L" jack[%i] color: 0x%08X\n", j, desc.Color);
}
}
}
}
}
}
}
}
}
}
enumerator.Release();
CoUninitialize();
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With