std::vector AudioEngine::GetRendererDetails()

in Audio/AudioEngine.cpp [1436:1643]


std::vector<AudioEngine::RendererDetail> AudioEngine::GetRendererDetails()
{
    std::vector<RendererDetail> list;

#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_GAMES)

    ComPtr<IMMDeviceEnumerator> devEnum;
    HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(devEnum.GetAddressOf()));
    ThrowIfFailed(hr);

    ComPtr<IMMDeviceCollection> devices;
    hr = devEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &devices);
    ThrowIfFailed(hr);

    ComPtr<IMMDevice> endpoint;
    ThrowIfFailed(devices->Item(0, endpoint.GetAddressOf()));

    LPWSTR id = nullptr;
    ThrowIfFailed(endpoint->GetId(&id));

    RendererDetail device;
    device.deviceId = id;
    device.description = L"Default";

    CoTaskMemFree(id);

    list.emplace_back(device);

#elif defined(_XBOX_ONE)

    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::Media::Devices;

    ComPtr<IMediaDeviceStatics> mdStatics;
    HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mdStatics);
    ThrowIfFailed(hr);

    HString id;
    hr = mdStatics->GetDefaultAudioRenderId(AudioDeviceRole_Default, id.GetAddressOf());
    ThrowIfFailed(hr);

    RendererDetail device;
    device.deviceId = id.GetRawBuffer(nullptr);
    device.description = L"Default";
    list.emplace_back(device);

#elif defined(USING_XAUDIO2_REDIST) || defined(_GAMING_DESKTOP)

    ComPtr<IMMDeviceEnumerator> devEnum;
    HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(devEnum.GetAddressOf()));
    ThrowIfFailed(hr);

    ComPtr<IMMDeviceCollection> devices;
    hr = devEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &devices);
    ThrowIfFailed(hr);

    UINT count = 0;
    ThrowIfFailed(devices->GetCount(&count));

    if (!count)
        return list;

    for (UINT j = 0; j < count; ++j)
    {
        ComPtr<IMMDevice> endpoint;
        hr = devices->Item(j, endpoint.GetAddressOf());
        ThrowIfFailed(hr);

        LPWSTR id = nullptr;
        ThrowIfFailed(endpoint->GetId(&id));

        RendererDetail device;
        device.deviceId = id;
        CoTaskMemFree(id);

        ComPtr<IPropertyStore> props;
        if (SUCCEEDED(endpoint->OpenPropertyStore(STGM_READ, props.GetAddressOf())))
        {
            PROPVARIANT var;
            PropVariantInit(&var);

            if (SUCCEEDED(props->GetValue(PKEY_Device_FriendlyName, &var)))
            {
                if (var.vt == VT_LPWSTR)
                {
                    device.description = var.pwszVal;
                }
                PropVariantClear(&var);
            }
        }

        list.emplace_back(device);
    }

#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN8)

#if defined(__cplusplus_winrt)

    // Enumerating with WinRT using C++/CX (Windows Store apps)
    using Windows::Devices::Enumeration::DeviceClass;
    using Windows::Devices::Enumeration::DeviceInformation;
    using Windows::Devices::Enumeration::DeviceInformationCollection;

    auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
    while (operation->Status == Windows::Foundation::AsyncStatus::Started) { Sleep(100); }
    if (operation->Status != Windows::Foundation::AsyncStatus::Completed)
    {
        throw std::runtime_error("FindAllAsync");
    }

    DeviceInformationCollection^ devices = operation->GetResults();

    for (unsigned i = 0; i < devices->Size; ++i)
    {
        using Windows::Devices::Enumeration::DeviceInformation;

        DeviceInformation^ d = devices->GetAt(i);

        RendererDetail device;
        device.deviceId = d->Id->Data();
        device.description = d->Name->Data();
        list.emplace_back(device);
    }
#else

    // Enumerating with WinRT using WRL (Win32 desktop app for Windows 8.x)
    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::Foundation::Collections;
    using namespace ABI::Windows::Devices::Enumeration;

#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    ThrowIfFailed(initialize);
#endif

    ComPtr<IDeviceInformationStatics> diFactory;
    HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &diFactory);
    ThrowIfFailed(hr);

    ComPtr<IAsyncOperation<DeviceInformationCollection*>> operation;
    hr = diFactory->FindAllAsyncDeviceClass(DeviceClass_AudioRender, operation.GetAddressOf());
    ThrowIfFailed(hr);

    ComPtr<IAsyncInfo> asyncinfo;
    hr = operation.As(&asyncinfo);
    ThrowIfFailed(hr);

    AsyncStatus status;
    hr = asyncinfo->get_Status(&status);
    ThrowIfFailed(hr);

    while (status == ABI::Windows::Foundation::AsyncStatus::Started)
    {
        Sleep(100);
        hr = asyncinfo->get_Status(&status);
        ThrowIfFailed(hr);
    }

    if (status != ABI::Windows::Foundation::AsyncStatus::Completed)
    {
        throw std::runtime_error("FindAllAsyncDeviceClass");
    }

    ComPtr<IVectorView<DeviceInformation*>> devices;
    hr = operation->GetResults(devices.GetAddressOf());
    ThrowIfFailed(hr);

    unsigned int count = 0;
    hr = devices->get_Size(&count);
    ThrowIfFailed(hr);

    if (!count)
        return list;

    for (unsigned int j = 0; j < count; ++j)
    {
        ComPtr<IDeviceInformation> deviceInfo;
        hr = devices->GetAt(j, deviceInfo.GetAddressOf());
        if (SUCCEEDED(hr))
        {
            RendererDetail device;

            HString id;
            if (SUCCEEDED(deviceInfo->get_Id(id.GetAddressOf())))
            {
                device.deviceId = id.GetRawBuffer(nullptr);
            }

            HString name;
            if (SUCCEEDED(deviceInfo->get_Name(name.GetAddressOf())))
            {
                device.description = name.GetRawBuffer(nullptr);
            }

            list.emplace_back(device);
        }
    }
#endif
#else
#error DirectX Tool Kit for Audio not supported on this platform
#endif

    return list;
}