potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C++20&WIL&Win API MMDevice APIでスピーカー(既定のマルチメディア出力)の音量情報を取得する

Windows Vistaからはマスター音量(システム全体の音量)の変更にCOMベースのMMDevice API (Windows Multimedia Device API)を用います。ここではスピーカー(既定のマルチメディア出力)の音量情報を取得するコードを記載します。

#include <format>

#define STRICT
#define NOMINMAX
#include <Windows.h>
// MMDeviceAPI
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <functiondiscoverykeys_devpkey.h>
// PropSys
#pragma comment(lib, "propsys.lib")
#include <propvarutil.h>

#include <wil/com.h>

// 既定のマルチメディア出力オーディオエンドポイントのボリューム情報インターフェイスを取得します。
wil::com_ptr<IAudioEndpointVolume> GetDefaultMultimediaRenderAudioEndpointVolume()
{
    wil::com_ptr<IMMDeviceEnumerator> deviceEnumerator{
        wil::CoCreateInstance<MMDeviceEnumerator, IMMDeviceEnumerator>() };

    wil::com_ptr<IMMDevice> device;
    THROW_IF_FAILED(deviceEnumerator->GetDefaultAudioEndpoint(
        EDataFlow::eRender,
        ERole::eMultimedia,
        device.put()));

    wil::com_ptr<IAudioEndpointVolume> audioEndpointVolume;
    THROW_IF_FAILED(device->Activate(
        __uuidof(IAudioEndpointVolume),
        CLSCTX_INPROC_SERVER,
        nullptr,
        audioEndpointVolume.put_void()));

    return std::move(audioEndpointVolume);
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) };

    auto audioEndpointVolume{ GetDefaultMultimediaRenderAudioEndpointVolume() };

    // 音量の現在地と範囲を取得する
    float volumeLevel;
    float volumeMin;
    float volumeMax;
    float volumeInc;
    THROW_IF_FAILED(audioEndpointVolume->GetMasterVolumeLevel(&volumeLevel));
    THROW_IF_FAILED(audioEndpointVolume->GetVolumeRange(&volumeMin, &volumeMax, &volumeInc));

    auto msg{ std::format(L"音量レベル:{} Db\n最小値:{} Db\n最大値:{} Db\n増加量:{} Db",
        volumeLevel, volumeMin, volumeMax, volumeInc) };
    ::MessageBoxW(nullptr, msg.c_str(), nullptr, MB_OK);

    return 0;
}