With Core Audio APIs
Test =>
HRESULT hr = HRESULT.E_FAIL;
Guid CLSID_MMDeviceEnumerator = new Guid("{BCDE0395-E52F-467C-8E3D-C4579291692E}");
Type MMDeviceEnumeratorType = Type.GetTypeFromCLSID(CLSID_MMDeviceEnumerator, true);
object MMDeviceEnumerator = Activator.CreateInstance(MMDeviceEnumeratorType);
IMMDeviceEnumerator pMMDeviceEnumerator = (IMMDeviceEnumerator)MMDeviceEnumerator;
if (pMMDeviceEnumerator != null)
{
IMMDevice pDevice = null;
hr = pMMDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, out pDevice);
if (hr == HRESULT.S_OK)
{
IntPtr pAudioEndpointVolumePtr = IntPtr.Zero;
PROPVARIANT pvActivate = new PROPVARIANT();
hr = pDevice.Activate(typeof(IAudioEndpointVolume).GUID, 0, ref pvActivate, out pAudioEndpointVolumePtr);
if (hr == HRESULT.S_OK)
{
string sFriendlyName = null;
string sDesc = null;
IPropertyStore pPropertyStore = null;
hr = pDevice.OpenPropertyStore(STGM_READ, out pPropertyStore);
if (hr == HRESULT.S_OK)
{
PROPVARIANT pv = new PROPVARIANT();
hr = pPropertyStore.GetValue(ref PKEY_Device_FriendlyName, out pv);
if (hr == HRESULT.S_OK)
{
sFriendlyName = Marshal.PtrToStringUni(pv.pwszVal);
}
hr = pPropertyStore.GetValue(ref PKEY_Device_DeviceDesc, out pv);
if (hr == HRESULT.S_OK)
{
sDesc = Marshal.PtrToStringUni(pv.pwszVal);
}
}
IAudioEndpointVolume pAudioEndpointVolume = Marshal.GetObjectForIUnknown(pAudioEndpointVolumePtr) as IAudioEndpointVolume;
float nVolume = 0;
hr = pAudioEndpointVolume.GetMasterVolumeLevelScalar(out nVolume);
bool bMute = false;
hr = pAudioEndpointVolume.GetMute(out bMute);
Marshal.ReleaseComObject(pAudioEndpointVolume);
int nState = 0;
string sState = "";
hr = pDevice.GetState(out nState);
if ((nState == DEVICE_STATE_ACTIVE))
sState = "Active";
else if ((nState == DEVICE_STATE_DISABLED))
sState = "Disabled";
else if ((nState == DEVICE_STATE_NOTPRESENT))
sState = "Not present";
else if ((nState == DEVICE_STATE_UNPLUGGED))
sState = "Unplugged";
Console.WriteLine("Device: {0} - {1} - Volume : {2} {3}", sFriendlyName, sState, nVolume.ToString(), bMute?"(Mute)":"");
}
Marshal.ReleaseComObject(pDevice);
}
Marshal.ReleaseComObject(pMMDeviceEnumerator);
}
Declarations :
public static PROPERTYKEY PKEY_Device_FriendlyName = new PROPERTYKEY(new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), 14);
public static PROPERTYKEY PKEY_Device_DeviceDesc = new PROPERTYKEY(new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), 2);
public enum HRESULT : int
{
S_OK = 0,
S_FALSE = 1,
E_NOINTERFACE = unchecked((int)0x80004002),
E_NOTIMPL = unchecked((int)0x80004001),
E_FAIL = unchecked((int)0x80004005)
}
[ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyStore
{
HRESULT GetCount([Out] out uint propertyCount);
HRESULT GetAt([In] uint propertyIndex, [Out, MarshalAs(UnmanagedType.Struct)] out PROPERTYKEY key);
HRESULT GetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [Out, MarshalAs(UnmanagedType.Struct)] out PROPVARIANT pv);
HRESULT SetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [In, MarshalAs(UnmanagedType.Struct)] ref PROPVARIANT pv);
HRESULT Commit();
}
public const int STGM_READ = 0x00000000;
public const int STGM_WRITE = 0x00000001;
public const int STGM_READWRITE = 0x00000002;
public enum EDataFlow
{
eRender = 0,
eCapture = (eRender + 1),
eAll = (eCapture + 1),
EDataFlow_enum_count = (eAll + 1)
}
public enum ERole
{
eConsole = 0,
eMultimedia = (eConsole + 1),
eCommunications = (eMultimedia + 1),
ERole_enum_count = (eCommunications + 1)
}
[ComImport]
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDeviceEnumerator
{
HRESULT EnumAudioEndpoints(EDataFlow dataFlow, int dwStateMask, out IMMDeviceCollection ppDevices);
HRESULT GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppEndpoint);
HRESULT GetDevice(string pwstrId,out IMMDevice ppDevice);
HRESULT RegisterEndpointNotificationCallback(IMMNotificationClient pClient);
HRESULT UnregisterEndpointNotificationCallback(IMMNotificationClient pClient);
}
public const int DEVICE_STATE_ACTIVE = 0x00000001;
public const int DEVICE_STATE_DISABLED = 0x00000002;
public const int DEVICE_STATE_NOTPRESENT = 0x00000004;
public const int DEVICE_STATE_UNPLUGGED = 0x00000008;
public const int DEVICE_STATEMASK_ALL = 0x0000000f;
[ComImport]
[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDeviceCollection
{
HRESULT GetCount(out uint pcDevices);
HRESULT Item(uint nDevice, out IMMDevice ppDevice);
}
[ComImport]
[Guid("D666063F-1587-4E43-81F1-B948E807363F")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDevice
{
[PreserveSig]
HRESULT Activate(ref Guid iid, int dwClsCtx, ref PROPVARIANT pActivationParams, out IntPtr ppInterface);
//HRESULT Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface);
HRESULT OpenPropertyStore(int stgmAccess, out IPropertyStore ppProperties);
//HRESULT GetId(StringBuilder ppstrId);
HRESULT GetId(out IntPtr ppstrId);
HRESULT GetState(out int pdwState);
}
[ComImport]
[Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMNotificationClient
{
HRESULT OnDeviceStateChanged(string pwstrDeviceId, int dwNewState);
HRESULT OnDeviceAdded(string pwstrDeviceId);
HRESULT OnDeviceRemoved(string pwstrDeviceId);
HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, string pwstrDefaultDeviceId);
HRESULT OnPropertyValueChanged(string pwstrDeviceId, ref PROPERTYKEY key);
}
[ComImport]
[Guid("1BE09788-6894-4089-8586-9A2A6C265AC5")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMEndpoint
{
HRESULT GetDataFlow(out EDataFlow pDataFlow);
}
public struct PROPERTYKEY
{
public PROPERTYKEY(Guid InputId, UInt32 InputPid)
{
fmtid = InputId;
pid = InputPid;
}
Guid fmtid;
uint pid;
};
[StructLayout(LayoutKind.Sequential)]
public struct PROPARRAY
{
public UInt32 cElems;
public IntPtr pElems;
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct PROPVARIANT
{
[FieldOffset(0)]
public ushort varType;
[FieldOffset(2)]
public ushort wReserved1;
[FieldOffset(4)]
public ushort wReserved2;
[FieldOffset(6)]
public ushort wReserved3;
[FieldOffset(8)]
public byte bVal;
[FieldOffset(8)]
public sbyte cVal;
[FieldOffset(8)]
public ushort uiVal;
[FieldOffset(8)]
public short iVal;
[FieldOffset(8)]
public UInt32 uintVal;
[FieldOffset(8)]
public Int32 intVal;
[FieldOffset(8)]
public UInt64 ulVal;
[FieldOffset(8)]
public Int64 lVal;
[FieldOffset(8)]
public float fltVal;
[FieldOffset(8)]
public double dblVal;
[FieldOffset(8)]
public short boolVal;
[FieldOffset(8)]
public IntPtr pclsidVal; // GUID ID pointer
[FieldOffset(8)]
public IntPtr pszVal; // Ansi string pointer
[FieldOffset(8)]
public IntPtr pwszVal; // Unicode string pointer
[FieldOffset(8)]
public IntPtr punkVal; // punkVal (interface pointer)
[FieldOffset(8)]
public PROPARRAY ca;
[FieldOffset(8)]
public System.Runtime.InteropServices.ComTypes.FILETIME filetime;
}
[ComImport]
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioEndpointVolume
{
HRESULT RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
HRESULT UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
HRESULT GetChannelCount(out uint pnChannelCount);
HRESULT SetMasterVolumeLevel(float fLevelDB, ref Guid pguidEventContext);
HRESULT SetMasterVolumeLevelScalar(float fLevel, ref Guid pguidEventContext);
HRESULT GetMasterVolumeLevel(out float pfLevelDB);
HRESULT GetMasterVolumeLevelScalar(out float pfLevel);
HRESULT SetChannelVolumeLevel(uint nChannel, float fLevelDB, ref Guid pguidEventContext);
HRESULT SetChannelVolumeLevelScalar(uint nChannel, float fLevel, ref Guid pguidEventContext);
HRESULT GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
HRESULT GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
HRESULT SetMute(bool bMute, ref Guid pguidEventContext);
HRESULT GetMute(out bool pbMute);
HRESULT GetVolumeStepInfo(out uint pnStep,out uint pnStepCount);
HRESULT VolumeStepUp(ref Guid pguidEventContext);
HRESULT VolumeStepDown(ref Guid pguidEventContext);
HRESULT QueryHardwareSupport(out int pdwHardwareSupportMask);
HRESULT GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
}
[ComImport]
[Guid("657804FA-D6AD-4496-8A60-352752AF4F89")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioEndpointVolumeCallback
{
HRESULT OnNotify(IntPtr pNotify);
}
[ComImport]
[Guid("f8679f50-850a-41cf-9c72-430f290290c8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPolicyConfig
{
HRESULT GetMixFormat([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, out WAVEFORMATEXTENSIBLE ppFormat);
HRESULT GetDeviceFormat([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.Bool)] bool bDefault, out WAVEFORMATEXTENSIBLE ppFormat);
HRESULT ResetDeviceFormat([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName);
HRESULT SetDeviceFormat([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.LPStruct)] WAVEFORMATEXTENSIBLE pEndpointFormat, [In] [MarshalAs(UnmanagedType.LPStruct)] WAVEFORMATEXTENSIBLE pMixFormat);
HRESULT GetProcessingPeriod([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.Bool)] bool bDefault, out Int64 pmftDefaultPeriod, out Int64 pmftMinimumPeriod);
HRESULT SetProcessingPeriod([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, Int64 pmftPeriod);
HRESULT GetShareMode([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [Out] out DeviceShareMode pMode);
HRESULT SetShareMode([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] DeviceShareMode mode);
HRESULT GetPropertyValue([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.Bool)] bool bFxStore, ref PROPERTYKEY pKey, out PROPVARIANT pv);
HRESULT SetPropertyValue([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.Bool)] bool bFxStore, [In] ref PROPERTYKEY pKey, ref PROPVARIANT pv);
HRESULT SetDefaultEndpoint([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.U4)] ERole role);
HRESULT SetEndpointVisibility([In] [MarshalAs(UnmanagedType.LPWStr)] string pszDeviceName, [In] [MarshalAs(UnmanagedType.Bool)] bool bVisible);
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public class WAVEFORMATEXTENSIBLE : WAVEFORMATEX
{
[FieldOffset(0)]
public short wValidBitsPerSample;
[FieldOffset(0)]
public short wSamplesPerBlock;
[FieldOffset(0)]
public short wReserved;
[FieldOffset(2)]
public WaveMask dwChannelMask;
[FieldOffset(6)]
public Guid SubFormat;
}
[Flags]
public enum WaveMask
{
None = 0x0,
FrontLeft = 0x1,
FrontRight = 0x2,
FrontCenter = 0x4,
LowFrequency = 0x8,
BackLeft = 0x10,
BackRight = 0x20,
FrontLeftOfCenter = 0x40,
FrontRightOfCenter = 0x80,
BackCenter = 0x100,
SideLeft = 0x200,
SideRight = 0x400,
TopCenter = 0x800,
TopFrontLeft = 0x1000,
TopFrontCenter = 0x2000,
TopFrontRight = 0x4000,
TopBackLeft = 0x8000,
TopBackCenter = 0x10000,
TopBackRight = 0x20000
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public class WAVEFORMATEX
{
public short wFormatTag;
public short nChannels;
public int nSamplesPerSec;
public int nAvgBytesPerSec;
public short nBlockAlign;
public short wBitsPerSample;
public short cbSize;
}
public enum DeviceShareMode
{
Shared,
Exclusive
}