|
| Previous Thread: Rendering with VFW codec |
|
|
7/15/2005 6:34:10 AM How to Mute Microphone (not Speaker) for All Applications |
Hello,
Is it possible to Mute (and Unmute) microphone globally so that none of the
applications can receive recording input? Is it possible to read such Mute
state back? If yes, how? My application is in c# so managed code examples
would be more helpful. Thanks.
Regards,
Vinay Agarwal
|
|
|
|
|
7/15/2005 10:03:24 AM Re: How to Mute Microphone (not Speaker) for All Applications |
"Vinay Agarwal" <VinayAgarwal@discussions.microsoft.com> wrote in message
news:DA000264-B1E5-46D4-AB40-EDA02E92E362@microsoft.com...
Yes, it is. See below.
I haven't had the "pleasure" of doing multimedia tasks in managed code so I
don't know what the platform offers. In the absence of better advice, what
follows is a native approach which you could build into a DLL, export a
function to do the job, and use Platform Invoke (aka P/Invoke) to do the
job.
In an old (Oct 2001) there is a knowledge base article on unmuting the
microrphone. I couldn't find it online just now when I looked. :-(
In any event, in the UnMute() function below, these lines
// Unmute the microphone line (for both channels)
pbool[0].fValue = pbool[cChannels - 1].fValue = 0;
unmute the microphone. On the other hand, if you set the value of the
control to 1, the mic should be muted.
Regards,
Will
PRB: No Signal is Recorded When Using MCI or waveInxxx APIs
Q159753
--------------------------------------------------------------------------------
The information in this article applies to:
Microsoft Platform Software Development Kit (SDK), on platform(s):
Microsoft Windows 98
Microsoft Windows 95
the operating system: Microsoft Windows 2000
--------------------------------------------------------------------------------
SYMPTOMS
There is no signal recorded using MCI (Media Control Interface) or waveInXXX
APIs to record through the microphone.
CAUSE
There are three possible causes:
The microphone line is muted.
The volume of the microphone line is turned to the minimum.
The microphone line is not selected into the wave input destination.
RESOLUTION
You need to make sure that none of the above conditions exist in your
applications. The audio mixer API set provides a means by which each
condition can be checked and set accordingly.
MORE INFORMATION
Two input lines are involved when recording from the microphone: the
physical source line (microphone) and the logical source line (wave in).
This recording architecture can be separated into two distinct components
where the signals from the microphone source line feed into the wave in
destination line. Multiple controls influence these lines.
The first condition is cleared through a mute control. The second condition
through a volume control. To clear the third one, use a LIST control
associated with the wave input line. The following Visual C++ sample code
consists of three functions for clearing these conditions, respectively.
Although this sample is written in Visual C++, you can move the in-line
declarations up front and modify the Visual C++ style initialization to make
it a C sample:
void UnMute()
{
// Open the mixer device
HMIXER hmx;
mixerOpen(&hmx, 0, 0, 0, 0);
// Get the line info for the wave in destination line
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);
// Now find the microphone source line connected to this wave in
// destination
DWORD cConnections = mxl.cConnections;
for(DWORD j=0; j<cConnections; j++){
mxl.dwSource = j;
mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_SOURCE);
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == mxl.dwComponentType)
break;
}
// Find a mute control, if any, of the microphone line
LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof MIXERCONTROL);
MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID,
MIXERCONTROL_CONTROLTYPE_MUTE, 1, sizeof MIXERCONTROL, pmxctrl};
if(!mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ONEBYTYPE)){
// Found, so proceed
DWORD cChannels = mxl.cChannels;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
cChannels = 1;
LPMIXERCONTROLDETAILS_BOOLEAN pbool =
(LPMIXERCONTROLDETAILS_BOOLEAN) malloc(cChannels * sizeof
MIXERCONTROLDETAILS_BOOLEAN);
MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl->dwControlID,
cChannels, (HWND)0,
sizeof MIXERCONTROLDETAILS_BOOLEAN, (LPVOID) pbool};
mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
// Unmute the microphone line (for both channels)
pbool[0].fValue = pbool[cChannels - 1].fValue = 0;
mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
free(pmxctrl);
free(pbool);
}
else
free(pmxctrl);
mixerClose(hmx);
}
void SetVolume()
{
// Open the mixer device
HMIXER hmx;
mixerOpen(&hmx, 0, 0, 0, 0);
// Get the line info for the wave in destination line
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mixerGetLineInfo((HMIXEROBJ)hmx, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
// Now find the microphone source line connected to this wave in
// destination
DWORD cConnections = mxl.cConnections;
for(DWORD j=0; j<cConnections; j++){
mxl.dwSource = j;
mixerGetLineInfo((HMIXEROBJ)hmx, &mxl, MIXER_GETLINEINFOF_SOURCE);
if (MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE == mxl.dwComponentType)
break;
}
// Find a volume control, if any, of the microphone line
LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(sizeof MIXERCONTROL);
MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID,
MIXERCONTROL_CONTROLTYPE_VOLUME, 1, sizeof MIXERCONTROL, pmxctrl};
if(!mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ONEBYTYPE)){
// Found!
DWORD cChannels = mxl.cChannels;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
cChannels = 1;
LPMIXERCONTROLDETAILS_UNSIGNED pUnsigned =
(LPMIXERCONTROLDETAILS_UNSIGNED)
malloc(cChannels * sizeof MIXERCONTROLDETAILS_UNSIGNED);
MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl->dwControlID,
cChannels, (HWND)0,
sizeof MIXERCONTROLDETAILS_UNSIGNED, (LPVOID) pUnsigned};
mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
// Set the volume to the middle (for both channels as needed)
pUnsigned[0].dwValue = pUnsigned[cChannels - 1].dwValue =
(pmxctrl->Bounds.dwMinimum+pmxctrl->Bounds.dwMaximum)/2;
mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
free(pmxctrl);
free(pUnsigned);
}
else
free(pmxctrl);
mixerClose(hmx);
}
void SelectMic()
{
// Open the mixer device
HMIXER hmx;
mixerOpen(&hmx, 0, 0, 0, 0);
// Get the line info for the wave in destination line
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mixerGetLineInfo((HMIXEROBJ)hmx, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
// Find a LIST control, if any, for the wave in line
LPMIXERCONTROL pmxctrl = (LPMIXERCONTROL)malloc(mxl.cControls * sizeof
MIXERCONTROL);
MIXERLINECONTROLS mxlctrl = {sizeof mxlctrl, mxl.dwLineID, 0,
mxl.cControls, sizeof MIXERCONTROL, pmxctrl};
mixerGetLineControls((HMIXEROBJ) hmx, &mxlctrl,
MIXER_GETLINECONTROLSF_ALL);
// Now walk through each control to find a type of LIST control. This
// can be either Mux, Single-select, Mixer or Multiple-select.
DWORD i;
for(i=0; i < mxl.cControls; i++)
if (MIXERCONTROL_CT_CLASS_LIST == (pmxctrl[i].dwControlType
&MIXERCONTROL_CT_CLASS_MASK))
break;
if (i < mxl.cControls) { // Found a LIST control
// Check if the LIST control is a Mux or Single-select type
BOOL bOneItemOnly = FALSE;
switch (pmxctrl[i].dwControlType) {
case MIXERCONTROL_CONTROLTYPE_MUX:
case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
bOneItemOnly = TRUE;
}
DWORD cChannels = mxl.cChannels, cMultipleItems = 0;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl[i].fdwControl)
cChannels = 1;
if (MIXERCONTROL_CONTROLF_MULTIPLE & pmxctrl[i].fdwControl)
cMultipleItems = pmxctrl[i].cMultipleItems;
// Get the text description of each item
LPMIXERCONTROLDETAILS_LISTTEXT plisttext =
(LPMIXERCONTROLDETAILS_LISTTEXT)
malloc(cChannels * cMultipleItems * sizeof
MIXERCONTROLDETAILS_LISTTEXT);
MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl[i].dwControlID,
cChannels,
(HWND)cMultipleItems, sizeof MIXERCONTROLDETAILS_LISTTEXT,
(LPVOID) plisttext};
mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_LISTTEXT);
// Now get the value for each item
LPMIXERCONTROLDETAILS_BOOLEAN plistbool =
(LPMIXERCONTROLDETAILS_BOOLEAN)
malloc(cChannels * cMultipleItems * sizeof
MIXERCONTROLDETAILS_BOOLEAN);
mxcd.cbDetails = sizeof MIXERCONTROLDETAILS_BOOLEAN;
mxcd.paDetails = plistbool;
mixerGetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
// Select the "Microphone" item
for (DWORD j=0; j<cMultipleItems; j = j + cChannels)
if (0 == strcmp(plisttext[j].szName, "Microphone"))
// Select it for both left and right channels
plistbool[j].fValue = plistbool[j+ cChannels - 1].fValue = 1;
else if (bOneItemOnly)
// Mux or Single-select allows only one item to be selected
// so clear other items as necessary
plistbool[j].fValue = plistbool[j+ cChannels - 1].fValue = 0;
// Now actually set the new values in
mixerSetControlDetails((HMIXEROBJ)hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
free(pmxctrl);
free(plisttext);
free(plistbool);
}
else
free(pmxctrl);
mixerClose(hmx);
}
Additional query words: 4.00 kbdsd waveInOpen waveInAddBuffer new type
waveaudio
Keywords : kbmm
Issue type : kbprb
Technology : kbWin32SDKSearch kbAudDeveloper kbSDKSearch
Last Reviewed: December 15, 2000
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.
--------------------------------------------------------------------------------
Send feedback to MSDN.Look here for MSDN Online resources.
|
|
|
7/15/2005 10:24:44 AM Re: How to Mute Microphone (not Speaker) for All Applications |
On Fri, 15 Jul 2005 06:34:10 -0700, Vinay Agarwal wrote:
There is no mute mode for inputs, but you can set the volume to 0.
I'm not aware of any mixer API for c# so you will be forced to call into
the WinAPI.
All mixer functionality is controlled by the mixer API, all functions start
with mixer...
Take a look at the follow C++ code derived from some on codeguru:
main(...)
{
CMixer mixer(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, CMixer::Record);
saveVolume = mixer.GetVolume();
mixer.SetVolume(0);
...
mixer.SetVolume(saveVolume);
}
CMixer::CMixer(DWORD ComponentType, DestKind dkKind): m_dwControlID(-1),
m_bOK(false), m_dwChannels(0)
{
HMIXER hMixer;
HRESULT hr;
hr = mixerOpen(&hMixer, 0, 0, 0, 0);
if (FAILED(hr)) return;
MIXERLINE mxl;
MIXERCONTROL mc;
MIXERLINECONTROLS mxlc;
DWORD kind, count;
int item=-1;
if (dkKind == Play)
{
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = ComponentType;
hr = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
if (FAILED(hr))
{
mixerClose(hMixer);
return;
}
kind = ComponentType;
item = mxl.dwSource;
}
else
{
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
// get the destination mxl.dwDestination
hr = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
mxl.dwComponentType = ComponentType;
// loop through the sources
count = 0xFFFF;
for(UINT i = 0; i < count; i++)
{
mxl.dwSource = i;
hr = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_SOURCE);
if (FAILED(hr))
return;
if (mxl.dwComponentType == ComponentType)
{
item = i;
m_dwChannels = mxl.cChannels;
break;
}
}
}
if (item >= 0)
{
mc.cbStruct = sizeof(mc);
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = &mc;
hr = mixerGetLineControls((HMIXEROBJ)hMixer, &mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
m_dwControlID = mc.dwControlID;
}
mixerClose(hMixer);
m_bOK = true;
}
int CMixer::GetDestination(HMIXER hMixer, DWORD ComponentType)
{
MIXERLINE mxl;
HRESULT hr;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = ComponentType;
hr = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
if (FAILED(hr))
{
mixerClose(hMixer);
return -1;
}
return mxl.dwDestination;
}
void CMixer::SetVolume(DWORD dwVol)
{
if (!m_bOK) return;
HMIXER hMixer;
HRESULT hr;
hr = mixerOpen(&hMixer, 0, 0, 0, 0);
if (FAILED(hr)) return;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxdu;
mxdu.dwValue = dwVol;
mxcd.cMultipleItems = 0;
mxcd.cChannels = 1;
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = m_dwControlID;
mxcd.cbDetails = sizeof(mxdu);
mxcd.paDetails = &mxdu;
hr = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
mixerClose(hMixer);
}
DWORD CMixer::GetVolume()
{
if (!m_bOK) return 0;
HMIXER hMixer;
HRESULT hr;
hr = mixerOpen(&hMixer, 0, 0, 0, 0);
if (FAILED(hr)) return 0;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxdu;
mxcd.cMultipleItems = 0;
mxcd.cChannels = m_dwChannels;
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = m_dwControlID;
mxcd.cbDetails = sizeof(mxdu);
mxcd.paDetails = &mxdu;
hr = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
mixerClose(hMixer);
return mxdu.dwValue;
}
|
|
|
7/15/2005 10:32:29 AM Re: How to Mute Microphone (not Speaker) for All Applications |
On Fri, 15 Jul 2005 10:03:24 -0400, William DePalo [MVP VC++] wrote:
But there is no mute control for the controls on the Record mixer? There
is only a selection Mux, so you could effectively mute by selecting an
unused input.
|
|
|
7/15/2005 1:48:39 PM Re: How to Mute Microphone (not Speaker) for All Applications |
"Chris P. [MVP]" <msdn@chrisnet.net> wrote in message
news:i8l7e2kxl04a$.1ra9ko6i2xnvx$.dlg@40tude.net...
My bad. Thanks for the correction.
Regards,
Will
|
|
|
7/16/2005 1:40:41 PM Re: How to Mute Microphone (not Speaker) for All Applications |
On Sat, 16 Jul 2005 08:29:02 -0700, Vinay Agarwal wrote:
I imagine that it does a soft mute, rather than actually muting the mixer.
For a soft mute the program would simply stop reading in audio data or set
the data stream to silence. You can't achieve this through external
control.
|
|
|
7/16/2005 1:49:12 PM Re: How to Mute Microphone (not Speaker) for All Applications |
On Fri, 15 Jul 2005 15:21:03 -0700, Vinay Agarwal wrote:
Some systems can have input mute controls, but most generic sound cards
don't.
All inputs have the potential to be used, but in a typical scenario there's
usually at least one that isn't used.
I will post a sample to that on Monday.
|
|
|
7/20/2005 1:01:21 PM Re: How to Mute Microphone (not Speaker) for All Applications |
On Wed, 20 Jul 2005 07:02:03 -0700, Vinay Agarwal wrote:
Sorry for the delay. Working on simplifying this ugly, ugly code.
|
|
|
7/23/2005 12:16:17 PM Re: How to Mute Microphone (not Speaker) for All Applications |
I recommend you to try some component.
E.G. www.mmsw.cz/cz/devcorner.aspx
Miroslav
--
"Vinay Agarwal" <VinayAgarwal@discussions.microsoft.com> pí¹e v diskusním pøíspìvku
news:DA000264-B1E5-46D4-AB40-EDA02E92E362@microsoft.com...
|
|
|
7/23/2005 12:29:15 PM Re: How to Mute Microphone (not Speaker) for All Applications |
On Wed, 20 Jul 2005 13:01:21 -0400, Chris P. [MVP] wrote:
Don't worry Vinay, I haven't forgotten about you. I'm very busy with
several projects and the "simple" code I wipped up for you wasn't working
right so I'm doing things the hard way.
|
|
|
7/26/2005 12:14:26 PM Re: How to Mute Microphone (not Speaker) for All Applications |
On Sat, 23 Jul 2005 12:29:15 -0400, Chris P. [MVP] wrote:
Sorry for the delay on this, here you go (the formatting is ugly):
// return the current mux input number and the name string
int GetMuxInput(HMIXER mix, CString &sInputName)
{
int retval = -1;
MMRESULT error;
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
MIXERLINECONTROLS controls;
MIXERCONTROL * control;
MIXERCONTROLDETAILS cd;
HRESULT hr;
memset(&mxl, 0, sizeof(mxl));
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
hr = mixerGetLineInfo((HMIXEROBJ)mix, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
hr = mixerGetLineInfo((HMIXEROBJ)mix, &mxl,
MIXER_GETLINEINFOF_DESTINATION);
if (hr == MMSYSERR_NOERROR)
{
// should always be the first, but should iterate to make sure
//for (int dest=0; dest<mxl.dwDestination; dest++)
{
controls.cbStruct = sizeof(MIXERLINECONTROLS);
controls.dwLineID = mxl.dwLineID; // from MIXERLINE
controls.cControls = mxl.cControls;
controls.cbmxctrl = sizeof(MIXERCONTROL);
control = (MIXERCONTROL *)LocalAlloc(LPTR, sizeof(MIXERCONTROL) *
controls.cControls);
controls.pamxctrl = control;
controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
error = mixerGetLineControls((HMIXEROBJ)mix, &controls,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR == error)
{
for (int c=0; c < controls.cControls; c++) // c should equal 0 (1
control) but you never know
{
// MUX - MULTIPLE SELECT
if (MIXERCONTROL_CONTROLTYPE_MUX == (MIXERCONTROL_CONTROLTYPE_MUX &
control[c].dwControlType))
{
cd.cbStruct = sizeof(MIXERCONTROLDETAILS);
cd.dwControlID = control->dwControlID;
cd.cChannels = 1;
cd.cMultipleItems = control->cMultipleItems;
//cd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
cd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);
MIXERCONTROLDETAILS_BOOLEAN * lv = (MIXERCONTROLDETAILS_BOOLEAN
*)LocalAlloc (LPTR, cd.cChannels * cd.cMultipleItems * cd.cbDetails);
MIXERCONTROLDETAILS_LISTTEXT * lt = (MIXERCONTROLDETAILS_LISTTEXT
*)LocalAlloc (LPTR, cd.cChannels * cd.cMultipleItems * cd.cbDetails);
if (NULL != lv)
{
// get the text names
cd.paDetails = lt;
error = mixerGetControlDetails((HMIXEROBJ)mix, &cd,
MIXER_GETCONTROLDETAILSF_LISTTEXT);
// get the state values
cd.paDetails = lv;
error = mixerGetControlDetails((HMIXEROBJ)mix, &cd,
MIXER_GETCONTROLDETAILSF_VALUE);
// find out which mux input is selected
for (int i = 0; i < cd.cMultipleItems; i++)
{
CString temp;
temp.Format("%-30s [%c]\n", lt[i].szName, lv[i].fValue?'X':' ');
OutputDebugString(temp);
if (lv[i].fValue)
{
retval = i;
sInputName = lt[i].szName;
}
}
LocalFree(lv);
LocalFree(lt);
}
}
}
}
}
}
return retval;
}
// Set the active Mux input select and return previous selection
int SetMuxInput(HMIXER mix, DWORD target)
{
int retval = -1;
MMRESULT error;
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
MIXERLINECONTROLS controls;
MIXERCONTROL * control;
MIXERCONTROLDETAILS cd;
HRESULT hr;
memset(&mxl, 0, sizeof(mxl));
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
hr = mixerGetLineInfo((HMIXEROBJ)mix, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
hr = mixerGetLineInfo((HMIXEROBJ)mix, &mxl,
MIXER_GETLINEINFOF_DESTINATION);
if (hr == MMSYSERR_NOERROR)
{
// should always be the first, but should iterate to make sure
//for (int dest=0; dest<mxl.dwDestination; dest++)
{
controls.cbStruct = sizeof(MIXERLINECONTROLS);
controls.dwLineID = mxl.dwLineID; // from MIXERLINE
controls.cControls = mxl.cControls;
controls.cbmxctrl = sizeof(MIXERCONTROL);
control = (MIXERCONTROL *)LocalAlloc(LPTR, sizeof(MIXERCONTROL) *
controls.cControls);
controls.pamxctrl = control;
controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
error = mixerGetLineControls((HMIXEROBJ)mix, &controls,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR == error)
{
if (target > control->cMultipleItems)
return -1; // value out of range
for (int c=0; c < controls.cControls; c++) // c should equal 0 (1
control) but you never know
{
// MUX - MULTIPLE SELECT
if (MIXERCONTROL_CONTROLTYPE_MUX == (MIXERCONTROL_CONTROLTYPE_MUX &
control[c].dwControlType))
{
cd.cbStruct = sizeof(MIXERCONTROLDETAILS);
cd.dwControlID = control->dwControlID;
cd.cChannels = 1;
cd.cMultipleItems = control->cMultipleItems;
cd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
MIXERCONTROLDETAILS_BOOLEAN * lv = (MIXERCONTROLDETAILS_BOOLEAN
*)LocalAlloc (LPTR, cd.cChannels * cd.cMultipleItems * cd.cbDetails);
if (NULL != lv)
{
// get the state values
cd.paDetails = lv;
error = mixerGetControlDetails((HMIXEROBJ)mix, &cd,
MIXER_GETCONTROLDETAILSF_VALUE);
// find out which mux input is selected
for (int i = 0; i < cd.cMultipleItems; i++)
{
if (lv[i].fValue)
{
// if the select flag is on turn it off
retval = i; // save it for return value
lv[i].fValue = 0;
}
}
// set the select flag for the target item
lv[target].fValue = 1;
error = mixerSetControlDetails((HMIXEROBJ)mix, &cd,
MIXER_SETCONTROLDETAILSF_VALUE);
LocalFree(lv);
}
}
}
}
}
}
return retval; // return previously selected item
}
|
|
|
|
|