How to difference headphones from integrated audio in PC

951 Views Asked by At

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) { }
}
2

There are 2 best solutions below

0
On BEST ANSWER

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...

}
1
On

This project seems to do what you're looking for. However from my research it seems what you're trying to do is called "jack detection" so maybe that will help further your searches some more.

From the linked project:

Project Description It's a simples iTunes connected app, to pause music when the headphones are unplugged. Last edited Apr 2, 2011 at 11:24 PM by yzraeu, version 2

It doesn't use NAUDIO however the most relevant code is here:

const string HEAD_PHONE_GUID = "46d16a2c-5654-41c0-911e-7860d2bce7ee";
const string HEAD_PHONE_PLUGGED_VALUE = "1";

void CheckHeadphone()
        {
            var device = new MMDeviceEnumerator().GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
            if (device.Properties[new Guid(HEAD_PHONE_GUID)].Value.ToString() == HEAD_PHONE_PLUGGED_VALUE)
                IsHeadphonePlugged = true;
            else
                IsHeadphonePlugged = false;
        }

The real "magic" behind everything is MMDeviceEnumerator, here is some more info on that.