Search code examples
c#naudioheadphonesaudio-devicenaudio-framework

How to difference headphones from integrated audio in PC


I am using amazing NAudio framework to get the list of the audio devices.

But as I see is impossible difference which audio device is PC's integrated audio and which is a headphones. I mean they have the same name and only if we plug the headphones it goes to Active state.

Imagine, if I start application with plugged in headphones how do I know if the current device is a headphones and not the PC's integrated audio?

I mean can do we detect via NAduio that plugged audio device is an external audio device and is a headphones itself?

var enumerator = new NAudio.CoreAudioApi.MMDeviceEnumerator();

// Allows you to enumerate rendering devices in certain states
var endpoints = enumerator.EnumerateAudioEndPoints(
    DataFlow.Render,
    DeviceState.Unplugged | DeviceState.Active);
foreach (var endpoint in endpoints)
{
    Console.WriteLine("{0} - {1}", endpoint.DeviceFriendlyName, endpoint.State);
}

// Aswell as hook to the actual event
enumerator.RegisterEndpointNotificationCallback(new NotificationClient());

Where NotificationClient is implemented as follows:

class NotificationClient : NAudio.CoreAudioApi.Interfaces.IMMNotificationClient
{
    void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState)
    {
        Console.WriteLine("OnDeviceStateChanged\n Device Id -->{0} : Device State {1}", deviceId, newState);
    }

    void IMMNotificationClient.OnDeviceAdded(string pwstrDeviceId) { }
    void IMMNotificationClient.OnDeviceRemoved(string deviceId) { }
    void IMMNotificationClient.OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId) { }
    void IMMNotificationClient.OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key) { }
}

Solution

  • The posted snippet is a incomplete, you need to look at the device properties of the (possibly new) default audio device. In particular the form factor, you'll want to detect a headset or headphone. Roughly like this:

    void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState) {
        Console.WriteLine("OnDeviceStateChanged\n Device Id -->{0} : Device State {1}", deviceId, newState);
        var endp = new NAudio.CoreAudioApi.MMDeviceEnumerator().GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
        bool isHeadPhone = false;
        PropertyKey key = PropertyKeys.PKEY_AudioEndpoint_FormFactor;
        var store = endp.Properties;
        for (var index = 0; index < store.Count; index++) {
            if (store.Get(index).Equals(key)) {
                var value = (uint)store.GetValue(index).Value;
                const uint formHeadphones = 3;
                const uint formHeadset = 5;
                if (value == formHeadphones || value == formHeadset) {
                    isHeadPhone = true;
                    break;
                }
            }
        }
        // Use isHeadPhone
        // etc...
    
    }