Skip to content

Instantly share code, notes, and snippets.

@im-tesla
Created July 1, 2024 23:48
Show Gist options
  • Save im-tesla/b5a137c3cd1cdb7c4b8526561593b6dd to your computer and use it in GitHub Desktop.
Save im-tesla/b5a137c3cd1cdb7c4b8526561593b6dd to your computer and use it in GitHub Desktop.
Windows Audio Control Utility
#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;
}
@im-tesla
Copy link
Author

im-tesla commented Jul 1, 2024

yeah thats really good quality code bro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment