Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Jack Information of Audio Device in MS WIndows 7

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));
                }
            }

enter image description here

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);
        }

    };
}
like image 271
Friend Avatar asked Dec 01 '15 16:12

Friend


1 Answers

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;
}
like image 191
Simon Mourier Avatar answered Oct 17 '22 02:10

Simon Mourier