Skip to content

Commit

Permalink
Merge feature-mute
Browse files Browse the repository at this point in the history
Closes #1
  • Loading branch information
davidcie committed Jan 29, 2018
1 parent c655042 commit 37a4d21
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 85 deletions.
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
## Not _another_ volume app!
I created this solely because the excellent [EventGhost](http://eventghost.org) automation tool is only able to adjust *speaker* volume by default due to Windows API limitations and their aim to be Windows 2000/XP compatible. This is a little annoying if you regularly use a remote control and headphones, whose volume you'd be unable to adjust using the remote.

Should work on Windows Vista and newer. Tested on Windows 7 and Windows 10.
Should work on Windows Vista and newer, tested on Windows 7 and Windows 10. You need to have a recent version of [Visual C++ libraries](https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads) installed (Visual Studio 2015 or newer) but chances are if you have any software on your PC, these libraries will have already been installed by other programs.

## Usage
* `SetVolume` reports the current default playback device volume as a percentage
* `SetVolume <percent>` sets the current default playback device volume (0..100)
* `SetVolume +<percent>` increases default playback device volume by a specified percentage (0..100)
* `SetVolume -<percent>` decreases default playback device volume by a specified percentage (0..100)
* `SetVolume` or `SetVolume help` displays usage information.
* `SetVolume get` reports current default playback device volume as a percentage.
* `SetVolume set <percent>` sets current default playback device volume to a percentage.
* `SetVolume set +<percent>` increases default playback device volume by a specified percentage.
* `SetVolume set -<percent>` decreases default playback device volume by a specified percentage.
* `SetVolume mute` mutes default playback device.
* `SetVolume unmute` unmutes default playback device.
* `SetVolume togglemute` toggles mute for default playback device.

## Building
1. Install [Microsoft Windows SDK for Vista](https://www.microsoft.com/en-us/download/details.aspx?id=14477)
2. Install Microsoft Visual Studio 2010
3. Get the source.
3. Build!
1. Install Microsoft Visual Studio 2015
1. Get the source.
1. Open solution &ndash; you should be prompted to install Windows 8.1 SDK if you have not done so yet. (Do not worry, the 8.1 SDK is backwards compatible down to Vista.)
1. Build!

## Credits
Based on and inspired by [code shared by Larry Osterman](https://blogs.msdn.microsoft.com/larryosterman/2007/03/06/how-do-i-change-the-master-volume-in-windows-vista/) of Microsoft.
181 changes: 105 additions & 76 deletions SetVolume.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,84 +18,32 @@
#define WINVER _WIN32_WINNT_VISTA
#define _WIN32_WINNT _WIN32_WINNT_VISTA

#define VERSION_MAJOR 1
#define VERSION_MAJOR 2
#define VERSION_MINOR 0

#include <cstdio>
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>

using namespace std;

enum VOLUME_OPERATION {
VOL_CHECK,
VOL_CHANGE,
VOL_SET
};

void DisplayUsageAndExit()
{
printf("SetVolume v%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
printf("Usage: \n");
printf(" SetVolume [Reports the current default playback device volume as a percentage]\n");
printf(" SetVolume <percent> [Sets the current default playback device volume]\n");
printf(" SetVolume +<percent> [Increases default playback device volume by a specified percentage]\n");
printf(" SetVolume -<percent> [Decreases default playback device volume by a specified percentage]\n");
exit(-1);
printf(" SetVolume get Reports current default playback device volume as a percentage.\n");
printf(" SetVolume set <percent> Sets current default playback device volume in percentage.\n");
printf(" SetVolume set +<percent> Increases default playback device volume by a specified percentage.\n");
printf(" SetVolume set -<percent> Decreases default playback device volume by a specified percentage.\n");
printf(" SetVolume mute Mute default playback device.\n");
printf(" SetVolume unmute Unmute default playback device.\n");
printf(" SetVolume togglemute Toggle mute for default playback device.\n");
exit(1);
}

void SetVolume(IAudioEndpointVolume *endpoint, float volume)
void InitializeAudioEndpoint(IAudioEndpointVolume **audioEndpoint)
{
HRESULT hr;

printf("Setting volume to: %.0f%%\n", volume * 100);
hr = endpoint->SetMasterVolumeLevelScalar(volume, nullptr);
if (hr != S_OK) {
printf("Unable to set master volume (error code: 0x%08lx)\n", hr);
endpoint->Release();
CoUninitialize();
exit(-1);
}
}

float GetVolume(IAudioEndpointVolume *endpoint)
{
HRESULT hr;
float volume = 0;

hr = endpoint->GetMasterVolumeLevelScalar(&volume);
if (hr != S_OK) {
printf("Unable to get master volume (error code: 0x%08lx)\n", hr);
endpoint->Release();
CoUninitialize();
exit(-1);
}
return volume;
}

int main(int argc, CHAR* argv[])
{
HRESULT hr;
VOLUME_OPERATION operation = VOL_CHECK;
float newVolume = 0;

if (argc != 2 && argc != 1)
{
DisplayUsageAndExit();
}

if (argc == 2)
{
newVolume = strtof(argv[1], nullptr) / 100;

if (argv[1][0] == '+' || argv[1][0] == '-') {
operation = VOL_CHANGE;
} else {
operation = VOL_SET;
}
}

// Initialize the COM library
CoInitialize(nullptr);

Expand All @@ -120,32 +68,113 @@ int main(int argc, CHAR* argv[])
}

// Ask default audio renderer for volume controller
IAudioEndpointVolume *endpointVolume = nullptr;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)&endpointVolume);
//IAudioEndpointVolume *endpointVolume = nullptr;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)audioEndpoint);
defaultDevice->Release();
defaultDevice = nullptr;
if (hr != S_OK) {
printf("Unable to get default audio volume controller (error code: 0x%08lx)\n", hr);
CoUninitialize();
exit(-1);
}
}

void DestroyAudioEndpoint(IAudioEndpointVolume *endpointVolume)
{
endpointVolume->Release();
CoUninitialize();
}

void SetVolume(IAudioEndpointVolume *endpoint, float volume)
{
HRESULT hr;
printf("Setting volume to: %.0f%%\n", volume * 100);
hr = endpoint->SetMasterVolumeLevelScalar(volume, nullptr);
if (hr != S_OK) {
printf("Unable to set master volume (error code: 0x%08lx)\n", hr);
DestroyAudioEndpoint(endpoint);
exit(-1);
}
}

float GetVolume(IAudioEndpointVolume *endpoint)
{
HRESULT hr;
float volume = 0;
hr = endpoint->GetMasterVolumeLevelScalar(&volume);
if (hr != S_OK) {
printf("Unable to get master volume (error code: 0x%08lx)\n", hr);
DestroyAudioEndpoint(endpoint);
exit(-1);
}
return volume;
}

void SetMute(IAudioEndpointVolume *endpoint, BOOL newValue)
{
HRESULT hr;
hr = endpoint->SetMute(newValue, nullptr);
if (hr != S_OK) {
printf("Unable to set mute (error code: 0x%08lx)\n", hr);
DestroyAudioEndpoint(endpoint);
exit(-1);
}
}

BOOL GetMute(IAudioEndpointVolume *endpoint)
{
HRESULT hr;
BOOL value;
hr = endpoint->GetMute(&value);
if (hr != S_OK) {
printf("Unable to get mute status (error code: 0x%08lx)\n", hr);
DestroyAudioEndpoint(endpoint);
exit(-1);
}
return value;
}

int main(int argc, CHAR* argv[])
{
HRESULT hr;
float newVolume = 0;
IAudioEndpointVolume *endpointVolume = nullptr;

// Exit early if only displaying help
if (argc == 1 || argc > 1 && strcmp(argv[1], "help") == 0) {
DisplayUsageAndExit();
}

// Find devices for manipulating mixer volumes
InitializeAudioEndpoint(&endpointVolume);

// Parse command line arguments and perform actions
if (argc == 2 && strcmp(argv[1], "get") == 0) {
printf("%.0f\n", GetVolume(endpointVolume) * 100);
} else if (argc == 3 && strcmp(argv[1], "set") == 0) {
newVolume = strtof(argv[2], nullptr) / 100;

if (argv[2][0] == '+' || argv[2][0] == '-') {
newVolume += GetVolume(endpointVolume);
}

// Do whatever user wanted to do
if (operation == VOL_CHECK) {
printf("Current volume: %.0f\n", GetVolume(endpointVolume) * 100);
} else if (operation == VOL_SET) {
if (newVolume < 0 || newVolume > 1) DisplayUsageAndExit();
SetVolume(endpointVolume, newVolume);
} else if (operation == VOL_CHANGE) {
newVolume += GetVolume(endpointVolume);
if (newVolume < 0) newVolume = 0;
if (newVolume > 1) newVolume = 1;
SetVolume(endpointVolume, newVolume);
} else if (argc == 2 && strcmp(argv[1], "mute") == 0) {
BOOL currentValue = GetMute(endpointVolume);
if (currentValue != TRUE)
SetMute(endpointVolume, TRUE);
} else if (argc == 2 && strcmp(argv[1], "unmute") == 0) {
BOOL currentValue = GetMute(endpointVolume);
if (currentValue != FALSE)
SetMute(endpointVolume, FALSE);
} else if (argc == 2 && strcmp(argv[1], "togglemute") == 0) {
BOOL currentValue = GetMute(endpointVolume);
SetMute(endpointVolume, !currentValue);
}

// Release resources
endpointVolume->Release();
CoUninitialize();

// Cleanup
DestroyAudioEndpoint(endpointVolume);
return 0;
}

0 comments on commit 37a4d21

Please sign in to comment.