Here's a small app I wrote years ago. Some of the comments look a little fishy, and I'm not even sure it's entirely correct, but it does seem to work for me.
Code:
#include <windows.h>
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* A small commandline tool to check the volume set on the speaker out line of
* the primary/default sound card mixer device.
*
* Basically, it prints out the master audio volume for the system.
*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
*/
int main(int argc, char ** argv) {
HMIXER mixerHandle;
MIXERCAPS mixcaps;
MIXERLINE mixerline;
MIXERCONTROL volumeControl;
MIXERLINECONTROLS mixerLineControls;
MIXERCONTROLDETAILS_UNSIGNED value;
MIXERCONTROLDETAILS mixerControlDetails;
// Open the mixer associated with the default sound card in the computer
if (mixerOpen(&mixerHandle, 0, 0, 0, 0)) {
printf("Couldn't open mixer\n");
}
else {
// Get info about the first Mixer Device
if (mixerGetDevCaps((UINT)mixerHandle, &mixcaps, sizeof(MIXERCAPS))) {
printf("Error calling mixerGetDevCaps()\n");
}
else {
printf("Sound Card: %s\n", mixcaps.szPname);
printf("There are %d supported destinations for this card\n", mixcaps.cDestinations);
printf("\nFetching info about the speaker line out:\n");
mixerline.cbStruct = sizeof(MIXERLINE);
mixerline.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
// Get info about the speaker destination line
if (mixerGetLineInfo((HMIXEROBJ)mixerHandle, &mixerline, MIXER_GETLINEINFOF_COMPONENTTYPE)) {
printf("Error getting speakers line info\n");
}
else {
printf(" Name: %s\n", mixerline.szShortName);
printf(" Description: %s\n", mixerline.szName);
mixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS);
mixerLineControls.dwLineID = mixerline.dwLineID;
mixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mixerLineControls.cControls = 1;
mixerLineControls.pamxctrl = &volumeControl;
mixerLineControls.cbmxctrl = sizeof(MIXERCONTROL);
// Get info about the speaker line's volume control
if (mixerGetLineControls((HMIXEROBJ)mixerHandle, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE)) {
printf("Couldn't get info about the speaker line's volume control\n");
}
else {
mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
mixerControlDetails.dwControlID = volumeControl.dwControlID;
mixerControlDetails.cChannels = 1;
mixerControlDetails.cMultipleItems = volumeControl.cMultipleItems;
mixerControlDetails.paDetails = &value;
mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
// Get the value of the speaker line's volume control
if (mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE)) {
printf("Couldn't get speaker line's volume control details\n");
}
else {
printf("Speaker line's volume is set to %u (%d%%)\n", value.dwValue,
(int)((double)value.dwValue/volumeControl.Bounds.dwMaximum*100));
}
}
}
}
}
printf("Closing mixer device's handle\n");
mixerClose(mixerHandle);
}
And here's a sample output running it once on my machine, increasing my system volume a bit, and then running it again:
Code:
Z:\>mixer
Sound Card: Realtek HD Audio output
There are 1 supported destinations for this card
Fetching info about the speaker line out:
Name: Master Volume
Description: Master Volume
Speaker line's volume is set to 7864 (11%)
Closing mixer device's handle
Z:\>mixer
Sound Card: Realtek HD Audio output
There are 1 supported destinations for this card
Fetching info about the speaker line out:
Name: Master Volume
Description: Master Volume
Speaker line's volume is set to 15728 (23%)
Closing mixer device's handle
I know they revamped the audio APIs when Vista came out. Obviously the mixer API is still there, but its been reimplemented on top of whatever it is that Vista uses now. If I remember right, the changes make it harder to get the actual "system volume" since a lot of the volume settings are per application in Vista. I know I wrote a version of my app that works in Vista, so I'll see if I can't dig up an example for that as well.