| |
DLLBinder Example - Adjust system volume
Do you ever need to get or set the system volume? Or check / set the
system mute?
By default, Director users can set the volume for different channels
in the current movie but not the
system volume (e.g. like when one clicks the volume control in the system tray).
This example makes use of DLLBinder to get and set the system volume
and system mute.
For more information about the use of this Win32 API, see the
msdn Audio Mixers web pages
.
Feel free to make use of this code in any way you want. If you make any great
improvements, please send us a copy. Or if you have any other examples you would
like to appear in these LIBRARY pages, please send it to
info@the-mindseye.co.uk
Minds Eye Visualisation Services accepts no responibility for the reliability
of any of the source code appearing in these pages. Use it at your own risk.
|
|
|
|
------------------------------------------------------------------------
-- Name sctVolController
-- Script Type Parent
-- Description provides access to the volume slider and mute
-- controls of the master audio line.
-- Creation Date 20/12/2004
-- Author Minds Eye Visualisation
------------------------------------------------------------------------
------------------------------------------------------------------------
--various consts we need to use -as defined in mmsystem.h
property MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
property MIXER_GETLINECONTROLSF_ONEBYTYPE
property MIXER_GETLINEINFOF_COMPONENTTYPE
property MIXERCONTROL_CONTROLTYPE_VOLUME
property MIXERCONTROL_CONTROLTYPE_MUTE
--useful constants found in mmsystem.h -see below for definitions
property MMSYSERR_NOERROR
--property for the name Win32 Dll containing the wave volume functions
property m_strDllName
property m_hMixer
property m_dwLineID
property m_dwChannels
property m_dwMuteControlID
property m_dwVolumeControlID
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: new
--
-- PURPOSE:
-- instance creation
------------------------------------------------------------------------
------------------------------------------------------------------------
on new me
--//////////////////////////////////////////////////
--// general error return values as defined in mmsystem.h
--//////////////////////////////////////////////////
--NB there are loads of others that really should be included here
-- but this'll do for now
MMSYSERR_NOERROR = 0
--//////////////////////////////////////////////////
--//various consts we need to use -as defined in mmsystem.h
--//////////////////////////////////////////////////
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = 4
MIXER_GETLINECONTROLSF_ONEBYTYPE = 2
MIXER_GETLINEINFOF_COMPONENTTYPE = 3
MIXERCONTROL_CONTROLTYPE_VOLUME = 1342373889
MIXERCONTROL_CONTROLTYPE_MUTE = 536936450
--//////////////////////////////////////////////////
--//the name of the Win32 dll containing our reqd API
--//constant across all instances of this script
--//////////////////////////////////////////////////
m_strDllName="winmm.dll"
me.m_hMixer=0
me.m_dwLineID=0
me.m_dwChannels=0
me.m_dwMuteControlID=0
me.m_dwVolumeControlID=0
return me
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: Initialise
--
-- PURPOSE:
-- gets the volume slider and mute checkbox control IDs.
------------------------------------------------------------------------
------------------------------------------------------------------------
on Initialise me
symRet=#OK
--1. open a mixer
if me.MixerOpen() = #CALL_FAILED then
symRet=#MIXER_OPEN_FAIL
--2. get master audio line ID
else if me.MixerGetLineInfo() = #CALL_FAILED then
symRet=#GET_AUDIO_LINE_FAIL
else
lstControlHandle=[]
--3. get the mute control ID
symRet = me.MixerGetLineControls(MIXERCONTROL_CONTROLTYPE_MUTE,\
lstControlHandle)
if symRet = #CALL_FAILED then
symRet=#GET_MUTE_ID_FAIL
else
me.m_dwMuteControlID=lstControlHandle[1]
--4. get the volume control ID
symRet = me.MixerGetLineControls(MIXERCONTROL_CONTROLTYPE_VOLUME,\
lstControlHandle)
if symRet = #CALL_FAILED then
symRet=#GET_VOLUME_ID_FAIL
else
me.m_dwVolumeControlID=lstControlHandle[1]
end if --get the volume control ID
end if --set the mute control ID
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: MixerOpen
--
-- wrapper for the following win32 API fn in winmm.dll -see mmsystem.h
--
-- MMRESULT mixerOpen(
-- LPHMIXER phmx,
-- UINT uMxId,
-- DWORD dwCallback,
-- DWORD dwInstance,
-- DWORD fdwOpen);
-- PURPOSE:
-- opens a handle to a mixer device
------------------------------------------------------------------------
------------------------------------------------------------------------
on MixerOpen me
symRet=#OK
strAPIName="mixerOpen"
strRetValFormat="D"
lstRetValList=[]
--the 1st arg is of type LPHMIXER which is defined as
--a reference to a word data type in mmsystem.h
strArgFormat="*D,D,D,D,D"
lstArgFormat=[0,0,0,0,0]
--call into the dll
nErr=mevCallDllFun(m_strDllName, \
strAPIName, \
strArgFormat, \
lstArgFormat, \
strRetValFormat, \
lstRetValList)
--most Win32 API calls return an integer representing the error
--status of the call. In this case we hope it equals MMSYSERR_NOERROR
dwRet=lstRetValList[1]
--skeleton error handling
if (nErr < 0) then
--the call to mevCallDllFun has failed
symRet=#CALL_FAILED
else if (dwRet <> MMSYSERR_NOERROR) then
--waveOutGetVolume has failed
--check dwRet against other values in mmsystem.h
symRet=#CALL_FAILED
else
--all ok. get the handle from the call results
me.m_hMixer=lstArgFormat[1]
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: MixerGetLineInfo
--
-- wrapper for the following win32 API fn in winmm.dll -see mmsystem.h
--
-- MMRESULT mixerGetLineInfoA(
-- HMIXEROBJ hmxobj,
-- LPMIXERLINEA pmxl,
-- DWORD fdwInfo);
--
-- the LPMIXERLINEA data type is defined in mmsystem.h as follows:
--
-- typedef struct tagMIXERLINEA {
-- DWORD cbStruct; /* size of MIXERLINE structure */
-- DWORD dwDestination; /* zero based destination index */
-- DWORD dwSource; /* zero based source index (if source) */
-- DWORD dwLineID; /* unique line id for mixer device */
-- DWORD fdwLine; /* state/information about line */
-- DWORD dwUser; /* driver specific information */
-- DWORD dwComponentType; /* component type line connects to */
-- DWORD cChannels; /* number of channels line supports */
-- DWORD cConnections; /* number of connections [possible] */
-- DWORD cControls; /* number of controls at this line */
-- CHAR szShortName[MIXER_SHORT_NAME_CHARS];
-- CHAR szName[MIXER_LONG_NAME_CHARS];
-- struct {
-- DWORD dwType; /* MIXERLINE_TARGETTYPE_xxxx */
-- DWORD dwDeviceID; /* target device ID of device type */
-- WORD wMid; /* of target device */
-- WORD wPid;
-- MMVERSION vDriverVersion;
-- CHAR szPname[MAXPNAMELEN];
-- } Target;
-- } MIXERLINEA, *PMIXERLINEA, *LPMIXERLINEA;
--
--
-- PURPOSE:
-- retrieves information about a specific line of a mixer device
------------------------------------------------------------------------
------------------------------------------------------------------------
on MixerGetLineInfo me
symRet=#OK
strAPIName="mixerGetLineInfoA"
strRetValFormat="D"
lstRetValList=[]
strSTMixerLineFormat="{D,D,D,D,D,D,D,D,D,D,S16,S64,{D,D,W,W,D,S32}}"
lstSTMixerLine=[]
lstSTMixerLine[1]=mevMemSizeOf(strSTMixerLineFormat)
lstSTMixerLine[7]=MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
lstSTMixerLine[11]=""
lstSTMixerLine[12]=""
lstSTMixerLine[13]=[0,0,0,0,0,""]
strArgFormat="D" & "*" & strSTMixerLineFormat & "D"
lstArgFormat=[]
lstArgFormat[1]=me.m_hMixer
lstArgFormat[2]=lstSTMixerLine
lstArgFormat[3]=MIXER_GETLINEINFOF_COMPONENTTYPE
--call into the dll
nErr=mevCallDllFun(m_strDllName, \
strAPIName, \
strArgFormat, \
lstArgFormat, \
strRetValFormat, \
lstRetValList)
--most Win32 API calls return an integer representing the error
--status of the call. In this case we hope it equals MMSYSERR_NOERROR
dwRet=lstRetValList[1]
--skeleton error handling
if (nErr < 0) then
--the call to mevCallDllFun has failed
symRet=#CALL_FAILED
else if (dwRet <> MMSYSERR_NOERROR) then
--waveOutGetVolume has failed
--check dwRet against other values in mmsystem.h
symRet=#CALL_FAILED
else
--all ok. we've got our audio line ID and the number of its channels
me.m_dwLineID=lstSTMixerLine[4]
me.m_dwChannels=lstSTMixerLine[8]
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: MixerGetLineControls
--
-- wrapper for the following win32 API fn in winmm.dll -see mmsystem.h
--
-- MMRESULT mixerGetLineControlsA(
-- HMIXEROBJ hmxobj,
-- LPMIXERLINECONTROLSA pmxlc,
-- DWORD fdwControls);
--
--
-- typedef struct tagMIXERCONTROLA {
-- DWORD cbStruct; /* size in bytes of MIXERCONTROL */
-- DWORD dwControlID; /* unique control id for mixer device */
-- DWORD dwControlType; /* MIXERCONTROL_CONTROLTYPE_xxx */
-- DWORD fdwControl; /* MIXERCONTROL_CONTROLF_xxx */
-- DWORD cMultipleItems; /* if MIXERCONTROL_CONTROLF_MULTIPLE set */
-- CHAR szShortName[MIXER_SHORT_NAME_CHARS];
-- CHAR szName[MIXER_LONG_NAME_CHARS];
-- union {
-- struct {
-- LONG lMinimum; /* signed minimum for this control */
-- LONG lMaximum; /* signed maximum for this control */
-- };
-- struct {
-- DWORD dwMinimum; /* unsigned minimum for this control */
-- DWORD dwMaximum; /* unsigned maximum for this control */
-- };
-- DWORD dwReserved[6];
-- } Bounds;
-- union {
-- DWORD cSteps; /* # of steps between min & max */
-- DWORD cbCustomData; /* size in bytes of custom data */
-- DWORD dwReserved[6]; /* !!! needed? we have cbStruct.... */
-- } Metrics;
-- } MIXERCONTROLA, *PMIXERCONTROLA, *LPMIXERCONTROLA;
--
--
-- the LPMIXERLINECONTROLSA data type is defined in mmsystem.h thus:
--
-- typedef struct tagMIXERLINECONTROLSA {
-- DWORD cbStruct; /* size in bytes of MIXERLINECONTROLS */
-- DWORD dwLineID; /* line id (from MIXERLINE.dwLineID) */
-- union {
-- DWORD dwControlID; /* MIXER_GETLINECONTROLSF_ONEBYID */
-- DWORD dwControlType; /* MIXER_GETLINECONTROLSF_ONEBYTYPE */
-- };
-- DWORD cControls; /* count of controls pmxctrl points to */
-- DWORD cbmxctrl; /* size in bytes of _one_ MIXERCONTROL */
-- LPMIXERCONTROLA pamxctrl; /* pointer to 1st MIXERCONTROL array */
-- } MIXERLINECONTROLSA, *PMIXERLINECONTROLSA, *LPMIXERLINECONTROLSA;
--
--
-- PURPOSE:
-- retrieves one or more controls associated with an audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on MixerGetLineControls me, dwControlType, lstControlHandle
symRet=#OK
strAPIName="mixerGetLineControlsA"
strRetValFormat="D"
lstRetValList=[]
strSTMixerControl="{D,D,D,D,D,S16,S64,{D,D,D,D,D,D},{D,D,D,D,D,D}}"
lstSTMixerControl=[]
strSTMixerLineCtrlsFormat="{D,D,D,D,D" & "*" & strSTMixerControl & "}"
lstSTMixerLineCtrls=[]
lstSTMixerLineCtrls[1]=mevMemSizeOf(strSTMixerLineCtrlsFormat)
lstSTMixerLineCtrls[2]=me.m_dwLineID
lstSTMixerLineCtrls[3]=dwControlType
lstSTMixerLineCtrls[4]=1
lstSTMixerLineCtrls[5]=mevMemSizeOf(strSTMixerControl)
lstSTMixerLineCtrls[6]=lstSTMixerControl
strArgFormat="D" & "*" & strSTMixerLineCtrlsFormat & "D"
lstArgFormat=[]
lstArgFormat[1]=me.m_hMixer
lstArgFormat[2]=lstSTMixerLineCtrls
lstArgFormat[3]=MIXER_GETLINECONTROLSF_ONEBYTYPE
--call into the dll
nErr=mevCallDllFun(m_strDllName, \
strAPIName, \
strArgFormat, \
lstArgFormat, \
strRetValFormat, \
lstRetValList)
--most Win32 API calls return an integer representing the error
--status of the call. In this case we hope it equals MMSYSERR_NOERROR
dwRet=lstRetValList[1]
--skeleton error handling
if (nErr < 0) then
--the call to mevCallDllFun has failed
symRet=#CALL_FAILED
else if (dwRet <> MMSYSERR_NOERROR) then
--waveOutGetVolume has failed
--check dwRet against other values in mmsystem.h
symRet=#CALL_FAILED
else
--all ok. get the handle from the call results
lstControlHandle[1]=lstSTMixerControl[2]
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: MixerSetControlDetails
--
-- wrapper for the following win32 API fn in winmm.dll -see mmsystem.h
--
-- MMRESULT mixerSetControlDetails(
-- HMIXEROBJ hmxobj,
-- LPMIXERCONTROLDETAILS pmxcd,
-- DWORD fdwDetails);
-- typedef struct tMIXERCONTROLDETAILS {
-- DWORD cbStruct; /* size in bytes of MIXERCONTROLDETAILS */
-- DWORD dwControlID; /* control id to get/set details on */
-- DWORD cChannels; /* number of channels in paDetails array */
-- union {
-- HWND hwndOwner; /* for MIXER_SETCONTROLDETAILSF_CUSTOM */
-- DWORD cMultipleItems; /* if _MULTIPLE, the # items/channel */
-- };
-- DWORD cbDetails; /* size of _one_ details_XX struct */
-- LPVOID paDetails; /* pointer to array of details_XX structs */
-- } MIXERCONTROLDETAILS,
-- *PMIXERCONTROLDETAILS,
-- FAR *LPMIXERCONTROLDETAILS;
--
-- PURPOSE:
-- sets the properties of a single control associated with an audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on MixerSetControlDetails me, dwChannels, dwControlID, lstChannelInfo
symRet=#OK
if dwChannels = lstChannelInfo.count() then
strAPIName="mixerSetControlDetails"
strRetValFormat="D"
lstRetValList=[]
strSTMxCtrlDetailsFormat="{D,D,D,D,D,[" & dwChannels & "D]}"
lstSTMxCtrlDetails=[]
lstSTMxCtrlDetails[1]=mevMemSizeOf(strSTMxCtrlDetailsFormat)
lstSTMxCtrlDetails[2]=dwControlID
lstSTMxCtrlDetails[3]=dwChannels
lstSTMxCtrlDetails[4]=0 --cMultipleItems
lstSTMxCtrlDetails[5]=(dwChannels * mevMemSizeOf("D"))
lstSTMxCtrlDetails[6]=lstChannelInfo
--we define the 2nd arg as a struct of two WORDS -see above note
strArgFormat="D," & "*" & strSTMxCtrlDetailsFormat & "D"
lstArgFormat=[]
lstArgFormat[1]=me.m_hMixer
lstArgFormat[2]=lstSTMxCtrlDetails
lstArgFormat[3]=0 --no flags
--call into the dll
nErr=mevCallDllFun(m_strDllName, \
strAPIName, \
strArgFormat, \
lstArgFormat, \
strRetValFormat, \
lstRetValList)
--most Win32 API calls return an integer representing the error
--status of the call. In this case we hope it equals MMSYSERR_NOERROR
dwRet=lstRetValList[1]
--skeleton error handling
if (nErr < 0) then
--the call to mevCallDllFun has failed
symRet=#CALL_FAILED
else if (dwRet <> MMSYSERR_NOERROR) then
--waveOutGetVolume has failed
--check dwRet against other values in mmsystem.h
symRet=#CALL_FAILED
end if
else
--number of channels does not match number of values in list
symRet=#CALL_FAILED
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: MixerGetControlDetails
--
-- wrapper for the following win32 API fn in winmm.dll -see mmsystem.h
--
-- MMRESULT mixerGetControlDetailsA(
-- HMIXEROBJ hmxobj,
-- LPMIXERCONTROLDETAILS pmxcd,
-- DWORD fdwDetails);
-- typedef struct tMIXERCONTROLDETAILS {
-- DWORD cbStruct; /* size in bytes of MIXERCONTROLDETAILS */
-- DWORD dwControlID; /* control id to get/set details on */
-- DWORD cChannels; /* number of channels in paDetails array */
-- union {
-- HWND hwndOwner; /* for MIXER_SETCONTROLDETAILSF_CUSTOM */
-- DWORD cMultipleItems; /* if _MULTIPLE, the # items/channel */
-- };
-- DWORD cbDetails; /* size of _one_ details_XX struct */
-- LPVOID paDetails; /* pointer to array of details_XX structs */
-- } MIXERCONTROLDETAILS,
-- *PMIXERCONTROLDETAILS,
-- FAR *LPMIXERCONTROLDETAILS;
--
-- PURPOSE:
-- gets the properties of a single control associated with an audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on MixerGetControlDetails me, dwChannels, dwControlID, lstChannelInfo
symRet=#OK
strAPIName="mixerGetControlDetailsA"
strRetValFormat="D"
lstRetValList=[]
strSTMxCtrlDetailsFormat="{D,D,D,D,D,[" & dwChannels & "D]}"
lstSTMxCtrlDetails=[]
lstSTMxCtrlDetails[1]=mevMemSizeOf(strSTMxCtrlDetailsFormat)
lstSTMxCtrlDetails[2]=dwControlID
lstSTMxCtrlDetails[3]=dwChannels
lstSTMxCtrlDetails[4]=0 --cMultipleItems
lstSTMxCtrlDetails[5]=(dwChannels * mevMemSizeOf("D"))
lstSTMxCtrlDetails[6]=lstChannelInfo
--we define the 2nd arg as a struct of two WORDS -see above note
strArgFormat="D," & "*" & strSTMxCtrlDetailsFormat & "D"
lstArgFormat=[]
lstArgFormat[1]=me.m_hMixer
lstArgFormat[2]=lstSTMxCtrlDetails
lstArgFormat[3]=0 --no flags
--call into the dll
nErr=mevCallDllFun(m_strDllName, \
strAPIName, \
strArgFormat, \
lstArgFormat, \
strRetValFormat, \
lstRetValList)
--most Win32 API calls return an integer representing the error
--status of the call. In this case we hope it equals MMSYSERR_NOERROR
dwRet=lstRetValList[1]
--skeleton error handling
if (nErr < 0) then
--the call to mevCallDllFun has failed
symRet=#CALL_FAILED
else if (dwRet <> MMSYSERR_NOERROR) then
--waveOutGetVolume has failed
--check dwRet against other values in mmsystem.h
symRet=#CALL_FAILED
end if
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: GetChannelCount
--
-- PURPOSE:
-- returns the number of channels supported by the audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on GetChannelCount me
return me.m_dwChannels
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: SetVolume
--
-- PURPOSE:
-- sets the volume levels for each channel supported by the audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on SetVolume me, lstVolLevels
symRet = me.MixerSetControlDetails(integer(me.m_dwChannels),\
me.m_dwVolumeControlID,\
lstVolLevels)
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: GetVolume
--
-- PURPOSE:
-- returns the volume levels for each channel supported by the
-- audio line
------------------------------------------------------------------------
------------------------------------------------------------------------
on GetVolume me, lstVolLevels
symRet = me.MixerGetControlDetails(integer(me.m_dwChannels),\
me.m_dwVolumeControlID,\
lstVolLevels)
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: SetMute
--
-- PURPOSE:
-- toggles mute on and off
------------------------------------------------------------------------
------------------------------------------------------------------------
on SetMute me, bMute
--sets mute uniformly across all channels
symRet = me.MixerSetControlDetails(1, me.m_dwMuteControlID, [bMute])
return symRet
end
------------------------------------------------------------------------
------------------------------------------------------------------------
-- FUNCTION: IsMute
--
-- PURPOSE:
-- tests if mute is toggled on or off
------------------------------------------------------------------------
------------------------------------------------------------------------
on IsMute me
lstMuteSetting=[]
symRet = me.MixerGetControlDetails(1,\
me.m_dwMuteControlID,\
lstMuteSetting)
if symRet=#OK then
return lstMuteSetting[1]
else
return lstMuteSetting[1]
end if
end
------------------------------------------------------------------------
------------------------------------------------------------------------
--end of script
|