Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Check for Window's Audio

Posted on 2009-07-09
1
Medium Priority
?
276 Views
Last Modified: 2013-11-27
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
Comment
Question by:ADawn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 
LVL 96

Accepted Solution

by:
Bob Learned earned 400 total points
ID: 24841538
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

Use Filtering Commands to Process Files in Linux

Learn how to manipulate data with the help of various filtering commands such as `cat`, `fmt`, `pr`, and others in Linux.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question