Isnt there anyway to debug this behavior?!
I can’t reproduce either. did you try using the last juce version?
changing to latest juce version, is a no go on our part, since we are already in beta. but using 4.3.1 and comparing aax wrappers and audio processor I dont see any changes affecting this.
Sorry tetrohed, I just noticed I had misread your post at first. I was not in touch mode in reaper.
I can now reproduce, but for me this behaviour is the correct one actually… You would expect the same behaviour as in latch mode?
yeah, I thought there was a miscommunication going on, yeah thats what I expect, since all native plugins from reaper and protools do behave like latch mode
Sorry I can’t help with older JUCE versions. Newest JUCE definitely works for me:

could you point me into the parts of the code that might have changed drastically since then?
which plugin is this in the video? can I reach the source code?
Sorry, you’ll need to do this yourself by doing a diff between both versions of the juce_AAX_Wrapper.cpp.
Here you go:
/*
==============================================================================
This file was auto-generated!
It contains the basic framework code for a JUCE plugin processor.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
//==============================================================================
//==============================================================================
//==============================================================================
class MyFirstPluginProjectAudioProcessor : public AudioProcessor
{
public:
//==============================================================================
MyFirstPluginProjectAudioProcessor()
: AudioProcessor (BusesProperties()
.withInput ("Input", AudioChannelSet::stereo(), true)
.withOutput ("Output", AudioChannelSet::stereo(), true))
{
addParameter (cutoffParameter = new AudioParameterBool ("cutoff", "cutoff", false));
}
//==============================================================================
void prepareToPlay (double, int) override {}
void releaseResources() override {}
bool isBusesLayoutSupported (const BusesLayout& layouts) const override
{
if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
&& layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
return false;
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
return false;
return true;
}
void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) override
{
const int totalNumInputChannels = getTotalNumInputChannels();
const int totalNumOutputChannels = getTotalNumOutputChannels();
for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
if (cutoffParameter->get())
buffer.clear();
}
//==============================================================================
AudioProcessorEditor* createEditor() override;
bool hasEditor() const override { return true; }
//==============================================================================
const String getName() const override { return "MyFirstPluginProject"; }
bool acceptsMidi() const override { return false; }
bool producesMidi() const override { return false; }
bool isMidiEffect () const override { return false; }
double getTailLengthSeconds() const override { return 0.0; }
//==============================================================================
int getNumPrograms() override { return 0; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram (int) override {}
const String getProgramName (int) override { return {}; }
void changeProgramName (int, const String&) override {}
//==============================================================================
void getStateInformation (MemoryBlock&) override {}
void setStateInformation (const void*, int) override {}
AudioParameterBool* cutoffParameter;
private:
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyFirstPluginProjectAudioProcessor)
};
//==============================================================================
//==============================================================================
//==============================================================================
class MyFirstPluginProjectAudioProcessorEditor
: public AudioProcessorEditor, private Button::Listener
{
public:
MyFirstPluginProjectAudioProcessorEditor (MyFirstPluginProjectAudioProcessor& p)
: AudioProcessorEditor (&p)
{
addAndMakeVisible (onOffButton);
oldState = onOffButton.getToggleState();
onOffButton.addListener (this);
setSize (400, 300);
}
//==============================================================================
void paint (Graphics& g) override
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
g.setColour (Colours::white);
g.setFont (15.0f);
g.drawFittedText ("Hello World!", getLocalBounds(), Justification::centred, 1);
}
void resized() override
{
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
onOffButton.setBounds (getLocalBounds().withHeight (40));
}
//==============================================================================
void buttonClicked (Button*) override {}
void buttonStateChanged (Button*) override
{
bool newState = onOffButton.getToggleState();
if (newState != oldState)
{
oldState = newState;
MyFirstPluginProjectAudioProcessor& ap = dynamic_cast<MyFirstPluginProjectAudioProcessor&> (*getAudioProcessor());
ap.cutoffParameter->beginChangeGesture();
ap.cutoffParameter->setValueNotifyingHost (newState ? 1.0f : 0.0f);
ap.cutoffParameter->endChangeGesture();
}
}
private:
ToggleButton onOffButton {"Cutoff"};
bool oldState;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyFirstPluginProjectAudioProcessorEditor)
};
//==============================================================================
AudioProcessorEditor* MyFirstPluginProjectAudioProcessor::createEditor()
{
return new MyFirstPluginProjectAudioProcessorEditor (*this);
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new MyFirstPluginProjectAudioProcessor();
}
thanks, by playing around with the example, found out the source of problem is the old parameter system, just have to figure out why, since both parameter systems do follow the same line of code
ok got it, I am just gonna go ahead and call myself an idiot, didnt implement getParameterNumSteps for my toggles. Thank you everyone for sticking with me.