c++windowswasapi

ISimpleAudioVolume G/SetMute not updating


Solution: I reference the pointer of a variable instead of the variable itself. Thank you @RomanR.

I'm trying to use GetMute/SetMute through ISimpleAudioVolume, and I'm having trouble with what I'm seeing. When I run GetMute I can see that it's not muted (which is good), but when I mute my audio output, or run SetMute(false) it fails to update anything. I'm not sure if I'm setting up AudioClient correctly, but don't know how to check it.

Thanks!

Edit: I think my issue is somewhere near the top of the initialization chain. When I run check the volume it says it's 100% which isn't true. When I check the device IDs & states, the beginning of the two IDs are a bunch of 0s, and the state says they're both inactive. If I check the AudioSessionControl, there's no name, but it says the session is also inactive.

My guess is that it's somewhere in this stack of init():

check(CoInitialize(NULL));
check(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID*)&m_deviceEnumerator));
check(m_deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_device));

MainVolumeControl.h

#pragma once

#include <cstdio>
#include <windows.h>
#include <audioclient.h>
#include <audiopolicy.h>
#include <Mmdeviceapi.h>

class MainVolumeControl
{

public:
    MainVolumeControl();

    void init();

    void destroy();

    void toggleMute();

    void GetMute(BOOL* o_mute);

    IMMDeviceEnumerator* m_deviceEnumerator;
    IMMDevice* m_device;
    IAudioClient* m_audioClient;
    ISimpleAudioVolume* m_audioVolume;
    WAVEFORMATEX* m_pwfx;
};

MainVolumeControl.cpp

MainVolumeControl::MainVolumeControl()
{
    m_deviceEnumerator = nullptr;
    m_device = nullptr;
    m_audioClient = nullptr;
    m_audioVolume = nullptr;
    m_pwfx = nullptr;
}


void MainVolumeControl::init()
{
    // Get Device
    check(CoInitialize(NULL));
    check(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID*)&m_deviceEnumerator));
    check(m_deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_device));

    // Get Audio Client
    m_device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&m_audioClient);

    // Activate Audio Client & Get Service 
    check(m_audioClient->GetMixFormat(&m_pwfx));
    check(m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 10000000, 0, m_pwfx, NULL));
    check(m_audioClient->GetService(__uuidof(ISimpleAudioVolume), (void**)&m_audioVolume));
}

void MainVolumeControl::destroy()
{
    // Release the resources
    m_audioVolume->Release();
    m_audioClient->Release();
    m_device->Release();
    m_deviceEnumerator->Release();
    CoUninitialize();
}

void MainVolumeControl::toggleMute()
{
    BOOL mute = 0;

    // Getting the mute value
    check(m_audioVolume->GetMute(&mute));
    check(m_audioVolume->SetMute(!&mute, NULL));
}

void MainVolumeControl::GetMute(BOOL* o_mute)
{
    // Finally getting the mute value
    check(m_audioVolume->GetMute(o_mute));
}

Main.cpp

int main(int argc, CHAR* argv[])
{
    MainVolumeControl mvc;
    BOOL mute = 1;

    mvc.init();

    mvc.GetMute(&mute);
    printf("Mute state: %d\n", mute);
    printf("Toggling mute\n");
    mvc.toggleMute();
    mvc.GetMute(&mute);
    printf("Mute state: %d\n", mute);

    mvc.destroy();

    return 0;
}

Output

Mute state: 0
Toggling mute
Mute state: 0

Solution

  • I reference the pointer of a variable instead of the variable itself. Thank you @RomanR.

    Should be:

    void MainVolumeControl::toggleMute()
    {
        BOOL mute = 0;
    
        // Getting the mute value
        check(m_audioVolume->GetMute(&mute));
        check(m_audioVolume->SetMute(!mute, NULL));
    }