Automatically switch audio output when headphones inserted

Ok this works…

// Settings.h
#ifndef SETTINGS_H_INCLUDED
#define SETTINGS_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
using namespace ::juce;
class AudioSettings : ChangeListener
{
private:
    ScopedPointer<AudioDeviceManager> pInputDeviceManager;
    ScopedPointer<AudioDeviceManager> pOutputDeviceManager;
    void launch(AudioDeviceManager* pDeviceManager, int inputs, int outputs)
    {
        AudioDeviceSelectorComponent* settingsPane = new AudioDeviceSelectorComponent(
            *pDeviceManager,
            inputs, inputs,        // min/max inputs
            outputs, outputs,    // min/max outputs
            inputs > 0,            // showMidiInputOptions
            outputs > 0,        // showMidiOutputSelector
            true,                // showChannelsAsStereoPairs
            true                // showAdvancedOptions
            );
        settingsPane->setSize(640, 480);
        DialogWindow::LaunchOptions options;
        options.content.setOwned(settingsPane);
        options.dialogTitle = "Audio Settings";
        options.dialogBackgroundColour = Colours::lightgrey;
        options.escapeKeyTriggersCloseButton = true;
        options.useNativeTitleBar = true;
        options.resizable = true;
        DialogWindow* dialogWindow = options.launchAsync();
        dialogWindow->centreWithSize(450, 250);
    }
public:
    AudioDeviceManager&amp; getInputDeviceManager() {
        return *pInputDeviceManager;
    }
    AudioDeviceManager&amp; getOutputDeviceManager() {
        return *pOutputDeviceManager;
    }
    AudioSettings()
    {
        pInputDeviceManager = new AudioDeviceManager();
        pOutputDeviceManager = new AudioDeviceManager();
        auto deviceSetup = AudioDeviceManager::AudioDeviceSetup();
        deviceSetup.sampleRate = 48000;
        pInputDeviceManager->initialise(
            0,                // numInputChannelsNeeded
            0,                // numOutputChannelsNeeded
            nullptr,        // XML
            true,            // selectDefaultDeviceOnFailure
            String(),        // preferredDefaultDeviceName
            &amp;deviceSetup    // preferredSetupOptions
            );
        pOutputDeviceManager->initialise(
            0,                // numInputChannelsNeeded
            2,                // numOutputChannelsNeeded
            nullptr,        // XML
            true,            // selectDefaultDeviceOnFailure
            String(),        // preferredDefaultDeviceName
            &amp;deviceSetup    // preferredSetupOptions
            );
        
        DBG(pOutputDeviceManager->getCurrentAudioDevice()->getCurrentSampleRate());
        for (auto s : pOutputDeviceManager->getCurrentAudioDevice()->getAvailableSampleRates())
            DBG(s);
    
        //deviceNames = pOutputDeviceManager->getCurrentDeviceTypeObject()->getDeviceNames();
        pOutputDeviceManager->addChangeListener(this);
    }
private:
    StringArray deviceNames;
public:
    void changeListenerCallback(ChangeBroadcaster*) override
    {
        AudioDeviceManager&amp; output = *pOutputDeviceManager;
        
        StringArray newDeviceNames = output.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()) 
            return;
        bool didAddDevice = newDeviceNames.size() > deviceNames.size();
        StringArray&amp; smaller = didAddDevice ? deviceNames : newDeviceNames;
        StringArray&amp; larger = didAddDevice ? newDeviceNames : deviceNames;
        String device;
        for (String s : larger)
            if (!smaller.contains(s))
                device = s;
        
        DBG("changeListenerCallback: " + String(didAddDevice ? "Added " : "Removed ") + device);
        output.removeChangeListener(this);
        // if removed a device, this will fail for device, but fallback to default
        auto deviceSetup = AudioDeviceManager::AudioDeviceSetup();
        deviceSetup.sampleRate = 44100;
        output.initialise(
            0,                // numInputChannelsNeeded
            2,                // numOutputChannelsNeeded
            nullptr,        // XML
            true,            // selectDefaultDeviceOnFailure
            device,            // preferredDefaultDeviceName
            &amp;deviceSetup    // preferredSetupOptions
            );
        output.addChangeListener(this);
        jassert(output.getCurrentAudioDevice());
        DBG(output.getCurrentAudioDevice()->getCurrentSampleRate());
        deviceNames = newDeviceNames;
    }
    void launchInputWindow() {
        launch(pInputDeviceManager, 1, 0);
    }
    void launchOutputWindow() {
        launch(pOutputDeviceManager, 0, 2);
    }
};
#endif  // SETTINGS_H_INCLUDED

π