I’m trying to refactor some code that currently uses a ChangeBroadcaster to send objects* to registered listeners (ChangeListeners). Searching the docs and forums, I’ve learned that Changelisteners weren’t designed for passing information around as I’m intending to (for my purposes, coalescing multiple changes into fewer callbacks is unfortunately undesirable).
I’ve been trying to figure out the right Broadcaster/Listener system to do this, but I am a bit confused. I thought I could pack my information in a Message object (or derive my own class from Message), but I don’t see how to register listeners and broadcast Messages to them. From what I gathered, MessageListeners can only post Message objects to and from themselves.
I next looked into ActionBroadcasters/ActionListeners, but it seems that they can only be passed Strings, not void* or Message objects.
Any insight would be greatly helpful! Thanks…
BTW, I apologize in advance if the answer to this is somewhere in the forums-- I’ve done a big of digging tonight and have found very useful information about changebroadcasters, changelisteners, actionbroadcasters, other callback systems, etc, but haven’t yet stumbled across a solution!
Hmm, you’re right, there’s nothing that’ll let you send an object to multiple listeners. That should really be the way ActionListeners work - I wrote the class about many, many years ago using strings, which is a bad piece of design that I should fix when I get a moment.
It’s actually quite easy to manage your own set of listeners - have a look at the ListenerList class - you could use that to easily post message objects to a set of MessageListeners.
It’s actually quite easy to manage your own set of listeners - have a look at the ListenerList class - you could use that to easily post message objects to a set of MessageListeners.[/quote]
Thanks for the tip-- I tried this out this morning, and got it working (took a bit of work because I’m actually still on version 1.50 and it doesn’t seem that ListenerList was in version 1.50, and I also had to do a forward declaration with the class type for the ListenerList which is new to me). I tested sending 44100 OSC messages (from a test app writen in Chuck) to my JUCE app, and could successfully retrieve them over OSC in my Juce app as fast as every 4::samples (delay in between sending the osc messages). I then tested how fast I could broadcast the messages from the OSC receiver in my juce app to registered listeners, and I had to push the time in between sent osc messages to 7 samples. Not quite audiorate, however, for my needs (serial sensor data, osc, etc), anything under 10ms is probably more than fast enough, and at every 7 samples, things are flying pretty fast.
Thanks for the help Jules! I downloaded the latest version of the tip and I think its time for me to bite the bullet and update-- I tried once in the past but was discouraged by the amount of errors I saw when I initially compiled
Had a quick question regarding my implementation of ListenerList. When using ListenerList, the type of object the list is going to be holding must be specified-- for me I’m holding a class of mine called OSCRecorder as so my implementation is as follows
ListenerList<OSCRecorder> myListeners; I have another class (“OSCSetup”) which gets used in a preferences pane / tabbed component to allow the user to configure the OSC setup) address / port, connect/disconnect, etc). I have a TextEditor window in there which basically dumps all OSC messages for the user to see, and so it should also be notified / passed all the OSC messages that my OSCRecorder instances receive, however, I can’t add it as a listener because its a separate class (type).
For now, I kept it as a changelistener (since the monitor is just to verify incoming data, and its speed / transmission coalescing isn’t crucial), and the broadcasting osc class (OSCListener) that implements ListenerList is also a Changebroadcaster so that it can notify both OSCRecorders (with the benefits of using ListenerList) and also my OSCSetup (via Changebroadcaster).
I was wondering if it was possible to setup my classes / ListenerList to be more flexible to allow only one notification system (ListenerList) to be used. I figure I could use a second ListenerList to also manage types (instead of a Changebroadcaster), however, if I could setup one ListenerList to manage both that would be most efficient-- only one instance of OSCSetup is instantiated at a time, and only temporarily while configuring the OSC settings, and so it seems a little superfluous to have a broadcaster for one object, thats only around temporarily. Also because of that, I have two messages each time an osc event comes in, even when theres no instance of OSCSetup around to be notified like so:
myListeners.call (&OSCRecorder::myCallbackMethod, oscMessage); //broadcast messages to osc recorders
sendChangeMessage(oscMessage); //broadcast message to osc monitor in OSC preferences
I figured this was unneccsary. Is there a way to make a ListenerList register any type like Changebroadcasters? Or, is there a way I could code my OSCSetup and OSCRecorder classes so that I can specify the same base-class or something for the ListenerList? Sorry if this is obvious, as I’m still pretty new to c++ :? Thanks for your help Jules!
Surely you should just derive all these classes from a listener base-class, e.g. “OSCMessageListener”?
yep, silly me-- I got that up and running in just a few minutes, and it works, but I’m experiencing a few issues / crashes now. I think it might be due to the speed at which a TextEditor can display text? Because of the way Changebroadcaster/Changelisteners coalesce multiple callbacks, I don’t think I experienced these symptoms before (sending lots and lots of data/text to be displayed), however, now with ListenerList, I can send data much faster, and I think its causing the crashes. Here are the symptoms if you have any advice:
The OSCSetup class experiences the following if I try sending the OSC data to the display of a TextEditor (using insertTextAtCursor):
 Crashes if the data is sent very fast
 If sent fast, but not fast enough the crash it, if I stop sending data, it takes the TextEditor display a minute to catch up to the last sent messages (it seems like theTextEditors message queue gets backed/clogged up)
[*] If im sending data quickly before connecting to the osc listener, it crashes upon connection
Because the TextEditor is merely just to notify the user of data coming in, it is not crucial that it actually gets/displays every message (which is important for the OSCRecorders)-- the way it behaved being notified as a Changelistener was actually a little more usable for its purposes, in that the display would not experience lag (from the messages being sent too fast / backlogged), or crash. The reason I wanted to get the OSCSetup class on the same notification system as the OSCRecorders, is just so that the osc receiver class only had to broadcast one message to all listeners, each time new osc data was available, and since OSCRecorder needs to use a ListenerList for speed reasons, it seemed logical to also get the OSCSetup class listening to the same messages.
As far as performance and ethical coding is concerned, would it be bad to broadcast to OSCRecorders via a ListenerList and to broadcast to the OSCSetup (TextEditor) via a Changebroadcaster each time new osc is available? That definitely works, I just thought it would be cleaner to get them going off the same broadcaster (which also works, as long as I dont try to display data in the texteditor too quickly, as described above).
Any advice is much appreciated, thanks! What would Jules do in this situation? (or anyone else that has any thoughts!)
What’s actually crashing? If you’re overloading the message queue then you’d need to do some kind of coalescing in your own code, I guess.