14

There is no example how to detect if headphones are plugged in or not via C#.

I assume should be some event for that...

Does make sense to use WMI?

 ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2",
                                                                  "SELECT * FROM Win32_SoundDevice");

foreach (ManagementObject queryObj in searcher.Get())
{
    Console.WriteLine("-----------------------------------");
    Console.WriteLine("Win32_SoundDevice instance");
    Console.WriteLine("-----------------------------------");
    Console.WriteLine("StatusInfo: {0}", queryObj["StatusInfo"]);
}

Would anyone be so pleased to provide it?

Thank you!

Markus Safar
  • 5,899
  • 5
  • 25
  • 41
DmitryBoyko
  • 32,983
  • 69
  • 281
  • 458

3 Answers3

12

I wouldn't recommend using the COM+ API yourself.

Take a look at the NAudio NuGet package:

Install-Package NAudio

You should be able to enumerate the audio devices with their plugged/unplugged states as follows:

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

Should produce a similar result to:

enter image description here

I think the reason why it detects plugging/unplugging twice in the above screenshot is because on Macbook they use one jack for both mic and headphones.

Yannick Motton
  • 30,752
  • 4
  • 37
  • 53
  • Thank you! I checked the first one. But your answer is great as well. – DmitryBoyko Nov 26 '15 at 18:50
  • Np, you were looking to detect the actual event, or enumerate the states? As NAudio covers the event as well. – Yannick Motton Nov 26 '15 at 18:51
  • 2
    In fact both of them. And event is extrimly important coz I need to provide text-to-speech functionality when headphones are plugged in. Thanx, man! – DmitryBoyko Nov 26 '15 at 18:57
  • Cool, extended the sample a bit. Should work out of the box. – Yannick Motton Nov 26 '15 at 18:59
  • Hey! I am facing another problem over there. Somehow It is impossible difference which audio device is 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 headphones how do I know if the current device is a headphones and not the integrated audio in PC? – DmitryBoyko Dec 01 '15 at 15:34
  • @Dimi: why do you even need to know if and when the headphones are plugged in? I can just as well connect external speakers to an audio-out jack... – Yannick Motton Dec 01 '15 at 15:39
  • I agree. But I need to turn on some special logic when headphones are plugged in and vise versa. – DmitryBoyko Dec 01 '15 at 15:41
  • Not sure the windows API knows whether or not a device is internal/external. So you want to provide text-to-speech only if something is connected to the audio-out jack, which may not even be headphones. The user will never want this with the integrated speakers? How about a button to let him choose? – Yannick Motton Dec 01 '15 at 15:45
  • Yeah... I have the application that has no GUI at all. So no buttons... But I like your defenition about internal/external audio device. I will try to search for that topic. Thank you for your help, bro! – DmitryBoyko Dec 01 '15 at 15:48
  • Hey Yannick! I found a way to do what I need. I have to get the "Jack information" of the audio device. MS Windows shows it like `LR Front Panel 3,5 mm Jack `. Do you know how to obtain this info via NAudio? – DmitryBoyko Dec 01 '15 at 16:47
  • Hi Anyone find solution to plug/unplug the Headphone Jack, I need to run logic based on plug/unplug headphone jack also for me the code above doesnot run when i plug the headphone jack all my windows application is crashed. – Alaa Abuzaghleh May 14 '20 at 05:17
10

Detecting changes of this kind is possible by using the IMMDeviceEnumerator::RegisterEndpointNotificationCallback method.

As you want to handle this in C# you will need a managed wrapper which has already been implemented by Akos Mattiassich. You can find a thourough example here: Managed Wrapper around MMAudioDeviceApi

He states:

The program can play test sound on selected devices and it updates the list automatically on changes eg. through the control panel or in case of plugging new device physically.

Markus Safar
  • 5,899
  • 5
  • 25
  • 41
4

Below is a (minimal) Windows Forms application sample based on the IMMNotificationClient interface which does not require any third-party library.

You will receive a notification whenever a multimedia device is plugged/unplugged. You can then look at the device properties and take the appropriate action. You are also able to enumerate existing devices and check whether a headphone is plugged (see the IsConnected property).

Creating COM Interop

