Search code examples
c++windowswasapi

Why is `IAudioMeterInformation` an incomplete type?


Trying to compile the following with g++ main.cpp -lwinmm throws the following errors:

main.cpp: In function 'int main()':
main.cpp:15:15: error: invalid use of incomplete type 'IAudioMeterInformation' {aka 'struct IAudioMeterInformation'}
     pMeterInfo->GetPeakValue(&audiolevel);
               ^~
In file included from main.cpp:3:
C:/Mingw-w64/mingw64/x86_64-w64-mingw32/include/endpointvolume.h:90:19: note: forward declaration of 'IAudioMeterInformation' {aka 'struct IAudioMeterInformation'}
 typedef interface IAudioMeterInformation IAudioMeterInformation;
                   ^~~~~~~~~~~~~~~~~~~~~~
main.cpp:18:19: error: invalid use of incomplete type 'IAudioMeterInformation' {aka 'struct IAudioMeterInformation'}
         pMeterInfo->GetPeakValue(&audiolevel);
                   ^~
In file included from main.cpp:3:
C:/Mingw-w64/mingw64/x86_64-w64-mingw32/include/endpointvolume.h:90:19: note: forward declaration of 'IAudioMeterInformation' {aka 'struct IAudioMeterInformation'}
 typedef interface IAudioMeterInformation IAudioMeterInformation;
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <iostream>

int main() {
    float audiolevel = 0.0;
    IMMDeviceEnumerator* pEnumerator = NULL;
    IMMDevice* pDevice = NULL;
    IAudioMeterInformation* pMeterInfo = NULL;
    CoInitialize(NULL);
    CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
    pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
    pDevice->Activate(__uuidof(IAudioMeterInformation), CLSCTX_ALL, NULL, (void**)&pMeterInfo);
    pMeterInfo->GetPeakValue(&audiolevel);
    while (1) {
        std::cout << audiolevel << std::endl;
        pMeterInfo->GetPeakValue(&audiolevel);
    }
}

Why?


Solution

  • MinGW doesn't seem to have the complete structure definition for IAudioMeterInformation.

    I managed to get your code work by copying the complete definition for IAudioMeterInformation from PortAudio repository and adding the needed __CRT_UUID_DECL to avoid compile error "undefined reference to _GUID const& __mingw_uuidof" (see here)

    The following code has been compiled on Windows using MinGW included in Strawberry Perl 5.32.1001 (gcc 8.3.0) with the command g++ main.cpp -lole32

    #include <windows.h>
    #include <mmdeviceapi.h>
    #include <endpointvolume.h>
    #include <iostream>
    
    __CRT_UUID_DECL(IAudioMeterInformation, 0xC02216F6, 0x8C67, 0x4B5B, 0x9D, 0x00, 0xD0, 0x08, 0xE7, 0x3E, 0x00, 0x64);
    
    MIDL_INTERFACE("C02216F6-8C67-4B5B-9D00-D008E73E0064")
    IAudioMeterInformation : public IUnknown
    {
    public:
        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetPeakValue( 
            /* [out] */ float *pfPeak) = 0;
        
        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMeteringChannelCount( 
            /* [out] */ 
              UINT *pnChannelCount) = 0;
        
        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelsPeakValues( 
            /* [in] */ UINT32 u32ChannelCount,
            /* [size_is][out] */ float *afPeakValues) = 0;
        
        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryHardwareSupport( 
            /* [out] */ 
              DWORD *pdwHardwareSupportMask) = 0;
    };
    
    int main() {
        float audiolevel = 0.0;
        IMMDeviceEnumerator* pEnumerator = NULL;
        IMMDevice* pDevice = NULL;
        IAudioMeterInformation* pMeterInfo = NULL;
        CoInitialize(NULL);
        CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
        pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
        pDevice->Activate(__uuidof(IAudioMeterInformation), CLSCTX_ALL, NULL, (void**)&pMeterInfo);
        pMeterInfo->GetPeakValue(&audiolevel);
        while (1) {
            std::cout << audiolevel << std::endl;
            pMeterInfo->GetPeakValue(&audiolevel);
        }
    }