Newbie question about GUI in conbination with gen~and Juce


#1

Hello, i’am an absolut beginner with Juce and C++.
I build an Audio plugin in Max/gen~ and i want automate my sliders/dials in my DAW as AU/VST.
The plugin works, it opens and make sound and the params to be automate are shown in Live but they are not accessible. I use these lines of code:
In PluginProcessor.cpp

sliderAttach = new AudioProcessorValueTreeState::SliderAttachment (processor.treeState, GAIN_ID, inputDial);

In PluginProsessor.cpp
C74GenAudioProcessor::C74GenAudioProcessor()
: m_CurrentBufferSize(0),
treeState(*this, nullptr)

In PluginEditor.h i use this:
ScopedPointer AudioProcessorValueTreeState::SliderAttachment sliderAttach;

In PluginProcessor.h
#define GAIN_ID “inputDial”
#define GAIN_NAME "inputDial"
AudioProcessorValueTreeState treeState;

Xcode give these errors back: No matching constructor for initialization of 'AudioProcessorValueTreeState::SliderAttachment’
Errors in juce_AudioProcessorValueTreeState.h

  1. Candidate constructor not viable: no known conversion from ‘ScopedPointerjuce::Slider’ to ‘juce::Slider &’ for 3rd argument

  2. Candidate constructor not viable: requires 1 argument, but 3 were provided

I stuck here.
I hope this is a simple error :slight_smile:

cheers in advance and best from Hamburg


#2

