Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 280
  • Last Modified:

Check for Window's Audio

Is there a way that I can check to see if a user has muted Window's audio using code. I have a program that runs in the background that alerts the user if something happens, however, if they mute audio, the alert isn't hear. I'd like to monitor the audio (to see if it is muted), and reset the volume if the user sets it too low. Is there something I can do?

ADawn
0
ADawn
Asked:
ADawn
1 Solution
 
Bob LearnedCommented:
You might be able to use calls from the winmm.dll, through p/invoke.

Here is some code from my bag-o-tricks that I haven't used in a long time, and is untested.
' Source:
'  Converted from C# code
'  http://csharp-home.com/index/tiki-print_article.php?articleId=134&PHPSESSID=72a4b6031f43a4ec8a61b288669cf9c9
 
Imports System.Math
Imports System.Runtime.InteropServices
 
Public Class AudioMixer
 
	Private Const MMSYSERR_NOERROR As Integer = 0
	Private Const MAXPNAMELEN As Integer = &H20
	Private Const MIXER_LONG_NAME_CHARS As Integer = &H40
	Private Const MIXER_SHORT_NAME_CHARS As Integer = &H10
	Private Const MIXER_GETLINEINFOF_COMPONENTTYPE As Integer = 3
	Private Const MIXER_GETCONTROLDETAILSF_VALUE As Integer = 0
	Private Const MIXER_GETLINECONTROLSF_ONEBYTYPE As Integer = 2
	Private Const MIXER_SETCONTROLDETAILSF_VALUE As Integer = 0
	Private Const MIXERLINE_COMPONENTTYPE_DST_FIRST As Integer = 0
	Private Const MIXERLINE_COMPONENTTYPE_SRC_FIRST As Integer = &H1000
	Private Const MIXERLINE_COMPONENTTYPE_DST_SPEAKERS As Integer = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 4)
	Private Const MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE As Integer = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3)
	Private Const MIXERLINE_COMPONENTTYPE_SRC_LINE As Integer = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2)
	Private Const MIXERCONTROL_CT_CLASS_FADER As Integer = &H50000000
	Private Const MIXERCONTROL_CT_UNITS_UNSIGNED As Integer = &H30000
	Private Const MIXERCONTROL_CONTROLTYPE_FADER As Integer = (MIXERCONTROL_CT_CLASS_FADER Or MIXERCONTROL_CT_UNITS_UNSIGNED)
	Private Const MIXERCONTROL_CONTROLTYPE_VOLUME As Integer = (MIXERCONTROL_CONTROLTYPE_FADER + 1)
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerClose(ByVal hmx As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerGetControlDetailsA(ByVal hmxobj As Integer, ByRef pmxcd As MIXERCONTROLDETAILS, ByVal fdwDetails As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerGetID(ByVal hmxobj As Integer, ByVal pumxID As Integer, ByVal fdwId As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerGetLineControlsA(ByVal hmxobj As Integer, ByRef pmxlc As MIXERLINECONTROLS, ByVal fdwControls As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerGetLineInfoA(ByVal hmxobj As Integer, ByRef pmxl As MIXERLINE, ByVal fdwInfo As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerGetNumDevs() As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerMessage(ByVal hmx As Integer, ByVal uMsg As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerOpen(ByRef phmx As Integer, ByVal uMxId As Integer, ByVal dwCallback As Integer, ByVal dwInstance As Integer, ByVal fdwOpen As Integer) As Integer
	End Function
 
	<DllImport("winmm.dll", CharSet:=CharSet.Ansi)> _
	Private Shared Function mixerSetControlDetails(ByVal hmxobj As Integer, ByRef pmxcd As MIXERCONTROLDETAILS, ByVal fdwDetails As Integer) As Integer
	End Function
 
	<StructLayout(LayoutKind.Sequential)> _
	Private Structure MIXERCONTROL
		Public cbStruct As Integer
		Public dwControlID As Integer
		Public dwControlType As Integer
		Public fdwControl As Integer
		Public cMultipleItems As Integer
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MIXER_SHORT_NAME_CHARS)> _
		Public szShortName As String
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MIXER_LONG_NAME_CHARS)> _
		Public szName As String
		Public lMinimum As Integer
		Public lMaximum As Integer
		<MarshalAs(UnmanagedType.U4, SizeConst:=10)> _
		Public reserved As Integer
	End Structure
 
	Private Structure MIXERCONTROLDETAILS
		Public cbStruct As Integer
		Public dwControlID As Integer
		Public cChannels As Integer
		Public item As Integer
		Public cbDetails As Integer
		Public paDetails As IntPtr
	End Structure
 
	Private Structure MIXERCONTROLDETAILS_UNSIGNED
		Public dwValue As Integer
	End Structure
 
	Private Structure MIXERLINE
		Public cbStruct As Integer
		Public dwDestination As Integer
		Public dwSource As Integer
		Public dwLineID As Integer
		Public fdwLine As Integer
		Public dwUser As Integer
		Public dwComponentType As Integer
		Public cChannels As Integer
		Public cConnections As Integer
		Public cControls As Integer
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MIXER_SHORT_NAME_CHARS)> _
		Public szShortName As String
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MIXER_LONG_NAME_CHARS)> _
		Public szName As String
		Public dwType As Integer
		Public dwDeviceID As Integer
		Public wMid As Integer
		Public wPid As Integer
		Public vDriverVersion As Integer
		<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAXPNAMELEN)> _
		Public szPname As String
	End Structure
 
	Private Structure MIXERLINECONTROLS
		Public cbStruct As Integer
		Public dwLineID As Integer
		Public dwControl As Integer
		Public cControls As Integer
		Public cbmxctrl As Integer
		Public pamxctrl As IntPtr
	End Structure
 
#Region "Public Members"
 
    Public Shared Function GetVolume() As Integer
 
        Dim volCtrl As MIXERCONTROL = New MIXERCONTROL
        Dim currentVol As Integer
        Dim mixer As Integer
 
        mixerOpen(mixer, 0, 0, 0, 0)
 
        Dim type As Integer = MIXERCONTROL_CONTROLTYPE_VOLUME
 
        GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, type, volCtrl, currentVol)
 
        mixerClose(mixer)
 
        Return currentVol
 
    End Function
 
	Public Shared Sub SetVolume(ByVal vVolume As Integer)
 
		Dim volCtrl As MIXERCONTROL = New MIXERCONTROL
		Dim mixer As Integer
		Dim currentVol As Integer
 
		mixerOpen(mixer, 0, 0, 0, 0)
 
		Dim type As Integer = MIXERCONTROL_CONTROLTYPE_VOLUME
		GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, type, volCtrl, currentVol)
		vVolume = Min(vVolume, volCtrl.lMaximum)
		vVolume = Max(vVolume, volCtrl.lMinimum)
		SetVolumeControl(mixer, volCtrl, vVolume)
		GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, type, volCtrl, currentVol)
		If Not (vVolume = currentVol) Then
			Throw New Exception("Cannot Set Volume")
		End If
		mixerClose(mixer)
    End Sub
 
