Files
fastfetch/src/detection/sound/sound_windows.cpp
T

100 lines
3.3 KiB
C++
Raw Normal View History

2023-01-25 17:17:31 +08:00
extern "C" {
#include "sound.h"
}
2026-03-25 16:17:20 +08:00
#include "common/windows/unicode.hpp"
2026-01-06 09:48:38 +08:00
#include "common/windows/com.hpp"
2026-03-25 16:17:20 +08:00
#include "common/windows/variant.hpp"
2023-01-25 17:17:31 +08:00
#include <initguid.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <functiondiscoverykeys_devpkey.h>
2025-03-31 16:38:58 +08:00
static void ffCoTaskMemFreeWrapper(void* pptr)
{
assert(pptr != NULL);
void* ptr = *(void**)pptr;
if (ptr) CoTaskMemFree(ptr);
}
#define FF_COTASK_AUTO_FREE __attribute__((__cleanup__(ffCoTaskMemFreeWrapper)))
const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
2023-01-25 17:17:31 +08:00
{
const char* error = ffInitCom();
if (error)
return error;
IMMDeviceEnumerator* FF_AUTO_RELEASE_COM_OBJECT pEnum = NULL;
2026-03-27 20:14:21 +08:00
if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pEnum))))
2024-02-02 15:34:21 +08:00
return "CoCreateInstance(CLSID_MMDeviceEnumerator) failed";
2023-01-25 17:17:31 +08:00
2025-03-31 16:38:58 +08:00
LPWSTR FF_COTASK_AUTO_FREE mainDeviceId = NULL;
2023-01-25 17:17:31 +08:00
{
IMMDevice* FF_AUTO_RELEASE_COM_OBJECT pDefaultDevice = NULL;
if (FAILED(pEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDefaultDevice)))
return "GetDefaultAudioEndpoint() failed";
if (FAILED(pDefaultDevice->GetId(&mainDeviceId)))
return "pDefaultDevice->GetId() failed";
}
IMMDeviceCollection* FF_AUTO_RELEASE_COM_OBJECT pDevices = NULL;
if (FAILED(pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED, &pDevices)))
2023-01-25 17:17:31 +08:00
return "EnumAudioEndpoints() failed";
uint32_t deviceCount;
if (FAILED(pDevices->GetCount(&deviceCount)))
return "pDevices->GetCount() failed";
for (uint32_t deviceIdx = 0; deviceIdx < deviceCount; ++deviceIdx)
{
IMMDevice* FF_AUTO_RELEASE_COM_OBJECT immDevice = NULL;
if (FAILED(pDevices->Item(deviceIdx, &immDevice)))
continue;
2025-03-31 16:38:58 +08:00
LPWSTR FF_COTASK_AUTO_FREE immDeviceId = NULL;
2023-01-25 17:17:31 +08:00
if (FAILED(immDevice->GetId(&immDeviceId)))
continue;
IPropertyStore* FF_AUTO_RELEASE_COM_OBJECT immPropStore;
if (FAILED(immDevice->OpenPropertyStore(STGM_READ, &immPropStore)))
continue;
DWORD immState;
if (FAILED(immDevice->GetState(&immState)))
continue;
2023-01-25 17:17:31 +08:00
FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices);
device->main = wcscmp(mainDeviceId, immDeviceId) == 0;
device->active = !!(immState & DEVICE_STATE_ACTIVE);
device->volume = FF_SOUND_VOLUME_UNKNOWN;
2023-05-27 22:30:38 +08:00
ffStrbufInitWS(&device->identifier, immDeviceId);
2023-01-25 17:17:31 +08:00
ffStrbufInit(&device->name);
2025-01-07 11:17:01 +08:00
ffStrbufInitStatic(&device->platformApi, "Core Audio APIs");
2023-01-25 17:17:31 +08:00
{
2026-03-25 16:17:20 +08:00
FFPropVariant friendlyName;
if (SUCCEEDED(immPropStore->GetValue(PKEY_Device_FriendlyName, &friendlyName)))
2026-03-25 16:17:20 +08:00
ffStrbufSetWSV(&device->name, friendlyName.get<std::wstring_view>());
2023-01-25 17:17:31 +08:00
}
IAudioEndpointVolume* FF_AUTO_RELEASE_COM_OBJECT immEndpointVolume;
if(SUCCEEDED(immDevice->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**) &immEndpointVolume)))
{
BOOL muted;
if (FAILED(immEndpointVolume->GetMute(&muted)) || !muted)
{
FLOAT volume;
if (SUCCEEDED(immEndpointVolume->GetMasterVolumeLevelScalar(&volume)))
device->volume = (uint8_t) (volume * 100 + 0.5);
}
}
}
return NULL;
}