Help understanding API/Examples, in particular MidiMessageCollector

Can someone please explain how to use the API, or how to make sense of the examples when making a plugin?

Basically I’m wondering could the API be enhanced to add some more helpful information? Like this class needs these functions to be called, this is what the inheritance diagram is showing you. I guess if you’re an experienced C++ developer, this makes sense, but I’m struggling to get the most basic things hooked up with help from the API.

Take for instance: https://docs.juce.com/master/classMidiKeyboardStateListener.html

It has an inheritance diagram, but what does that mean? The top part is like the Employee and all other employees, part time or full time inherit from that, does that mean I have to make an Employee first and then assign it the role of Part time or full time? So To Get MidiMessageCollector to work I need a MidiKeyBoardStateListener? Or the functions of MidiKeyBoardStateListener are already inside and part of MessageCollector? In the example of MPE where it uses a MidiMessageCollector, there’s an MidiInputCallback, do I need to implement this to make Message Collector work? Or get the callback working on the GUI thread?

Can I just have one MessageCollector one the main audio thread, and then grab the information from the GUI thread via processor.midiMessageCollector, and just feed the buffer into midiCollector.removeNextblockOfMessages? Do I put a MidiInputCallback on the GUI thread and implement the virtual functions there? I’m struggling to see the logic through the example

I get there’s a sentiment of hatred for noobs around here, so I’m not exactly hopeful for a response here.

No hatred here that I’ve seen. But there is a general assumption of programming knowledge. Still, I’ve seen very basic C++ questions answered here often. Here’s a link to one page I found that explains inheritance, with diagrams, and what they mean. I’m sure there are many more you can find out there. https://www.geeksforgeeks.org/inheritance-in-c/

I understand the C part of C++, that’s about it, and beginning to understand referencing/deref, pointers and memory, but it’s a slow process. I understand how to make a class. But using the some of the built in stuff to Juce is not intuitive yet.

Thanks for linking the inheritance tut, the arrows go the other way to Juce. Which is the base class and which is the derived class in, base is parent and derived is child? https://docs.juce.com/master/classMidiMessageCollector.html

Why do I see MidiInput Callback in the MPE example when using MessageCollector, does this have to be implemented to receive the callback on GUI thread?

I just don’t understand the logic of hooking it up based on the information provided by the API.

If the logic is MidiInput call back is only for hardware miidi and Keyboard state Listener is a requirement for audio/midi plugins, could that not be explained or eluded to in the API? Even colour coded so users don’t go down the wrong path like it looks like I have.

Or someone tell me explicitly, do you need to have a MidiKeyBoard Component on an Audio thread, and KeyBoardstateListener on GUI thread? I don’t need a visual key board that the user can click, I literally just want trigger a callback via midi input, so I thought MidiMessageColector would work as it inherits from the same place as MidiKeyboard Component. https://docs.juce.com/master/classMidiKeyboardStateListener.htm

I understand it is not easy without any starting point.
To get a starting point, it is probably worth doing one or a few of the tutorials

To learn about where the audio thread is working, maybe that post I wrote a while back helps a bit:

About your questions about MidiKeyboardComponent:

This is a software keyboard that your app can display. It needs a corresponding MidiKeyboardState. The reason why that is not in one class is, because in a plugin you have an AudioProcessor, that is always present, and a GUI called AudioProcessorEditor, that may or may not be present. To know, which key is pressed, the MidiKeyboardState has to observe the stream of noteOn and noteOff events. Otherwise, if you open the editor while a midi note is playing, it couln’t display that.

Any class called FooListener or Foo::Listener is an interface to register for notifications. In the case of MidiKeyboardState::Listener you can add yourself as listener to a state and get a call, if a noteOn or a noteOff or other things happen, that you can see in the API docs of that Listener

The MidiInputCallback is indeed listening directly to the port and should not be used in a plugin. The reason is, it collides with the host’s routing and second, the data will not be timestamped and therefore not synchronous with the timeline of your DAW.

Something that probably makes is additionally hard is, what parts are actually under control of a plugin, and what is the host’s responsibility. Recording audio and midi events is what the host is doing.

Before I write a whole book, maybe you could already get an idea, otherwise just keep asking…

And sometimes it takes a few hours until someone comes back with an idea how to help you, have a little patience :wink:

Well thank you so much for having the patience to write all of that. It does clear up quite a bit of confusion.

So I can just extend from PluginEditor.h, with MidiKeyBoardStateListener, define a private variable as MidiKeyBoardState midiKeyState, then in the editor.cpp I can just write midiKeyState.addListener(this); and implement the two virtual functions. I don’t have to send midi from the processBlock to the midiKeyState on the GUI thread? It can’t be that simple.

This is where I’m getting confused, whether I need to implement anything on the PluginProcessor and send reference of the keyboard state to the plugin editor. I literally don’t need any midi in the pluginProcessor, so if I can bypass getting midi data from the processor entirely that would be great.

I think I understand how to I’d pull it from reference if I did need to implement KeyBoardState on the Processor, with the ampersand. Do I have to feed this keyboard state manually with data in the audioprocess block, or is it some magic and the function will just get called whever something happens?

Ok so that was a really un-intuitive process for a beginner. I think the examples have only complicated things! So to set this up correctly and register call backs on the Editor thread, you need a KeyBoardState on the Plugin Processor, then in the process block you put midiKeyState.processNextMidiBuffer(midiMessages, 0, buffer.getNumSamples(), true);

And you don’t give a reference in the editor, you put midiKeyListener there, implement virtual functions and then in constructor you put processor.midiKeyState.addListener(this);

I kept on thinking where (this) goes would be the reference to the object on a different thread, instead of referring to put this thing on this current class.

Confusion over I have the call backs working and printing something to the console.

WOOHOO!! Thank you so much Daniel!! I honestly didn’t think I was gonna make it here

2 Likes

F*** yeah: