Accessing deviceManager from a child component

Hi everyone,

This will be basic for most of you but well…I’m stuck.

I want a settings window in my Audio App where I can change input and output sources. I created a child component and created a new AudioDeviceSelectorComponent in this but the changes it makes don’t seem to be detected by the parent. Here is the code for the child component:

class MyAudioSelector : public Component
{


public:

MyAudioSelector(){
    

        audioSetupComp.reset (new AudioDeviceSelectorComponent (audioDeviceManager,
                                                                0, 256, 0, 256, false, true, false, false));
        addAndMakeVisible (audioSetupComp.get());
        audioSetupComp->centreWithSize (600, 400);
        
        //if (auto* peer = audioSetupComp->getPeer())
        //peer->setTitle ("Audio Settings");
        
        //audioSetupComp->setOpaque(true);

}

private:


#ifndef JUCE_DEMO_RUNNER
    AudioDeviceManager audioDeviceManager;
   #else
    AudioDeviceManager& audioDeviceManager { getSharedAudioDeviceManager() };
   #endif
   
std::unique_ptr<AudioDeviceSelectorComponent> audioSetupComp;


void paint (Graphics& g) override
    {
        g.fillAll ();
    }


void resized() override
    {
        auto r =  getLocalBounds().reduced (4);
        audioSetupComp->setBounds (r.removeFromTop (proportionOfHeight (0.65f)));
    }
    
void userTriedToCloseWindow() override
    {
        
    }
    
};

I have tried declaring audioDeviceManager outside of the class but that doesn’t seem to work. What is the best way to have one device manager that can be accessed by all components?

You need to pass a pointer or reference to the parent’s AudioDeviceManager to the child component. AudioDeviceManager isn’t a singleton, so the instance you are creating in your child component isn’t the same one that is in the parent component and won’t control the same device settings.

1 Like

Hey there! Thanks for the reply.

I created the following function in the parent:

AudioDeviceManager& getAudioDeviceManager()
    {
        return deviceManager;
    }

I then tried to access this method from the child component as follows:

auto theParent = this->getParentComponent();

    audioSetupComp.reset (new AudioDeviceSelectorComponent (theParent->getAudioDeviceManager(), 0, 256, 0, 256, false, true, false, false));

This is giving the error: getAudioDeviceManager’: is not a member of ‘juce::Component’

Where am I going wrong?

juce::Component::getParent() returns a pointer to a juce::Component. Even if the object the pointer is pointing to is of your custom type, you can’t access it through a juce::Component*.

You would need to dynamic_cast the juce::Component* to your custom type:

if (auto parent = dynamic_cast<CustomComponent*> (getParentComponent())
{
    // parent is now a pointer to CustomComponent
}
else
{
    // Either this has no parent, or the parent wasn't of the expected type.
}
1 Like

N.B. this is not the best architecture. If the child needs access to the deviceManager, you should pass a reference to the manager down via a constructor argument.

But to add to @ImJimmi s method, this exists as a juce function findParentComponentOfType():

if (auto* myAudioSelector = findParentComponentOfClass<MyAudioSelector>())
{
    auto& deviceManager = myAudioSelector->getAudioDeviceManager();
}
else // this can still return nullptr if there is no parent of that type
{
    // ...
2 Likes