// LowLevelAudio.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "Mmdeviceapi.h"
#include "Functiondiscoverykeys_devpkey.h"
#include <iostream>

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);

int main()
{
    CoInitialize(nullptr);
    IMMDeviceEnumerator* pEnumerator = nullptr;
    IMMDeviceCollection* pDeviceCollection = nullptr;
    HRESULT hr = S_OK;

    hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
        IID_IMMDeviceEnumerator, (void**)& pEnumerator);
    if (!pEnumerator)
    {
        std::cout << "Failed to populate enumerator" << std::endl;
        return 0;
    }

    hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDeviceCollection);
    UINT  count;
    hr = pDeviceCollection->GetCount(&count);
    if (count == 0)
    {
        std::cout << "No devices found\n";
    }
    // Each loop prints the name of an endpoint device.
    IMMDevice* pEndpoint = nullptr;
    IPropertyStore* pProps = nullptr;
    LPWSTR pwszID = nullptr;
    for (ULONG i = 0; i < count; i++)
    {
        // Get pointer to endpoint number i.
        hr = pDeviceCollection->Item(i, &pEndpoint);

        // Get the endpoint ID string.
        hr = pEndpoint->GetId(&pwszID);
        hr = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);

        PROPVARIANT varName;
        // Initialize container for property value.
        PropVariantInit(&varName);

        // Get the endpoint's friendly-name property.
        hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);

        // Print endpoint friendly name and endpoint ID.
        std::cout << "Endpoint: " << i << " " << varName.pwszVal << " " << pwszID << std::endl;
        CoTaskMemFree(pwszID);
        pwszID = nullptr;

        PropVariantClear(&varName);
        if (pProps)
        {
            pProps->Release();
            pProps = nullptr;
        }
        if (pEndpoint)
        {
            pEndpoint->Release();
            pEndpoint = nullptr;
        }
    }
    if (pEnumerator)
    {
        pEnumerator->Release();
        pEnumerator = nullptr;
    }
    if (pDeviceCollection)
    {
        pDeviceCollection->Release();
        pDeviceCollection = nullptr;
    }
    return 0;
}

