TextButton for Process ON/OFF


#1

Hallo

This is my first plugin project with JUCE. For the starting i am trying to make a simple plugin with two textbutton (On/Off). When on is clicked some filtering will occur and when off is clicked the original input will go through the plugin. So the plugin is just used for filtering.

I have assigned two textbuttons and added a listener class for them. I can see them on GUI. I am using the JUCE host for now. Can you please suggest what the next step would be

i am guessing i would need two functions
OnbuttonClicked()
{
Processing:
}
OffbuttonClicked()
{

}
and a condition to determine which button is clicked. Can you give me an idea where should i put this functions?


#2

try this:
http://www.redwoodaudio.net/Tutorials/juce_for_vst_development__intro.html

the tutorial is for juce version 4 but still quite valuable for beginners (and it has the bypass button you are looking for)


#3

You can simply set them setClickingTogglesState (true);
and put them into the same radio group using setRadioGroupID (5).

That way they will turn each other on and off, you don’t have to implement that yourself.


#4

thanks daniel. Your suggestions worked. Now they are mutualy exclusive radio buttons.
So now i can just create a buttonClicked function and there decide what happens when each button is clicked and then call this function in the process block right?


#5

Yes, it is up to you, if you want to simply add a listener function in the editor and call your setFeatureOn (bool) method of your processor, or if you want to learn about the AudioProcessorValueTreeState and use a ButtonAttachment, see this tutorial.


#6

I guess i will try the easier way by setting the setFeatureOn (bool) method.
Just one more question, the filter application will be later depended on the frequency. Would be better to use a text box or a slider for the user to chose the desired frequency?
This is my first plugin design project, so my questions might sound a bit dumb, sorry for that


#7

Definitely a slider, as the user can have a play. In a text box you would have to validate yourself, if the user added a number, or invalid text.
PLUS: the slider has a nice feature, which is a TextBox the user can click and enter the value numerically. So with the slider you can have both in one…


#8

Hallo Daniel

could you clarify a bit more about setting up this setFeatureOn (bool) method . Where should i declare this and how can i call it my process block in the PluginProcessor.cpp file
I understand from the tutorial that i have to declare a function on the plugin edition.h class and then use it on the other files, just failing to get them togehter

*Edited the question, because i already found the solution to my last problem


#9

First, a master bypass triggered by the host exists. If bypass is off, the normal processBlock is called. If bypass is on, the processBlockBypassed is called.
But maybe you want to disable only certain features, so it might be still a useful thing to do:
Either if you want this function just to be accessible by your plugin, just add a bool member to your processor and an accessor method to set it (I assume you know how to do that). In you processBlock you can just use this bool value as conditional for your code.
If you want this parameter to be automated by the host, the most convenient way I found was to use the AudioProcessorValueTreeState, I posted the link to the tutorials before.
Side note, you only need one ButtonAttachment, the off button triggers the parameter as well.

I hope that get’s you going.


#10

to be honest i am completely lost right now. I have trying to figure out since you replied what you exactly meant.
So what i understood from the JUCE the tutorial is the processBlock function in the PluginProcessor.cpp file controls the playing of the audio and i need to put my conditions there.
So as you know i have two buttons ON and OFF. So when ON is clicked some filtering will occur and OFF is clicked no processing occurs and the incoming signal is output signal.

I don’t want my parameters to be automated by the host. The user will manually select the buttons.

I understood that i need a method to find out which button is active, and i think i can do it with the
bool isDown() function from juce button class. But not really sure how to set it up. Could you please provide me a sample code if possible?


#11

Ok, no problem.

1st rule: the AudioProcessor must be able to fully function without the AudioProcessorEditor. That’s why you can’t call the button->isDown() method, because the button might not exist.

In AudioProcessor.h add:

class MyAudioProcessor : public AudioProcessor {
public:
    // ...

    void setFilteringEnabled (const bool shouldBeEnabled) {
        filteringEnabled = shouldBeEnabled;
    }
private:
    bool filteringEnabled;
};

In processBlock:

void MyAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midi) {
    if (filteringEnabled) {
        // apply filter
    }
    // ...
}

In your AudioProcessorEditor:

void MyAudioProcessorEditor::buttonChanged (Button* buttonThatWasClicked) {
    if (buttonThatWasClicked == onButton || buttonThatWasClicked == offButton)
        processor.setFilteringEnabled (onButton->getToggleState());
    }
}

HTH


#12

thanks a lot for the code. I really appreciate the time you are taking to help me. Just a bit more :slight_smile:

In my Audio Processor Editor i added the code you gave me but i get the two errors
if (buttonThatWasClicked == onButton || buttonThatWasClicked == offButton) ---- Invalid operands to binary expression (juce::Button and and juce:: TextBUutton)

processor.setFilteringEnabled (onButton->getToggleState()); — Member reference type juce:: TextButton is not a pointer, did you mean to use ‘.’?

I am using two TextButton for my buttons.


#13

Seems like you use the Buttons as member rather than pointers. Then . instead of -> is correct.
The best would be, post your code, so I can put the real names into my answers instead of making names up.
Sure you have to change the names of the buttons in my example to the names you are using. I don’t know your code.
If you want to compare a Button member pointer in the callback, use the address operator:

if (buttonThatWasPressed == &myButton)

#14

Here is my source code, i still have one error left , In the plugin processor.cpp file

AudioProcessorEditor* Gdv1AudioProcessor::createEditor()
{
return new Gdv1AudioProcessorEditor (*this);
}

here i get a error Allocating an object of abstract class type Gdv1AudioProcessorEditor

PluginEditor.cpp (2.5 KB)
PluginEditor.h (1.3 KB)
PluginProcessor.h (2.5 KB)
PluginProcessor.cpp (4.6 KB)


#15

An abstract class is a class, that has pure virtual methods, that are not implemented (You googled that, right?)
This means, Button::Listener defines

This means, some class inheriting from Button::Listener shall implement that (otherwise this one is abstract as well and cannot be instanciated.

First thing is, to add the override keyword. That checks, if there exists a method in a base class, that this method would override. In your case, it would give you the error something like overriding a non existing method. That way you know, that your method was defined differently (and therefore will never be called).

tl;dr: Change your

void buttonChanged(Button* buttonThatWasClicked) ; 

into

void buttonClicked(Button* buttonThatWasClicked) override;

NB 1: The name of the argument doesn’t matter
NB2: You can also use buttonStateChanged(Button*), but you have still to implement the buttonClicked. Otherwise your PluginEditor class is still abstract. You can leave it empty.


#16

thanks a lot again, now its more clear what is happening and how things work. Once i am done with my filter design i will try to put the plugin to my desired host and see how it performs.