Triggering buttons with MIDI


#1

Hello JUCE community,
a JUCE beginner is speaking here. I need help with some communication between Audio Processor and Audio Plugin Editor in my AudioPlugin. Problem is that I have my Audio Processor to handle all MIDI events, but on the other side I have a GUI where I would like a specific button to be click triggered ( or in my case because I have an Image Button ,it would do the work just to be pressed down without triggering a click and triggering button pressed method).Back to the problem,I would like my button to be clicked when specific MIDI note is sent,but since Editor is seen as parent to Processor,I do not know how to do that.
If you have help of any kind,at least some direction where should I try to find solution or some idea ,I will be extremely grateful to you.

Sincerely,
Cila.


#2

In your main processor processBlock() you can check your MIDI buffer and you can use Button:: triggerClick() to send an Asynchronous click to your button. The main thing is to make sure your editor exists… otherwise the button doesn’t exist… so what happens when the user closes their UI… ?? Make sure you consider the scope and lifetime of all your Components.

Rail


#3

Hey Rail,

thanks for taking your time to answer me. I understand your idea here but I have some problems in its realization. How can I trigger click from my Process Block function when my processor class doesn’t know anything about my editor components?

Thanks in advance,
Cila.


#4

Well AudioProcessor has a method getActiveEditor() but you need to cast it to your Editor class… I have a helper method in my main processor class:

CMyProcessorEditor* CMyAudioProcessor::getEditor() const noexcept
{
    return dynamic_cast<CMyProcessorEditor*>(getActiveEditor());
}

Then you can use that in your main processor class to test if there’s an active Editor… just check if getEditor() doesn’t return nullptr.

The problem I foresee is that you trigger the button via MIDI which only works when you have an active Editor.

Rail


#5

The other problem you will face is, if you call something in your editor from processBlock, you are likely to block your AudioThread, that is calling processBlock. The code in the editor will have to trigger a repaint, which will happen on the message thread (aka MessageManager).
This is way easier to achieve, if you implement all data (in model-view-controller terms the model) in the processor, of the controller only what is related to specific buttons in the editor, the rest like reacting to parameter changes or reacting on midi messages or audio data in the processor.

Make sure you can create an editor at any point in time (because that is what the host will do if someone clicks on the plugin), and it will populate it’s views from the processors state or other data held in the processor.

And the thread problem will vanish if you use a Timer to repaint at a certain frequency, i.e. 30 times per second. If your painting needs much time, you can add a “needUpdate” flag in the processor, that the audio thread can safely set to true and the repaint in the timer can reset it.

This update method can also take care of your initial problem:

// in processor
public:
    bool specificMidiActive () const { return specificNoteDown; }
    processBlock (AudioBuffer< float > &buffer, MidiBuffer &midiMessages) override {
        // haven't done much MIDI but you will figure that out
        if (/* find noteDown in midiMessages */) specificNoteDown = true;
        if (/* find noteUp in midiMessages */) specificNoteDown = false;
        // ...
    }
private:
    bool specificNoteDown;

// in your editor
public:
    void timerCallback () override {
        myButton->setToggleState (processor.specificMidiActive());
        // ...
    }

The other direction is trivial then, because if there is an Editor there will always be an AudioProcessor…

BTW. you can get inspiration how JUCE is doing it in the MidiKeyboardComponent. Instead of only a bool they have all midinotes in a MidiKeyboardState object:


#6

Hello people,

sorry for late answer,I have some problems with computer access. I like your ideas and I thankful for them, I will try to implement the timer one. If I face some bigger problems, I will come here again to cry.

Cila.


#7

Make button and MIDI event to send the same event on the audio/midi engine. This way you do not have to have editor open to make it work.

Button->Event->GUIToEngineEventQueue->EventHandler
MIDIEvent->EventHandler


#8

That’s exactly the opposite of what he asked though.

He want MIDI to trigger his button… not his button to trigger his MIDI.

Rail