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

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



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.

Comments (80)

  1. Anonymous says:

    If that’s the case, then why list in the mixer? Why would I want to change the volume of an application that has exited?

  2. Because while the mixer might not be able to figure out which app just made a noise, <i>you</i> might.

  3. Anonymous says:

    What is the need of listing App in mixer anyway if I myself can figure it out.

    Is it possible to reduce the volume of the app even if it is already exited (for future use)? I guess no.

  4. Anonymous says:

    I have to agree with David here: the cases where being able to figure out that the application which recently exited made a sound (after Googling, discovering this post, and reading it) is actually *useful* must pale into insignificance when compared to the number of people who’ll run across it throughout the lifetime of Vista, be exposed to the behaviour, and after a moment of head-scratching just decide it’s yet /another/ weird Vista bug.

    …or is being able to determine which app recently played a sound and then exited massively important to some focus group somewhere?

  5. Anonymous says:

    That’s still not the reason to keep it in the mixer. What exactly is the purpose of it being there? Even if you knew what application made the sound what exactly will changing the volume after it exited do? It certainly won’t be saved for the next time that application is launched, since neither the sound system nor the volume mixer know which application’s volume you’re adjusting. So, why exactly is it in the mixer?

    And what will happen if that PID is reused? Will the sound system use the old application’s volume for the new application that just happened to get the same PID?

  6. Anonymous says:

    I assume right now that volume settings are auto-remembered. If that’s correct, how is the setting maintained, when the actual identity is unknown/fuzzy? If not, why is the slider for Name not disabled? I had previously assumed that it was for "weird", but still running, apps of some kind (like a binary with no top-level window).

  7. sandeep: exactly.  If the app starts up again, the final volume from the mixer will be used for the app.

    And internally we keep the name of the executable, it’s just that that information isn’t available to sndvol (the reasons why are complicated).

  8. CN: The volume settings are kept in the registry.  And the identity is only fuzzy for the volume mixer, not for the audio subsystem.

    Jerry: The pid re-use issue is one we’ve considered and may fix in a future version of Windows.  The reality is that the risk associated with a re-used PID is relatively minor, the worst case is that we get an application mis-identified in sndvol.  The cost associated with fixing it is that the audio subsystem needs to keep a handle opened to every process that’s ever played audio and close it when the process exits.  That in turn has its own set of issues associated with it.

  9. Anonymous says:

    It would be nice if we could find out what PID it was. This way, I could track it down to the .exe file and know for myself what app I would be changing if there were several of those…

  10. Anonymous says:

    1. "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)."

    2. "If the app starts up again, the final volume from the mixer will be used for the app."

    3. "And the identity is only fuzzy for the volume mixer, not for the audio subsystem."

    Ok, now I’m more confused.  #1 and #3 appear to directly contradict each other.  #2 seems impossible if the audio subsystem only knows the PID of the app, since it will have a different PID when it is started again.

    Now if the audio subsystem does know the app name (so it can save the volume label for next time), but only provides an API for the mixer to get the PID, then that would explain #2 and #3 (but begs the question of why there isn’t an API for the mixer to get more detailed information, if it’s already sitting there anyway).  I can’t reconcile this with #1, though.

  11. Anonymous says:

    yeah, that’s why we can’t have nice things.

    cannot it be named at least "Recently played app"?

    can’t audio service keep app names in registry (yeah, that’s not nice, but Vista have a lot of worser things)?

  12. Anonymous says:

    Do you save volumes by exe name? I’m afraid to think what happens if that unidentified app was actually iexplore.exe.

  13. SvenGroot says:

    It seems there should be a better solution here. If the audio subsystem can persist the settings correctly for the next time the process starts even if you change the slider after it has closed, it must have more information than just the PID. It probably also has the exe name. If it can’t persist the settings correctly I see no reason why the slider is even there.

    If it has the exe name, why not make that available to the volume mixer and have it display that?

    Failing all those things, having a "Why?" link to a help file that explains why the name is not available in simple terms below the "Name not available" text would’ve helped a lot too, and it would be consistent with Vista’s UI which has help links all over the place (which users then completely ignore anyway πŸ˜› ).

  14. Anonymous says:

    If have to agree with most people so far…

    "after a moment of head-scratching just decide it’s yet /another/ weird Vista bug"

    This is excatly what I thought it was as i hadn’t seen it on other installations, and so ‘grouped’ it with other similar issues like apps that don’t get preview thumbnails when the app is open on (any) other monitor other that the primary.

    Good to know there’s a reason for this behaviour and even better to know it may be looked at in Win 7/8?


  15. Anonymous says:

    ‘Jerry: The pid re-use issue is one we’ve considered and may fix in a future version of Windows.’

    I love how everything is going to be fixed in a future version of Windows πŸ™‚

  16. Jonathan: Try it and see :).  The full path to the EXE is included in the persisted value, so you’d have to actually replace the exe on the disk to confuse the system.

    Triangle: So?  We took a look at the PID re-use issue and decided that it didn’t make the bar for fixing the issue in Vista.  The issue is real, so we deferred the fix for a future version of Windows (when we’ll have more time to work on a more complete fix).  It happens – every software project ever created has had bugs that weren’t fixed before it released.

    Miral: I think I need to write another blog post explaining in more detail.

  17. > And what will happen if that PID is reused?

    This is a very interesting question in a much larger scope than the volume mixer.

    Suppose I’m a sysadmin looking at a list of processes and I want to kill one.  I type kill … processid and the process with that ID is killed.

    But what if, between looking at the list and running the "kill", all the following happened?

    1) the process I was looking at exited

    2) another process started

    3) the new process happened to use the processid

    I’ve killed the wrong process.

    There’s a reasonable expectation that the thing that hands out process IDs should make an effort to avoid this… say, by giving recently used process IDs a well-deserved vacation.

  18. Maurits: Absolutely.  And the thing that hands out process IDs does make an effort to avoid this (sort-of).  But there is a limit to what it can do and stuff does happen.

  19. Anonymous says:

    err.. an engineer-type decision that doesn’t work well and possibly confuses the user frequently in the hope of some possible edge case when it might be useful.  Absolutely revolting to have these sort of things still going in software 2007.   Remove this ENTIRE debugging feature and keep-the-os-simple is the correct solution.  Not more cruft with trying to find the correct name of the name, for that one guy in billion that knows to look in the sound mixer for figure which app made a beep.  Please read The Inmates are Running the Assylum.

  20. The slider is a troubleshooting feature (in fact, the entire audio mixer is a troubleshooting feature).

    If we were to remove it, we’d get complaints "There’s this app that keeps on making noises on my machine and I can’t get it to stop".

  21. Anonymous says:

    I would like to have a control panel which would allow me to view and adjust already existing persistent parameters for individual executables  which did not play any sound in the current session.

    For example for program which plays a notification sound when some event happens (e.g. Alarm Clock, TV notifier) I can not adjust the volume before that event happens (at least I did not found a way to do it) nor check how loud it will be.

  22. Anonymous says:

    OK, so there’s an application that’s making a sound and I want to know why it’s happening.

    That there’s no "sound history" to go on means I’m left muting random applications until I find it the cause.  But if there’s an entry in the list with no name available (or worse, the wrong name when a PID get reused) how is this going to help me track down the rogue app?  I see a best case scenario being "Ah ha!  There’s the bugger!  Now I wait patiently for it to relaunch so I can see it’s name."  (That assumes it updates realtime).   And worst case being a complete miscarriage of justice as I uninstall the unlucky program that took the PID.

    I’m not saying it’s a totally bad idea, but maybe it should have been an advanced option defaulted to not display the extra information.  And maybe an option to display even more information related to processes playing sounds (EXE name, PID, history, etc.).

    I imagine with basic to intermediate users this would actually cause more calls for support than it would fix.

  23. Anonymous says:

    I think this feature makes sense. Let’s say some app makes a sounds as it exits, so a user goes to the mixer to see what app could have made the sound. If they only see the currently running apps, they are liable to assume that one of those made the sound. If they see an unnamed app, they are able to see that some app other than those currently running could have been the culprit.

  24. Anonymous says:

    It’s called a timeout queue. I have recently had to implement such a feature for my own component. If some information is unreliable, then simply keep a reliable copy of it around for ‘a while’ say 10 sec after it terminates. Clean it up afterwards. Should the app relaunch again, you’d have to link up with this ‘reliable copy’ of course to prevent lots of duplicates being generated…

  25. Andre says:

    Hello Larry,

    is PID reuse really a concern? The PID is a DWORD, so there are 4 billion unique IDs before they need to be reused.

    Even if you create one process per second, every power supply I know needs to be replaced before a PID is reused.

    Or is the handle internally reused? Then why not give it a new PID?

    Maybe I’m missing something here, haven’t cared much about CreateProcess and PIDs yet.

  26. Andre: A PID is essentially a handle, and as such it can be reused just like handles can be reused.

    On checked builds of Windows, there’s actually code in the handle manager to enhance the likelihood that a handle gets re-used (I don’t know if the same is true for PIDs).

  27. Andre says:

    Also why don’t you just use the process creation time (GetProcessTimes) to figure out if a PID has been reused?

  28. Andre says:

    Thanks for your reply Larry. I understand that it makes sense to reuse processes internally but the handle manager could assign a new unique handle to it and also like on FreeBSD the PID could just be a counter.

    What’s the rationale behind handle/PID reuse?

  29. It’s more efficient.  Ultimately a handle maps to an object.

    If the handle is just a counter, then you need to do a linear scan through your list of open objects until you find the object that matches the handle.  If your handle is more complicated you can use a more sophisticated data structure to represent your handle.  The downside of using a more sophisticated structure is that your handles can get re-used.

  30. Andre says:

    I’m not aware of any Win32 functions that take a PID, they all want the handle. So why is the PID reused too?

    I would also be great if you could comment why you are not using the process creation time to figure out if a handle/PID has been reused.

  31. Anonymous says:

    Andre: OpenProcess takes a PID

  32. Andre says:

    You’re right, OpenProcess() takes the PID, but that’s the only function. The mapping from the PID to the handle doesn’t have to be sophisticated high performance code. A simple iteration over the running processes should be fine.

    Windows users don’t need the PID anywhere, so there is no need to keep the PID small.

  33. Anonymous says:

    just to add to the onslaught of commentry….

    what a crap name…. "name not available".   This is describing your problem as a programmer rather than telling anyone anything useful.  

  34. Keith: What text would you prefer to "Name not available"?

    We want to display the slider because the user has context that we don’t (they know what apps they ran previously, we don’t).

  35. Andre says:

    Maybe something like "Recently closed application"?

  36. Anonymous says:

    Here are a couple of stories about reuse of things like PIDs and handles.

    In early releases of the predecessor of WNT, when OpenVMS was still known as VMS, PIDs were 32 bits long, but no practical system was going to run more than around 65536 processes at once.  So someone had the brilliant idea of using 16 bits for the actual PID number and another 16 bits for a kind of serial number or password.  When the first 16 bits were going to be reused, the other 16 bits would get incremented.  If some poorly written app wanted to attack some innocent new process that happened to get a reused number, then the odds would be pretty low of getting the entire 32 bits to match.  Of course "one in a million is two minutes from now" but still there would be a high probability of the errant attacker getting caught, so programmers would get some assistance in debugging.

    Later versions of VMS no longer did that.

    One former employer, making embedded systems with no memory protection, had lots of problems with poorly written processes overwriting structures in the memory manager, freeing stack variables onto the heap, and various other bugs that would crash the system.  I copied an idea from what I’d seen in old VMS.  My memory manager returned handles, aligned blocks on 8-byte boundaries, and used the low-order 3 bits of a handle as a kind of serial number or password.  A really poorly written process could still smash my structures, but the average poorly written client would just pass me a handle that had already been freed.  I had an 87.5% chance of catching their bugs.

    Later versions stopped doing that.  My colleages didn’t want to be informed of their bugs, and didn’t want to fix them.

  37. Andre says:

    Hey Larry, no reply?

  38. Anonymous says:

    > Andre: What’s to reply?

    Uh, yeah.  If the path from suggester to listener was recently closed, then maybe "topic not available" is better than "recently closed discussion".  Otherwise, I thought Andre’s suggestion would be more understandable by users outside of Microsoft.

  39. Andre says:

    I would also be great if you could comment why you are not using the process creation time to figure out if a handle/PID has been reused.

  40. Andre says:



  41. Anonymous says:

    I find this whole sound ‘volume per app’ ridiculous. I can’t think of any useful application for it, except for eye candy and pleasing lazy users.  I wish all this effort was put into filesystem (sorry Larry, didn’t mean to underestimate your work), or fixing stupid bugs like file copy and poor network performance, which are essential for an OS.

    Another thing, this just increases the amount of ‘user tracking’ or ‘instrumentation’. Without going into privacy issues, just think about the performance hit. On XP for example (I’m not touching Vista anytime soon) registry items like ShellNoRoam, MenuOrder, TrayNotify & PastIconsStreams get written and rewritten all the time, whether one wants their ‘services’ or not. I assume there are many similar (additional) things in Vista which, when added up, make the concept that is associatied with it – bloat.

  42. Grigi: Interesting.  Our studies of XP customers showed pretty clearly that they were extremely annoyed that some applications (Certain media players were particular offenders) would change the master volume of the system instead of changing their own volume.  The per-application volume feature came out of that.

    The reality is that every feature in Windows has people who like it and people who hate it.  When my wife’s riding instructor learned that she could control the volume of system sounds independantly from the volume of other applications, she was ecstatic.

    The extra "overhead" associated with per-application volume is negligable – there’s a string that internally identifies an "application" (which is persisted in the registry, and rewritten 2 seconds after an application changes the volume), and a structure that tracks the volume of the application (and a number of other things, including all the audio streams for the application).  

  43. Anonymous says:

    Then the applications should have been forced to behave. I know, I know, it’s always perceived as Microsoft’s fault… maybe ban that behaviour and introduce a new ‘proper’ api… (hm… breaking compatibility – no win here). Or just keeping the old api, but nonfuctional (i.e. it doesn’t change the volume)? Plenty of possibilities there… But I’m no programmer, just ordinary user who gets p****d off by the bloat creeping in every new version of windows…

    Take care

  44. Grigi: How do we "force" applications to behave?  It’s 3rd party code, we can’t control it.

    What we CAN do is what we did – reset the system-wide behavior and make it local.  Which is what you’re complaining about.

  45. Anonymous says:

    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.

  46. Anonymous says:

    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!!!

  47. 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.

  48. Anonymous says:

    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?

  49. 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.

  50. Anonymous says:

    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.

  51. 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 :(.

  52. Anonymous says:

    Thanks for your patience!

    Now i’ve 2 questions:(.


      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 ?


      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);


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


    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,



    if (MicrophoneLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)



    MicrophoneSourceLineIndex = MicrophoneLine.dwSource;





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


    return false;



    // Set checkbox state in ‘Recording Control’


    MIXERCONTROL mc = {0};

    mlc.cbStruct = sizeof(MIXERLINECONTROLS);

    mlc.dwLineID = MicrophoneLine.dwLineID;


    mlc.cControls = 1;

    mlc.pamxctrl = &mc;

    mlc.cbmxctrl = sizeof(MIXERCONTROL);

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


    return false;




    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,


    return false;


    return true;



  53. 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.

  54. Anonymous says:

    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.


  55. 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.

  56. Anonymous says:

    Hey Larry why my vista vol mixer looks like this?

    Sp1 does not fix this.


  57. 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.

  58. Anonymous says:

    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 :(.

  59. 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.

  60. Anonymous says:

    Larry,  i would use the following steps to mute a microphone:


    then find MICROPHONE and mute it.

    But, if i mute microphone as you suggested, how can i  use it to capture sounds?


  61. Aurora: You can’t.  But that’s what your XP code did.  I was just showing you how to do it on Vista.

  62. Anonymous says:

    On vista I tried every way including mute micphone, all don’t work except mute the "Mic mute" control.

    It seems that mute the "Mic mute" control is the ONLY way to do this, and matching name is the ONLY way to find the "Mic mute" control.

    Thanks, larry! You are really nice.

  63. Anonymous says:

    Hi, lerry,

    When i use EXCLUDSIVE mode to create a stream, doesn’t that mean the device cann’t not be used by other applications except the stream itself ?

    For example , if i created an excluseive-mode stream successfully on my SPEAKERS, can i still hear the music played by windows media player?

  64. Aurora: Exclusive means that you own the device.  That means that nobody else can render to it.

  65. Anonymous says:

    Can different applications share the same session?

    If so, what’s the way to manage volume per application, must i refer to stream volume?

  66. Anonymous says:

    Can different applications share the same session?

    If so, what’s the way to manage volume per application, must i refer to stream volume?

  67. Aurora: Yes, that’s what the cross process stream initialization flag does.

    You have a multitude of ways you can manage volume: Per stream, per channel, and per session (I strongly recommend you avoid per channel).  You need to figure out which is the right one for your application.

    See my posts on that subject (you can search for them).

  68. Anonymous says:

    WAVEINCAPS and WAVEOUTCAPS , those two structures has a field  declared like this:

    CHAR    szPname[MAXPNAMELEN];

    the macro MAXPNAMELEN is defined in mmsystem.h

    #define MAXPNAMELEN   32  /* max product name length including NULL) */

    while in Vista, 32 bytes seems too short. When i use waveInGetDevCaps or waveOutGetDevCaps under vista, i usually got truncated names like "Realtek Digital Output (Realtek"

    ,which is exactly 31 characters long.

    Is this a bug?

  69. Aurora: Feel free to get in your time machine, set the time slider to 1991 and submit a bug to the Windows 3.0 team to get them to increase the size of the field.

    Unfortunately, it’s quite difficult to fix structures which were defined 17 years ago.

  70. Anonymous says:

    Hi, Larry, Could you please take a look at the following code and tell me why the IAudioEndpointVolumeCallback::OnNotify() could not receive anything?

    class CAudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback{

    … …

    // Callback method for endpoint-volume-change notifications.


           return S_OK;



    bool RegisterAudioEndpointVolumeCallBack(){

    CComPtr<IAudioEndpointVolume> pEndPntVol;

    HRESULT hr ;

    CComPtr<IMMDeviceEnumerator> spEnumerator;

    hr = CoCreateInstance(

    __uuidof(MMDeviceEnumerator), NULL,CLSCTX_INPROC_SERVER,


    (void**)&spEnumerator  );

    hr = spEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &CurrentOutputDevice);

    hr = m_CurrentOutputDevice->Activate( __uuidof(IAudioEndpointVolume),CLSCTX_ALL, NULL, (void**)&pEndPntVol);

    hr = pEndPntVol->RegisterControlChangeNotify( (IAudioEndpointVolumeCallback*)&EPVolEvents );


    CAudioEndpointVolumeCallback EPVolEvents;

    CComPtr<IMMDevice> CurrentOutputDevice;

    int _tmain(int argc, _TCHAR* argv[])




    //I let it stop to see the results





    return 0;


    The OnNotify function is NEVER called when i change endpoint volume in SndVol. could you give some hints?


  71. Search my blog, there’s a sample I posted a while ago that does that (it’s a volume slider, but it should work).

  72. Anonymous says:

    Thanks larry, i searched you blog and read your artical

    "Fun with the endpoint volume interfaces – closing the loop ", but i think it contains not enough information.

    Now i tried to create a new thread and put "RegisterAudioEndpointVolumeCallBack()" as the thread function, and i modified this function a little(i call Sleep(10) at the end of the function in a dead loop to prevent this thread from exit), this time it works, i can receive notifications when i change speaker volume and mute state.

    but i don’t know why? Doesn’t the RegisterControlChangeNotify() function requires a new thread?

  73. Aurora, it does – the system owns that thread though.

  74. Anonymous says:

    Hi Larry, what do you mean by "the system owns that thread"?

    Does that mean i need not call CloseHandle() for that thread manually?  

    In other words, all i need is to call IAudioEndpointVolume::UnregisterControlChangeNotify()

    ,and this will terminate that thread automatically, right?

  75. I mean that the thread that’s used to call back into your application for the notification is owned by the system.

    The thread won’t be terminated because it’s a system managed threadpool thread – other things in the OS use it as well.

  76. Anonymous says:

    I solved the problem. It’s all because i declared a IAudioEndpointVolume using CComPtr, which automatically release the interface after the function.

    After i replaced it with "IAudioEndpointVolume *pEndPntVol;" and manually release it at proper time. Everything works fine.

    Thanks larry!

  77. Anonymous says:

    Larry, when i saw the document of ISimpleAudioVolume, i doubt why must i retrieve this interface by creating a stream?

    Why cann’t I get this interface just by specifying the guid of the session without creating any useless stream?

    Please let me know if i misunderstood all this. Thanks!

  78. Aurora: You don’t need a stream to create the interface.  You can use the IAudioSessionManager interface to access the simple volume for the current process.

  79. Anonymous says:

    As someone who occasionally gets seemingly-random sounds on my PC and  has tried to figure out what application was responsible for random noises from my PC, I’m very happy that MS has taken some steps that make this possible.  Even if it’s not exactly perfect.

    I’d much rather have some volume slider sometimes show up without a clear identifier than have sounds being played without being able to easily determine what was making hte sounds (or why).


Skip to main content