6

I have an application which has sound. I have a global property to mute the sound. The problem is, there's so many different things which can make sound, I would hate to iterate through different class types and mute/unmute their sound. Instead, I'm looking for a way to mute the sound on a global application level. I don't mean muting the entire system volume either.

One scenario: In Windows 7, you can open the Volume Mixer and adjust the volume of individual applications. While I don't intend to change this actual particular value (as I know it's Windows 7 specific), I would like to change the volume of everything in my application all at once. I would also need the ability to completely mute the sound of everything in my application. I need this ability to be compatible with Windows XP and above. I am assuming it will involve Windows API calls, but I have no idea what calls to make.

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • Have a look at this question: http://stackoverflow.com/questions/1092466/windows-xp-mute-unmute-audio-in-programmatically-in-python – Sebi Aug 25 '12 at 23:25
  • 3
    for what i remember, XP had not per-application sound level. You would have some central sound output API in you application and there toggle if you let it out to Windows API or just ignore and dispose – Arioch 'The Aug 26 '12 at 00:32
  • 1
    WinXP doesn't have per application sound control capabilities. This was added in Vista, and it uses a totally separate (new) API to do so, with new interfaces added to support it. Larry Osterman (one of the MS old-timers) had a series on the new sound APIs on his blog; I don't have a link to it on this machine, but you should be able to find him by Googling. There are posts on this on SO in C/C++ I remember seeing a while back as well; I'll see if I can find a search term for you to use to find them. – Ken White Aug 26 '12 at 00:38
  • 3
    Use `IAudioEndpointVolume` as your search term here (and on MSDN as well) for posts and API documentation. – Ken White Aug 26 '12 at 00:40
  • 1
    Can't you just stop playing sound when the user asks for it to be muted? – David Heffernan Aug 26 '12 at 08:03
  • @DavidHeffernan I'm actually using multiple instances of a third-party ActiveX control which has an internal glitch keeping the sound from cutting off immediately, and makes an awful sketchy sound when it does so. 9 different plugins producing this scratchy sound together when user mutes, changes streams, or closes the app sounds horrible, so as a tweak, I'd like to temporarily mute the entire app. – Jerry Dodge Aug 26 '12 at 08:17
  • 1
    I suspect you'll have to suck it down on XP and do it right on Vista+. – David Heffernan Aug 26 '12 at 08:26

2 Answers2

4

XP does not support per-application volume control. That capability was added in Vista. So what you are attempting to do cannot be done in XP by fair means.

There is software called IndieVolume that retro fits per-app volume control to XP. I can only imagine it does so by means of low-level hacking, DLL injection and so on. I doubt that's really an option for you.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
3

What you're asking for isn't possible on XP; the OS simply does not support per-application volume levels.

You can accomplish what you want by creating a settings class that keeps things like SoundActive: Boolean or PlaySounds: Boolean or something similar. Place it in it's own unit, and have an initialization section that creates an instance of it and a finalization section that frees it (making it effectively a collection of global values).

Each unit that needs access to these settings simply uses the unit containing them, and adjusts behavior accordingly. So each of your child classes or forms or whatever would just need a check added:

if CurrentSettings.PlaySounds then
  // Code that makes sounds, plays music, whatever.

The settings class can also contain methods that keep track of the current volume level (on XP, the system-wide level), and methods to increase or decrease volume using the MMSystem volume functions (there are tons of examples here and through Google of doing so). Your app can then use the OnActivate and OnDeactivate events to set the volume level when your app gains focus, and restore it to the proper volume when your app loses focus.

In Vista and higher, you can use the IAudioEndPointVolume interface I mentioned earlier and either the GetMasterVolumeLevel or SetMasterVolumeLevel methods to control system wide volume (I have an example of doing this, along with the appropriate MMDevAPI interface definitions) or device level volume (using IMMDevioce.Activate to select the proper device first and then the above IAudioEndPointVolume methods on the device interface received from IMMDevice.Activate in the ppInterface parameter).

For individual applications, you use the ISimpleAudioVolume interface, which has four methods: GetMasterVolume and SetMasterVolume, which control the volume level for your application's audio session, and GetMute and SetMute to allow you to retrieve the current mute flag value or set it respectively. (Larry Osterman of MS, who was one of the developers who worked on the new audio support in Vista and Win7, has a great starting point article on his blog about the types of audio in the new API and when to use each of them.)

It's conceptually possible to determine at runtime which operating system you're using, and to programmatically switch between using the MMSystem functionality on XP and earlier, and the MMDevAPI functionality on Vista and higher. Expecting someone here to provide the code for doing so is a little unreasonable, however. The links I've provided should get you started on the right track, and when you run into snags along the way specific help in working through those snags would be great questions.

Ken White
  • 123,280
  • 14
  • 225
  • 444