Larry Osterman's WebLog

Confessions of an Old Fogey
Blog - Title

What's this untitled slider doing on the Vista volume mixer?

What's this untitled slider doing on the Vista volume mixer?

Rate This
  • Comments 80

Someone sent the following screen shot to one of our internal troubleshooting aliases.  They wanted to know what the "Name Not Available" slider meant.

clip_image002[7]

 

The audio system on Vista keeps track of the apps that are playing sounds (it has to, to be able to display the information on what apps are playing sounds :)).  It keeps this information around for a period of time after the application has made the sound to enable the scenario where your computer makes a weird sound and you want to find out which application made the noise.

The system only keeps track of the PID for each application, it's the responsibility of the volume mixer to convert the PID to a reasonable name (the audio service can't track this information because of session 0 isolation).

This works great, but there's one possible problem: If an application exits between the time when the application made a noise and the system times out the fact that it played the noise, then the volume mixer has no way of knowing what the name of the application that made the noise was. In that case, it uses the "Name Not Available" text to give the user some information.

  • Thanks Larry.

    I have another puzzling problem.

    Q1. My application requires mic selected as input device while program startup.But i don't know how could i tell which is which while enumerating end point devices.

    Q2. Also, i have no idea how to disable capture monitoring, because i do not want to hear myself when speaking into my micphone.

    It will be very nice of you to answer these questions.

  • Thanks larry!

    I am new to vista, and now i am deadly puzzled by two questions:

    my application requires mic selected as input device while program startup.But i don't know how could i tell which is which while enumerating end point devices.

    And also, i have no idea how to disable capture monitoring, because

    i do not want to hear myself when i am speaking into micphone.

    Could you help me? Many many thanks!!!

  • Unfortunately, it's not easy to enable or disable capture monitoring because it's built into the hardware - there is sample code available on the MSDN web site that can get you close, but it's not trivial.

    To determine if a device is a microphone, you can get the device form factor property on the endpoint, that will let you know what kind of device the audio driver thinks the device is.

  • I really appreciate your reply. Thanks very much!

    You said "it's not easy to enable or disable capture monitoring". Does that mean disabling capture monitoring is impossible? Is this new to Vista? Can XP do so?

    When i traverse a render endpoint's topology, i can find a subunit which is labeled as "Mic mute" by name, which is really what i am trying to find out, so i get the IAudioMute interface of that part and then mute it. But problem is i can not

    identify the part only by its name, because it varys with OS, right?   So here i want an ID or something unique, is it impossible?

    " there is sample code available on the MSDN web site that can get you close". Larry, actually i searched the MSDN and still i didn't find anything that could help. Could you please give some hyperlink?

    You said "To determine if a device is a microphone, you can get the device form factor property on the endpoint", i have also tried that following these steps:

    1. Get IMMDevice interface of an endpoint.

    2. Get IPropertyStore interface of that endpoint.

    3. Get PKEY_AudioEndpoint_Association value using                 IPropertyStore.

    Here i assume the return value from step 3 could match something like KSNODETYPE_MICROPHONE,KSNODETYPE_DESKTOP_MICROPHONE,... which are defined in ksmedia.h.   But actually i got value "VT_EMPTY". why?

    Later i tried getting EndpointFormFactor value of an endpoint during enumeration. This time i got an enum value "Microphone" from my mic device, but TV Tuner gave this value too. So this method doesn't work either?

  • Aurora: You want to use PKEY_AudioEndpoint_FormFactor (http://msdn2.microsoft.com/en-us/library/ms679150(VS.85).aspx) to retrieve the formfactor.

    To find the line in volume control programatically, you should see this http://msdn2.microsoft.com/en-us/library/ms678713(VS.85).aspx sample, which finds a MUX control on a particular endpoint.  In your case, you want to look for a mute control named "mic mute".

    The part name varies by driver, not by OS.  And most audio solutions won't have that part anyway.

  • Thanks for your response!

    I did use PKEY_AudioEndpoint_FormFactor, but i got two devices

    that labeled themselves as "Microphone". one is Microphone and the other is TV Tuner. the latter is obviously what i don't want. So why i got two?

    i have read the actical about how to find a MUX. but i don't think that helps. My problem is how to determine whether a part is "mic mute" or not. I can find all parts, but i cann't tell which is which.

    Does that mean when i speak into micphone i can not prevent myself from hearing myself through speakers ?

    I can do this through Vista'UI manually.

  • Aurora: You need to talk to the vendor for your TV tuner driver to find out why they categorized their device as a microphone.  This information comes from the driver, we just report it through the API (and yes, it sucks).

    I know you can do this through the UI - I'm trying to give you instructions on how to do it programatically.  The UI simply walks down the paths from the endpoint to the actual output jack looking for various controls - it then puts a UI element in the dialog for each of those controls.  In your case, you only want a Mute control named "Mic Mute".  Unfortunately the only way to discover that the mute control is for a microphone is by matching the name - that's been the case since Windows 3.1 :(.

  • Thanks for your patience!

    Now i've 2 questions:(.

    Q1.

      If name-matching is the only way to find 'Mic mute', it is of no use at all, because names are what used to display to users,

    and it is not safe to use names to determine a control. Names may vary on different drives and different hard devices. Simply put, it

    is NOT POSSIBLE to prevent users from hearing themselves through speakers programtically. Am i right this time ?

    Q2.

      You said "that's been the case since Windows 3.1". Doesn't this mean it is impossible to do so on XP? But i used to do this on XP using the following code(it wroks at least for my computer), but it doesn't work on vista at all(mxl.cConnections equals 1 on vista while 11 on XP).

    bool DisableCaptureMonitoring(DWORD& dwLineID){

    MIXERLINE mxl;

    memset(&mxl, 0, sizeof(MIXERLINE));

    mxl.cbStruct = sizeof(MIXERLINE);

    mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;

    if(MMSYSERR_NOERROR != ::mixerGetLineInfo((HMIXEROBJ)m_hMixer,

    &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE))

    return false;

    dwLineID = mxl.dwLineID;

    DWORD MicrophoneSourceLineIndex = 0;

    MIXERLINE MicrophoneLine;

    for (DWORD dwLine = 0; dwLine < mxl.cConnections; dwLine++)

    {

    memset(&MicrophoneLine, 0, sizeof(MIXERLINE));

    MicrophoneLine.cbStruct = sizeof(MIXERLINE);

    MicrophoneLine.dwDestination = mxl.dwDestination;

    MicrophoneLine.dwSource = dwLine;

    if(MMSYSERR_NOERROR == mixerGetLineInfo((HMIXEROBJ)m_hMixer,

    &MicrophoneLine, MIXER_GETLINEINFOF_SOURCE))

    {

    if (MicrophoneLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)

    {

    //Unused

    MicrophoneSourceLineIndex = MicrophoneLine.dwSource;

    break;

    }

    }

    }

    if(mxl.cConnections <= 0 || MicrophoneSourceLineIndex == 0){

    //error

    return false;

    }

    else{

    // Set checkbox state in 'Recording Control'

    MIXERLINECONTROLS mlc = {0};

    MIXERCONTROL mc = {0};

    mlc.cbStruct = sizeof(MIXERLINECONTROLS);

    mlc.dwLineID = MicrophoneLine.dwLineID;

    mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;

    mlc.cControls = 1;

    mlc.pamxctrl = &mc;

    mlc.cbmxctrl = sizeof(MIXERCONTROL);

    if( MMSYSERR_NOERROR != mixerGetLineControls((HMIXEROBJ) m_hMixer,

    &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE)){

    return false;

    }

    MIXERCONTROLDETAILS mcd = {0};

    MIXERCONTROLDETAILS_BOOLEAN mcb = {0};

    mcb.fValue    = true;

    mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);

    mcd.dwControlID = mc.dwControlID;

    mcd.cChannels = 1;

    mcd.cMultipleItems = mc.cMultipleItems;

    mcd.paDetails = &mcb;

    mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);

    if( MMSYSERR_NOERROR != mixerSetControlDetails((HMIXEROBJ) m_hMixer,

    &mcd, MIXER_SETCONTROLDETAILSF_VALUE)){

    return false;

    }

    return true;

    }

    }

  • Aurora: Your code on XP is looking for a mute control on a microphone intput.  You can do the same thing on Vista (actually, on Vista it's orders of magnitude easier - you activate IAudioEndpointVolume on the microphone input and call the SetMute API on the interface).

    I didn't realize you were trying to mute the microphone (which doesn't work on most microphones).  I thought you were trying to mute the "Microphone" input on the render device.

    And on XP if you want to mute that control, you also have to match by name.

  • Still puzzled (like we are talking different things). May be that's because of poor english(I am not from english-speaking countries). Now i list 4 questions and it would be nice of you to give clear answers in the form of A1, A2, A3, A4. I apologize for the troubles it causes to you :).

    Q1: When i say "disable capture monitoring", i mean to prevent me from hearing myself through my speakers when i talk to my microphone. Have i got the concept "capture monitoring" right?

    Q2: Do you think matching-name a safe and feasible way to find a control? If so,how could i know their names, i think they are driver-dependent and different sound card may give different names too. For example, they could be labeled as "Mic mute" or "Microphone Mute" ... So if i am trying to match its names using something like strcmp( NameIWant, NameDriverGive ), what's the value of NameIWant?

    Since vista has overwritten the whole audio stack, why you still make name-matching(from Windows 3.1) the only way to find a control. I think it better to pre-define an ID for every possible controls a driver could provide,and expose those IDs for programmers of vista.

    Q3:You said "I didn't realize you were trying to mute the microphone (which doesn't work on most microphones).  I thought you were trying to mute the "Microphone" input on the render device."

    Yes, sure, i WAS trying to mute microphone(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) input on the render device(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS). Shouldn't i do so if i want to disable capture monitoring ? This code works well on XP and it does what i want(At least on my computer).

    Q4:I don't know why the same code doesn't work on vista. Have you broken the compatibility of mixerXXX functions, or it is just a matter of different drivers?

    I just want to disable capture monitoring (hope i have got this concept right),now i feel it a mess,and i cann't even tell if i can do so or not.  Vista is new to me, and i am new to vista. I hope you could help me.

    Thanks.

  • Q1: when you hear yourself on the speakers, it's because your audio solution has an internal loopback tap that mixes the microphone (or line in) input with the output.  This loopback tap operates outside the knowledge of the operating system.

    Most current audio solutions don't include this hardware (it costs money to implement) but some legacy solutions do.  I call this functionality a "capture monitor".

    As I said, this is done without the audio subsystem's knowledge.

    Q2: If you want to control this internal loopback tap, matching by name is your only option, both on XP and on Vista.  That's because there is no way of identifying which of several volume or mute controls actually controls this loopback circuit.

    Q3: There is another option to achieve your goal (which is the one that you apparently stumbled upon with your Windows XP mixer code).  That is to mute the microphone.  On Vista, this is trivial to implement (it's handled by theIAudioEndpointVolume interface).  Most microphone's don't actually have a mute control, but for those that do, your code will work.  On Vista, we synthesize a software mute for those devices that don't have a hardware mute, so the IAudioEndpointVolume API will work on all microphones.

    Q4: The reason the same code doesn't work on Vista is that on Vista, we intentionally broke the compatibility of the mixerXxx functions.  On XP, the mixer APIs controlled the hardware directly, on Vista they don't.  When you run your application in XP compatibility mode, we allow the mixer APIs to control the hardware.  The only caveat is that when you run in XP compatibility mode, you see ONLY the capabilities of the hardware.

  • Hey Larry why my vista vol mixer looks like this?

    Sp1 does not fix this.

    http://img523.imageshack.us/my.php?image=strangefx2.jpg

  • Carlos, beats me - there were a couple of paint problems that could have caused that, I thought they were fixed in SP1, but possibly it was after then.

  • Your explaination makes things clearer. Many thanks, Larry.

    About my computer:I've noticed the device properties displayed by Sndvol.exe control panel.(I don't know how to post a picture here). In the record tap, i double-clicked my microphone, and in the level tap, i saw my microphone didn't have a mute control(only a volume slide bar). But in play tap, i double clicked my speaker, and in the level tap, i saw the master volume control slide bar and a mute control button as well as other controls listed below, such as PC Speaker,line in,microphone, cd player, etc, all have a volume control slide bar and a mute control button(here, the mute control button of microphone is just what i want to program to control).

    Q1:You suggested to mute microphone, but i

    doubt that if microphone is muted, how can i  use it to capture sounds?

    Q2:When i tried to call IAudioEndpointVolume::SetMute(TRUE,NULL),i got a return value S_FALSE.

    MSDN says "If the method succeeds and the new muting state is the same as the previous muting state, the method returns S_FALSE. " it's confusing. If the method succeeded, why new muting state stayed unchanged?  

    Q3:QueryHardwareSupport() shows my microphone doesn't support contorls other than volume control. Does this mean i can not program to disable capture monitor on my machine?

    Q4:I also tried to run my old code in XP compatibility mode, while it has no effect :(.

  • Aurora: Q2: That means that the endpoint is already muted (see the docs for the returns for that API).  It lets you know that the call you made was a NOP (and, among other things, you're not going to get the notification).

    Q3: No, it means you need to match against the Mic Mute control that exists in your audio topology, just like I said you had to do.

Page 4 of 6 (80 items) «23456