Sound Utils : Windows API « Windows « C# / C Sharp






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

   
    
  








Related examples in the same category

1.DLL: GetVersionEx
2.Keyboard timer: GetTickCountKeyboard timer: GetTickCount
3.BitBlt
4.Get the Total Free Space on a Drive by using kernel32.dll
5.imports three functions to display the vertical and horizontal size of the screen.
6.MessageBox from user32.dll
7.Get OS Version from kernel32.dll
8.imports the printf function
9.import CreateDirectory and FormatMessage
10.marshals string for unmanaged memory as ANSI.
11.imports the GetModuleHandleW function specifically
12.Set mouse and keyboard hooks.
13.Returns the HRESULT associated with the given error code.