Broadcaster / Listener for dedicated Midi events

Sorry for me being dense, but I can’t decently wrap my head around the “Listener” paradigm.
I successfully use a listener for a slider. but here I don’t need to do a broadcaster.
Now I need to do a Listener/Broadcaster pair that is not tied to a GUI element but should “fire” only when I detect certain Midi events.
As the Midi messages are received in another OS Thread than the GUI (etc) resides in and where I want to use them, I understand that in JUCE, the Broadcaster/Lister pipe paradigm is the way to go.
but how to do such a dedicated pipe ?
Do I need to derive a dedicated class from the Listener base class, or co-derive (e.g.) the Editor class from something ? How to use AddLister() in this case ? How to link the broadcaster and the listener together ?
-Michael

Others here may be able to give more detailed advice, but I would recommend reading the source for the MidiLoggerPluginDemo as a good starting point. This plugin has to solve a very similar problem - it must re-render a list of midi messages in the UI every time a new midi message is received. To achieve this, we use a wait-free queue to store the midi events as they arrive in processBlock. Then, we use a Timer to periodically read events out of this queue.

You mentioned using Broadcasters/Listeners. In general, these techniques are synchronous, so they are probably not a good choice if you need to communicate values between threads.

Hmm…
While for a logger it might be appropriate to do polling in a timer, in realtime applications (“live” parameter modulation), using a decent “pipe” mechanism should be applied.
I understand that the “Listener” is provided exactly for this purpose. I found this comment by CrushedPixel in the forum:
"If you need your ListenerList to be thread-safe, use a juce::ListenerList<YourListenerClass, juce::Array<YourListenerClass*, juce::CriticalSection>>"
Hence I think that this is the way to go. Only that I fail to understand how to “construct” a new listener/broadcaster pair.
-Michael

A ListenerList is a way of decoupling your application so that things that emit events (midi message received, mouse pressed, component moved, and so on) don’t need to know about all the things that might be interested in those events.

A ListenerList does not transfer messages between threads. If ListenerList::call is called from one thread, then all of the listeners will be notified synchronously (i.e. on the same thread). For this reason, I don’t think a ListenerList is the right tool for your use-case.

The type that CrushedPixel mentions is a ListenerList with some additional synchronisation. If you were to use this type, it would be safe to (for example) register a new listener on one thread at the same time as call is running on another thread. However, assuming your list notifies from the audio thread, it would still be unsafe to update your UI directly in a listener callback because this callback will still run on the audio thread. In order to safely update elements of your UI, you’d need to use a Timer, or an AsyncUpdater. You could potentially use a ChangeBroadcaster too, as long as you use sendChangeMessage to notify of new events.

I’ll do some more research on this.
In fact I have been doing similar stuff (gathering data in a worker thread - e.g. waiting in a blocking read - and transferring those to the GUI thread with minimal CPU overhead and minimal latency ) in several other languages and libraries. I do know that a kind of pipe / FiFo / Queue needs to be used together with an OS based notification mechanism (Signal / Semaphore / Message) to implement this.
As JUICE is made (among other things) to do Audio plugins, which always use a dedicated OS thread for the Audio/Midi streams and another thread for the GUI and parameter modulation stuff, I think it’s very likely that such synchronization is provided in some easy to use way “out of the box”, and of course there should be multiple examples using such technique. .
-Michael

Still slightly dense with this C++ class stuff :blush: :
Do I need to create a new independent AsyncUpdater instance, do I need to derive a new independent class from AsnycUpdater or should I add AsyncUpdater to the ancestor list of my AudioProcessor or AudioEdior class.
Once this sorted out, I will do some tests and try to find out how to send a stream of data from one thread to another in a safe way. AbstractFIFO seems to do this. does “lock free” mean that it is thread save/asyncronous ?
Thanks for enlightenment.
-Michael

BTW.:
AFAIK, with VST2 DAW, parameter changes (“modulation”) are done on the GUI thread.
But with VST3, DAW parameter changes can be “sample accurate” and hence need to be related to audio blocks. Does that mean that they are done on the Audio thread ?
Moreover how does Juce support sample accurate DAW parameter changing ?
Thanks again,.
-Michael

I’d advise to create a new class to keep things simple - if you have a lot of different base classes, it can be challenging to work out how all the different pieces interact. Both approaches will work though.

It’s best to be very specific when talking about thread safety. Certain operations on the AbstractFifo are threadsafe, while others are not. As an example, it’s safe for one thread to push items onto the fifo while another threads is popping items off the fifo. However, it’s not safe for two threads to simultaneously push items or pop items. “Lock-free” means that if any thread is suspended, all other threads interacting with the fifo will be able to make progress.

I’m not sure this is a rule, even if the majority of parameter changes will come from the UI thread in response to user interactions. Unfortunately it’s difficult to find the ‘official’ guidance or documentation these days. If I stick a breakpoint in setParameterCB and play back some automation in REAPER, the breakpoint seems to be hit on a realtime thread.

The host can supply parameter changes to the plugin with sample-accuracy on the audio thread. It must also update the editor on the main thread so that the editor reflects the state of the processor. JUCE plugins must be prepared for parameter change callbacks to come from any thread.

At present JUCE does not support sample-accurate automation.

Thanks a lot for your comprehensive explanations !
I’ll try to digest all that :slight_smile:
-Michael

Doing more research, I am not sure about the thread safety of AudioParameterFloat and friends. Can we be sure that this called by the DAW host in the GUI thread so that in audioProcessorParameterChanged() we can do GUI activities ? (Right now this does seem to work for me.)
Can we happily call AudioParameterFloat.set() (by assigning a value to AudioParameterFloat) in the GUI thread without disturbing the host ?
Thanks,
Michael

  • You can make no assumptions about which thread will be used for parameter change callbacks.
  • It’s safe to call setValue() on any thread.

I tested that with Reaper I can read and write envelopes with my VST3, assigning values to AudioParameterFloat (by “=”) in the GUI thread and setting slider values (i.e. GUI stuff) in the parameter change callback. Of course according to your advice, I will add code to transfer the parameter change to the GUI thread.
Thanks again,
-Michael

I now seem to understand that with " setValue()" you mean setVelue provided by GUI elements such as Sliders.
That explains why my code does work right now.
Thanks yet again
-Michnael

In my opinion, its best to inherit from AsyncUpdater directly. You only need to override one virtual function, and I haven’t found many cases where the interaction isn’t clear. If you create a new class as @reuk is suggesting, you will have to pass it a reference to the parent class, and that means you need to give it a constructor. In my opinion, this adds unnecessary code bloat. I’d be interested to hear if other people disagree though.

I would also give the same advice for listener classes, and for the same reasons.

With listen I already did this:

class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor,
public juce::Slider::Listener

with DAW Parameter change, I use the getStateInformation callback (suposedly inherited from JuceVST3Component via JuceVST3EditController.

-Michael

Im testing this on VST3 right now. where seemingly we don’t have setParameterCB.
Here the place I get informed about DAW Parrameter change seems to be “audioProcessorParameterChanged()” and same (in Reaper) seems to be called in the Main Thread. So no problem here.
Right now I can’t test on VST2, but audioProcessorParameterChanged also is referenced in juce_VST_Wrapper.cpp for VST2 and supposedly follows the same paradig.
-Michael

I found that AsyncUpdater and abstractFifo do a great job for inter thread communication, in exactly the way I hoped.
And when receiving and sending midi messages (on the track’s realtime thread) this is necessary.
-Michael