#End Region
 
#Region "Private Members"
 
    Private Shared Function GetVolumeControl(ByVal hMixer As Integer, ByVal componentType As Integer, ByVal ctrlType As Integer, ByRef mxc As MIXERCONTROL, ByRef vCurrentVol As Integer) As Boolean
 
        Dim mxlc As MIXERLINECONTROLS = New MIXERLINECONTROLS
        Dim mxl As MIXERLINE = New MIXERLINE
        Dim pmxcd As MIXERCONTROLDETAILS = New MIXERCONTROLDETAILS
        Dim du As MIXERCONTROLDETAILS_UNSIGNED = New MIXERCONTROLDETAILS_UNSIGNED
 
        mxc = New MIXERCONTROL
 
        Dim retValue As Boolean
 
        vCurrentVol = -1
 
        mxl.cbStruct = Marshal.SizeOf(mxl)
        mxl.dwComponentType = componentType
 
        Dim rc As Integer = mixerGetLineInfoA(hMixer, mxl, MIXER_GETLINEINFOF_COMPONENTTYPE)
        If rc = MMSYSERR_NOERROR Then
            Dim sizeofMIXERCONTROL As Integer = 152
            Dim ctrl As Integer = Marshal.SizeOf(GetType(MIXERCONTROL))
 
            mxlc.pamxctrl = Marshal.AllocCoTaskMem(sizeofMIXERCONTROL)
            mxlc.cbStruct = Marshal.SizeOf(mxlc)
            mxlc.dwLineID = mxl.dwLineID
            mxlc.dwControl = ctrlType
            mxlc.cControls = 1
            mxlc.cbmxctrl = sizeofMIXERCONTROL
            mxc.cbStruct = sizeofMIXERCONTROL
            rc = mixerGetLineControlsA(hMixer, mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE)
            If rc = MMSYSERR_NOERROR Then
                retValue = True
                mxc = CType(Marshal.PtrToStructure(mxlc.pamxctrl, GetType(MIXERCONTROL)), MIXERCONTROL)
            Else
                retValue = False
            End If
 
            Dim sizeofMIXERCONTROLDETAILS As Integer = Marshal.SizeOf(GetType(MIXERCONTROLDETAILS))
            Dim sizeofMIXERCONTROLDETAILS_UNSIGNED As Integer = Marshal.SizeOf(GetType(MIXERCONTROLDETAILS_UNSIGNED))
 
            pmxcd.cbStruct = sizeofMIXERCONTROLDETAILS
            pmxcd.dwControlID = mxc.dwControlID
            pmxcd.paDetails = Marshal.AllocCoTaskMem(sizeofMIXERCONTROLDETAILS_UNSIGNED)
            pmxcd.cChannels = 1
            pmxcd.item = 0
            pmxcd.cbDetails = sizeofMIXERCONTROLDETAILS_UNSIGNED
 
            rc = mixerGetControlDetailsA(hMixer, pmxcd, MIXER_GETCONTROLDETAILSF_VALUE)
 
            du = CType(Marshal.PtrToStructure(pmxcd.paDetails, GetType(MIXERCONTROLDETAILS_UNSIGNED)), MIXERCONTROLDETAILS_UNSIGNED)
 
            vCurrentVol = du.dwValue
 
            Return retValue
 
        End If
 
        retValue = False
 
        Return retValue
 
    End Function
 
    Private Shared Function SetVolumeControl(ByVal hMixer As Integer, ByVal mxc As MIXERCONTROL, ByVal volume As Integer) As Boolean
 
        Dim retValue As Boolean
        Dim rc As Integer
        Dim mxcd As MIXERCONTROLDETAILS = New MIXERCONTROLDETAILS
        Dim vol As MIXERCONTROLDETAILS_UNSIGNED = New MIXERCONTROLDETAILS_UNSIGNED
 
        mxcd.item = 0
        mxcd.dwControlID = mxc.dwControlID
        mxcd.cbStruct = Marshal.SizeOf(mxcd)
        mxcd.cbDetails = Marshal.SizeOf(vol)
        mxcd.cChannels = 1
 
        vol.dwValue = volume
 
        mxcd.paDetails = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(MIXERCONTROLDETAILS_UNSIGNED)))
 
        Marshal.StructureToPtr(vol, mxcd.paDetails, False)
 
        rc = mixerSetControlDetails(hMixer, mxcd, MIXER_SETCONTROLDETAILSF_VALUE)
        If rc = MMSYSERR_NOERROR Then
            retValue = True
        Else
            retValue = False
        End If
 
        Return retValue
 
    End Function
 
#End Region
 
End Class

Open in new window

0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now