views:

548

answers:

2

Does anyone know how to get the current volume level of an audio session* in Vista or 7?

I've got the IAudioSessionControl2 and IAudioSessionManager2 instances you need to listen for volume changes, but actually getting the current volume is proving elusive.

*by audio session I mean (roughly) the per-application audio control, not the "master" one


Note that (so far as I can tell) IAudioSessionManager2->GetSimpleVolume() isn't the right answer here. The only thing that publishes a GUID in IAudioSessionControl2 is the Grouping parameter, and using it in GetSimpleVolume creates new sessions rather than giving you the control for an existing one.

GetSimpleVolume() is what I want, but where are the params coming from in this setup?

+1  A: 

I think the ISimpleAudioVolume interface should do what you need.
It has a method called GetMasterVolume witch returns the volume for the audio session.
To obtain the interface you can call IAudioSessionManager::GetSimpleAudioVolume.

For the guid parameter you can use the one you specify when creating the audio streams with IAudioClient::Initialize. I honestly don't know if there are other ways to get the guid for a session.

The grouping parameter is the id of the group to witch the session belongs and not an id of a session.

Roald
ISimpleAudioVolume from an IAudioSessionManager gives you the Master volume. The volume for each session is distinct, such that the **actual** volume of a session is (MasterVolume x SessionVolume) x 100.
Kevin Montrose
Kevin, one nit: Volume in Windows Vista and beyond is measured in floating point units from 0.0 to 1.0. A volume multiplied by 100 is likely to be invalid.Also the master volume has a volume taper applied to it, there isn't a direct relationship between the Scalar volume value and the actual dB output from the speakers. You can set the actual dB attenuation by using the SetMasterVolumeLevel API.
Larry Osterman
+1  A: 

Actually IAudioSessionManager::GetSimpleAudioVolume IS what you're looking for.

An audio session is identified by two (or three) things: The session guid, the process ID and the cross process flag (if the cross process flag is specified when the stream is created, the process ID is ignored).

The simple audio volume controls the volume of all the streams within that audio session. It's fairly straightforward (most rendering frameworks specify NULL for the session GUID). If your application uses a specific session GUID, you should just specify the session GUID your application is using.

There's one other twist though. The volume control (sndvol.exe) combines all sessions with the same "grouping param" together in the UI - this isn't a part of the volume control, it's a UI convenience feature that exists only for web browsers like IE - it exists to allow 3rd party audio frameworks (which specify a GUID_NULL session GUID) and the WMP OCX (which specifies a cross process session with a specific session GUID) to share a single slider in the volume UI.

Larry Osterman
I'm missing something then. The process ID is pretty obvious, the AudioSessionGUID less so. Like I said in the question, the only thing I've found that shunts out a GUID is IAudioSessionControl->GetGroupingParam(); which doesn't make sense. This may just be my search-fu failing.
Kevin Montrose
When you call IAudioClient::Initialize to create an audio stream, one of the parameters is the session GUID. By default, all the rendering frameworks in Windows specify a NULL GUID (it's possible to override the GUID when you render from MediaFoundation or DirectSound but most apps don't do it, and if they DO, it's not a big deal because your app knows which GUID it's using for its sessions).Btw, The GetSimpleAudioVolume API will only retrieve a session control for the current process, not for another process.
Larry Osterman
So, duplicating SndVol functionality is still painfully complicated then. At least its getting easier in 7.
Kevin Montrose
Kevin: sndvol is painfully complicated :). And there's really no way of making it simple.
Larry Osterman
Absolutely, but you'd think getting/setting per application volume levels would be simpler than it is. Though admittedly, its a very edge case for prospective developers.
Kevin Montrose
If GetSimpleAudioVolume will only give control of sessions of the current process, how would you go on to control other processes' volume? I am trying to mute another process. (Windows 7)
Anton Hansson
Anton: In Windows 7 the IAudioSessionManager2 interface will allow you to get a session enumerator which will allow you to enumerate the audio sessions for all apps running under your account (actually your TS session but that's nitpciking). This is the same API that sndvol uses to control the volume of other apps.
Larry Osterman
This should probably have been in a question of it's own, but after getting a reference to the correct IAudioSessionControl2, how do I go on to actually change the volume? I can only find methods to subscribe to events and get info about the session. Thanks!
Anton Hansson
Question asked here: http://stackoverflow.com/questions/1791361/controlling-the-volume-of-other-applications
Anton Hansson