Как получить аудиоустройство устройства отображения в Windows? - PullRequest
0 голосов
/ 27 мая 2020

Мне нужна помощь в связывании устройств отображения с соответствующими аудиоустройствами, и, в конце концов, я хочу иметь путь к аудиоустройству с использованием WinApi и C ++.

Проблема в том, что нет прямого способа выполнить sh this.

Что у меня сейчас: из MSDN я могу перечислить аудио конечные устройства, и некоторые из них являются графическими c аудио карты:

#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

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

void PrintEndpointNames()
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator* pEnumerator = NULL;
    IMMDeviceCollection* pCollection = NULL;
    IMMDevice* pEndpoint = NULL;
    IPropertyStore* pProps = NULL;
    LPWSTR pwszID = NULL;

    hr = CoInitialize((LPVOID)NULL);

    hr = CoCreateInstance(
        CLSID_MMDeviceEnumerator, NULL,
        CLSCTX_ALL, IID_IMMDeviceEnumerator,
        (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

        hr = pEnumerator->EnumAudioEndpoints(
            eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_UNPLUGGED,
            &pCollection);
    EXIT_ON_ERROR(hr)

        UINT  count;
    hr = pCollection->GetCount(&count);
    EXIT_ON_ERROR(hr)

        if (count == 0)
        {
            printf("No endpoints found.\n");
        }

    // Each loop prints the name of an endpoint device.
    for (ULONG i = 0; i < count; i++)
    {
        // Get pointer to endpoint number i.
        hr = pCollection->Item(i, &pEndpoint);
        EXIT_ON_ERROR(hr)

            // Get the endpoint ID string.
            hr = pEndpoint->GetId(&pwszID);
        EXIT_ON_ERROR(hr)

            hr = pEndpoint->OpenPropertyStore(
                STGM_READ, &pProps);
        EXIT_ON_ERROR(hr)

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


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

            // Print endpoint friendly name and endpoint ID.
            printf("Endpoint %d: \"%S\" (%S)\n",
                i, varName.pwszVal, pwszID);

        CoTaskMemFree(pwszID);
        pwszID = NULL;
        PropVariantClear(&varName);
        SAFE_RELEASE(pProps)
            SAFE_RELEASE(pEndpoint)
    }
    SAFE_RELEASE(pEnumerator)
        SAFE_RELEASE(pCollection)
        return;

    CoUninitialize();
Exit:
    printf("Error!\n");
    CoTaskMemFree(pwszID);
    SAFE_RELEASE(pEnumerator)
        SAFE_RELEASE(pCollection)
        SAFE_RELEASE(pEndpoint)
        SAFE_RELEASE(pProps)
}

Но как определить, какие из них являются аудиоустройствами графической c карты, я не знаю.

Я также нашел структуру , которая определяет информацию о цифровом аудиоустройстве, связанном с дисплеем

и я попытался получить от него некоторую информацию, запустив этот код:

#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

HRESULT GetJackInfo(IMMDevice* pDevice)
{
    HRESULT hr = S_OK;
    IDeviceTopology* pDeviceTopology = NULL;
    IConnector* pConnFrom = NULL;
    IConnector* pConnTo = NULL;
    IPart* pPart = NULL;
    IKsJackSinkInformation* pJackInf = NULL;
    KSJACK_SINK_INFORMATION pJackSinkInformation;

    if (NULL == pDevice )
    {
        return E_POINTER;
    }


    // Get the endpoint device's IDeviceTopology interface.
    hr = pDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL,
        NULL, (void**)&pDeviceTopology);
    EXIT_ON_ERROR(hr)



        // The device topology for an endpoint device always
        // contains just one connector (connector number 0).
        hr = pDeviceTopology->GetConnector(0, &pConnFrom);
    EXIT_ON_ERROR(hr)

        // Step across the connection to the jack on the adapter.
        hr = pConnFrom->GetConnectedTo(&pConnTo);
    if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
    {
        // The adapter device is not currently active.
        hr = E_NOINTERFACE;
    }
    EXIT_ON_ERROR(hr)

        // Get the connector's IPart interface.
        hr = pConnTo->QueryInterface(__uuidof(IPart), (void**)&pPart);
    EXIT_ON_ERROR(hr)


    hr = pPart->Activate(CLSCTX_ALL,
        __uuidof(IKsJackSinkInformation), (void**)&pJackInf);
    EXIT_ON_ERROR(hr)

    hr = pJackInf->GetJackSinkInformation(&pJackSinkInformation);


Exit:
    SAFE_RELEASE(pDeviceTopology)
        SAFE_RELEASE(pConnFrom)
        SAFE_RELEASE(pConnTo)
        SAFE_RELEASE(pPart)
        return hr;
}

IMMDevice* pDevice я получил от выполнения предыдущего кода, и единственное, что делает этот код, это pPart->Activate, терпит неудачу, если устройство не является аудиоустройством графической c карты, а когда нет, pJackInf->GetJackSinkInformation устанавливает странные идентификаторы в структуре KSJACK_SINK_INFORMATION, например: PortId = {LowPart=3206951034 HighPart=-1360285969 } когда CCD api возвращает мне adapterId = {LowPart=56473 HighPart=0 } для всех дисплеев. И я не могу найти способ обнаружить аудиоустройство дисплея.

Буду очень благодарен за любую помощь.

...