locked
How to set the volume? RRS feed

  • Question

  • How can I adjust the volume from my program?
    Saturday, July 19, 2014 6:09 PM

Answers

  • There is a way that works on every OS and give total control over every sound channels. It is to access the COM interfaces directly

    You can Mute, un-mute, adjust the volume, adjust the decibels, etc ... for every channels/speakers independently

    It also handles the events coming from the COM audioEndPoint

    This code is interesting when you have a several speakers connected to your sound card

    It sure don't meet the User requirement of being simple and I am just posting this code as info for who ever may need it.

    I've made a test application some time ago

    So, if you like that kind of thing, have fun

    -

    -

    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Button1.Text = "Mute"
            Button2.Text = "Un-Mute"
            Button3.Text = "Down"
            Button4.Text = "Up"
            Button5.Text = "SetVolume"
            Button6.Text = "GetVolume"
            Button7.Text = "GetMaxStep"
            Button8.Text = "CurrentStep"
            Button9.Text = "MaxDB"
            Button10.Text = "MinDB"
            Button11.Text = "IncremDB"
            Button12.Text = "MSetDB -20"
            Button13.Text = "GetDB"
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Using epVol As New EndpointVolume()
                epVol.Mute = True
            End Using
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Using epVol As New EndpointVolume()
                epVol.Mute = False
            End Using
        End Sub
    
        Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
            Using epVol As New EndpointVolume()
                epVol.VolumeDown()
            End Using
        End Sub
    
        Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
            Using epVol As New EndpointVolume()
                epVol.VolumeUp()
            End Using
        End Sub
    
        Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
            Using epVol As New EndpointVolume()
                epVol.MasterVolume = 0.5
            End Using
        End Sub
    
        Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
            Using epVol As New EndpointVolume()
                Button6.Text = CStr(epVol.MasterVolume)
            End Using
        End Sub
    
        Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
            Using epVol As New EndpointVolume()
                Button7.Text = CStr(epVol.GetMaxVolumeStep)
            End Using
        End Sub
    
        Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
            Using epVol As New EndpointVolume()
                Button8.Text = CStr(epVol.GetCurrentVolumeStep)
            End Using
        End Sub
    
        Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
            Using epVol As New EndpointVolume()
                Button9.Text = CStr(epVol.MaxVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
            Using epVol As New EndpointVolume()
                Button10.Text = CStr(epVol.MinVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button11.Click
            Using epVol As New EndpointVolume()
                Button11.Text = CStr(epVol.IncrementVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button12_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button12.Click
            Using epVol As New EndpointVolume()
                epVol.MasterVolumeDecibel = -20
            End Using
        End Sub
    
        Private Sub Button13_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button13.Click
            Using epVol As New EndpointVolume()
                Button13.Text = CStr(epVol.MasterVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button14_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button14.Click
            Using epVol As New EndpointVolume()
                Button14.Text = CStr(epVol.GetNumberOfChannel)
            End Using
        End Sub
    
        Private Sub Button15_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button15.Click
            Using epVol As New EndpointVolume()
                Button15.Text = epVol.GetHardwareSupport.ToString
            End Using
        End Sub
    
        Private Sub Button16_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button16.Click
            Using epVol As New EndpointVolume()
                epVol.ChannelVolume(1) = 0.1
            End Using
        End Sub
    
        Private Sub Button18_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button18.Click
            Using epVol As New EndpointVolume()
                Button18.Text = CStr(epVol.ChannelVolumeDecibel(0))
            End Using
        End Sub
    
        Private Sub Button17_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button17.Click
            Using epVol As New EndpointVolume()
                epVol.ChannelVolumeDecibel(0) = -60
            End Using
        End Sub
    
        'ReportVolumeChanged
        Private EP As EndpointVolume
        Private Sub Button19_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button19.Click
            EP = New EndpointVolume()
            EP.ReportVolumeChanged = True
            AddHandler EP.VolumeChanged, AddressOf EP_VolumeChanged
        End Sub
    
        Private Sub EP_VolumeChanged(ByVal s As Object, ByVal e As NotifyVolumeChangedEventArgs)
            Me.BackColor = Color.Red
        End Sub
    
        Private Sub Button20_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button20.Click
            EP.ReportVolumeChanged = False
        End Sub
    End Class
    
    
    
    
    
    
    
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks>
    ''' The methods of this class do not dispose of the COM objects when they throw.
    ''' if the class is not creating by a "Using" scope,...
    ''' The User must catch the exceptions and dispose of those objects by calling Dispose if the application
    ''' must be aborted or the if the class instance gets abandonned.
    ''' 
    ''' This class represent the default Audio device renderer (Output).
    ''' To get a end point for different audio device, the constructor can call the IMMDeviceEnumerator.EnumAudioEndpoints to get a list of the 
    ''' available audio devices and then call the IMMDeviceEnumerator.GetDevice instead of GetDefaultAudioEndpoint.
    ''' I have put in the code the signature for the interface IMMDeviceCollection, as it can be usefull to an implementation handling
    ''' other device than the default Audio device.
    ''' 
    ''' 
    ''' </remarks>
    Public Class EndpointVolume : Implements IDisposable
    
        'Unmanaged Objects
        Private oIMMDE As Object = Nothing
        Private IMMDE As IMMDeviceEnumerator = Nothing
        Private oDefaultDevice As Object = Nothing
        Private IMM_DefaultDevice As IMMDevice = Nothing
        Private oVolumeEndPoint As Object = Nothing
        Private iAudioEndpoint As IAudioEndpointVolume = Nothing
    
    
    #Region " Constructor "
    
        Public Sub New()
            'Create a IMMDeviceEnumerator object
            Dim IID_IUnknown As Guid = New Guid("00000000-0000-0000-C000-000000000046")
            Dim IMMDE_clsid As Guid = New Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")
            If CoCreateInstance(IMMDE_clsid, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IUnknown, oIMMDE) Then
                Throw New EndPointVolumeException("Failed:  CoCreateInstance", CCI)
            Else
                'COM cast it to our interface
                IMMDE = CType(oIMMDE, IMMDeviceEnumerator)
                If IMMDE Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IMMDeviceEnumerator", "")
                End If
            End If
    
            'Get the default audio device end point object from the IMMDeviceEnumerator
            Dim pDefaultDevice As IntPtr = IntPtr.Zero
            'Get a pointer to the COM object
            If IMMDE.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, pDefaultDevice) Then
                Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.GetDefaultAudioEndpoint()", IMMDE_HL)
            Else
                'Get the object
                oDefaultDevice = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pDefaultDevice)
                'COM cast it to our interface
                IMM_DefaultDevice = CType(oDefaultDevice, IMMDevice)
                If IMM_DefaultDevice Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IMMDevice", "")
                End If
            End If
    
            'create a AudioVolumeEndPoint object with IMMDevice.activate for our default device
            Dim iid As Guid = New Guid("5CDF2C82-841E-4546-9722-0CF74078229A")
            Dim pActivationParams As IntPtr = IntPtr.Zero
            Dim pVolumeEndPoint As IntPtr = IntPtr.Zero
            'Get the pointer to the COM object
            If IMM_DefaultDevice.Activate(iid, CUInt(CLSCTX.CLSCTX_ALL), pActivationParams, pVolumeEndPoint) Then
                Throw New EndPointVolumeException("Failed: IMMDevice.Activate", IMMD_HL)
            Else
                'Get the object
                oVolumeEndPoint = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pVolumeEndPoint)
                'COM cast it to our interface
                iAudioEndpoint = CType(oVolumeEndPoint, IAudioEndpointVolume)
                If iAudioEndpoint Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IAudioEndpointVolume", "")
                End If
            End If
    
    
            'Dim ppProperties As IntPtr
            'IMM_DefaultDevice.OpenPropertyStore(0, ppProperties)
            'Dim oPropertiesStore = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(ppProperties)
            'Dim PROPERTYSTORE As IPropertyStore = CType(oPropertiesStore, IPropertyStore)
    
            'Dim nb As UInteger
            'PROPERTYSTORE.GetCount(nb)
    
            'Dim Pk As New PROPERTYKEY
            'PROPERTYSTORE.GetAt(1, Pk) '<---------Returns a valid PROPERTYKEY
    
            'Dim s = Marshal.SizeOf(Pk)
            'Dim pPropvalue As New PropVariant 'IntPtr = IntPtr.Zero
            'PROPERTYSTORE.GetValue(Pk, pPropvalue)
    
            'Stop
            'If (PROPERTYSTORE IsNot Nothing) Then
            '    System.Runtime.InteropServices.Marshal.ReleaseComObject(PROPERTYSTORE)
            '    PROPERTYSTORE = Nothing
            'End If
        End Sub
    
        '****************************************************************************
        'TO USE A DEVICE OTHER THAN THE DEFAULT RENDERING ONE:
    
        'Create a IMMDeviceEnumerator
    
        'Enumerate the ACTIVE devices
        '   Dim dwStateMask As Integer = DEVICE_STATE_ACTIVE
        '   Dim pCollection As IntPtr = IntPtr.Zero
        '   Dim retVal = IMMDE.EnumAudioEndpoints(EDataFlow.eRender, dwStateMask, pCollection)
    
        'Then call GetDevice selecting an active device
    
        'Then call Activate and cast the object to the IAudioEndpointVolume interface
        '*****************************************************************************
    
    
    
        'PKEY_DeviceInterface_FriendlyName 
    
        'The friendly name of the audio adapter to which the endpoint device is attached (for example, "XYZ Audio Adapter"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.
    
    
    
        'PKEY_Device_DeviceDesc 
    
        'The device description of the endpoint device (for example, "Speakers"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the device description.
    
    
    
        'PKEY_Device_FriendlyName 
    
        'The friendly name of the endpoint device (for example, "Speakers (XYZ Audio Adapter)"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.
    
    
    #End Region
    
    
    #Region " IDisposable "
    
        Private disposedValue As Boolean
    
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If IsReportingVolumeChanged Then
                    ReportVolumeChanged = False
                End If
                If IsReportingDeviceChanged Then
                    ReportDevicePropertyChanged = False
                End If
                If (iAudioEndpoint IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(iAudioEndpoint) > 0 : End While
                    iAudioEndpoint = Nothing
                End If
                If (oVolumeEndPoint IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oVolumeEndPoint) > 0 : End While
                    oVolumeEndPoint = Nothing
                End If
                If (IMM_DefaultDevice IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(IMM_DefaultDevice) > 0 : End While
                    IMM_DefaultDevice = Nothing
                End If
                If (oDefaultDevice IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oDefaultDevice) > 0 : End While
                    oDefaultDevice = Nothing
                End If
                If (IMMDE IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(IMMDE) > 0 : End While
                    IMMDE = Nothing
                End If
                If (oIMMDE IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oIMMDE) > 0 : End While
                    oIMMDE = Nothing
                End If
            End If
            Me.disposedValue = True
        End Sub
    
        Protected Overrides Sub Finalize()
            Dispose(False)
            MyBase.Finalize()
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
    
    #End Region
    
    
    #Region " EndpointVolume: Wrapper's methods  (Exposed methods, Callbacks and Helpers) "
    
        '******** EVENTS ************************************************************************
    
        Public Event VolumeChanged(ByVal sender As Object, ByVal e As NotifyVolumeChangedEventArgs)
        Public Event DefaultDeviceChanged(ByVal sender As Object, ByVal e As DefaultDeviceChangedEventArgs)
        Public Event DeviceAdded(ByVal sender As Object, ByVal e As DeviceAddedEventArgs)
        Public Event DeviceRemoved(ByVal sender As Object, ByVal e As DeviceRemovedEventArgs)
        Public Event DeviceStateChanged(ByVal sender As Object, ByVal e As DeviceStateChangedEventArgs)
        Public Event DevicePropertyValueChanged(ByVal sender As Object, ByVal e As PropertyValueChangedEventArgs)
    
        Private IsReportingVolumeChanged As Boolean = False
        Private IsReportingDeviceChanged As Boolean = False
    
        'Our notification reporting objects
        Private VolumeNotification As AudioEndpointVolumeCallback
        Private DeviceNotification As MMNotificationClient
    
    
        ''' <summary>
        ''' Set or Get a value that indicate if the AudioEndPoint will raise the device five events or not. By default the events are not raised
        ''' </summary>
        Public Property ReportDevicePropertyChanged As Boolean
            Get
                Return IsReportingDeviceChanged
            End Get
            Set(ByVal value As Boolean)
                If value Then
                    If Not IsReportingDeviceChanged Then
                        DeviceNotification = New MMNotificationClient
                        DeviceNotification.HookOnDeviceAdded(AddressOf OnDeviceAdded)
                        DeviceNotification.HookOnDeviceRemoved(AddressOf OnDeviceRemoved)
                        DeviceNotification.HookOnDeviceStateChanged(AddressOf OnDeviceStateChanged)
                        DeviceNotification.HookOnPropertyValueChanged(AddressOf OnPropertyValueChanged)
                        DeviceNotification.HookOnDefaultDeviceChanged(AddressOf OnDefaultDeviceChanged)
                        Dim retVal As Integer = IMMDE.RegisterEndpointNotificationCallback(DeviceNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.RegisterEndpointNotificationCallback", IMMDE_HL)
                        End If
                        IsReportingDeviceChanged = True
                    End If
                Else
                    If IsReportingDeviceChanged Then
                        Dim retVal As Integer = IMMDE.UnregisterEndpointNotificationCallback(DeviceNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.UnregisterEndpointNotificationCallback", IMMDE_HL)
                        End If
                        IsReportingDeviceChanged = False
                        DeviceNotification = Nothing
                    End If
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Set or Get a value that indicate if the AudioEndPoint will raise the VolumeChanged event or not. By default the event is not raised
        ''' </summary>
        Public Property ReportVolumeChanged As Boolean
            Get
                Return IsReportingVolumeChanged
            End Get
            Set(ByVal value As Boolean)
                If value Then
                    If Not IsReportingVolumeChanged Then
                        VolumeNotification = New AudioEndpointVolumeCallback
                        VolumeNotification.HookCallback(AddressOf OnVolumeNotification)
                        Dim retVal As Integer = iAudioEndpoint.RegisterControlChangeNotify(VolumeNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.RegisterControlChangeNotify", IAEPV_HL)
                        End If
                        IsReportingVolumeChanged = True
                    End If
                Else
                    If IsReportingVolumeChanged Then
                        Dim retVal As Integer = iAudioEndpoint.UnregisterControlChangeNotify(VolumeNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.UnregisterControlChangeNotify", IAEPV_HL)
                        End If
                        IsReportingVolumeChanged = False
                        VolumeNotification = Nothing
                    End If
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Raise the VolumeChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface IAudioEndpointVolumeCallback</remarks>
        Protected Overridable Sub OnVolumeNotification(ByVal e As NotifyVolumeChangedEventArgs)
            RaiseEvent VolumeChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceStateChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceStateChanged(ByVal e As DeviceStateChangedEventArgs)
            RaiseEvent DeviceStateChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceAdded event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceAdded(ByVal e As DeviceAddedEventArgs)
            RaiseEvent DeviceAdded(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceRemoved event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceRemoved(ByVal e As DeviceRemovedEventArgs)
            RaiseEvent DeviceRemoved(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DefaultDeviceChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDefaultDeviceChanged(ByVal e As DefaultDeviceChangedEventArgs)
            RaiseEvent DefaultDeviceChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the PropertyValueChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnPropertyValueChanged(ByVal e As PropertyValueChangedEventArgs)
            RaiseEvent DevicePropertyValueChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Mute or Un-Mute the computer master volume
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        Public Property Mute(Optional ByVal ContextGuid As Guid = Nothing) As Boolean
            Get
                Dim IsMuted As Boolean = False
                Dim retVal As Integer = iAudioEndpoint.GetMute(IsMuted)
                If retVal <> 0 Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMute", IAEPV_HL)
                End If
                Return IsMuted
            End Get
            Set(ByVal value As Boolean)
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMute(Convert.ToInt32(value), ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMute", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        '******** MASTER VOLUME CONTROL ****************************************************************
    
        ''' <summary>
        ''' Set or get the master volume setting
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value>A value between 0.0 and 1.0 : 1.0 being the maximum volume</value>
        ''' <returns></returns>
        Public Property MasterVolume(Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetMasterVolumeLevelScalar(level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMasterVolumeLevelScalar", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                Dim level As Single = value
                If level < 0 Then level = 0
                If level > 1 Then level = 1
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMasterVolumeLevelScalar(level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMasterVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Get or set the maximum decibel allow by the master volume
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value>To get the minimum and maximum allowed values, Use the functions MaxVolumeDecibel and MinVolumeDecibel. Typically -64db to 0db</value>
        ''' <returns></returns>
        Public Property MasterVolumeDecibel(Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetMasterVolumeLevel(level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMasterVolumeLevel", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                Dim level As Single = value
                If level < MinVolumeDecibel() Then level = MinVolumeDecibel()
                If level > MaxVolumeDecibel() Then level = MaxVolumeDecibel()
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMasterVolumeLevel(level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMasterVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Change the volume to one step up. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <remarks></remarks>
        Public Sub VolumeUp(Optional ByVal ContextGuid As Guid = Nothing)
            If ContextGuid = Nothing Then ContextGuid = Guid.Empty
            Dim retVal As Integer = iAudioEndpoint.VolumeStepUp(ContextGuid)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.VolumeStepUp", IAEPV_HL)
            End If
        End Sub
    
    
        ''' <summary>
        ''' Change the volume to one step down. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <remarks></remarks>
        Public Sub VolumeDown(Optional ByVal ContextGuid As Guid = Nothing)
            If ContextGuid = Nothing Then ContextGuid = Guid.Empty
            Dim retVal As Integer = iAudioEndpoint.VolumeStepDown(ContextGuid)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.VolumeStepDown", IAEPV_HL)
            End If
        End Sub
    
    
        ''' <summary>
        ''' Returns the total amount of volume steps defined by the device between the minimum volume and the maximum volume
        ''' </summary>
        Public Function GetMaxVolumeStep() As UInteger
            Dim MaxStep As UInteger
            Dim CurrentStep As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetVolumeStepInfo(CurrentStep, MaxStep)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeStepInfo", IAEPV_HL)
            End If
            Return MaxStep
        End Function
    
    
        ''' <summary>
        ''' Return the current volume setting in volume step. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetCurrentVolumeStep() As UInteger
            Dim MaxStep As UInteger
            Dim CurrentStep As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetVolumeStepInfo(CurrentStep, MaxStep)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeStepInfo", IAEPV_HL)
            End If
            Return CurrentStep
        End Function
    
    
        ''' <summary>
        ''' Get the minimum volume decibel
        ''' </summary>
        Public Function MinVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return MinVol
        End Function
    
    
        ''' <summary>
        ''' Get the maximum volume decibel
        ''' </summary>
        Public Function MaxVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return MaxVol
        End Function
    
    
        ''' <summary>
        ''' Get the size of the smallest decibel increment that will be create an decibel volume change
        ''' </summary>
        Public Function IncrementVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return IncrVol
        End Function
    
    
        '****** CHANNELS VOLUME CONTROL ***************************************************************************
    
        ''' <summary>
        ''' Get or set the volume of a specified channel
        ''' </summary>
        ''' <param name="channel"></param>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value></value>
        Public Property ChannelVolume(ByVal channel As UInteger, Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim retVal As Integer = iAudioEndpoint.GetChannelVolumeLevelScalar(channel, level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetChannelVolumeLevelScalar", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = value
                If level < 0 Then level = 0
                If level > 1 Then level = 1
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetChannelVolumeLevelScalar(channel, level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetChannelVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Get or set the decibel volume of a specified channel
        ''' </summary>
        ''' <param name="channel"></param>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value></value>
        Public Property ChannelVolumeDecibel(ByVal channel As UInteger, Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetChannelVolumeLevel(channel, level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetChannelVolumeLevel", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = value
                If level < MinVolumeDecibel() Then level = MinVolumeDecibel()
                If level > MaxVolumeDecibel() Then level = MaxVolumeDecibel()
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetChannelVolumeLevel(channel, level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetChannelVolumeLevel", IAEPV_HL)
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Return the number of channel for the device
        ''' </summary>
        Public Function GetNumberOfChannel() As UInteger
            Dim ChanleNb As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetChannelCount(ChanleNb)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetChannelCount", IAEPV_HL)
            End If
            Return ChanleNb
        End Function
    
    
        '******* DEVICES ******************************************************************
    
        ''' <summary>
        ''' Get the unique ID for the device
        ''' </summary>
        Public Function GetDeviceID() As String
            Dim DevID As String = ""
            Dim retVal As Integer = IMM_DefaultDevice.GetId(DevID)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: IMMDevice.GetId", IMMD_HL)
            End If
            Return DevID
        End Function
    
        ''' <summary>
        ''' Get the device state ( Active, Disabled, unplugged, not present )
        ''' </summary>
        Public Function GetDeviceState() As IMMDeviceStatesFlags
            Dim State As IMMDeviceStatesFlags
            Dim retVal As Integer = IMM_DefaultDevice.GetState(State)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: IMMDevice.GetState", IMMD_HL)
            End If
            Return State
        End Function
    
        ''' <summary>
        ''' Get the support provided by the hardware for this device ( SupportsVolume, SupportsMute, SupportsMeter)
        ''' </summary>
        Public Function GetHardwareSupport() As EndPointHardwareSupportFlags
            Dim State As EndPointHardwareSupportFlags
            Dim retVal As Integer = iAudioEndpoint.QueryHardwareSupport(State)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.QueryHardwareSupport", IAEPV_HL)
            End If
            Return State
        End Function
    
    #End Region
    
    
    #Region " COM Interfaces "
    
        'Exception links
        Private IAEPV_HL As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/dd370892(v=vs.85).aspx"
        Private IMMD_HL As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/dd371395(v=vs.85).aspx"
        Private IMMDE_HL As String = " http://msdn.microsoft.com/en-us/library/windows/desktop/dd371399(v=vs.85).aspx"
        Private CCI As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/ms686615(v=vs.85).aspx"
    
    
        '********** PINVOKE ****************************************************************
        <DllImport("ole32.Dll")>
        Private Shared Function CoCreateInstance(ByRef clsid As Guid,
            <MarshalAs(UnmanagedType.IUnknown)> ByVal inner As Object,
            ByVal context As Integer,
            ByRef uuid As Guid,
            <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As Boolean
        End Function
    
        '****** COM INTERFACES ********************************************************************
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd370892(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        '''C Header Interface declaration: Mmdeviceapi.h 
        '''HRESULT RegisterControlChangeNotify(/* [in] */__in IAudioEndpointVolumeCallback *pNotify) = 0;
        '''HRESULT UnregisterControlChangeNotify(/* [in] */ __in IAudioEndpointVolumeCallback *pNotify) = 0;
        '''HRESULT GetChannelCount(/* [out] */ __out UINT *pnChannelCount) = 0;
        '''HRESULT SetMasterVolumeLevel( /* [in] */ __in float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT SetMasterVolumeLevelScalar( /* [in] */ __in float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetMasterVolumeLevel(/* [out] */ __out float *pfLevelDB) = 0;
        '''HRESULT GetMasterVolumeLevelScalar( /* [out] */ __out float *pfLevel) = 0;
        '''HRESULT SetChannelVolumeLevel(/* [in] */__in UINT nChannel,float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT SetChannelVolumeLevelScalar(/* [in] */ __in UINT nChannel,float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetChannelVolumeLevel(/* [in] */ __in UINT nChannel,/* [out] */__out float *pfLevelDB) = 0;
        '''HRESULT GetChannelVolumeLevelScalar(/* [in] */__in UINT nChannel,/* [out] */__out float *pfLevel) = 0;
        '''HRESULT SetMute( /* [in] *__in BOOL bMute, /* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetMute( /* [out] */ __out BOOL *pbMute) = 0;
        '''HRESULT GetVolumeStepInfo( /* [out] */ __out UINT *pnStep,/* [out] */__out UINT *pnStepCount) = 0;
        '''HRESULT VolumeStepUp( /* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT VolumeStepDown(/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT QueryHardwareSupport(/* [out] */ __out DWORD *pdwHardwareSupportMask) = 0;
        '''HRESULT GetVolumeRange( /* [out] */ __out float *pflVolumeMindB,/* [out] */ __out float *pflVolumeMaxdB,/* [out] */ __out float *pflVolumeIncrementdB) = 0;
        '''</remarks>
        <Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IAudioEndpointVolume
            Function RegisterControlChangeNotify(ByVal pNotify As IAudioEndpointVolumeCallback) As Integer '<------------Tested
            Function UnregisterControlChangeNotify(ByVal pNotify As IAudioEndpointVolumeCallback) As Integer '<------------Tested
            Function GetChannelCount(ByRef pnChannelCount As UInteger) As Integer '<------------Tested
            Function SetMasterVolumeLevel(ByVal fLevelDB As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function SetMasterVolumeLevelScalar(ByVal fLevel As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetMasterVolumeLevel(ByRef pfLevelDB As Single) As Integer '<------------Tested
            Function GetMasterVolumeLevelScalar(ByRef pfLevel As Single) As Integer '<------------Tested
            Function SetChannelVolumeLevel(ByVal nChannel As UInteger, ByVal fLevelDB As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function SetChannelVolumeLevelScalar(ByVal nChannel As UInteger, ByVal fLevel As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetChannelVolumeLevel(ByVal nChannel As UInteger, ByRef pfLevelDB As Single) As Integer '<------------Tested
            Function GetChannelVolumeLevelScalar(ByVal nChannel As UInteger, ByRef pfLevel As Single) As Integer '<------------Tested
            Function SetMute(ByVal bMute As Integer, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetMute(ByRef pbMute As Boolean) As Integer '<------------Tested
            Function GetVolumeStepInfo(ByRef pnStep As UInteger, ByRef pnStepCount As UInteger) As Integer '<------------Tested`
            Function VolumeStepUp(ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function VolumeStepDown(ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function QueryHardwareSupport(ByRef pdwHardwareSupportMask As EndPointHardwareSupportFlags) As Integer '<------------Tested
            Function GetVolumeRange(ByRef pflVolumeMindB As Single, ByRef pflVolumeMaxdB As Single, ByRef pflVolumeIncrementdB As Single) As Integer '<------------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd370894(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C Header
        ''' HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) = 0;
        '''  </remarks>
        <Guid("657804FA-D6AD-4496-8A60-352752AF4F89"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IAudioEndpointVolumeCallback
            Sub OnNotify(ByVal pNotifyData As IntPtr)  '<--------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        '''  C Header
        '''  HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(/* [in] */ __in  LPCWSTR pwstrDeviceId,/* [in] */ __in  DWORD dwNewState) = 0; 
        '''  HRESULT STDMETHODCALLTYPE OnDeviceAdded(/* [in] */ __in  LPCWSTR pwstrDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnDeviceRemoved(/* [in] */ __in  LPCWSTR pwstrDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(/* [in] */ __in  EDataFlow flow,/* [in] */__in  ERole role,/* [in] */__in  LPCWSTR pwstrDefaultDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(/* [in] */ __in  LPCWSTR pwstrDeviceId, /* [in] */__in  const PROPERTYKEY key) = 0;
        '''  </remarks>
        <Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMNotificationClient
            Sub OnDeviceStateChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger) '<------Implemented, not fully tested
            Sub OnDeviceAdded(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String) '<------Implemented, not fully tested
            Sub OnDeviceRemoved(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String) '<------Implemented, not fully tested
            Sub OnDefaultDeviceChanged(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal flow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDefaultDeviceId As String) '<------Implemented, not fully tested
            Sub OnPropertyValueChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal key As _tagpropertykey) '<------Implemented, not fully tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371396(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' HRESULT GetCount([out, annotation("__out")] UINT* pcDevices);
        ''' HRESULT Item([in, annotation("__in")]UINT nDevice, [out, annotation("__out")] IMMDevice** ppDevice);
        ''' </remarks>
        <Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceCollection
            Function GetCount(ByRef pcDevices As UInteger) As Integer '***************
            Function Item(ByVal nDevice As UInteger, ByRef ppDevice As IntPtr) As Integer '************
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371395(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C header
        ''' 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);
        ''' HRESULT OpenPropertyStore([in, annotation("__in")] DWORD stgmAccess, [out, annotation("__out")] IPropertyStore** ppProperties);
        ''' HRESULT GetId([out,annotation("__deref_out")] LPWSTR* ppstrId);
        ''' HRESULT GetState([out, annotation("__out")] DWORD* pdwState);
        '''</remarks>
        <Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDevice
            Function Activate(ByRef iid As Guid, ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, ByRef ppInterface As IntPtr) As Boolean '<-----Tested
            Function OpenPropertyStore(ByVal stgmAccess As Integer, ByRef ppProperties As IntPtr) As Integer '***************
            Function GetId(<MarshalAs(UnmanagedType.LPWStr)> ByRef ppstrId As String) As Integer '<--------Tested
            Function GetState(ByRef pdwState As IMMDeviceStatesFlags) As Integer '<--------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371399(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C header
        ''' HRESULT EnumAudioEndpoints([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] DWORD dwStateMask, [out, annotation("__out")] IMMDeviceCollection** ppDevices);
        ''' HRESULT GetDefaultAudioEndpoint([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] ERole role, [out, annotation("__out")] IMMDevice** ppEndpoint);
        ''' HRESULT GetDevice([, annotation("__in")]LPCWSTR pwstrId, [out, annotation("__out")] IMMDevice** ppDevice);
        ''' HRESULT RegisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);
        ''' HRESULT UnregisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);
        ''' </remarks>
        <Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceEnumerator
            Function EnumAudioEndpoints(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, ByVal dwStateMask As Integer, ByRef ppDevices As IntPtr) As Integer '************
            Function GetDefaultAudioEndpoint(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, ByRef ppEndpoint As IntPtr) As Boolean '<-----  Tested
            Function GetDevice(ByVal pwstrId As String, ByRef ppDevice As IntPtr) As Integer '*******************
            Function RegisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer '<------Implemented, not fully tested
            Function UnregisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer '<------Implemented, not fully tested
        End Interface
    
    
        '*********** ENUMERATION *****************************************************
    
        <Flags()>
        Private Enum CLSCTX
            CLSCTX_INPROC_SERVER = &H1
            CLSCTX_INPROC_HANDLER = &H2
            CLSCTX_LOCAL_SERVER = &H4
            CLSCTX_INPROC_SERVER16 = &H8
            CLSCTX_REMOTE_SERVER = &H10
            CLSCTX_INPROC_HANDLER16 = &H20
            CLSCTX_RESERVED1 = &H40
            CLSCTX_RESERVED2 = &H80
            CLSCTX_RESERVED3 = &H100
            CLSCTX_RESERVED4 = &H200
            CLSCTX_NO_CODE_DOWNLOAD = &H400
            CLSCTX_RESERVED5 = &H800
            CLSCTX_NO_CUSTOM_MARSHAL = &H1000
            CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
            CLSCTX_NO_FAILURE_LOG = &H4000
            CLSCTX_DISABLE_AAA = &H8000
            CLSCTX_ENABLE_AAA = &H10000
            CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
            CLSCTX_ALL = CLSCTX_SERVER Or CLSCTX_INPROC_HANDLER
        End Enum
    
    
        Private Enum EDataFlow
            eRender
            eCapture
            eAll
            EDataFlow_enum_count
        End Enum
    
    
        Private Enum ERole
            eConsole
            eMultimedia
            eCommunications
            ERole_enum_count
        End Enum
    
        '****** STRUCTURES ******************************************************************
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure AUDIO_VOLUME_NOTIFICATION_DATA 'Total: 32 bytes
            Dim guidEventContext As Guid '16
            Dim bMuted As Boolean '4
            Dim fMasterVolume As Single '4
            Dim nChannels As UInteger '4
            <MarshalAs(UnmanagedType.ByValArray)> Dim afChannelVolumes() As Single '4
        End Structure
    
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure _tagpropertykey
            Dim fmtid As Guid
            Dim pid As UInteger
        End Structure
    
    #End Region
    
    
    #Region " Notification reporting objects implementation "
        '******** NOTIFICATION OBJECTS IMPLEMENTATION *************************************************
    
        ''' <remarks>This provide the implementation for our interface IAudioEndpointVolumeCallback</remarks>
        Private Class AudioEndpointVolumeCallback : Implements IAudioEndpointVolumeCallback
    
            ''' <remarks>Forward the notification to the EndpointVolume class</remarks>
            Private Callback As Action(Of NotifyVolumeChangedEventArgs)
            Public Sub HookCallback(ByVal Callback As Action(Of NotifyVolumeChangedEventArgs))
                Me.Callback = Callback
            End Sub
    
            ''' <remarks>Called by the system when the system volume change
            ''' The structure is crazy to Marshal !! The data extend pass the end of the structure (See documentation for AUDIO_VOLUME_NOTIFICATION_DATA)</remarks>
            Private Sub OnNotify(ByVal pNotifyData As IntPtr) Implements IAudioEndpointVolumeCallback.OnNotify
                If Callback IsNot Nothing Then
                    Dim Data As AUDIO_VOLUME_NOTIFICATION_DATA
                    Data = CType(Marshal.PtrToStructure(pNotifyData, GetType(AUDIO_VOLUME_NOTIFICATION_DATA)), AUDIO_VOLUME_NOTIFICATION_DATA)
                    pNotifyData += 32
                    Dim ChannelVolume(CInt(Data.nChannels) - 1) As Single
                    ChannelVolume(0) = CSng(Math.Round(CDbl(Data.afChannelVolumes(0)), 1))
                    For i As Integer = 1 To CInt(Data.nChannels) - 1
                        Dim SingleAsByte(3) As Byte
                        Marshal.Copy(pNotifyData, SingleAsByte, 0, 4)
                        ChannelVolume(i) = CSng(Math.Round(CDbl(BitConverter.ToSingle(SingleAsByte, 0)), 1))
                        pNotifyData += 4
                    Next
                    Dim e As New NotifyVolumeChangedEventArgs(Data.guidEventContext, Data.bMuted, Data.fMasterVolume, ChannelVolume, CInt(Data.nChannels))
                    Callback(e)
                End If
            End Sub
        End Class
    
    
    
        ''' <remarks>This provide the implementation for our interface IMMNotificationClient</remarks>
        Private Class MMNotificationClient : Implements IMMNotificationClient
    
            Private CallbackOnDefaultDeviceChanged As Action(Of DefaultDeviceChangedEventArgs)
            Public Sub HookOnDefaultDeviceChanged(ByVal Callback As Action(Of DefaultDeviceChangedEventArgs))
                CallbackOnDefaultDeviceChanged = Callback
            End Sub
    
            Public Sub OnDefaultDeviceChanged(ByVal flow As EDataFlow, ByVal role As ERole, ByVal pwstrDefaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged
                If CallbackOnDefaultDeviceChanged IsNot Nothing Then
                    Dim CRole As DeviceRole = CType(role, DeviceRole)
                    Dim Cflow As AudioFlow = CType(flow, AudioFlow)
                    Dim e As New DefaultDeviceChangedEventArgs(Cflow, CRole, pwstrDefaultDeviceId)
                    CallbackOnDefaultDeviceChanged(e)
                End If
            End Sub
    
            Private CallbackOnDeviceAdded As Action(Of DeviceAddedEventArgs)
            Public Sub HookOnDeviceAdded(ByVal Callback As Action(Of DeviceAddedEventArgs))
                CallbackOnDeviceAdded = Callback
            End Sub
    
            Public Sub OnDeviceAdded(ByVal pwstrDeviceId As String) Implements IMMNotificationClient.OnDeviceAdded
                If CallbackOnDeviceAdded IsNot Nothing Then
                    Dim e As New DeviceAddedEventArgs(pwstrDeviceId)
                    CallbackOnDeviceAdded(e)
                End If
            End Sub
    
            Private CallbackOnDeviceRemoved As Action(Of DeviceRemovedEventArgs)
            Public Sub HookOnDeviceRemoved(ByVal Callback As Action(Of DeviceRemovedEventArgs))
                CallbackOnDeviceRemoved = Callback
            End Sub
    
            Public Sub OnDeviceRemoved(ByVal pwstrDeviceId As String) Implements IMMNotificationClient.OnDeviceRemoved
                If CallbackOnDeviceRemoved IsNot Nothing Then
                    Dim e As New DeviceRemovedEventArgs(pwstrDeviceId)
                    CallbackOnDeviceRemoved(e)
                End If
            End Sub
    
            Private CallbackOnDeviceStateChanged As Action(Of DeviceStateChangedEventArgs)
            Public Sub HookOnDeviceStateChanged(ByVal Callback As Action(Of DeviceStateChangedEventArgs))
                CallbackOnDeviceStateChanged = Callback
            End Sub
    
            Public Sub OnDeviceStateChanged(ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger) Implements IMMNotificationClient.OnDeviceStateChanged
                If CallbackOnDeviceStateChanged IsNot Nothing Then
                    Dim e As New DeviceStateChangedEventArgs(pwstrDeviceId, dwNewState)
                    CallbackOnDeviceStateChanged(e)
                End If
            End Sub
    
            Private CallbackOnPropertyValueChanged As Action(Of PropertyValueChangedEventArgs)
            Public Sub HookOnPropertyValueChanged(ByVal Callback As Action(Of PropertyValueChangedEventArgs))
                CallbackOnPropertyValueChanged = Callback
            End Sub
    
            Public Sub OnPropertyValueChanged(ByVal pwstrDeviceId As String, ByVal key As _tagpropertykey) Implements IMMNotificationClient.OnPropertyValueChanged
                If CallbackOnPropertyValueChanged IsNot Nothing Then
                    Dim e As New PropertyValueChangedEventArgs(pwstrDeviceId, key.fmtid, key.pid)
                    CallbackOnPropertyValueChanged(e)
                End If
            End Sub
        End Class
    
    #End Region
    
    End Class
    
    
    #Region " Event arguments "
    '********** EVENT ARGUMENTS ************************************************************
    ''' <summary>
    ''' Event argument associated with the EndpointVolume.VolumeChanged event
    ''' </summary>
    Public Class NotifyVolumeChangedEventArgs : Inherits EventArgs
        Public EventContextGuid As Guid
        Public Muted As Boolean
        Public MasterVolume As Single
        Public ChannelsVolume() As Single
        Public NbChannel As Integer
        Sub New(ByVal EventContextGuid As Guid, ByVal Muted As Boolean, ByVal MasterVolume As Single, ByVal ChannelsVolume() As Single, ByVal NbChannel As Integer)
            Me.EventContextGuid = EventContextGuid
            Me.Muted = Muted
            Me.MasterVolume = MasterVolume
            Me.ChannelsVolume = ChannelsVolume
            Me.NbChannel = NbChannel
        End Sub
    End Class
    
    Public Class DefaultDeviceChangedEventArgs : Inherits EventArgs
    
        Public AudioFlow As AudioFlow
        Public DeviceRole As DeviceRole
        Public DeviceID As String
        Public Sub New(ByVal Flow As AudioFlow, ByVal role As DeviceRole, ByVal ID As String)
            Me.AudioFlow = AudioFlow
            Me.DeviceRole = DeviceRole
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceAddedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public Sub New(ByVal ID As String)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceRemovedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public Sub New(ByVal ID As String)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceStateChangedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public NewState As IMMDeviceStatesFlags
        Public Sub New(ByVal ID As String, ByVal NewState As UInteger)
            Me.NewState = CType(NewState, IMMDeviceStatesFlags)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class PropertyValueChangedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public PropertyID As UInteger
        Public UniquePropertyID As Guid
        Public Sub New(ByVal ID As String, ByVal fmtid As Guid, ByVal PropertyID As UInteger)
            Me.DeviceID = ID
            Me.PropertyID = PropertyID
            Me.UniquePropertyID = fmtid
        End Sub
    End Class
    
    #End Region
    
    
    '********** EXCEPTION CLASS **********************************************************
    
    Public Class EndPointVolumeException : Inherits Exception
        Public Sub New(ByVal m As String, ByVal HL As String)
            MyBase.New(m)
            Me.HelpLink = HL
        End Sub
    End Class
    
    
    #Region "Public enumerations"
    '********* PUBLIC ENUM **************************************************************
    
    <Flags()>
    Public Enum IMMDeviceStatesFlags
        DEVICE_STATE_ACTIVE = 1
        DEVICE_STATE_DISABLED = 2
        DEVICE_STATE_NOTPRESENT = 4
        DEVICE_STATE_UNPLUGGED = 8
    End Enum
    
    
    
    <Flags()>
    Public Enum EndPointHardwareSupportFlags
        SupportsVolume = 1
        SupportsMute = 2
        SupportsMeter = 4
    End Enum
    
    
    
    Public Enum AudioFlow
        RenderAudio
        CaptureAudio
        RenderAndCaptureAudio
        EDataFlow_enum_count
    End Enum
    
    
    
    Public Enum DeviceRole
        Console
        Multimedia
        Communications
        ERole_enum_count
    End Enum
    
    #End Region

    Friday, July 25, 2014 12:44 PM
  • I just saw your post IronRazerz and the code works but Option Strict On altered some of it due to conversion issues.

    I placed a copy of the CoreAudioAPI.Dll, created by building the appropriate project from the download, into my apps project folder and browse/ref'd it as well as using the Imports statement which is unecessary once the .Dll is ref'd of course.

    Also I ran the app in VS Debugger and the TrackBar was at the value that the volume control was at when the app finished loading.

    So Razerz email me if you want me to send you the apps zip folder that I downloaded. It's small.

    Option Strict On
    
    Imports CoreAudioApi
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            TrackBar1.Maximum = 100
            TrackBar1.Value = GetVolume()
        End Sub
    
        Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
            SetVolume(TrackBar1.Value)
        End Sub
    
        ' Gets the volume level as an integer
        Private Function GetVolume() As Integer
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            Return CInt(CStr(CInt(mmDev.AudioEndpointVolume.MasterVolumeLevelScalar * 100)))
        End Function
    
        'Sets the volume to the integer
        Private Sub SetVolume(ByVal Level As Integer)
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            mmDev.AudioEndpointVolume.MasterVolumeLevelScalar = CSng((Level / 100))
        End Sub
    
    
    End Class


    La vida loca


    Monday, July 21, 2014 5:38 AM
  • Hi,

     If you want to just set the volume to maximum then you will need to download the Sample Project from the link below and add a reference to the CoreAudio.dll file in the unzipped folder to your project. Then you can use this code.

    Vista Core Audio API Master Volume Control

    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            SetVolume(100)
        End Sub
    
        Private Sub SetVolume(ByVal Level As Integer)
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            mmDev.AudioEndpointVolume.MasterVolumeLevelScalar = CSng(Level / 100)
        End Sub
    
    End Class

     I don`t know if it will work on XP so if you want the code for XP that i have then i will show you that but, it is longer and more complicated.   :)

     

    EDIT : I misread you post this morning and thought you said you wanted it at minimum so i fixed this to show how to set the volume to Maximum.


    If you say it can`t be done then i`ll try it

    Friday, July 25, 2014 9:25 AM

All replies

  • Saturday, July 19, 2014 6:12 PM
  • Option Strict On
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        Private Const APPCOMMAND_VOLUME_MUTE As Integer = &H80000
        Private Const APPCOMMAND_VOLUME_UP As Integer = &HA0000
        Private Const APPCOMMAND_VOLUME_DOWN As Integer = &H90000
        Private Const WM_APPCOMMAND As Integer = &H319
    
        <DllImport("user32.dll")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        Dim TrkBar1 As Integer = 0
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            TrackBar1.Minimum = 0
            TrackBar1.Maximum = 50
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_MUTE))
        End Sub
    
        Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll
            If TrackBar1.Value > TrkBar1 Then
                SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_UP))
            End If
            If TrackBar1.Value < TrkBar1 Then
                SendMessageW(Me.Handle, WM_APPCOMMAND, Me.Handle, New IntPtr(APPCOMMAND_VOLUME_DOWN))
            End If
    
            TrkBar1 = TrackBar1.Value
        End Sub
    
    End Class
    


    La vida loca

    Sunday, July 20, 2014 3:41 AM
  • Hi,

     Here is another way to do it using the keybd_event API that uses 3 buttons on the form for Volume Up, Down, and Mute. I looked at the link that Ioana gave but, that is code for VB5 and VB6 so it will not work in VB.Net. However, i have been trying to convert it into VB.Net so if i get it working i will post it. It seems to have a problem i have not figured out yet.   8)

    Public Class Form1
        Private Const KEYEVENTF_KEYUP As Integer = &H2
        Private Const KEYEVENTF_KEYDOWN As Integer = &H0
    
        <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="keybd_event")> _
        Private Shared Sub keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As UInteger, ByVal dwExtraInfo As UInteger)
        End Sub
    
        Private Sub Button_Up_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Up.Click
            keybd_event(CByte(Keys.VolumeUp), 0, KEYEVENTF_KEYDOWN, 0)
            keybd_event(CByte(Keys.VolumeUp), 0, KEYEVENTF_KEYUP, 0)
        End Sub
    
        Private Sub Button_Down_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Down.Click
            keybd_event(CByte(Keys.VolumeDown), 0, KEYEVENTF_KEYDOWN, 0)
            keybd_event(CByte(Keys.VolumeDown), 0, KEYEVENTF_KEYUP, 0)
        End Sub
    
        Private Sub Button_Mute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Mute.Click
            keybd_event(CByte(Keys.VolumeMute), 0, KEYEVENTF_KEYDOWN, 0)
            keybd_event(CByte(Keys.VolumeMute), 0, KEYEVENTF_KEYUP, 0)
        End Sub
    End Class
    


    If you say it can`t be done then i`ll try it

    Sunday, July 20, 2014 4:33 AM
  • Nice code IronRazerz. Yeah I saw that code Ioana Vasilescu provided a link to but it seemed rather much just for changing the volume and muting. Although if the mixer code worked that would be nice.

    I read Ioana's profile the first time I saw a post from her. She's got a Master of Science (MS), Distributed Systems and Web Technologies. Anyhow she's from Romania.

    I was there working out of the airport in Bucharest for about 60 days with the equivalent of the FAA in Romania for a satellite system install. Worked with their head engineer who was also a member of ICAO. We went to numerous towns and cities installing systems all around the country. It's a beautiful country and great food too. Plus everybody makes their own palinka which is some kind of brandy made from plums. But that stuff is like 180 grain alcohol and everybody wanted you to drink some that they made. We would stop by some of the engineers parents houses while traveling around the country and they would give you palinka, then feed you, then give you more palinka till you were smashed! 8)~


    La vida loca



    Sunday, July 20, 2014 7:05 AM
  • @ Mr. Mpnkeyboy,

    Well, i have tried once or twice before to figure it out and get some of the code to work on my own because, it would be nice for the times when you need to select the Mic or LineIn and adjust there recording levels from your apps instead of having to open the Mixer and set it from your program. The first time i tried i didn`t make it far, the second time i tried i got to where i could at least read some of the info from the mixer controls, and i figure maybe the third time will be the charm.

     Yes, i see Ioana poped up yesterday and i had never seen her around before so i checked out her profile also. She seems to be a very nice smart young lady, and a pretty one too.  8)

     I have never had a chance to go to Romania but, it sounds like a fun place. You sure have done a lot of interesting things in your time.  :)


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Sunday, July 20, 2014 10:24 AM
    Sunday, July 20, 2014 10:23 AM
  • Hey John Ap. You have three open threads on this page. Does that mean nobody answered any of your questions?

    La vida loca

    Sunday, July 20, 2014 11:35 PM
  • I have managed to get the part using the Win32 API`s to adjust the volume and turn the Mute on and off but, i have some more work to do to it before i will post any code for it. I have found that if you are using Vista, Win7, or Win8 then you can use the Vista Core Audio API found at the link below to adjust your volume. They have changed the way they control the volume settings in the newer OS`s so i am not sure as the API`s i am working on will work for the newer OS`s or not.

    Vista Core Audio API Master Volume Control

     Here is a code that i believe should work for using a TrackBar to adjust the volume but, i have not tested it yet. Maybe Mr. Monkeyboy or someone will test it real quick and see if there are any flaws with it. You will need to download the dll from the CodeProject link and add a reference to it.

    Imports CoreAudioApi
    
    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            TrackBar1.Maximum = 100
            TrackBar1.Value = GetVolume()
        End Sub
    
        Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
            SetVolume(TrackBar1.Value)
        End Sub
    
        ' Gets the volume level as an integer
        Private Function GetVolume() As Integer
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            Return CStr(CInt(mmDev.AudioEndpointVolume.MasterVolumeLevelScalar * 100))
        End Function
    
        'Sets the volume to the integer
        Private Sub SetVolume(ByVal Level As Integer)
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            mmDev.AudioEndpointVolume.MasterVolumeLevelScalar = (Level / 100)
        End Sub
    
    End Class
    


    If you say it can`t be done then i`ll try it

    Monday, July 21, 2014 12:06 AM
  • I just saw your post IronRazerz and the code works but Option Strict On altered some of it due to conversion issues.

    I placed a copy of the CoreAudioAPI.Dll, created by building the appropriate project from the download, into my apps project folder and browse/ref'd it as well as using the Imports statement which is unecessary once the .Dll is ref'd of course.

    Also I ran the app in VS Debugger and the TrackBar was at the value that the volume control was at when the app finished loading.

    So Razerz email me if you want me to send you the apps zip folder that I downloaded. It's small.

    Option Strict On
    
    Imports CoreAudioApi
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            TrackBar1.Maximum = 100
            TrackBar1.Value = GetVolume()
        End Sub
    
        Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
            SetVolume(TrackBar1.Value)
        End Sub
    
        ' Gets the volume level as an integer
        Private Function GetVolume() As Integer
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            Return CInt(CStr(CInt(mmDev.AudioEndpointVolume.MasterVolumeLevelScalar * 100)))
        End Function
    
        'Sets the volume to the integer
        Private Sub SetVolume(ByVal Level As Integer)
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            mmDev.AudioEndpointVolume.MasterVolumeLevelScalar = CSng((Level / 100))
        End Sub
    
    
    End Class


    La vida loca


    Monday, July 21, 2014 5:38 AM
  • @ Mr. Monkeyboy,

     You know, i didn`t even notice the Return line in the GetVolume sub was being converted to a string which eill not work because it is suppose to return an integer. You should be able to change that line to how it is shown below. The way it is in your code, it actually is being converted to an integer then to a string and then back to an integer.

    Return CInt(mmDev.AudioEndpointVolume.MasterVolumeLevelScalar * 100)

     That was my mistake, i was going to return it as a string to be shown in a lable and then decided to make the GetVolume function return an integer so it could be used to set the TrackBar directly without a conversion from a String to an integer. Being i don`t have .Net 4.0 on this machine i couldn`t test it and Option Strict didn`t point out the problems to me. I was guessing by what i read and seen on the net. I will have to instal VS on my Vista machine so i can test it on there.

     I have the project and the Demo app from CodeProject if thats the one your talking about but, have not looked at any of it really. I have been busy playing with the Win32 API`s which work on my XP machine. I hope to build a Class that has the Win32 API`s and will reference the Vista Core Audio API and then have it made to check the version of windows it is being used on so it knows to access the Win32 API`s if it is on XP and the Vista Core Audio API if it is on Vista or above.


    If you say it can`t be done then i`ll try it

    Monday, July 21, 2014 10:53 AM
  • Is there a simple way to just turn the volume to maximum?
    Friday, July 25, 2014 9:01 AM
  • Hi,

     If you want to just set the volume to maximum then you will need to download the Sample Project from the link below and add a reference to the CoreAudio.dll file in the unzipped folder to your project. Then you can use this code.

    Vista Core Audio API Master Volume Control

    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            SetVolume(100)
        End Sub
    
        Private Sub SetVolume(ByVal Level As Integer)
            Dim mmDevEnum As New MMDeviceEnumerator()
            Dim mmDev As MMDevice = mmDevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)
            mmDev.AudioEndpointVolume.MasterVolumeLevelScalar = CSng(Level / 100)
        End Sub
    
    End Class

     I don`t know if it will work on XP so if you want the code for XP that i have then i will show you that but, it is longer and more complicated.   :)

     

    EDIT : I misread you post this morning and thought you said you wanted it at minimum so i fixed this to show how to set the volume to Maximum.


    If you say it can`t be done then i`ll try it

    Friday, July 25, 2014 9:25 AM
  • Is there a simple way to just turn the volume to maximum?

    Yeah. Click on the volume control in the task bar and move the slider to max.

    La vida loca

    Friday, July 25, 2014 10:47 AM
  • There is a way that works on every OS and give total control over every sound channels. It is to access the COM interfaces directly

    You can Mute, un-mute, adjust the volume, adjust the decibels, etc ... for every channels/speakers independently

    It also handles the events coming from the COM audioEndPoint

    This code is interesting when you have a several speakers connected to your sound card

    It sure don't meet the User requirement of being simple and I am just posting this code as info for who ever may need it.

    I've made a test application some time ago

    So, if you like that kind of thing, have fun

    -

    -

    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Button1.Text = "Mute"
            Button2.Text = "Un-Mute"
            Button3.Text = "Down"
            Button4.Text = "Up"
            Button5.Text = "SetVolume"
            Button6.Text = "GetVolume"
            Button7.Text = "GetMaxStep"
            Button8.Text = "CurrentStep"
            Button9.Text = "MaxDB"
            Button10.Text = "MinDB"
            Button11.Text = "IncremDB"
            Button12.Text = "MSetDB -20"
            Button13.Text = "GetDB"
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Using epVol As New EndpointVolume()
                epVol.Mute = True
            End Using
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Using epVol As New EndpointVolume()
                epVol.Mute = False
            End Using
        End Sub
    
        Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
            Using epVol As New EndpointVolume()
                epVol.VolumeDown()
            End Using
        End Sub
    
        Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
            Using epVol As New EndpointVolume()
                epVol.VolumeUp()
            End Using
        End Sub
    
        Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
            Using epVol As New EndpointVolume()
                epVol.MasterVolume = 0.5
            End Using
        End Sub
    
        Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
            Using epVol As New EndpointVolume()
                Button6.Text = CStr(epVol.MasterVolume)
            End Using
        End Sub
    
        Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
            Using epVol As New EndpointVolume()
                Button7.Text = CStr(epVol.GetMaxVolumeStep)
            End Using
        End Sub
    
        Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
            Using epVol As New EndpointVolume()
                Button8.Text = CStr(epVol.GetCurrentVolumeStep)
            End Using
        End Sub
    
        Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
            Using epVol As New EndpointVolume()
                Button9.Text = CStr(epVol.MaxVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
            Using epVol As New EndpointVolume()
                Button10.Text = CStr(epVol.MinVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button11_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button11.Click
            Using epVol As New EndpointVolume()
                Button11.Text = CStr(epVol.IncrementVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button12_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button12.Click
            Using epVol As New EndpointVolume()
                epVol.MasterVolumeDecibel = -20
            End Using
        End Sub
    
        Private Sub Button13_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button13.Click
            Using epVol As New EndpointVolume()
                Button13.Text = CStr(epVol.MasterVolumeDecibel)
            End Using
        End Sub
    
        Private Sub Button14_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button14.Click
            Using epVol As New EndpointVolume()
                Button14.Text = CStr(epVol.GetNumberOfChannel)
            End Using
        End Sub
    
        Private Sub Button15_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button15.Click
            Using epVol As New EndpointVolume()
                Button15.Text = epVol.GetHardwareSupport.ToString
            End Using
        End Sub
    
        Private Sub Button16_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button16.Click
            Using epVol As New EndpointVolume()
                epVol.ChannelVolume(1) = 0.1
            End Using
        End Sub
    
        Private Sub Button18_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button18.Click
            Using epVol As New EndpointVolume()
                Button18.Text = CStr(epVol.ChannelVolumeDecibel(0))
            End Using
        End Sub
    
        Private Sub Button17_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button17.Click
            Using epVol As New EndpointVolume()
                epVol.ChannelVolumeDecibel(0) = -60
            End Using
        End Sub
    
        'ReportVolumeChanged
        Private EP As EndpointVolume
        Private Sub Button19_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button19.Click
            EP = New EndpointVolume()
            EP.ReportVolumeChanged = True
            AddHandler EP.VolumeChanged, AddressOf EP_VolumeChanged
        End Sub
    
        Private Sub EP_VolumeChanged(ByVal s As Object, ByVal e As NotifyVolumeChangedEventArgs)
            Me.BackColor = Color.Red
        End Sub
    
        Private Sub Button20_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button20.Click
            EP.ReportVolumeChanged = False
        End Sub
    End Class
    
    
    
    
    
    
    
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks>
    ''' The methods of this class do not dispose of the COM objects when they throw.
    ''' if the class is not creating by a "Using" scope,...
    ''' The User must catch the exceptions and dispose of those objects by calling Dispose if the application
    ''' must be aborted or the if the class instance gets abandonned.
    ''' 
    ''' This class represent the default Audio device renderer (Output).
    ''' To get a end point for different audio device, the constructor can call the IMMDeviceEnumerator.EnumAudioEndpoints to get a list of the 
    ''' available audio devices and then call the IMMDeviceEnumerator.GetDevice instead of GetDefaultAudioEndpoint.
    ''' I have put in the code the signature for the interface IMMDeviceCollection, as it can be usefull to an implementation handling
    ''' other device than the default Audio device.
    ''' 
    ''' 
    ''' </remarks>
    Public Class EndpointVolume : Implements IDisposable
    
        'Unmanaged Objects
        Private oIMMDE As Object = Nothing
        Private IMMDE As IMMDeviceEnumerator = Nothing
        Private oDefaultDevice As Object = Nothing
        Private IMM_DefaultDevice As IMMDevice = Nothing
        Private oVolumeEndPoint As Object = Nothing
        Private iAudioEndpoint As IAudioEndpointVolume = Nothing
    
    
    #Region " Constructor "
    
        Public Sub New()
            'Create a IMMDeviceEnumerator object
            Dim IID_IUnknown As Guid = New Guid("00000000-0000-0000-C000-000000000046")
            Dim IMMDE_clsid As Guid = New Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")
            If CoCreateInstance(IMMDE_clsid, Nothing, CLSCTX.CLSCTX_INPROC_SERVER, IID_IUnknown, oIMMDE) Then
                Throw New EndPointVolumeException("Failed:  CoCreateInstance", CCI)
            Else
                'COM cast it to our interface
                IMMDE = CType(oIMMDE, IMMDeviceEnumerator)
                If IMMDE Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IMMDeviceEnumerator", "")
                End If
            End If
    
            'Get the default audio device end point object from the IMMDeviceEnumerator
            Dim pDefaultDevice As IntPtr = IntPtr.Zero
            'Get a pointer to the COM object
            If IMMDE.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, pDefaultDevice) Then
                Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.GetDefaultAudioEndpoint()", IMMDE_HL)
            Else
                'Get the object
                oDefaultDevice = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pDefaultDevice)
                'COM cast it to our interface
                IMM_DefaultDevice = CType(oDefaultDevice, IMMDevice)
                If IMM_DefaultDevice Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IMMDevice", "")
                End If
            End If
    
            'create a AudioVolumeEndPoint object with IMMDevice.activate for our default device
            Dim iid As Guid = New Guid("5CDF2C82-841E-4546-9722-0CF74078229A")
            Dim pActivationParams As IntPtr = IntPtr.Zero
            Dim pVolumeEndPoint As IntPtr = IntPtr.Zero
            'Get the pointer to the COM object
            If IMM_DefaultDevice.Activate(iid, CUInt(CLSCTX.CLSCTX_ALL), pActivationParams, pVolumeEndPoint) Then
                Throw New EndPointVolumeException("Failed: IMMDevice.Activate", IMMD_HL)
            Else
                'Get the object
                oVolumeEndPoint = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pVolumeEndPoint)
                'COM cast it to our interface
                iAudioEndpoint = CType(oVolumeEndPoint, IAudioEndpointVolume)
                If iAudioEndpoint Is Nothing Then
                    Throw New EndPointVolumeException("Failed: COM cast to IAudioEndpointVolume", "")
                End If
            End If
    
    
            'Dim ppProperties As IntPtr
            'IMM_DefaultDevice.OpenPropertyStore(0, ppProperties)
            'Dim oPropertiesStore = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(ppProperties)
            'Dim PROPERTYSTORE As IPropertyStore = CType(oPropertiesStore, IPropertyStore)
    
            'Dim nb As UInteger
            'PROPERTYSTORE.GetCount(nb)
    
            'Dim Pk As New PROPERTYKEY
            'PROPERTYSTORE.GetAt(1, Pk) '<---------Returns a valid PROPERTYKEY
    
            'Dim s = Marshal.SizeOf(Pk)
            'Dim pPropvalue As New PropVariant 'IntPtr = IntPtr.Zero
            'PROPERTYSTORE.GetValue(Pk, pPropvalue)
    
            'Stop
            'If (PROPERTYSTORE IsNot Nothing) Then
            '    System.Runtime.InteropServices.Marshal.ReleaseComObject(PROPERTYSTORE)
            '    PROPERTYSTORE = Nothing
            'End If
        End Sub
    
        '****************************************************************************
        'TO USE A DEVICE OTHER THAN THE DEFAULT RENDERING ONE:
    
        'Create a IMMDeviceEnumerator
    
        'Enumerate the ACTIVE devices
        '   Dim dwStateMask As Integer = DEVICE_STATE_ACTIVE
        '   Dim pCollection As IntPtr = IntPtr.Zero
        '   Dim retVal = IMMDE.EnumAudioEndpoints(EDataFlow.eRender, dwStateMask, pCollection)
    
        'Then call GetDevice selecting an active device
    
        'Then call Activate and cast the object to the IAudioEndpointVolume interface
        '*****************************************************************************
    
    
    
        'PKEY_DeviceInterface_FriendlyName 
    
        'The friendly name of the audio adapter to which the endpoint device is attached (for example, "XYZ Audio Adapter"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.
    
    
    
        'PKEY_Device_DeviceDesc 
    
        'The device description of the endpoint device (for example, "Speakers"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the device description.
    
    
    
        'PKEY_Device_FriendlyName 
    
        'The friendly name of the endpoint device (for example, "Speakers (XYZ Audio Adapter)"). PROPVARIANT member vt is set to VT_LPWSTR and member pwszVal points to a null-terminated, wide-character string that contains the friendly name.
    
    
    #End Region
    
    
    #Region " IDisposable "
    
        Private disposedValue As Boolean
    
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If IsReportingVolumeChanged Then
                    ReportVolumeChanged = False
                End If
                If IsReportingDeviceChanged Then
                    ReportDevicePropertyChanged = False
                End If
                If (iAudioEndpoint IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(iAudioEndpoint) > 0 : End While
                    iAudioEndpoint = Nothing
                End If
                If (oVolumeEndPoint IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oVolumeEndPoint) > 0 : End While
                    oVolumeEndPoint = Nothing
                End If
                If (IMM_DefaultDevice IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(IMM_DefaultDevice) > 0 : End While
                    IMM_DefaultDevice = Nothing
                End If
                If (oDefaultDevice IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oDefaultDevice) > 0 : End While
                    oDefaultDevice = Nothing
                End If
                If (IMMDE IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(IMMDE) > 0 : End While
                    IMMDE = Nothing
                End If
                If (oIMMDE IsNot Nothing) Then
                    While System.Runtime.InteropServices.Marshal.ReleaseComObject(oIMMDE) > 0 : End While
                    oIMMDE = Nothing
                End If
            End If
            Me.disposedValue = True
        End Sub
    
        Protected Overrides Sub Finalize()
            Dispose(False)
            MyBase.Finalize()
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
    
    #End Region
    
    
    #Region " EndpointVolume: Wrapper's methods  (Exposed methods, Callbacks and Helpers) "
    
        '******** EVENTS ************************************************************************
    
        Public Event VolumeChanged(ByVal sender As Object, ByVal e As NotifyVolumeChangedEventArgs)
        Public Event DefaultDeviceChanged(ByVal sender As Object, ByVal e As DefaultDeviceChangedEventArgs)
        Public Event DeviceAdded(ByVal sender As Object, ByVal e As DeviceAddedEventArgs)
        Public Event DeviceRemoved(ByVal sender As Object, ByVal e As DeviceRemovedEventArgs)
        Public Event DeviceStateChanged(ByVal sender As Object, ByVal e As DeviceStateChangedEventArgs)
        Public Event DevicePropertyValueChanged(ByVal sender As Object, ByVal e As PropertyValueChangedEventArgs)
    
        Private IsReportingVolumeChanged As Boolean = False
        Private IsReportingDeviceChanged As Boolean = False
    
        'Our notification reporting objects
        Private VolumeNotification As AudioEndpointVolumeCallback
        Private DeviceNotification As MMNotificationClient
    
    
        ''' <summary>
        ''' Set or Get a value that indicate if the AudioEndPoint will raise the device five events or not. By default the events are not raised
        ''' </summary>
        Public Property ReportDevicePropertyChanged As Boolean
            Get
                Return IsReportingDeviceChanged
            End Get
            Set(ByVal value As Boolean)
                If value Then
                    If Not IsReportingDeviceChanged Then
                        DeviceNotification = New MMNotificationClient
                        DeviceNotification.HookOnDeviceAdded(AddressOf OnDeviceAdded)
                        DeviceNotification.HookOnDeviceRemoved(AddressOf OnDeviceRemoved)
                        DeviceNotification.HookOnDeviceStateChanged(AddressOf OnDeviceStateChanged)
                        DeviceNotification.HookOnPropertyValueChanged(AddressOf OnPropertyValueChanged)
                        DeviceNotification.HookOnDefaultDeviceChanged(AddressOf OnDefaultDeviceChanged)
                        Dim retVal As Integer = IMMDE.RegisterEndpointNotificationCallback(DeviceNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.RegisterEndpointNotificationCallback", IMMDE_HL)
                        End If
                        IsReportingDeviceChanged = True
                    End If
                Else
                    If IsReportingDeviceChanged Then
                        Dim retVal As Integer = IMMDE.UnregisterEndpointNotificationCallback(DeviceNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IMMDeviceEnumerator.UnregisterEndpointNotificationCallback", IMMDE_HL)
                        End If
                        IsReportingDeviceChanged = False
                        DeviceNotification = Nothing
                    End If
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Set or Get a value that indicate if the AudioEndPoint will raise the VolumeChanged event or not. By default the event is not raised
        ''' </summary>
        Public Property ReportVolumeChanged As Boolean
            Get
                Return IsReportingVolumeChanged
            End Get
            Set(ByVal value As Boolean)
                If value Then
                    If Not IsReportingVolumeChanged Then
                        VolumeNotification = New AudioEndpointVolumeCallback
                        VolumeNotification.HookCallback(AddressOf OnVolumeNotification)
                        Dim retVal As Integer = iAudioEndpoint.RegisterControlChangeNotify(VolumeNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.RegisterControlChangeNotify", IAEPV_HL)
                        End If
                        IsReportingVolumeChanged = True
                    End If
                Else
                    If IsReportingVolumeChanged Then
                        Dim retVal As Integer = iAudioEndpoint.UnregisterControlChangeNotify(VolumeNotification)
                        If retVal <> 0 Then
                            Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.UnregisterControlChangeNotify", IAEPV_HL)
                        End If
                        IsReportingVolumeChanged = False
                        VolumeNotification = Nothing
                    End If
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Raise the VolumeChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface IAudioEndpointVolumeCallback</remarks>
        Protected Overridable Sub OnVolumeNotification(ByVal e As NotifyVolumeChangedEventArgs)
            RaiseEvent VolumeChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceStateChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceStateChanged(ByVal e As DeviceStateChangedEventArgs)
            RaiseEvent DeviceStateChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceAdded event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceAdded(ByVal e As DeviceAddedEventArgs)
            RaiseEvent DeviceAdded(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DeviceRemoved event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDeviceRemoved(ByVal e As DeviceRemovedEventArgs)
            RaiseEvent DeviceRemoved(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the DefaultDeviceChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnDefaultDeviceChanged(ByVal e As DefaultDeviceChangedEventArgs)
            RaiseEvent DefaultDeviceChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Raise the PropertyValueChanged event
        ''' </summary>
        ''' <remarks>The event argument is provided by the implementation of the interface MMNotificationClient</remarks>
        Protected Overridable Sub OnPropertyValueChanged(ByVal e As PropertyValueChangedEventArgs)
            RaiseEvent DevicePropertyValueChanged(Me, e)
        End Sub
    
    
        ''' <summary>
        ''' Mute or Un-Mute the computer master volume
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        Public Property Mute(Optional ByVal ContextGuid As Guid = Nothing) As Boolean
            Get
                Dim IsMuted As Boolean = False
                Dim retVal As Integer = iAudioEndpoint.GetMute(IsMuted)
                If retVal <> 0 Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMute", IAEPV_HL)
                End If
                Return IsMuted
            End Get
            Set(ByVal value As Boolean)
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMute(Convert.ToInt32(value), ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMute", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        '******** MASTER VOLUME CONTROL ****************************************************************
    
        ''' <summary>
        ''' Set or get the master volume setting
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value>A value between 0.0 and 1.0 : 1.0 being the maximum volume</value>
        ''' <returns></returns>
        Public Property MasterVolume(Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetMasterVolumeLevelScalar(level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMasterVolumeLevelScalar", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                Dim level As Single = value
                If level < 0 Then level = 0
                If level > 1 Then level = 1
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMasterVolumeLevelScalar(level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMasterVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Get or set the maximum decibel allow by the master volume
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value>To get the minimum and maximum allowed values, Use the functions MaxVolumeDecibel and MinVolumeDecibel. Typically -64db to 0db</value>
        ''' <returns></returns>
        Public Property MasterVolumeDecibel(Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetMasterVolumeLevel(level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetMasterVolumeLevel", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                Dim level As Single = value
                If level < MinVolumeDecibel() Then level = MinVolumeDecibel()
                If level > MaxVolumeDecibel() Then level = MaxVolumeDecibel()
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetMasterVolumeLevel(level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetMasterVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Change the volume to one step up. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <remarks></remarks>
        Public Sub VolumeUp(Optional ByVal ContextGuid As Guid = Nothing)
            If ContextGuid = Nothing Then ContextGuid = Guid.Empty
            Dim retVal As Integer = iAudioEndpoint.VolumeStepUp(ContextGuid)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.VolumeStepUp", IAEPV_HL)
            End If
        End Sub
    
    
        ''' <summary>
        ''' Change the volume to one step down. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <remarks></remarks>
        Public Sub VolumeDown(Optional ByVal ContextGuid As Guid = Nothing)
            If ContextGuid = Nothing Then ContextGuid = Guid.Empty
            Dim retVal As Integer = iAudioEndpoint.VolumeStepDown(ContextGuid)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.VolumeStepDown", IAEPV_HL)
            End If
        End Sub
    
    
        ''' <summary>
        ''' Returns the total amount of volume steps defined by the device between the minimum volume and the maximum volume
        ''' </summary>
        Public Function GetMaxVolumeStep() As UInteger
            Dim MaxStep As UInteger
            Dim CurrentStep As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetVolumeStepInfo(CurrentStep, MaxStep)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeStepInfo", IAEPV_HL)
            End If
            Return MaxStep
        End Function
    
    
        ''' <summary>
        ''' Return the current volume setting in volume step. To know how many steps total the device has, use the function GetMaxVolumeStep
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetCurrentVolumeStep() As UInteger
            Dim MaxStep As UInteger
            Dim CurrentStep As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetVolumeStepInfo(CurrentStep, MaxStep)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeStepInfo", IAEPV_HL)
            End If
            Return CurrentStep
        End Function
    
    
        ''' <summary>
        ''' Get the minimum volume decibel
        ''' </summary>
        Public Function MinVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return MinVol
        End Function
    
    
        ''' <summary>
        ''' Get the maximum volume decibel
        ''' </summary>
        Public Function MaxVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return MaxVol
        End Function
    
    
        ''' <summary>
        ''' Get the size of the smallest decibel increment that will be create an decibel volume change
        ''' </summary>
        Public Function IncrementVolumeDecibel() As Single
            Dim MinVol As Single
            Dim MaxVol As Single
            Dim IncrVol As Single
            Dim retVal As Integer = iAudioEndpoint.GetVolumeRange(MinVol, MaxVol, IncrVol)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetVolumeRange", IAEPV_HL)
            End If
            Return IncrVol
        End Function
    
    
        '****** CHANNELS VOLUME CONTROL ***************************************************************************
    
        ''' <summary>
        ''' Get or set the volume of a specified channel
        ''' </summary>
        ''' <param name="channel"></param>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value></value>
        Public Property ChannelVolume(ByVal channel As UInteger, Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                Dim level As Single = 0.0
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim retVal As Integer = iAudioEndpoint.GetChannelVolumeLevelScalar(channel, level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetChannelVolumeLevelScalar", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = value
                If level < 0 Then level = 0
                If level > 1 Then level = 1
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetChannelVolumeLevelScalar(channel, level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetChannelVolumeLevelScalar", IAEPV_HL)
                End If
            End Set
        End Property
    
    
        ''' <summary>
        ''' Get or set the decibel volume of a specified channel
        ''' </summary>
        ''' <param name="channel"></param>
        ''' <param name="ContextGuid">[Optional] A Guid that will be passed by the NotifyVolumeChangedEventArgs to identify who changed the volume. 
        ''' If not specified, an empty Guid will be passed</param>
        ''' <value></value>
        Public Property ChannelVolumeDecibel(ByVal channel As UInteger, Optional ByVal ContextGuid As Guid = Nothing) As Single
            Get
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = 0.0
                Dim retVal As Integer = iAudioEndpoint.GetChannelVolumeLevel(channel, level)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.GetChannelVolumeLevel", IAEPV_HL)
                End If
                Return level
            End Get
            Set(ByVal value As Single)
                If channel > GetNumberOfChannel() - 1 Then
                    Throw New ArgumentOutOfRangeException("Channel value must be 0 to GetNumberOfChannel - 1")
                End If
                Dim level As Single = value
                If level < MinVolumeDecibel() Then level = MinVolumeDecibel()
                If level > MaxVolumeDecibel() Then level = MaxVolumeDecibel()
                If ContextGuid = Nothing Then ContextGuid = Guid.Empty
                Dim retVal As Integer = iAudioEndpoint.SetChannelVolumeLevel(channel, level, ContextGuid)
                If (retVal <> 0) Then
                    Throw New EndPointVolumeException("Failed: IAudioEndpointVolume.SetChannelVolumeLevel", IAEPV_HL)
                End If
            End Set
        End Property
    
    
    
        ''' <summary>
        ''' Return the number of channel for the device
        ''' </summary>
        Public Function GetNumberOfChannel() As UInteger
            Dim ChanleNb As UInteger
            Dim retVal As Integer = iAudioEndpoint.GetChannelCount(ChanleNb)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.GetChannelCount", IAEPV_HL)
            End If
            Return ChanleNb
        End Function
    
    
        '******* DEVICES ******************************************************************
    
        ''' <summary>
        ''' Get the unique ID for the device
        ''' </summary>
        Public Function GetDeviceID() As String
            Dim DevID As String = ""
            Dim retVal As Integer = IMM_DefaultDevice.GetId(DevID)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: IMMDevice.GetId", IMMD_HL)
            End If
            Return DevID
        End Function
    
        ''' <summary>
        ''' Get the device state ( Active, Disabled, unplugged, not present )
        ''' </summary>
        Public Function GetDeviceState() As IMMDeviceStatesFlags
            Dim State As IMMDeviceStatesFlags
            Dim retVal As Integer = IMM_DefaultDevice.GetState(State)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: IMMDevice.GetState", IMMD_HL)
            End If
            Return State
        End Function
    
        ''' <summary>
        ''' Get the support provided by the hardware for this device ( SupportsVolume, SupportsMute, SupportsMeter)
        ''' </summary>
        Public Function GetHardwareSupport() As EndPointHardwareSupportFlags
            Dim State As EndPointHardwareSupportFlags
            Dim retVal As Integer = iAudioEndpoint.QueryHardwareSupport(State)
            If retVal <> 0 Then
                Throw New EndPointVolumeException("Failed: iAudioEndpoint.QueryHardwareSupport", IAEPV_HL)
            End If
            Return State
        End Function
    
    #End Region
    
    
    #Region " COM Interfaces "
    
        'Exception links
        Private IAEPV_HL As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/dd370892(v=vs.85).aspx"
        Private IMMD_HL As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/dd371395(v=vs.85).aspx"
        Private IMMDE_HL As String = " http://msdn.microsoft.com/en-us/library/windows/desktop/dd371399(v=vs.85).aspx"
        Private CCI As String = "http://msdn.microsoft.com/en-us/library/windows/desktop/ms686615(v=vs.85).aspx"
    
    
        '********** PINVOKE ****************************************************************
        <DllImport("ole32.Dll")>
        Private Shared Function CoCreateInstance(ByRef clsid As Guid,
            <MarshalAs(UnmanagedType.IUnknown)> ByVal inner As Object,
            ByVal context As Integer,
            ByRef uuid As Guid,
            <MarshalAs(UnmanagedType.IUnknown)> ByRef rReturnedComObject As Object) As Boolean
        End Function
    
        '****** COM INTERFACES ********************************************************************
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd370892(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        '''C Header Interface declaration: Mmdeviceapi.h 
        '''HRESULT RegisterControlChangeNotify(/* [in] */__in IAudioEndpointVolumeCallback *pNotify) = 0;
        '''HRESULT UnregisterControlChangeNotify(/* [in] */ __in IAudioEndpointVolumeCallback *pNotify) = 0;
        '''HRESULT GetChannelCount(/* [out] */ __out UINT *pnChannelCount) = 0;
        '''HRESULT SetMasterVolumeLevel( /* [in] */ __in float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT SetMasterVolumeLevelScalar( /* [in] */ __in float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetMasterVolumeLevel(/* [out] */ __out float *pfLevelDB) = 0;
        '''HRESULT GetMasterVolumeLevelScalar( /* [out] */ __out float *pfLevel) = 0;
        '''HRESULT SetChannelVolumeLevel(/* [in] */__in UINT nChannel,float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT SetChannelVolumeLevelScalar(/* [in] */ __in UINT nChannel,float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetChannelVolumeLevel(/* [in] */ __in UINT nChannel,/* [out] */__out float *pfLevelDB) = 0;
        '''HRESULT GetChannelVolumeLevelScalar(/* [in] */__in UINT nChannel,/* [out] */__out float *pfLevel) = 0;
        '''HRESULT SetMute( /* [in] *__in BOOL bMute, /* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT GetMute( /* [out] */ __out BOOL *pbMute) = 0;
        '''HRESULT GetVolumeStepInfo( /* [out] */ __out UINT *pnStep,/* [out] */__out UINT *pnStepCount) = 0;
        '''HRESULT VolumeStepUp( /* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT VolumeStepDown(/* [unique][in] */ LPCGUID pguidEventContext) = 0;
        '''HRESULT QueryHardwareSupport(/* [out] */ __out DWORD *pdwHardwareSupportMask) = 0;
        '''HRESULT GetVolumeRange( /* [out] */ __out float *pflVolumeMindB,/* [out] */ __out float *pflVolumeMaxdB,/* [out] */ __out float *pflVolumeIncrementdB) = 0;
        '''</remarks>
        <Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IAudioEndpointVolume
            Function RegisterControlChangeNotify(ByVal pNotify As IAudioEndpointVolumeCallback) As Integer '<------------Tested
            Function UnregisterControlChangeNotify(ByVal pNotify As IAudioEndpointVolumeCallback) As Integer '<------------Tested
            Function GetChannelCount(ByRef pnChannelCount As UInteger) As Integer '<------------Tested
            Function SetMasterVolumeLevel(ByVal fLevelDB As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function SetMasterVolumeLevelScalar(ByVal fLevel As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetMasterVolumeLevel(ByRef pfLevelDB As Single) As Integer '<------------Tested
            Function GetMasterVolumeLevelScalar(ByRef pfLevel As Single) As Integer '<------------Tested
            Function SetChannelVolumeLevel(ByVal nChannel As UInteger, ByVal fLevelDB As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function SetChannelVolumeLevelScalar(ByVal nChannel As UInteger, ByVal fLevel As Single, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetChannelVolumeLevel(ByVal nChannel As UInteger, ByRef pfLevelDB As Single) As Integer '<------------Tested
            Function GetChannelVolumeLevelScalar(ByVal nChannel As UInteger, ByRef pfLevel As Single) As Integer '<------------Tested
            Function SetMute(ByVal bMute As Integer, ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function GetMute(ByRef pbMute As Boolean) As Integer '<------------Tested
            Function GetVolumeStepInfo(ByRef pnStep As UInteger, ByRef pnStepCount As UInteger) As Integer '<------------Tested`
            Function VolumeStepUp(ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function VolumeStepDown(ByVal pguidEventContext As Guid) As Integer '<------------Tested
            Function QueryHardwareSupport(ByRef pdwHardwareSupportMask As EndPointHardwareSupportFlags) As Integer '<------------Tested
            Function GetVolumeRange(ByRef pflVolumeMindB As Single, ByRef pflVolumeMaxdB As Single, ByRef pflVolumeIncrementdB As Single) As Integer '<------------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd370894(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C Header
        ''' HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) = 0;
        '''  </remarks>
        <Guid("657804FA-D6AD-4496-8A60-352752AF4F89"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IAudioEndpointVolumeCallback
            Sub OnNotify(ByVal pNotifyData As IntPtr)  '<--------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        '''  C Header
        '''  HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(/* [in] */ __in  LPCWSTR pwstrDeviceId,/* [in] */ __in  DWORD dwNewState) = 0; 
        '''  HRESULT STDMETHODCALLTYPE OnDeviceAdded(/* [in] */ __in  LPCWSTR pwstrDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnDeviceRemoved(/* [in] */ __in  LPCWSTR pwstrDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(/* [in] */ __in  EDataFlow flow,/* [in] */__in  ERole role,/* [in] */__in  LPCWSTR pwstrDefaultDeviceId) = 0;
        '''  HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(/* [in] */ __in  LPCWSTR pwstrDeviceId, /* [in] */__in  const PROPERTYKEY key) = 0;
        '''  </remarks>
        <Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMNotificationClient
            Sub OnDeviceStateChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger) '<------Implemented, not fully tested
            Sub OnDeviceAdded(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String) '<------Implemented, not fully tested
            Sub OnDeviceRemoved(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String) '<------Implemented, not fully tested
            Sub OnDefaultDeviceChanged(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal flow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDefaultDeviceId As String) '<------Implemented, not fully tested
            Sub OnPropertyValueChanged(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwstrDeviceId As String, ByVal key As _tagpropertykey) '<------Implemented, not fully tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371396(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' HRESULT GetCount([out, annotation("__out")] UINT* pcDevices);
        ''' HRESULT Item([in, annotation("__in")]UINT nDevice, [out, annotation("__out")] IMMDevice** ppDevice);
        ''' </remarks>
        <Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceCollection
            Function GetCount(ByRef pcDevices As UInteger) As Integer '***************
            Function Item(ByVal nDevice As UInteger, ByRef ppDevice As IntPtr) As Integer '************
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371395(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C header
        ''' 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);
        ''' HRESULT OpenPropertyStore([in, annotation("__in")] DWORD stgmAccess, [out, annotation("__out")] IPropertyStore** ppProperties);
        ''' HRESULT GetId([out,annotation("__deref_out")] LPWSTR* ppstrId);
        ''' HRESULT GetState([out, annotation("__out")] DWORD* pdwState);
        '''</remarks>
        <Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDevice
            Function Activate(ByRef iid As Guid, ByVal dwClsCtx As Integer, ByVal pActivationParams As IntPtr, ByRef ppInterface As IntPtr) As Boolean '<-----Tested
            Function OpenPropertyStore(ByVal stgmAccess As Integer, ByRef ppProperties As IntPtr) As Integer '***************
            Function GetId(<MarshalAs(UnmanagedType.LPWStr)> ByRef ppstrId As String) As Integer '<--------Tested
            Function GetState(ByRef pdwState As IMMDeviceStatesFlags) As Integer '<--------Tested
        End Interface
    
    
    
        ''' <summary>
        ''' http://msdn.microsoft.com/en-us/library/windows/desktop/dd371399(v=vs.85).aspx
        ''' </summary>
        ''' <remarks>
        ''' C header
        ''' HRESULT EnumAudioEndpoints([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] DWORD dwStateMask, [out, annotation("__out")] IMMDeviceCollection** ppDevices);
        ''' HRESULT GetDefaultAudioEndpoint([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] ERole role, [out, annotation("__out")] IMMDevice** ppEndpoint);
        ''' HRESULT GetDevice([, annotation("__in")]LPCWSTR pwstrId, [out, annotation("__out")] IMMDevice** ppDevice);
        ''' HRESULT RegisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);
        ''' HRESULT UnregisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient);
        ''' </remarks>
        <Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Private Interface IMMDeviceEnumerator
            Function EnumAudioEndpoints(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, ByVal dwStateMask As Integer, ByRef ppDevices As IntPtr) As Integer '************
            Function GetDefaultAudioEndpoint(<ComAliasName("MMDeviceAPILib.EDataFlow")> ByVal dataFlow As EDataFlow, <ComAliasName("MMDeviceAPILib.ERole")> ByVal role As ERole, ByRef ppEndpoint As IntPtr) As Boolean '<-----  Tested
            Function GetDevice(ByVal pwstrId As String, ByRef ppDevice As IntPtr) As Integer '*******************
            Function RegisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer '<------Implemented, not fully tested
            Function UnregisterEndpointNotificationCallback(ByVal pClient As IMMNotificationClient) As Integer '<------Implemented, not fully tested
        End Interface
    
    
        '*********** ENUMERATION *****************************************************
    
        <Flags()>
        Private Enum CLSCTX
            CLSCTX_INPROC_SERVER = &H1
            CLSCTX_INPROC_HANDLER = &H2
            CLSCTX_LOCAL_SERVER = &H4
            CLSCTX_INPROC_SERVER16 = &H8
            CLSCTX_REMOTE_SERVER = &H10
            CLSCTX_INPROC_HANDLER16 = &H20
            CLSCTX_RESERVED1 = &H40
            CLSCTX_RESERVED2 = &H80
            CLSCTX_RESERVED3 = &H100
            CLSCTX_RESERVED4 = &H200
            CLSCTX_NO_CODE_DOWNLOAD = &H400
            CLSCTX_RESERVED5 = &H800
            CLSCTX_NO_CUSTOM_MARSHAL = &H1000
            CLSCTX_ENABLE_CODE_DOWNLOAD = &H2000
            CLSCTX_NO_FAILURE_LOG = &H4000
            CLSCTX_DISABLE_AAA = &H8000
            CLSCTX_ENABLE_AAA = &H10000
            CLSCTX_FROM_DEFAULT_CONTEXT = &H20000
            CLSCTX_INPROC = CLSCTX_INPROC_SERVER Or CLSCTX_INPROC_HANDLER
            CLSCTX_SERVER = CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER Or CLSCTX_REMOTE_SERVER
            CLSCTX_ALL = CLSCTX_SERVER Or CLSCTX_INPROC_HANDLER
        End Enum
    
    
        Private Enum EDataFlow
            eRender
            eCapture
            eAll
            EDataFlow_enum_count
        End Enum
    
    
        Private Enum ERole
            eConsole
            eMultimedia
            eCommunications
            ERole_enum_count
        End Enum
    
        '****** STRUCTURES ******************************************************************
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure AUDIO_VOLUME_NOTIFICATION_DATA 'Total: 32 bytes
            Dim guidEventContext As Guid '16
            Dim bMuted As Boolean '4
            Dim fMasterVolume As Single '4
            Dim nChannels As UInteger '4
            <MarshalAs(UnmanagedType.ByValArray)> Dim afChannelVolumes() As Single '4
        End Structure
    
    
        <StructLayout(LayoutKind.Sequential)>
        Private Structure _tagpropertykey
            Dim fmtid As Guid
            Dim pid As UInteger
        End Structure
    
    #End Region
    
    
    #Region " Notification reporting objects implementation "
        '******** NOTIFICATION OBJECTS IMPLEMENTATION *************************************************
    
        ''' <remarks>This provide the implementation for our interface IAudioEndpointVolumeCallback</remarks>
        Private Class AudioEndpointVolumeCallback : Implements IAudioEndpointVolumeCallback
    
            ''' <remarks>Forward the notification to the EndpointVolume class</remarks>
            Private Callback As Action(Of NotifyVolumeChangedEventArgs)
            Public Sub HookCallback(ByVal Callback As Action(Of NotifyVolumeChangedEventArgs))
                Me.Callback = Callback
            End Sub
    
            ''' <remarks>Called by the system when the system volume change
            ''' The structure is crazy to Marshal !! The data extend pass the end of the structure (See documentation for AUDIO_VOLUME_NOTIFICATION_DATA)</remarks>
            Private Sub OnNotify(ByVal pNotifyData As IntPtr) Implements IAudioEndpointVolumeCallback.OnNotify
                If Callback IsNot Nothing Then
                    Dim Data As AUDIO_VOLUME_NOTIFICATION_DATA
                    Data = CType(Marshal.PtrToStructure(pNotifyData, GetType(AUDIO_VOLUME_NOTIFICATION_DATA)), AUDIO_VOLUME_NOTIFICATION_DATA)
                    pNotifyData += 32
                    Dim ChannelVolume(CInt(Data.nChannels) - 1) As Single
                    ChannelVolume(0) = CSng(Math.Round(CDbl(Data.afChannelVolumes(0)), 1))
                    For i As Integer = 1 To CInt(Data.nChannels) - 1
                        Dim SingleAsByte(3) As Byte
                        Marshal.Copy(pNotifyData, SingleAsByte, 0, 4)
                        ChannelVolume(i) = CSng(Math.Round(CDbl(BitConverter.ToSingle(SingleAsByte, 0)), 1))
                        pNotifyData += 4
                    Next
                    Dim e As New NotifyVolumeChangedEventArgs(Data.guidEventContext, Data.bMuted, Data.fMasterVolume, ChannelVolume, CInt(Data.nChannels))
                    Callback(e)
                End If
            End Sub
        End Class
    
    
    
        ''' <remarks>This provide the implementation for our interface IMMNotificationClient</remarks>
        Private Class MMNotificationClient : Implements IMMNotificationClient
    
            Private CallbackOnDefaultDeviceChanged As Action(Of DefaultDeviceChangedEventArgs)
            Public Sub HookOnDefaultDeviceChanged(ByVal Callback As Action(Of DefaultDeviceChangedEventArgs))
                CallbackOnDefaultDeviceChanged = Callback
            End Sub
    
            Public Sub OnDefaultDeviceChanged(ByVal flow As EDataFlow, ByVal role As ERole, ByVal pwstrDefaultDeviceId As String) Implements IMMNotificationClient.OnDefaultDeviceChanged
                If CallbackOnDefaultDeviceChanged IsNot Nothing Then
                    Dim CRole As DeviceRole = CType(role, DeviceRole)
                    Dim Cflow As AudioFlow = CType(flow, AudioFlow)
                    Dim e As New DefaultDeviceChangedEventArgs(Cflow, CRole, pwstrDefaultDeviceId)
                    CallbackOnDefaultDeviceChanged(e)
                End If
            End Sub
    
            Private CallbackOnDeviceAdded As Action(Of DeviceAddedEventArgs)
            Public Sub HookOnDeviceAdded(ByVal Callback As Action(Of DeviceAddedEventArgs))
                CallbackOnDeviceAdded = Callback
            End Sub
    
            Public Sub OnDeviceAdded(ByVal pwstrDeviceId As String) Implements IMMNotificationClient.OnDeviceAdded
                If CallbackOnDeviceAdded IsNot Nothing Then
                    Dim e As New DeviceAddedEventArgs(pwstrDeviceId)
                    CallbackOnDeviceAdded(e)
                End If
            End Sub
    
            Private CallbackOnDeviceRemoved As Action(Of DeviceRemovedEventArgs)
            Public Sub HookOnDeviceRemoved(ByVal Callback As Action(Of DeviceRemovedEventArgs))
                CallbackOnDeviceRemoved = Callback
            End Sub
    
            Public Sub OnDeviceRemoved(ByVal pwstrDeviceId As String) Implements IMMNotificationClient.OnDeviceRemoved
                If CallbackOnDeviceRemoved IsNot Nothing Then
                    Dim e As New DeviceRemovedEventArgs(pwstrDeviceId)
                    CallbackOnDeviceRemoved(e)
                End If
            End Sub
    
            Private CallbackOnDeviceStateChanged As Action(Of DeviceStateChangedEventArgs)
            Public Sub HookOnDeviceStateChanged(ByVal Callback As Action(Of DeviceStateChangedEventArgs))
                CallbackOnDeviceStateChanged = Callback
            End Sub
    
            Public Sub OnDeviceStateChanged(ByVal pwstrDeviceId As String, ByVal dwNewState As UInteger) Implements IMMNotificationClient.OnDeviceStateChanged
                If CallbackOnDeviceStateChanged IsNot Nothing Then
                    Dim e As New DeviceStateChangedEventArgs(pwstrDeviceId, dwNewState)
                    CallbackOnDeviceStateChanged(e)
                End If
            End Sub
    
            Private CallbackOnPropertyValueChanged As Action(Of PropertyValueChangedEventArgs)
            Public Sub HookOnPropertyValueChanged(ByVal Callback As Action(Of PropertyValueChangedEventArgs))
                CallbackOnPropertyValueChanged = Callback
            End Sub
    
            Public Sub OnPropertyValueChanged(ByVal pwstrDeviceId As String, ByVal key As _tagpropertykey) Implements IMMNotificationClient.OnPropertyValueChanged
                If CallbackOnPropertyValueChanged IsNot Nothing Then
                    Dim e As New PropertyValueChangedEventArgs(pwstrDeviceId, key.fmtid, key.pid)
                    CallbackOnPropertyValueChanged(e)
                End If
            End Sub
        End Class
    
    #End Region
    
    End Class
    
    
    #Region " Event arguments "
    '********** EVENT ARGUMENTS ************************************************************
    ''' <summary>
    ''' Event argument associated with the EndpointVolume.VolumeChanged event
    ''' </summary>
    Public Class NotifyVolumeChangedEventArgs : Inherits EventArgs
        Public EventContextGuid As Guid
        Public Muted As Boolean
        Public MasterVolume As Single
        Public ChannelsVolume() As Single
        Public NbChannel As Integer
        Sub New(ByVal EventContextGuid As Guid, ByVal Muted As Boolean, ByVal MasterVolume As Single, ByVal ChannelsVolume() As Single, ByVal NbChannel As Integer)
            Me.EventContextGuid = EventContextGuid
            Me.Muted = Muted
            Me.MasterVolume = MasterVolume
            Me.ChannelsVolume = ChannelsVolume
            Me.NbChannel = NbChannel
        End Sub
    End Class
    
    Public Class DefaultDeviceChangedEventArgs : Inherits EventArgs
    
        Public AudioFlow As AudioFlow
        Public DeviceRole As DeviceRole
        Public DeviceID As String
        Public Sub New(ByVal Flow As AudioFlow, ByVal role As DeviceRole, ByVal ID As String)
            Me.AudioFlow = AudioFlow
            Me.DeviceRole = DeviceRole
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceAddedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public Sub New(ByVal ID As String)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceRemovedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public Sub New(ByVal ID As String)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class DeviceStateChangedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public NewState As IMMDeviceStatesFlags
        Public Sub New(ByVal ID As String, ByVal NewState As UInteger)
            Me.NewState = CType(NewState, IMMDeviceStatesFlags)
            Me.DeviceID = ID
        End Sub
    End Class
    
    Public Class PropertyValueChangedEventArgs : Inherits EventArgs
        Public DeviceID As String
        Public PropertyID As UInteger
        Public UniquePropertyID As Guid
        Public Sub New(ByVal ID As String, ByVal fmtid As Guid, ByVal PropertyID As UInteger)
            Me.DeviceID = ID
            Me.PropertyID = PropertyID
            Me.UniquePropertyID = fmtid
        End Sub
    End Class
    
    #End Region
    
    
    '********** EXCEPTION CLASS **********************************************************
    
    Public Class EndPointVolumeException : Inherits Exception
        Public Sub New(ByVal m As String, ByVal HL As String)
            MyBase.New(m)
            Me.HelpLink = HL
        End Sub
    End Class
    
    
    #Region "Public enumerations"
    '********* PUBLIC ENUM **************************************************************
    
    <Flags()>
    Public Enum IMMDeviceStatesFlags
        DEVICE_STATE_ACTIVE = 1
        DEVICE_STATE_DISABLED = 2
        DEVICE_STATE_NOTPRESENT = 4
        DEVICE_STATE_UNPLUGGED = 8
    End Enum
    
    
    
    <Flags()>
    Public Enum EndPointHardwareSupportFlags
        SupportsVolume = 1
        SupportsMute = 2
        SupportsMeter = 4
    End Enum
    
    
    
    Public Enum AudioFlow
        RenderAudio
        CaptureAudio
        RenderAndCaptureAudio
        EDataFlow_enum_count
    End Enum
    
    
    
    Public Enum DeviceRole
        Console
        Multimedia
        Communications
        ERole_enum_count
    End Enum
    
    #End Region

    Friday, July 25, 2014 12:44 PM
  • @ Crazypennie,

     Very interesting code. I will have to try it out on my XP machine later. I did not realize you could use the AudioEndPoint in XP machines. I thought it was just for Vista and up. Does it require a certain framework or anything else?

     I have been working on a class that i use the Mixer API`s to get the mute and Volume status and can set/adjust the Mute and Volume status and level. I also want to include settings for adjusting the Mic and LineIn status and levels on the recording mixer. Got the first part done but, have not made it to the Recording part yet. Should be pretty close to the same code used for the Mute and Volume though.   8)


    If you say it can`t be done then i`ll try it

    Friday, July 25, 2014 4:22 PM
  • Now that you are pointing it, I realize that you are right, all the MMDevice interfaces started with Vista.

    My Bad,  sorry for the confusion  :(

    Friday, July 25, 2014 7:20 PM
  • Now that you are pointing it, I realize that you are right, all the MMDevice interfaces started with Vista.

    My Bad,  sorry for the confusion  :(


     OK, i thought so. You had me wondering. Oh well, i plan on  making my class by putting the Mixer API code i have for XP in it and add a reference to the Vista Core Audio API dll and just have it check the system OS to tell which subs and functions to execute. I may use some of your code in it instead of referencing the dll from CodeProject though.  8)

    If you say it can`t be done then i`ll try it

    Friday, July 25, 2014 9:29 PM
  • How can I adjust the volume from my program?

    Look at all the effort that went into answering John Ap's original question, which was answered IMO multiple times, and no post is proposed as the answer. Instead John Ap comes back with this "Is there a simple way to just turn the volume to maximum?" so I answered that with this "Yeah. Click on the volume control in the task bar and move the slider to max." and still no response apparently answered John Ap's original question. Man, you just can't please certain people. Even with so much information they actually have a choice about which code to use. But NOOOOOO instead they want it another way from their original request. What's next John Ap? You want VB.Net code that can read your mind so you can think the volume control higher and lower? LOL!


    La vida loca

    Saturday, July 26, 2014 10:17 AM
  • Is there a simple way to just turn the volume to maximum?


    Yeah. Click on the volume control in the task bar and move the slider to max.

    La vida loca


    I meant from my program you know
    Monday, July 28, 2014 11:04 AM