Created
July 1, 2024 23:48
-
-
Save im-tesla/b5a137c3cd1cdb7c4b8526561593b6dd to your computer and use it in GitHub Desktop.
Windows Audio Control Utility
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <windows.h> | |
#include <mmdeviceapi.h> | |
#include <endpointvolume.h> | |
#include <propvarutil.h> | |
#include <functiondiscoverykeys_devpkey.h> | |
#include <iostream> | |
#include <vector> | |
#include <string> | |
#include <algorithm> | |
#pragma comment(lib, "Ole32.lib") | |
void initialize_com() { | |
CoInitialize(nullptr); | |
} | |
void cleanup_com() { | |
CoUninitialize(); | |
} | |
std::vector<IMMDevice*> enumerate_audio_endpoints() { | |
IMMDeviceEnumerator* enumerator = nullptr; | |
CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&enumerator); | |
IMMDeviceCollection* device_collection = nullptr; | |
enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &device_collection); | |
UINT device_count = 0; | |
device_collection->GetCount(&device_count); | |
std::vector<IMMDevice*> devices(device_count); | |
for (UINT i = 0; i < device_count; ++i) { | |
device_collection->Item(i, &devices[i]); | |
} | |
device_collection->Release(); | |
enumerator->Release(); | |
return devices; | |
} | |
std::string get_device_name(IMMDevice* device) { | |
IPropertyStore* property_store = nullptr; | |
device->OpenPropertyStore(STGM_READ, &property_store); | |
PROPVARIANT device_name; | |
PropVariantInit(&device_name); | |
property_store->GetValue(PKEY_Device_FriendlyName, &device_name); | |
//jebac julke | |
std::wstring ws(device_name.pwszVal); | |
std::string name(ws.begin(), ws.end()); | |
PropVariantClear(&device_name); | |
property_store->Release(); | |
return name; | |
} | |
IAudioEndpointVolume* get_audio_endpoint_volume(IMMDevice* device) { | |
IAudioEndpointVolume* endpoint_volume = nullptr; | |
device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, nullptr, (void**)&endpoint_volume); | |
return endpoint_volume; | |
} | |
void set_channel_volume(IAudioEndpointVolume* endpoint_volume, UINT channel, float volume) { | |
endpoint_volume->SetChannelVolumeLevelScalar(channel, volume, nullptr); | |
} | |
float get_channel_volume(IAudioEndpointVolume* endpoint_volume, UINT channel) { | |
float volume = 0; | |
endpoint_volume->GetChannelVolumeLevelScalar(channel, &volume); | |
return volume; | |
} | |
void get_current_volume(IAudioEndpointVolume* endpoint_volume, float &volumeL, float &volumeR) { | |
volumeL = get_channel_volume(endpoint_volume, 0); | |
volumeR = get_channel_volume(endpoint_volume, 1); | |
} | |
int main(int argc, char* argv[]) { | |
initialize_com(); | |
IAudioEndpointVolume* endpoint = nullptr; | |
auto devices = enumerate_audio_endpoints(); | |
int deviceIndex = -1; | |
float volumeL = 0; | |
float volumeR = 0; | |
if (argc > 1) { | |
for (int i = 1; i < argc; ++i) { | |
std::string argument = argv[i]; | |
if (argument.find("list") != std::string::npos) { | |
for (size_t i = 0; i < devices.size(); ++i) { | |
std::cout << i << ": " << get_device_name(devices[i]) << std::endl; | |
} | |
cleanup_com(); | |
return 0; | |
} | |
if (argument.find("I") != std::string::npos) { | |
argument.erase(std::remove_if(argument.begin(), argument.end(), [](char c) { return !std::isdigit(c); }), argument.end()); | |
deviceIndex = std::stoi(argument); | |
endpoint = get_audio_endpoint_volume(devices[deviceIndex]); | |
} | |
if (deviceIndex == -1) { | |
std::cout << "pick a device using I<index> argument\n\n" << std::endl; | |
cleanup_com(); | |
return 0; | |
} | |
if (argument.find("L") != std::string::npos && argument.find("GR") == std::string::npos && argument.find("GL") == std::string::npos) { | |
argument.erase(std::remove_if(argument.begin(), argument.end(), [](char c) { return !std::isdigit(c); }), argument.end()); | |
volumeL = std::stof(argument); | |
std::cout << "setting left to " << volumeL << std::endl; | |
set_channel_volume(endpoint, 0, volumeL / 100); | |
} | |
if (argument.find("R") != std::string::npos && argument.find("GR") == std::string::npos && argument.find("GL") == std::string::npos) { | |
argument.erase(std::remove_if(argument.begin(), argument.end(), [](char c) { return !std::isdigit(c); }), argument.end()); | |
volumeR = std::stof(argument); | |
std::cout << "setting right to " << volumeR << std::endl; | |
set_channel_volume(endpoint, 1, volumeR / 100); | |
} | |
if (argument.find("GR") != std::string::npos) { | |
get_current_volume(endpoint, volumeL, volumeR); | |
std::cout << "current right volume is " << volumeR * 100 << std::endl; | |
} | |
if (argument.find("GL") != std::string::npos) { | |
get_current_volume(endpoint, volumeL, volumeR); | |
std::cout << "current left volume is " << volumeL * 100 << std::endl; | |
} | |
} | |
} | |
else { | |
std::cout << "n***a you gotta tell me what you wanna do" << std::endl; | |
system("pause"); | |
cleanup_com(); | |
return 0; | |
} | |
if (endpoint) { | |
endpoint->Release(); | |
} | |
for (auto device : devices) { | |
device->Release(); | |
} | |
cleanup_com(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
yeah thats really good quality code bro