GUI Problems

I’m still new to JUICE so this may be a stupid thing, sry for that if this is the case.
No my actual problem I try to convert some of my Max (gen~)-Patches to VST/AU Plugins.
The plugins them self work, but the VST3 version of the plugin has no GUI at all.
For the AU version the sliders in the gui are changing the right parameters, but they are not connected to the parameters shown in the DAW(Ableton), while those parameters shown in the daw are also controlling the right parameters, but if I move a slider in Abelton the GUI dosen’t respond to that and the other way round, meaning if I automate a parameter it is not reflected in the GUI.

So how do you connect your sliders to your parameters?

Without some more information about your approach and maybe some code snippets of the relevant functions it can be anything.

The code I use to connect the sliders with the parameter is:

if (sliderThatWasMoved == amount__slider.get())

That’s also the only Code I added to the sliders on top of the code generated by JUCE GUI Editor

So here a bit more code, I guess these are the 2 most relevant parts of the code:

C74projucerGenPluginAudioProcessorEditor::C74projucerGenPluginAudioProcessorEditor (C74GenAudioProcessor& p)
: AudioProcessorEditor (&p), processor §
{ amount__slider.reset (new juce::Slider (“amount__slider”));
addAndMakeVisible (amount__slider.get());
amount__slider->setRange (0, 1, 0.01);
amount__slider->setSliderStyle (juce::Slider::LinearHorizontal);
amount__slider->setTextBoxStyle (juce::Slider::TextBoxLeft, false, 80, 20);
amount__slider->addListener (this);

    amount__slider->setBounds (72, 64, 272, 24);

    outmode__slider.reset (new juce::Slider ("outmode__slider"));
    addAndMakeVisible (outmode__slider.get());
    outmode__slider->setRange (0, 1, 0.01);
    outmode__slider->setSliderStyle (juce::Slider::LinearHorizontal);
    outmode__slider->setTextBoxStyle (juce::Slider::TextBoxLeft, false, 80, 20);
    outmode__slider->addListener (this);

    outmode__slider->setBounds (72, 96, 272, 24);

    setSize (600, 400);


And the second part.

void C74projucerGenPluginAudioProcessorEditor::sliderValueChanged (juce::Slider* sliderThatWasMoved)
if (sliderThatWasMoved == amount__slider.get())
else if (sliderThatWasMoved == outmode__slider.get())


Or here’s the complete project with all the code

Most relevant files are gen_exported.cpp and .h and PluginEditor.cpp and .h

I encourage you to use SliderAttachment or SliderParameterAttachment.

  • One reason is DRY (lot of code you wrote for a standard task)
  • Second reason: the attachments take care of beginChangeGesture() and endChangeGesture(), which your implementation lacks (important for host automation or conflicts with that)
  • Third reason making sure that circular updates don’t happen
1 Like

Hmm was looking into this, but didn’t realy got it running. I was looking for tutorials a stupid beginner would understand about it but sadly didn’t found one.
However, I was at least able to solve half the problem by changing

else if (sliderThatWasMoved == outmode__slider.get())


else if (sliderThatWasMoved == outmode__slider.get())

Now at least the DAW reacts if I move a slider on the GUI, however if I change the parameter in the DAW the GUI dosen’t react. Which of course is bad for Automating.

Definitely try this as a tutorial: JUCE: Tutorial: Saving and loading your plug-in state

All you need for that slider is really

C74projucerGenPluginAudioProcessorEditor::C74projucerGenPluginAudioProcessorEditor (C74GenAudioProcessor& p)
: AudioProcessorEditor (p), processor (p)
    addAndMakeVisible (amount__slider);
    addAndMakeVisible (outmode__slider);

    setSize (600, 400);

class C74projucerGenPluginAudioProcessorEditor : public juce::AudioProcessorEditor
    C74projucerGenPluginAudioProcessorEditor (C74projucerGenPluginAudioProcessor& p);

    void paint (juce::Graphics& g) override { ... }
    void resized() override { ... }

    juce::Slider amount__slider { juce::Slider::LinearHorizontal, juce::Slider::TextBoxLeft };
    juce::SliderParameterAttachment amound__attachment { amount__slider, processor.getParameter ("amount"), nullptr };

    juce::Slider outmode__slider { juce::Slider::LinearHorizontal, juce::Slider::TextBoxLeft };
    juce::SliderParameterAttachment outmode__attachment { outmode__slider, processor.getParameter ("outmode"), nullptr };

// in processor add a special getter which takes an parameter ID:
juce::RangedAudioParameter* C74projucerGenPluginAudioProcessor::getParameter (const juce::String& paramID)
    for (p : getParameters())
        if (auto* ranged = dynamic_cast<juce::RangedAudioParameter*>(&p))
            if (ranged->paramID == paramID)
                return ranged;

    // no suitable parameter found, check your implementation
    return nullptr;

No additional listeners needed, no need to put slider or attachment in unique_ptrs.
And No APVTS needed (but can be present, it doesn’t matter for that approach)

EDIT: added missing juce namespace for Slider and SliderParameterAttachment

Hmm first thanks for your help.
But I don’t get it to work, just a ton of errors.


SliderParameterAttachment amount__attachment { amount__slider, processor.getParameter("amount"), nullptr };

I get the error Cannot initialize a parameter of type ‘int’ with an lvalue of type ‘const char [7]’
I tried to replace “Amount” with 0, still does not work

And the part for the processor, I actually have no real idea where to place it. Wherever I place it, I get an error.

Thanks, will have a look at that.

My bad, I forgot to add the juce namespace for Slider and SliderParameterAttachment. I edited the post above to reflect that.

For the getParameter() method in the processor, I presumed a little C++ knowledge. I think some general C++ tutorials would be in order.

The AudioProcessor works with any kind of parameter, that’s why there is only the method to lookup a processor after the integer index.
In the current API you use usually AudioParameters that inherit from RangedAudioParameter, so that all have a parameter ID. I added a getter method that looks up parameters after it’s ID.

The method I gave you goes into the cpp file, and you have to declare the method in your processors public section (that’s what I meant you should look up in some basic C++ tutorials)
The declaration looks like:

juce::RangedAudioParameter* getParameter (const juce::String& paramID);