Note that the sample code includes the definition of the relevant COM object. In production, I would probably create a COM interop assembly for the underlying mmdevapi.dll. You can do so by first creating a type lib from the header files (Windows SDK needs to be installed):

midl /out c:\tmp /header "C:\Program Files (x86)\Windows Kits\8.1\Include\um\mmdeviceapi.h" "C:\Program Files (x86)\Windows Kits\8.1\Include\um\mmdeviceapi.idl"

Then you need to generate the interop assembly from the typelib using tlbimp.exe:

tlbimp /out:MMDevAPI.Interop.dll mmdeviceapi.tlb

MultiMediaNotificationListener Sample

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace MultiMediaNotificationListenerSample
{
    class MainWindow : Form
    {
        [STAThread]
        private static void Main(string[] args)
        {
            using (var notificationClient = new MultiMediaNotificationListener())
            {
                Trace.WriteLine(string.Format("Headphone is {0}connected", notificationClient.IsConnected ? "": "not "));
                Application.Run(new MainWindow());
            }
        }
    }

    class MultiMediaNotificationListener : IMMNotificationClient, IDisposable
    {
        private readonly IMMDeviceEnumerator _deviceEnumerator;

        public MultiMediaNotificationListener()
        {
            if (Environment.OSVersion.Version.Major < 6)
            {
                throw new NotSupportedException("This functionality is only supported on Windows Vista or newer.");
            }
            _deviceEnumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
            _deviceEnumerator.RegisterEndpointNotificationCallback(this);
        }

        ~MultiMediaNotificationListener()
        {
            Dispose(false);
        }

        public bool IsConnected
        {
            get
            {
                IMMDeviceCollection deviceCollection;
                _deviceEnumerator.EnumAudioEndpoints(EDataFlow.eRender, (uint)DeviceState.DEVICE_STATE_ACTIVE, out deviceCollection);

                uint deviceCount = 0;
                deviceCollection.GetCount(out deviceCount);
                for (uint i = 0; i < deviceCount; i++)
                {
                    IMMDevice device;
                    deviceCollection.Item(i, out device);

                    IPropertyStore propertyStore;
                    device.OpenPropertyStore((uint)STGM.STGM_READ, out propertyStore);

                    PROPVARIANT property;
                    propertyStore.GetValue(ref PropertyKey.PKEY_Device_DeviceDesc, out property);

                    var value = (string)property.Value;
                    Marshal.ReleaseComObject(propertyStore);
                    Marshal.ReleaseComObject(device);

                    if (value == "Headphones")
                    {
                        return true;
                    }
                }

                Marshal.ReleaseComObject(deviceCollection);
                return false;
            }
        }

        public void OnDefaultDeviceChanged(EDataFlow dataFlow, ERole deviceRole, string pwstrDefaultDeviceId)
        {
        }

        public void OnDeviceStateChanged(string pwstrDeviceId, uint dwNewState)
        {
            IMMDevice device;
            _deviceEnumerator.GetDevice(pwstrDeviceId, out device);

            IPropertyStore propertyStore;
            device.OpenPropertyStore((uint)STGM.STGM_READ, out propertyStore);

            Trace.WriteLine(string.Format("OnDeviceStateChanged:\n  Device Id {0}\tDevice State {1}", pwstrDeviceId, (DeviceState)dwNewState));

            var properties = PropertyKey.GetPropertyKeys()
                .Select(
                propertyKey =>
                {
                    PROPVARIANT property;
                    propertyStore.GetValue(ref propertyKey, out property);
                    return new { Key = PropertyKey.GetKeyName(propertyKey), Value = property.Value };
                })
                .Where(@t => @t.Value != null);

            foreach (var property in properties)
            {
                Trace.WriteLine(string.Format("    {0}\t{1}", property.Key, property.Value));
            }

            Marshal.ReleaseComObject(propertyStore);
            Marshal.ReleaseComObject(device);
        }

        public void OnDeviceAdded(string deviceId)
        {
        }

        public void OnDeviceRemoved(string deviceId)
        {
        }

        public void OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key)
        {
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            _deviceEnumerator.UnregisterEndpointNotificationCallback(this);
            Marshal.ReleaseComObject(_deviceEnumerator);
        }
    }

    public enum STGM : uint
    {
        STGM_READ = 0x0,
        STGM_WRITE = 0x1,
        STGM_READWRITE = 0x2
    }

    public enum DeviceState
    {
        DEVICE_STATE_ACTIVE = 0x00000001,
        DEVICE_STATE_DISABLED = 0x00000002,
        DEVICE_STATE_NOTPRESENT = 0x00000004,
        DEVICE_STATE_UNPLUGGED = 0x00000008,
        DEVICE_STATEMASK_ALL = 0x0000000f
    }

    [ComImport]
    [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
    internal class MMDeviceEnumerator
    {
    }

    public enum EDataFlow
    {
        eRender,
        eCapture,
        eAll,
        EDataFlow_enum_count
    }

    public enum ERole
    {
        eConsole,
        eMultimedia,
        eCommunications,
        ERole_enum_count
    }

    [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDeviceCollection
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetCount(out uint pcDevices);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Item([In] uint nDevice, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppDevice);
    }

    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDeviceEnumerator
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void EnumAudioEndpoints([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow dataFlow, [In] uint dwStateMask, [MarshalAs(UnmanagedType.Interface)] out IMMDeviceCollection ppDevices);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetDefaultAudioEndpoint([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow dataFlow, [ComAliasName("MMDevAPI.Interop.ERole")] [In] ERole role, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppEndpoint);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetDevice([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrId, [MarshalAs(UnmanagedType.Interface)] out IMMDevice ppDevice);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void RegisterEndpointNotificationCallback([MarshalAs(UnmanagedType.Interface)] [In] IMMNotificationClient pClient);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void UnregisterEndpointNotificationCallback([MarshalAs(UnmanagedType.Interface)] [In] IMMNotificationClient pClient);
    }

    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMDevice
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Activate([In] ref Guid iid, [In] uint dwClsCtx, [In] IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OpenPropertyStore([In] uint stgmAccess, [MarshalAs(UnmanagedType.Interface)] out IPropertyStore ppProperties);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetId([MarshalAs(UnmanagedType.LPWStr)] out string ppstrId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetState(out uint pdwState);
    }

    [Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FNonExtensible)]
    [ComImport]
    public interface IMMNotificationClient
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId, [In] uint dwNewState);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnDefaultDeviceChanged([ComAliasName("MMDevAPI.Interop.EDataFlow")] [In] EDataFlow flow, [ComAliasName("MMDevAPI.Interop.ERole")] [In] ERole role, [MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDefaultDeviceId);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] [In] string pwstrDeviceId, [In] PropertyKey key);
    }

    [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImport]
    public interface IPropertyStore
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetCount(out uint cProps);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetAt([In] uint iProp, out PropertyKey pkey);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void GetValue([In] ref PropertyKey key, out PROPVARIANT pv);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void SetValue([In] ref PropertyKey key, [In] ref PROPVARIANT propvar);
        [MethodImpl(MethodImplOptions.InternalCall)]
        void Commit();
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct PropertyKey
    {
        public static PropertyKey PKEY_Device_DeviceDesc = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 2 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_HardwareIds = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 3 }; // DEVPROP_TYPE_STRING_LIST
        public static PropertyKey PKEY_Device_Service = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 6 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Class = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 9 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Driver = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 11 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_ConfigFlags = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 12 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_Manufacturer = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 13 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_FriendlyName = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 14 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_LocationInfo = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 15 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_Capabilities = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 17 }; // DEVPROP_TYPE_UNINT32
        public static PropertyKey PKEY_Device_BusNumber = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 23 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_EnumeratorName = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 24 }; // DEVPROP_TYPE_STRING
        public static PropertyKey PKEY_Device_DevType = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 27 }; // DEVPROP_TYPE_UINT32
        public static PropertyKey PKEY_Device_Characteristics = new PropertyKey { fmtid = new Guid(unchecked((int)0xa45c254e), unchecked((short)0xdf1c), 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), pid = 29 }; // DEVPROP_TYPE_UINT32


        public static PropertyKey PKEY_Device_ManufacturerAttributes = new PropertyKey { fmtid = new Guid(unchecked((int)0x80d81ea6), unchecked((short)0x7473), 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b), pid = 4 }; // DEVPROP_TYPE_UINT32

        public static PropertyKey PKEY_DeviceClass_IconPath = new PropertyKey { fmtid = new Guid(unchecked((int)0x259abffc), 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66), pid = 12 }; // DEVPROP_TYPE_STRING_LIST

        public static PropertyKey PKEY_DeviceClass_ClassCoInstallers = new PropertyKey { fmtid = new Guid(unchecked((int)0x713d1703), 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c), pid = 2 }; // DEVPROP_TYPE_STRING_LIST

        public static PropertyKey PKEY_DeviceInterface_FriendlyName = new PropertyKey { fmtid = new Guid(unchecked((int)0x026e516e), 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22), pid = 2 }; // DEVPROP_TYPE_STRING

        public Guid fmtid;
        public uint pid;

        public static IEnumerable<PropertyKey> GetPropertyKeys()
        {
            var keyFields = typeof(PropertyKey).GetFields(BindingFlags.Public | BindingFlags.Static);
            return keyFields.Where(fieldInfo => fieldInfo.FieldType == typeof(PropertyKey))
                            .Select(fieldInfo => (PropertyKey)fieldInfo.GetValue(null));
        }

        public static string GetKeyName(PropertyKey propertyKey)
        {
            var keyFields = typeof(PropertyKey).GetFields(BindingFlags.Public | BindingFlags.Static);
            return keyFields.Select(fieldInfo => new { fieldInfo, value = (PropertyKey)fieldInfo.GetValue(null) })
                            .Where(@t => propertyKey.pid == @t.value.pid && propertyKey.fmtid == @t.value.fmtid)
                            .Select(@t => @t.fieldInfo.Name).FirstOrDefault();
        }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct PROPVARIANT
    {
        public ushort variantType;
        public byte wReserved1;
        public byte wReserved2;
        public uint wReserved3;
        public PROPVARIANTVALUE value;

        public object Value
        {
            get
            {
                switch ((VarEnum)variantType)
                {
                    case VarEnum.VT_EMPTY:
                        return null;
                    case VarEnum.VT_NULL:
                        return null;
                    case VarEnum.VT_VARIANT:
                        break;
                    case VarEnum.VT_DECIMAL:
                        return value.cyVal;
                    case VarEnum.VT_VOID:
                        break;
                    case VarEnum.VT_HRESULT:
                        break;
                    case VarEnum.VT_PTR:
                        break;
                    case VarEnum.VT_SAFEARRAY:
                        break;
                    case VarEnum.VT_CARRAY:
                        break;
                    case VarEnum.VT_USERDEFINED:
                        break;
                    case VarEnum.VT_RECORD:
                        break;
                    case VarEnum.VT_STREAM:
                        break;
                    case VarEnum.VT_STORAGE:
                        break;
                    case VarEnum.VT_STREAMED_OBJECT:
                        break;
                    case VarEnum.VT_STORED_OBJECT:
                        break;
                    case VarEnum.VT_BLOB_OBJECT:
                        break;
                    case VarEnum.VT_CF:
                        break;
                    case VarEnum.VT_CLSID:
                        return Marshal.PtrToStructure(value.pVal, typeof(Guid));
                    case VarEnum.VT_VECTOR:
                        break;
                    case VarEnum.VT_ARRAY:
                        break;
                    case VarEnum.VT_BYREF:
                        break;
                    case VarEnum.VT_I1:
                        return value.cVal;
                    case VarEnum.VT_UI1:
                        return value.bVal;
                    case VarEnum.VT_I2:
                        return value.iVal;
                    case VarEnum.VT_UI2:
                        return value.uiVal;
                    case VarEnum.VT_I4:
                    case VarEnum.VT_INT:
                        return value.intVal;
                    case VarEnum.VT_UI4:
                    case VarEnum.VT_UINT:
                        return value.uintVal;
                    case VarEnum.VT_I8:
                        return value.hVal;
                    case VarEnum.VT_UI8:
                        return value.uhVal;
                    case VarEnum.VT_R4:
                        return value.fltVal;
                    case VarEnum.VT_R8:
                        return value.dblVal;
                    case VarEnum.VT_BOOL:
                        return value.boolVal;
                    case VarEnum.VT_ERROR:
                        return value.scode;
                    case VarEnum.VT_CY:
                        return value.cyVal;
                    case VarEnum.VT_DATE:
                        return value.date;
                    case VarEnum.VT_FILETIME:
                        return DateTime.FromFileTime(value.hVal);
                    case VarEnum.VT_BSTR:
                        return Marshal.PtrToStringBSTR(value.pVal);
                    case VarEnum.VT_BLOB:
                        var blob = value.blob;
                        var blobData = new byte[blob.cbSize];
                        Marshal.Copy(blob.pBlobData, blobData, 0, (int)blob.cbSize);
                        return blobData;
                    case VarEnum.VT_LPSTR:
                        return Marshal.PtrToStringAnsi(value.pVal);
                    case VarEnum.VT_LPWSTR:
                        return Marshal.PtrToStringUni(value.pVal);
                    case VarEnum.VT_UNKNOWN:
                        return Marshal.GetObjectForIUnknown(value.pVal);
                    case VarEnum.VT_DISPATCH:
                        return value.pVal;
                    //default:
                    //    throw new NotSupportedException("The type of this variable is not support ('" + variantType + "')");
                }
                return string.Format("unsupported {0}", ((VarEnum)variantType));
                //throw new NotSupportedException("The type of this variable is not support ('" + variantType.ToString() + "')");
            }
        }
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 8)]
    public struct PROPVARIANTVALUE
    {
        [FieldOffset(0)]
        public sbyte cVal;
        [FieldOffset(0)]
        public byte bVal;
        [FieldOffset(0)]
        public short iVal;
        [FieldOffset(0)]
        public ushort uiVal;
        [FieldOffset(0)]
        public int intVal;
        [FieldOffset(0)]
        public uint uintVal;
        [FieldOffset(0)]
        public long hVal;
        [FieldOffset(0)]
        public ulong uhVal;
        [FieldOffset(0)]
        public float fltVal;
        [FieldOffset(0)]
        public double dblVal;
        [FieldOffset(0)]
        public short boolVal;
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Error)]
        public int scode;
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Currency)]
        public decimal cyVal;
        [FieldOffset(0)]
        public DateTime date;
        [FieldOffset(0)]
        public tagFILETIME filetime;
        [FieldOffset(0)]
        public tagARRAY array;
        [FieldOffset(0)]
        public tagBLOB blob;
        [ComConversionLoss]
        [FieldOffset(0)]
        public IntPtr pVal;
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagARRAY
    {
        public uint cElems;
        [ComConversionLoss]
        public IntPtr pElems;
    }

    [ComConversionLoss]
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagBLOB
    {
        public uint cbSize;
        [ComConversionLoss]
        public IntPtr pBlobData;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct tagFILETIME
    {
        public uint dwLowDateTime;
        public uint dwHighDateTime;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct tagLARGEINTEGER
    {
        public long QuadPart;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct tagULARGEINTEGER
    {
        public ulong QuadPart;
    }
}
Dirk Vollmar
  • 161,833
  • 52
  • 243
  • 303
  • can anyone please provide the above code in asp.net web application i need urgent requirement please provide me –  Jul 04 '16 at 12:42
  • @user123: What browser/platform? There is nothing in the Web Audio API spec about detecting such hardware events (see http://stackoverflow.com/a/26085043/40347). You might be lucky on some mobile platforms, but I would highly doubt it. – Dirk Vollmar Jul 04 '16 at 14:53
  • may i know the how can i do this Earphones are not connected properly to a system i want to display on alert message in asp.net could you please tell me how to do this.i tried to search but i am not getting any idea can you please tell me to how to do this Thank you –  Jul 05 '16 at 05:06
  • This will only work on English systems. The endpoint name won't be 'Headphones' on non-English PCs. – Randall Deetz Aug 02 '16 at 23:19
  • @RandallDeetz The code is just a sample explaining how to program against that API. The sample just focuses on the basic things, and it doesn't deal with localization, error handling or anything else you might want to add in production. – Dirk Vollmar Aug 03 '16 at 02:16