std::vector<ProcessVolume> GetProcessVolumes() {
  std::vector<ProcessVolume> volumes;

  CoInitialize(NULL);

  IAudioSessionEnumerator* enumerator = GetAudioSessionEnumerator();
  int sessionCount;
  enumerator->GetCount(&sessionCount);
  for (int index = 0; index < sessionCount; index++) {
    IAudioSessionControl* session = nullptr;
    IAudioSessionControl2* session2 = nullptr;
    enumerator->GetSession(index, &session);
    session->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&session2);

    DWORD id = 0;
    session2->GetProcessId(&id);

    std::string processName = GetProcessNameFromPid(id);
    float peakVolume = GetPeakVolumeFromAudioSessionControl(session);

    ProcessVolume data;
    data.processName = processName;
    data.processId = id;
    data.peakVolume = peakVolume;
    volumes.push_back(data);

    session2->Release();
    session->Release();
  }
  enumerator->Release();

  return std::move(volumes);
}
AudioSessionNotificationHook::AudioSessionNotificationHook()
{
    //need to pin this and only this pointer because f**k you
    sessionManager = NULL;
    pin_ptr<IAudioSessionManager2*> pinnedSM = &sessionManager;
    THROW_HR( CreateSessionManager(pinnedSM) );

    //create a notification listener
    sessionNotification = new AudioSessionNotificationReceiver(this);
    THROW_HR( sessionManager->RegisterSessionNotification(sessionNotification) );

    //need to get list to kickstart notifications because f**k you again
    IAudioSessionEnumerator* sessionEnum = NULL;
    THROW_HR( sessionManager->GetSessionEnumerator(&sessionEnum) );
    sessionEnum->Release();
}
void changeFGWindowVolume()
{
	if (soundOption == dncItemID) return;

	char titleBuff[128];
	HWND activeHWND = GetForegroundWindow();
	GetWindowText(activeHWND, titleBuff, 128);

	UINT count = sizeof(mediaCommands) / sizeof(mediaCommands[0]);
	for (UINT i = 0; i < count; i++)
	{
		if (strstr(titleBuff, mediaCommands[i].title) > 0) return;
	}

	IMMDevice *mmDevice;
	IMMDeviceEnumerator *mmDeviceEnum;
	IAudioSessionManager2 *sessionManager;
	IAudioSessionEnumerator *sessionEnum;
	IAudioSessionControl *sessionControl;
	IAudioSessionControl2 *sessionControl2;
	ISimpleAudioVolume *audioVolume;

	CoCreateInstance(__uuidof(MMDeviceEnumerator), 0, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&mmDeviceEnum);
	mmDeviceEnum->GetDefaultAudioEndpoint(eRender, eMultimedia, &mmDevice);
	mmDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, 0, (void**)&sessionManager);
	sessionManager->GetSessionEnumerator(&sessionEnum);

	DWORD activePid;
	GetWindowThreadProcessId(activeHWND, &activePid);

	int sessionCount;
	sessionEnum->GetCount(&sessionCount);
	for (int i = 0; i < sessionCount; i++)
	{
		sessionEnum->GetSession(i, &sessionControl);
		sessionControl->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl2);

		DWORD pid;
		sessionControl2->GetProcessId(&pid);
		if (activePid == pid)
		{
			sessionControl->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&audioVolume);

			BOOL muted;
			audioVolume->GetMute(&muted);

			float volumeLevel;
			audioVolume->GetMasterVolume(&volumeLevel);

			if (soundOption == muteItemID)
			{
				audioVolume->SetMute(!muted, 0);

				if (volumeLevel != 1.0f)
				{
					audioVolume->SetMasterVolume(1.0f, 0);
				}
			}
			else
			{
				float newVolumeLevel = (soundOption - sBaseItemID) / 100.0f;
				audioVolume->SetMasterVolume(volumeLevel == 1.0f ? newVolumeLevel : 1.0f, 0);

				if (muted)
				{
					audioVolume->SetMute(false, 0);
				}
			}

			audioVolume->Release();
		}

		sessionControl->Release();
		sessionControl2->Release();
	}

	sessionEnum->Release();
	sessionManager->Release();
	mmDevice->Release();
	mmDeviceEnum->Release();
}