Mega Code Archive

 
Categories / C# / Windows
 

Sound Utils

/////////////////////////////////////////////////////////////////////////////////////////////// // //    This File is Part of the CallButler Open Source PBX (http://www.codeplex.com/callbutler // //    Copyright (c) 2005-2008, Jim Heising //    All rights reserved. // //    Redistribution and use in source and binary forms, with or without modification, //    are permitted provided that the following conditions are met: // //    * Redistributions of source code must retain the above copyright notice, //      this list of conditions and the following disclaimer. // //    * Redistributions in binary form must reproduce the above copyright notice, //      this list of conditions and the following disclaimer in the documentation and/or //      other materials provided with the distribution. // //    * Neither the name of Jim Heising nor the names of its contributors may be //      used to endorse or promote products derived from this software without specific prior //      written permission. // //    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND //    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED //    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. //    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, //    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT //    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR //    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, //    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //    POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////////////////////// using System; using System.Runtime.InteropServices; using System.IO; namespace WOSI.Utilities {     /// <summary>     /// Summary description for SoundUtilities.     /// </summary>     public sealed class SoundUtils     {         private const int MMSYSERR_NOERROR = 0;         private const int MAXPNAMELEN = 32;         private const int MIXER_LONG_NAME_CHARS = 64;         private const int MIXER_SHORT_NAME_CHARS = 16;         private const int MIXER_GETLINEINFOF_COMPONENTTYPE = 0x3;         private const int MIXER_GETCONTROLDETAILSF_VALUE = 0x0;         private const int MIXER_GETLINECONTROLSF_ONEBYTYPE = 0x2;         private const int MIXER_SETCONTROLDETAILSF_VALUE = 0x0;         private const int MIXERLINE_COMPONENTTYPE_DST_FIRST = 0x0;         private const int MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x1000;         private const int MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 4);         private const int MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3);         private const int MIXERLINE_COMPONENTTYPE_SRC_LINE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2);         private const int MIXERCONTROL_CT_CLASS_FADER = 0x50000000;         private const int MIXERCONTROL_CT_UNITS_UNSIGNED = 0x30000;         private const int MIXERCONTROL_CT_CLASS_SWITCH = 0x20000000;         private const int MIXERCONTROL_CT_SC_SWITCH_BOOLEAN = 0x0;         private const int MIXERCONTROL_CT_UNITS_BOOLEAN = 0x10000;         private const int MIXERCONTROL_CONTROLTYPE_FADER = (MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED);         private const int MIXERCONTROL_CONTROLTYPE_VOLUME = (MIXERCONTROL_CONTROLTYPE_FADER + 1);         private const int MIXERCONTROL_CONTROLTYPE_BOOLEAN = (MIXERCONTROL_CT_CLASS_SWITCH | MIXERCONTROL_CT_SC_SWITCH_BOOLEAN | MIXERCONTROL_CT_UNITS_BOOLEAN);         private const int MIXERCONTROL_CONTROLTYPE_MUTE = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2);         private struct MIXERCAPS         {             public int wMid;             public int wPid;             public int vDriverVersion;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)]             public string szPname;             public int fdwSupport;             public int cDestinations;         }         private struct MIXERCONTROL         {             public int cbStruct;             public int dwControlID;             public int dwControlType;             public int fdwControl;             public int cMultipleItems;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]             public string szShortName;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]             public string szName;             public int lMinimum;             public int lMaximum;             [MarshalAs(UnmanagedType.U4, SizeConst = 10)]             public int reserved;         }         private struct MIXERCONTROLDETAILS         {             public int cbStruct;             public int dwControlID;             public int cChannels;             public int item;             public int cbDetails;             public IntPtr paDetails;         }         private struct MIXERCONTROLDETAILS_UNSIGNED         {             public int dwValue;         }         private struct MIXERCONTROLDETAILS_BOOLEAN         {             public int dwValue;         }         private struct MIXERLINE         {             public int cbStruct;             public int dwDestination;             public int dwSource;             public int dwLineID;             public int fdwLine;             public int dwUser;             public int dwComponentType;             public int cChannels;             public int cConnections;             public int cControls;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)]             public string szShortName;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)]             public string szName;             public int dwType;             public int dwDeviceID;             public int wMid;             public int wPid;             public int vDriverVersion;             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)]             public string szPname;         }         private struct MIXERLINECONTROLS         {             public int cbStruct;             public int dwLineID;             public int dwControl;             public int cControls;             public int cbmxctrl;             public IntPtr pamxctrl;         }         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerClose(int hmx);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetControlDetailsA(int hmxobj, ref MIXERCONTROLDETAILS pmxcd, int fdwDetails);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetDevCapsA(int uMxId, MIXERCAPS pmxcaps, int cbmxcaps);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetID(int hmxobj, int pumxID, int fdwId);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetLineControlsA(int hmxobj, ref MIXERLINECONTROLS pmxlc, int fdwControls);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetLineInfoA(int hmxobj, ref MIXERLINE pmxl, int fdwInfo);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerGetNumDevs();         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerMessage(int hmx, int uMsg, int dwParam1, int dwParam2);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerOpen(out int phmx, int uMxId, int dwCallback, int dwInstance, int fdwOpen);         [DllImport("winmm.dll", CharSet = CharSet.Ansi)]         private static extern int mixerSetControlDetails(int hmxobj, ref MIXERCONTROLDETAILS pmxcd, int fdwDetails);         [DllImport("winmm.dll", EntryPoint = "sndPlaySoundA")]         private static extern int sndPlaySound(string lpszSoundName, int uFlags);         private const int SND_ASYNC = 0x1;         private const int SND_LOOP = 0x8;         private SoundUtils()         {         }         public static void PlaySound(string filename, bool loop)         {             if (File.Exists(filename))             {                 if (loop)                     sndPlaySound(filename, SND_ASYNC | SND_LOOP);                 else                     sndPlaySound(filename, SND_ASYNC);             }         }         public static void StopSound()         {             sndPlaySound(null, SND_ASYNC);         }         public static void Mute(bool mute)         {             // Check if this is vista or XP             if (System.Environment.OSVersion.Version.Major >= 6)             {                 EndpointVolume epVol = new EndpointVolume();                 epVol.Mute = mute;                 epVol.Dispose();             }             else             {                 int mixerID = 0;                 if (mixerOpen(out mixerID, 0, 0, 0, 0) == MMSYSERR_NOERROR)                 {                     MIXERLINE line = new MIXERLINE();                     line.cbStruct = Marshal.SizeOf(line);                     line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;                     if (mixerGetLineInfoA(mixerID, ref line, MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR)                     {                         int sizeofMIXERCONTROL = 152;                         MIXERCONTROL mixerControl = new MIXERCONTROL();                         MIXERLINECONTROLS lineControl = new MIXERLINECONTROLS();                         lineControl.pamxctrl = Marshal.AllocCoTaskMem(sizeofMIXERCONTROL);                         lineControl.cbStruct = Marshal.SizeOf(lineControl);                         lineControl.dwLineID = line.dwLineID;                         lineControl.dwControl = MIXERCONTROL_CONTROLTYPE_MUTE;                         lineControl.cControls = 1;                         lineControl.cbmxctrl = sizeofMIXERCONTROL;                         mixerControl.cbStruct = sizeofMIXERCONTROL;                         if (mixerGetLineControlsA(mixerID, ref lineControl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)                         {                             mixerControl = (MIXERCONTROL)Marshal.PtrToStructure(lineControl.pamxctrl, typeof(MIXERCONTROL));                             MIXERCONTROLDETAILS controlDetails = new MIXERCONTROLDETAILS();                             MIXERCONTROLDETAILS_BOOLEAN muteValue = new MIXERCONTROLDETAILS_BOOLEAN();                             controlDetails.item = 0;                             controlDetails.dwControlID = mixerControl.dwControlID;                             controlDetails.cbStruct = Marshal.SizeOf(controlDetails);                             controlDetails.cbDetails = Marshal.SizeOf(muteValue);                             controlDetails.cChannels = 1;                             muteValue.dwValue = Convert.ToInt32(mute);                             controlDetails.paDetails = Marshal.AllocCoTaskMem(Marshal.SizeOf(muteValue));                             Marshal.StructureToPtr(muteValue, controlDetails.paDetails, false);                             int rc = mixerSetControlDetails(mixerID, ref controlDetails, MIXER_SETCONTROLDETAILSF_VALUE);                             Marshal.FreeCoTaskMem(controlDetails.paDetails);                             Marshal.FreeCoTaskMem(lineControl.pamxctrl);                         }                     }                 }             }         }     }     public class EndpointVolume     {         #region Interface to COM objects         const int DEVICE_STATE_ACTIVE = 0x00000001;         const int DEVICE_STATE_DISABLE = 0x00000002;         const int DEVICE_STATE_NOTPRESENT = 0x00000004;         const int DEVICE_STATE_UNPLUGGED = 0x00000008;         const int DEVICE_STATEMASK_ALL = 0x0000000f;         [DllImport("ole32.Dll")]         static public extern uint CoCreateInstance(ref Guid clsid,         [MarshalAs(UnmanagedType.IUnknown)] object inner,         uint context,         ref Guid uuid,         [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);         // C Header file : Include Mmdeviceapi.h (Windows Vista SDK)         [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"),         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         public interface IAudioEndpointVolume         {             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RegisterControlChangeNotify(/* [in] */__in IAudioEndpointVolumeCallback *pNotify) = 0;             //int RegisterControlChangeNotify(IntPtr pNotify);             int RegisterControlChangeNotify(DelegateMixerChange pNotify);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnregisterControlChangeNotify(/* [in] */ __in IAudioEndpointVolumeCallback *pNotify) = 0;             //int UnregisterControlChangeNotify(IntPtr pNotify);             int UnregisterControlChangeNotify(DelegateMixerChange pNotify);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelCount(/* [out] */ __out UINT *pnChannelCount) = 0;             int GetChannelCount(ref uint pnChannelCount);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevel( /* [in] */ __in float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;             int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevelScalar( /* [in] */ __in float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;             int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevel(/* [out] */ __out float *pfLevelDB) = 0;             int GetMasterVolumeLevel(ref float pfLevelDB);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevelScalar( /* [out] */ __out float *pfLevel) = 0;             int GetMasterVolumeLevelScalar(ref float pfLevel);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevel(/* [in] */__in UINT nChannel,float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;             int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevelScalar(/* [in] */ __in UINT nChannel,float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;             int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevel(/* [in] */ __in UINT nChannel,/* [out] */__out float *pfLevelDB) = 0;             int GetChannelVolumeLevel(uint nChannel, ref float pfLevelDB);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevelScalar(/* [in] */__in UINT nChannel,/* [out] */__out float *pfLevel) = 0;             int GetChannelVolumeLevelScalar(uint nChannel, ref float pfLevel);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMute( /* [in] *__in BOOL bMute, /* [unique][in] */ LPCGUID pguidEventContext) = 0;             int SetMute(int bMute, Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMute( /* [out] */ __out BOOL *pbMute) = 0;             int GetMute(ref bool pbMute);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeStepInfo( /* [out] */ __out UINT *pnStep,/* [out] */__out UINT *pnStepCount) = 0;             int GetVolumeStepInfo(ref uint pnStep, ref uint pnStepCount);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepUp( /* [unique][in] */ LPCGUID pguidEventContext) = 0;             int VolumeStepUp(Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepDown(/* [unique][in] */ LPCGUID pguidEventContext) = 0;             int VolumeStepDown(Guid pguidEventContext);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryHardwareSupport(/* [out] */ __out DWORD *pdwHardwareSupportMask) = 0;             int QueryHardwareSupport(ref uint pdwHardwareSupportMask);             //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeRange( /* [out] */ __out float *pflVolumeMindB,/* [out] */ __out float *pflVolumeMaxdB,/* [out] */ __out float *pflVolumeIncrementdB) = 0;             int GetVolumeRange(ref float pflVolumeMindB, ref float pflVolumeMaxdB, ref float pflVolumeIncrementdB);         }         [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"),         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         public interface IMMDeviceCollection         {             //HRESULT GetCount([out, annotation("__out")] UINT* pcDevices);             int GetCount(ref uint pcDevices);             //HRESULT Item([in, annotation("__in")]UINT nDevice, [out, annotation("__out")] IMMDevice** ppDevice);             int Item(uint nDevice, ref IntPtr ppDevice);         }         [Guid("D666063F-1587-4E43-81F1-B948E807363F"),         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         public interface IMMDevice         {             //HRESULT Activate([in, annotation("__in")] REFIID iid, [in, annotation("__in")] DWORD dwClsCtx, [in,unique, annotation("__in_opt")] PROPVARIANT* pActivationParams, [out,iid_is(iid), annotation("__out")] void** ppInterface);             int Activate(ref Guid iid, uint dwClsCtx, IntPtr pActivationParams, ref IntPtr ppInterface);             //HRESULT OpenPropertyStore([in, annotation("__in")] DWORD stgmAccess, [out, annotation("__out")] IPropertyStore** ppProperties);             int OpenPropertyStore(int stgmAccess, ref IntPtr ppProperties);             //HRESULT GetId([out,annotation("__deref_out")] LPWSTR* ppstrId);             int GetId(ref string ppstrId);             //HRESULT GetState([out, annotation("__out")] DWORD* pdwState);             int GetState(ref int pdwState);         }         [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"),         //[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E"),         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]         public interface IMMDeviceEnumerator         {             //HRESULT EnumAudioEndpoints([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] DWORD dwStateMask, [out, annotation("__out")] IMMDeviceCollection** ppDevices);             int EnumAudioEndpoints(EDataFlow dataFlow, int dwStateMask, ref IntPtr ppDevices);             //HRESULT GetDefaultAudioEndpoint([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] ERole role, [out, annotation("__out")] IMMDevice** ppEndpoint);             int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, ref IntPtr ppEndpoint);             //HRESULT GetDevice([, annotation("__in")]LPCWSTR pwstrId, [out, annotation("__out")] IMMDevice** ppDevice);             int GetDevice(string pwstrId, ref IntPtr ppDevice);             //HRESULT RegisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);             int RegisterEndpointNotificationCallback(IntPtr pClient);             //HRESULT UnregisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);             int UnregisterEndpointNotificationCallback(IntPtr pClient);         }         [Flags]         enum CLSCTX : uint         {             CLSCTX_INPROC_SERVER = 0x1,             CLSCTX_INPROC_HANDLER = 0x2,             CLSCTX_LOCAL_SERVER = 0x4,             CLSCTX_INPROC_SERVER16 = 0x8,             CLSCTX_REMOTE_SERVER = 0x10,             CLSCTX_INPROC_HANDLER16 = 0x20,             CLSCTX_RESERVED1 = 0x40,             CLSCTX_RESERVED2 = 0x80,             CLSCTX_RESERVED3 = 0x100,             CLSCTX_RESERVED4 = 0x200,             CLSCTX_NO_CODE_DOWNLOAD = 0x400,             CLSCTX_RESERVED5 = 0x800,             CLSCTX_NO_CUSTOM_MARSHAL = 0x1000,             CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000,             CLSCTX_NO_FAILURE_LOG = 0x4000,             CLSCTX_DISABLE_AAA = 0x8000,             CLSCTX_ENABLE_AAA = 0x10000,             CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000,             CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,             CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,             CLSCTX_ALL = CLSCTX_SERVER | CLSCTX_INPROC_HANDLER         }         public enum EDataFlow         {             eRender,             eCapture,             eAll,             EDataFlow_enum_count         }         public enum ERole         {             eConsole,             eMultimedia,             eCommunications,             ERole_enum_count         }         #endregion         // Private internal var         object oEnumerator = null;         IMMDeviceEnumerator iMde = null;         object oDevice = null;         IMMDevice imd = null;         object oEndPoint = null;         IAudioEndpointVolume iAudioEndpoint = null;         // TODO         // Problem #1 : I can't handle a volume changed event by other applications         // (example while using the program SndVol.exe)         public delegate void DelegateMixerChange();         //public DelegateMixerChange delMixerChange = null;         public delegate void MixerChangedEventHandler();         //public event MixerChangedEventHandler MixerChanged;         #region Class Constructor and Dispose public methods         /// <summary>         /// Constructor         /// </summary>         public EndpointVolume()         {             const uint CLSCTX_INPROC_SERVER = 1;             Guid clsid = new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E");             Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");             oEnumerator = null;             uint hResult = CoCreateInstance(ref clsid, null, CLSCTX_INPROC_SERVER, ref IID_IUnknown, out oEnumerator);             if (hResult != 0 || oEnumerator == null)             {                 throw new Exception("CoCreateInstance() pInvoke failed");             }             iMde = oEnumerator as IMMDeviceEnumerator;             if (iMde == null)             {                 throw new Exception("COM cast failed to IMMDeviceEnumerator");             }             IntPtr pDevice = IntPtr.Zero;             int retVal = iMde.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, ref pDevice);             if (retVal != 0)             {                 throw new Exception("IMMDeviceEnumerator.GetDefaultAudioEndpoint()");             }             int dwStateMask = DEVICE_STATE_ACTIVE | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED;             IntPtr pCollection = IntPtr.Zero;             retVal = iMde.EnumAudioEndpoints(EDataFlow.eRender, dwStateMask, ref pCollection);             if (retVal != 0)             {                 throw new Exception("IMMDeviceEnumerator.EnumAudioEndpoints()");             }             oDevice = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pDevice);             imd = oDevice as IMMDevice;             if (imd == null)             {                 throw new Exception("COM cast failed to IMMDevice");             }             Guid iid = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A");             uint dwClsCtx = (uint)CLSCTX.CLSCTX_ALL;             IntPtr pActivationParams = IntPtr.Zero;             IntPtr pEndPoint = IntPtr.Zero;             retVal = imd.Activate(ref iid, dwClsCtx, pActivationParams, ref pEndPoint);             if (retVal != 0)             {                 throw new Exception("IMMDevice.Activate()");             }             oEndPoint = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pEndPoint);             iAudioEndpoint = oEndPoint as IAudioEndpointVolume;             if (iAudioEndpoint == null)             {                 throw new Exception("COM cast failed to IAudioEndpointVolume");             }             /*             delMixerChange = new DelegateMixerChange(MixerChange);             retVal = iAudioEndpoint.RegisterControlChangeNotify(delMixerChange);             if (retVal != 0)             {             throw new Exception("iAudioEndpoint.RegisterControlChangeNotify(delMixerChange)");             }             */         }         /// <summary>         /// Call this method to release all com objetcs         /// </summary>         public virtual void Dispose()         {             /*             if (delMixerChange != null && iAudioEndpoint != null)             {             iAudioEndpoint.UnregisterControlChangeNotify(delMixerChange);             }             */             if (iAudioEndpoint != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(iAudioEndpoint);                 iAudioEndpoint = null;             }             if (oEndPoint != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(oEndPoint);                 oEndPoint = null;             }             if (imd != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(imd);                 imd = null;             }             if (oDevice != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(oDevice);                 oDevice = null;             }             //System.Runtime.InteropServices.Marshal.ReleaseComObject(pCollection);             if (iMde != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(iMde);                 iMde = null;             }             if (oEnumerator != null)             {                 System.Runtime.InteropServices.Marshal.ReleaseComObject(oEnumerator);                 oEnumerator = null;             }         }         #endregion         #region Private internal functions         private void MixerChange()         {             /*             if (MixerChanged != null)             // Notify (raise) event             MixerChanged();             */         }         #endregion         #region Public properties         /// <summary>         /// Get/set the master mute. WARNING : The set mute do NOT work!         /// </summary>         public bool Mute         {             get             {                 bool mute = false;                 int retVal = iAudioEndpoint.GetMute(ref mute);                 if (retVal != 0)                 {                     throw new Exception("IAudioEndpointVolume.GetMute() failed!");                 }                 return mute;             }             set             {                 //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null                 // {dddddddd-dddd-dddd-dddd-dddddddddddd}                 Guid nullGuid = Guid.Empty;                 bool mute = value;                 // TODO                 // Problem #2 : This function always terminate with an internal error!                 int retVal = iAudioEndpoint.SetMute(Convert.ToInt32(mute), nullGuid);                 if (retVal != 0)                 {                     throw new Exception("IAudioEndpointVolume.SetMute() failed!");                 }             }         }         /// <summary>         /// Get/set the master volume level. Valid range is from 0.00F (0%) to 1.00F (100%).         /// </summary>         public float MasterVolume         {             get             {                 float level = 0.0F;                 int retVal = iAudioEndpoint.GetMasterVolumeLevelScalar(ref level);                 if (retVal != 0)                 {                     throw new Exception("IAudioEndpointVolume.GetMasterVolumeLevelScalar()");                 }                 return level;             }             set             {                 float level = value;                 Guid nullGuid;                 //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null                 // {dddddddd-dddd-dddd-dddd-dddddddddddd}                 nullGuid = Guid.Empty;                 int retVal = iAudioEndpoint.SetMasterVolumeLevelScalar(level, nullGuid);                 if (retVal != 0)                 {                     throw new Exception("IAudioEndpointVolume.SetMasterVolumeLevelScalar()");                 }             }         }         #endregion         #region Public Methods         /// <summary>         /// Increase the master volume         /// </summary>         public void VolumeUp()         {             Guid nullGuid;             //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null             // {dddddddd-dddd-dddd-dddd-dddddddddddd}             nullGuid = Guid.Empty;             int retVal = iAudioEndpoint.VolumeStepUp(nullGuid);             if (retVal != 0)             {                 throw new Exception("IAudioEndpointVolume.SetMute()");             }         }         /// <summary>         /// Decrease the master volume         /// </summary>         public void VolumeDown()         {             Guid nullGuid;             //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null             // {dddddddd-dddd-dddd-dddd-dddddddddddd}             nullGuid = Guid.Empty;             int retVal = iAudioEndpoint.VolumeStepDown(nullGuid);         }         #endregion     } }