=====Interrogating the audio mixer=====
//by Richard Russell, June 2010//\\ \\ **Note: On Windows Vista and Windows 7 each running application has its own independent audio mixer. The code listed here will work correctly, but the mixer interrogated is that for the specific application.**\\ \\ The article [[/Controlling%20the%20audio%20mixer|Controlling the audio mixer]] explains how to control the volume of Wave, Synth and CD outputs and the level of CD, Microphone and Line inputs (and often several others) using the **FN_mixerset** routine. The **FN_mixerget** function listed at the end of this article allows you to interrogate the settings of the various mixer controls. The function should be called using code similar to the following:
setting% = FN_mixerget(Dest%, Source%, Control%)
The routine returns the current setting of the control (typically 0-65535 for Volume).\\ \\ The parameters are as follows:
* **"Dest%"** - The destination for the control, which will generally be either the **Speaker Output** (= **4**) or the **Recording Input** (= **7**).
* **"Source%"** - The audio source for the control, for example the **Line Input** (= **&1002**), **Microphone** (= **&1003**), **Synthesizer** (= **&1004**), **CD** (= **&1005**) or **Wave Output** (= **&1008**).
* **"Control%"** - The control type, which will generally be **Volume** (= **&50030001**).
For other possible values consult the Microsoft documentation.\\ \\ So for example to interrogate the **Microphone recording level** you could use code like this:
miclevel% = FN_mixerget(7, &1003, &50030001)
To read the **CD Player output volume**:
cdvolume% = FN_mixerget(4, &1005, &50030001)
To read a **Master Volume** setting (which does not have a specific source) set the **"Source%"** parameter to zero. So to discover the **Master speaker volume** you could do:
master% = FN_mixerget(4, 0, &50030001)
Finally here is the code for **FN_mixerget** itself:
DEF FN_mixerget(dest%, source%, ctrl%)
LOCAL hmx%, res%, ndevs%, dev%, src%, level%, MixerLine{}
MIXER_OBJECTFMIXER = 0
MIXER_GETLINEINFOF_SOURCE = 1
MIXER_GETLINEINFOF_COMPONENTTYPE = 3
DIM MixerLine{cbStruct%, dwDestination%, dwSource%, dwLineID%, fdwLine%, \
\ dwUser%, dwComponentType%, cChannels%, cConnections%, \
\ cControls%, szShortName&(15), szName&(63), Target{dwType%, \
\ dwDeviceID%, wMid{l&, h&}, wPid{l&, h&}, vDriverVersion%, \
\ szPname&(31)}}
SYS "mixerGetNumDevs" TO ndevs%
IF ndevs%=0 ERROR 100, "No audio mixer devices"
level% = -1
FOR dev% = ndevs%-1 TO 0 STEP -1
SYS "mixerOpen", ^hmx%, dev%, 0, 0, MIXER_OBJECTFMIXER TO res%
IF res% ERROR 100, "mixerOpen failed"
MixerLine.cbStruct% = DIM(MixerLine{})
MixerLine.dwComponentType% = dest%
SYS "mixerGetLineInfo", hmx%, MixerLine{}, \
\ MIXER_GETLINEINFOF_COMPONENTTYPE TO res%
IF res% ERROR 100, "mixerGetLineInfo (destination) failed"
IF source% = 0 THEN
level% = FN_controlget(hmx%, MixerLine.dwLineID%, ctrl%)
ELSE
FOR src% = 0 TO MixerLine.cConnections%-1
MixerLine.cbStruct% = DIM(MixerLine{})
MixerLine.dwSource% = src%
SYS "mixerGetLineInfo", hmx%, MixerLine{}, \
\ MIXER_GETLINEINFOF_SOURCE TO res%
IF res% ERROR 100, "mixerGetLineInfo (source) failed"
IF MixerLine.dwComponentType% = source% THEN
level% = FN_controlget(hmx%, MixerLine.dwLineID%, ctrl%)
ENDIF
NEXT src%
ENDIF
SYS "mixerClose", hmx%
NEXT dev%
= level%
DEF FN_controlget(hmx%, id%, ctrl%)
LOCAL res%, MixerLineControls{}, MixerControl{}
LOCAL MixerControlDetails{}, MixerControlDetailsData{}
MIXER_GETLINECONTROLSF_ONEBYTYPE = 2
MIXER_GETCONTROLDETAILSF_VALUE = 0
DIM MixerLineControls{cbStruct%, dwLineID%, dwControl%, cControls%, \
\ cbmxctrl%, pamxctrl%}
DIM MixerControl{cbStruct%, dwControlID%, dwControlType%, fdwControl%, \
\ cMultipleItems%, szShortName&(15), szName&(63), \
\ lMinimum%, lMaximum%, dwReserved%(9)}
DIM MixerControlDetails{cbStruct%, dwControlID%, cChannels%, hwndOwner%, \
\ cbDetails%, paDetails%}
DIM MixerControlDetailsData{dwValue%}
MixerLineControls.cbStruct% = DIM(MixerLineControls{})
MixerLineControls.dwLineID% = id%
MixerLineControls.dwControl% = ctrl%
MixerLineControls.cControls% = 1
MixerLineControls.cbmxctrl% = DIM(MixerControl{})
MixerLineControls.pamxctrl% = MixerControl{}
SYS "mixerGetLineControls", hmx%, MixerLineControls{}, \
\ MIXER_GETLINECONTROLSF_ONEBYTYPE TO res%
IF res% ERROR 100, "mixerGetLineControls failed"
MixerControlDetails.cbStruct% = DIM(MixerControlDetails{})
MixerControlDetails.dwControlID% = MixerControl.dwControlID%
MixerControlDetails.cChannels% = 1
MixerControlDetails.cbDetails% = DIM(MixerControlDetailsData{})
MixerControlDetails.paDetails% = MixerControlDetailsData{}
SYS "mixerGetControlDetails", hmx%, MixerControlDetails{}, \
\ MIXER_GETCONTROLDETAILSF_VALUE TO res%
IF res% ERROR 100, "mixerGetControlDetails failed"
= MixerControlDetailsData.dwValue%