audioDeviceIOCallback scuppered by route-change (headphones)

I’m processing mic-input using audioDeviceIOCallback

    void audioDeviceIOCallback (
        const float** inputChannelData, int numInputChannels,
        float** outputChannelData, int numOutputChannels,
        int numSamples
    ) override
    {
    DBG((int64_t)inputChannelData[0]);

This code shows the same address each call up until the point I insert/remove the headphoone jack.
And 0 afterwards!

Is this a bug/UB, or am I missing something?

Ok I seem to have a fix, though it does not feel so satisfying.

    // Notes:
    //   - First pass fetches available buffer sizes, second pass sets one of them
    //   - If init fails for `device`, it falls back to default device
    void initializeDevice(String device = "") {
        int bufSize = 0;
        for(int pass=1; pass <= 2; ++pass) {
            DBG("    PASS: " << pass);
            auto deviceSetup = AudioDeviceManager::AudioDeviceSetup();
            deviceSetup.sampleRate = 44100;
            deviceSetup.bufferSize = bufSize;

            deviceManager.initialise(
                1,            // numInputChannelsNeeded
                2,            // numOutputChannelsNeeded
                nullptr,      // XML
                true,         // selectDefaultDeviceOnFailure
                device,       // preferredDefaultDeviceName
                &deviceSetup  // preferredSetupOptions
                );

            DBG("        Buffer size: " << deviceManager.getCurrentAudioDevice()->getCurrentBufferSizeSamples());

            bufSize = max(MIN_BUFSAMPS, deviceManager.getCurrentAudioDevice()->getAvailableBufferSizes()[0]);
        }
    }

    void initialSetup()
    {
        initializeDevice();

        deviceManager.setMidiInputDeviceEnabled(
            MidiInput::getAvailableDevices()[0].name,
            true
        );
        deviceManager.addMidiInputDeviceCallback(
            String(""),
            this
        );

        deviceManager.addChangeListener(this);
    }

    // Switches to phones when inserted
    void changeListenerCallback(ChangeBroadcaster*) override
    {
        DBG("🔹changeListenerCallback()");
        logDeviceTypes();

        StringArray newDeviceNames = deviceManager.getCurrentDeviceTypeObject()->getDeviceNames();
        if (deviceNames.size() == 0) // first time only!
            deviceNames = newDeviceNames;
        // changeListenerCallback hits twice for each insert or removal, giving us
        // before-change and after-change lists
        if (newDeviceNames.size() == deviceNames.size()) {
            DBG("    device-list did not change size, returning!");
            return;
        }

        bool didAddDevice = newDeviceNames.size() > deviceNames.size();
        StringArray& smaller = didAddDevice ? deviceNames : newDeviceNames;
        StringArray& larger = didAddDevice ? newDeviceNames : deviceNames;
        String device;
        for (String s : larger)
            if (!smaller.contains(s))
                device = s;

        DBG("    " + String(didAddDevice ? "Added: " : "Removed: ") + device);
        deviceManager.removeChangeListener(this);

        // if removed a device, this will fail for device, but fallback to default
        initializeDevice(device);

        deviceManager.addChangeListener(this);

        jassert(deviceManager.getCurrentAudioDevice() != NULL);

        deviceNames = newDeviceNames;
    }

The previous code was only invoking deviceManager.initialise once in the changeListener-callback, using buffer size = 0.

I guess that was the problem.

New code uses the same two-pass technique I employ in the initial setup.