It’s difficult to figure out what’s going on without seeing more code (also please format your code properly by surrounding it with ``` or indenting by 4 spaces!)

But it looks like your are passing a ScopedPointer<Slider> to an AudioProcessorValueTreeState::SliderAttachment when it expects a reference, so you need to dereference it by using *.


#3

Hello ed95, cheers for your reply :slight_smile:
I try to format more Code, i hope it`s enough to see what happens here .
:slight_smile:
PluginProcessor.cpp

C74GenAudioProcessor::C74GenAudioProcessor()
: m_CurrentBufferSize(0),

    treeState(*this, nullptr)

{
    
    
    
	// use a default samplerate and vector size here, reset it later
	m_C74PluginState = (CommonState *)C74_GENPLUGIN::create(44100, 64);
	C74_GENPLUGIN::reset(m_C74PluginState);

	m_InputBuffers = new t_sample *[C74_GENPLUGIN::num_inputs()];
	m_OutputBuffers = new t_sample *[C74_GENPLUGIN::num_outputs()];
	
	for (int i = 0; i < C74_GENPLUGIN::num_inputs(); i++) {
		m_InputBuffers[i] = NULL;
	}
	for (int i = 0; i < C74_GENPLUGIN::num_outputs(); i++) {
		m_OutputBuffers[i] = NULL;
	}
    
    NormalisableRange<float> gainRange (0.0f, 1.0f);
    treeState.createAndAddParameter(GAIN_ID, GAIN_NAME, GAIN_NAME, gainRange, 1.0f, nullptr, nullptr);
    
    NormalisableRange<float> depthRange (0.0f, 15.0f);
    treeState.createAndAddParameter(Depth_ID, Depth_NAME, Depth_NAME, depthRange, 10.0f, nullptr, nullptr);
}

PluginProcessor.h

#define GAIN_ID "inputDial"
#define GAIN_NAME "inputDial"
#define Depth_ID "depth"
#define Depth_NAME "depth"

//==============================================================================
/**
*/
class C74GenAudioProcessor  : public AudioProcessor
{
public:
    //==============================================================================
    C74GenAudioProcessor();
    ~C74GenAudioProcessor();

    //==============================================================================
    void prepareToPlay (double sampleRate, int samplesPerBlock) override;
    void releaseResources() override;

    void processBlock (AudioSampleBuffer&, MidiBuffer&) override;

    //==============================================================================
    AudioProcessorEditor* createEditor() override;
    bool hasEditor() const override;

    //==============================================================================
    const String getName() const override;

    int getNumParameters() override;
    float getParameter (int index) override;
    void setParameter (int index, float newValue) override;

    const String getParameterName (int index) override;
    const String getParameterText (int index) override;

    const String getInputChannelName (int channelIndex) const override;
    const String getOutputChannelName (int channelIndex) const override;
    bool isInputChannelStereoPair (int index) const override;
    bool isOutputChannelStereoPair (int index) const override;

    bool acceptsMidi() const override;
    bool producesMidi() const override;
    bool silenceInProducesSilenceOut() const override;
    double getTailLengthSeconds() const override;

    //==============================================================================
    int getNumPrograms() override;
    int getCurrentProgram() override;
    void setCurrentProgram (int index) override;
    const String getProgramName (int index) override;
    void changeProgramName (int index, const String& newName) override;

    //==============================================================================
    void getStateInformation (MemoryBlock& destData) override;
    void setStateInformation (const void* data, int sizeInBytes) override;
    
    AudioProcessorValueTreeState treeState;

PluginEditor.cpp

C74GenAudioProcessorEditor::C74GenAudioProcessorEditor (C74GenAudioProcessor& p)
    : AudioProcessorEditor (&p), processor (p)

{
    //[Constructor_pre] You can add your own custom stuff here..
    //[/Constructor_pre] 

    sliderAttach = new AudioProcessorValueTreeState::SliderAttachment (processor.treeState, GAIN_ID, inputDial);
    addAndMakeVisible (inputDial = new Slider ("inputDial"));
    inputDial->setRange (0, 1, 0.01);
    inputDial->setSliderStyle (Slider::RotaryHorizontalVerticalDrag);
    inputDial->setTextBoxStyle (Slider::TextBoxBelow, false, 58, 20);
    inputDial->setColour (Slider::thumbColourId, Colour (0xff5c6061));
    inputDial->setColour (Slider::rotarySliderFillColourId, Colour (0xff57588b));
    inputDial->setColour (Slider::rotarySliderOutlineColourId, Colour (0xff444646));
    inputDial->setColour (Slider::textBoxTextColourId, Colour (0xffa7aaa9));
    inputDial->setColour (Slider::textBoxOutlineColourId, Colour (0x002b2c2c));
    inputDial->addListener (this);
}

PluginEditor.h

#include “…/JuceLibraryCode/JuceHeader.h”
#include “PluginProcessor.h”

//==============================================================================
/**
*/
class C74GenAudioProcessorEditor : public AudioProcessorEditor,
public Slider::Listener,
public Button::Listener

{
public:
C74GenAudioProcessorEditor (C74GenAudioProcessor&);
~C74GenAudioProcessorEditor();

//==============================================================================
void paint (Graphics&) override;
void resized() override;
void sliderValueChanged (Slider* sliderThatWasMoved) override;
void buttonClicked (Button* buttonThatWasClicked) override;

ScopedPointer <AudioProcessorValueTreeState::SliderAttachment> sliderAttach;

// Binary resources: 
static const char* dialBackround_jpg;
static const int dialBackround_jpgSize;

private:
// This reference is provided as a quick way for your editor to
// access the processor object that created it.
C74GenAudioProcessor& processor;

ScopedPointer<Slider> delayDial;
ScopedPointer<Slider> depthDial;
ScopedPointer<Slider> rateDial;
ScopedPointer<Slider> spreadDial;
ScopedPointer<Slider> phaseLevelDial;
ScopedPointer<Slider> crossDial;
ScopedPointer<Slider> offsetDial;
ScopedPointer<Slider> inputDial;
ScopedPointer<Slider> feedbackDial;
ScopedPointer<ToggleButton> noiseButton;
ScopedPointer<ToggleButton> deflectionButton;
Image cachedImage_dialBackround_jpg_1;
Image cachedImage_dialBackround_jpg_2;
Image cachedImage_dialBackround_jpg_3;
Image cachedImage_dialBackround_jpg_4;
Image cachedImage_dialBackround_jpg_5;
Image cachedImage_dialBackround_jpg_6;
Image cachedImage_dialBackround_jpg_7;
Image cachedImage_dialBackround_jpg_8;
Image cachedImage_dialBackround_jpg_9;


JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (C74GenAudioProcessorEditor)

};


#4

Like I said before, in this line:

sliderAttach = new AudioProcessorValueTreeState::SliderAttachment (processor.treeState, GAIN_ID, inputDial);

you are passing a ScopedPointer<Slider> as the 3rd argument to the AudioProcessorValueTreeState::SliderAttachment constructor when it is expecting a Slider& so you need to dereference inputDial like this:

sliderAttach = new AudioProcessorValueTreeState::SliderAttachment (processor.treeState, GAIN_ID, *inputDial);

#5

The Compiler error is now gone but now Live crashes instantly when i open the plugin.
Following errors from Live:

Application Specific Information:
dyld: in dlopen()

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.cycling74.C74GenPlugin    	0x000000012afa857c juce::ScopedPointer<juce::Slider::Pimpl>::operator->() const + 12 (juce_ScopedPointer.h:173)
1   com.cycling74.C74GenPlugin    	0x000000012af9c98b juce::Slider::setRange(double, double, double) + 43 (juce_Slider.cpp:1478)
2   com.cycling74.C74GenPlugin    	0x000000012acd00b7 juce::AudioProcessorValueTreeState::SliderAttachment::Pimpl::Pimpl(juce::AudioProcessorValueTreeState&, juce::String const&, juce::Slider&) + 343 (juce_AudioProcessorValueTreeState.cpp:416)
3   com.cycling74.C74GenPlugin    	0x000000012acbbfed juce::AudioProcessorValueTreeState::SliderAttachment::Pimpl::Pimpl(juce::AudioProcessorValueTreeState&, juce::String const&, juce::Slider&) + 45 (juce_AudioProcessorValueTreeState.cpp:424)
4   com.cycling74.C74GenPlugin    	0x000000012acbbf73 juce::AudioProcessorValueTreeState::SliderAttachment::SliderAttachment(juce::AudioProcessorValueTreeState&, juce::String const&, juce::Slider&) + 99 (juce_AudioProcessorValueTreeState.cpp:461)
5   com.cycling74.C74GenPlugin    	0x000000012acbc07d juce::AudioProcessorValueTreeState::SliderAttachment::SliderAttachment(juce::AudioProcessorValueTreeState&, juce::String const&, juce::Slider&) + 45 (juce_AudioProcessorValueTreeState.cpp:463)
6   com.cycling74.C74GenPlugin    	0x000000012ac4c6fa C74GenAudioProcessorEditor::C74GenAudioProcessorEditor(C74GenAudioProcessor&) + 906 (PluginEditor.cpp:24)
7   com.cycling74.C74GenPlugin    	0x000000012ac4f8bd C74GenAudioProcessorEditor::C74GenAudioProcessorEditor(C74GenAudioProcessor&) + 29 (PluginEditor.cpp:155)
8   com.cycling74.C74GenPlugin    	0x000000012ac4bd4d C74GenAudioProcessor::createEditor() + 61 (PluginProcessor.cpp:232)
9   com.cycling74.C74GenPlugin    	0x000000012aca865d juce::AudioProcessor::createEditorIfNeeded() + 93 (juce_AudioProcessor.cpp:1013)
10  com.cycling74.C74GenPlugin    	0x000000012ac17a44 JuceAU::JuceUICreationClass::uiViewForAudioUnit(objc_object*, objc_selector*, ComponentInstanceRecord*, CGSize) + 116 (juce_AU_Wrapper.mm:1620)

damned :smiley:
I think we are on the right way…thanks a lot ed95 :wink:


#6

You need to swap these lines:

sliderAttach = new AudioProcessorValueTreeState::SliderAttachment (processor.treeState, GAIN_ID, inputDial);
addAndMakeVisible (inputDial = new Slider ("inputDial"));

as your inputDial member isn’t pointing to anything valid when you pass it to the SliderAttachment.


#7

Hello ed95,
this works Live doesn’t crash now…cheers :slight_smile:
The next challenge is to bring the params to work. I try to make a small vid to describe the problem.
Many thanks to you…you win a Beer :slight_smile: