AudioDeviceManager::setAudioDeviceSetup sends changes early

Here is the beginning of setAudioDeviceSetup:

String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
                                                const bool treatAsChosenDevice)
{

    jassert (&newSetup != &currentSetup);    // this will have no effect

    if (newSetup == currentSetup && currentAudioDevice != nullptr)
        return String();

    if (! (newSetup == currentSetup))
        sendChangeMessage();

Is there a reason why sendChangeMessage() is called so early in the function?

I've set a class up to listen to my AudioDeviceManager instance so that I can display some information on the selected input and output channels, but when I call:

    void changeListenerCallback(ChangeBroadcaster *source)
    {
      AudioDeviceManager::AudioDeviceSetup setup;
      source->getAudioDeviceSetup(setup);
      DBG(setup.inputChannels.toString(2));

the changes that I have applied to my AudioDeviceSetup before calling setAudioDeviceSetup are not there anymore.

Am I using it wrong?

The message is asynchronous - it doesn't matter where it gets sent within the function, the result is the same.

Well the callback is asyncronous so it doesn't matter when the sendChangeMessage() is posted, it will never callback untill after
AudioDeviceManager::setAudioDeviceSetup has finished. Your setup probably isn't being applied for some reason. I'd step through it, mabe putting a watchpoint on the setup to see if it gets changed correctly.

I found this ancient thread because I just made the same observation :grinning_face_with_smiling_eyes:

But:

the callback is asyncronous so it doesn’t matter when the sendChangeMessage() is posted, it will never callback untill after
AudioDeviceManager::setAudioDeviceSetup has finished

IFAICT, this in only true if setAudioDeviceSetup is called on the message thread, right? But this is not guaranteed; setAudioDeviceSetup does not make any checks for this and it is not mentioned in the docs.

If setAudioDeviceSetup would be called from another thread, there would be a race, wouldn’t it?