diff --git a/README.md b/README.md index bfef584..07262cb 100644 --- a/README.md +++ b/README.md @@ -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 ` sets the current default playback device volume (0..100) -* `SetVolume +` increases default playback device volume by a specified percentage (0..100) -* `SetVolume -` 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 ` sets current default playback device volume to a percentage. +* `SetVolume set +` increases default playback device volume by a specified percentage. +* `SetVolume set -` 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 – 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. diff --git a/SetVolume.cpp b/SetVolume.cpp index cbe656e..cf56a80 100644 --- a/SetVolume.cpp +++ b/SetVolume.cpp @@ -18,7 +18,7 @@ #define WINVER _WIN32_WINNT_VISTA #define _WIN32_WINNT _WIN32_WINNT_VISTA -#define VERSION_MAJOR 1 +#define VERSION_MAJOR 2 #define VERSION_MINOR 0 #include @@ -26,76 +26,24 @@ #include #include -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 [Sets the current default playback device volume]\n"); - printf(" SetVolume + [Increases default playback device volume by a specified percentage]\n"); - printf(" SetVolume - [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 Sets current default playback device volume in percentage.\n"); + printf(" SetVolume set + Increases default playback device volume by a specified percentage.\n"); + printf(" SetVolume set - 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); @@ -120,8 +68,8 @@ 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) { @@ -129,23 +77,104 @@ int main(int argc, CHAR* argv[]) 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; } \ No newline at end of file