Possible to communicate between plugins?
-
@Christoph-Hart I'm not able to have more than 1 instance of the receiver plugin, this is my setup
This is the "main" plugin that sends information to the receiver plugins
The "subdomains" array is working great, I'm able to switch between the sub domains while running.Also the callback works, it will receive data from the all the instances of the receiver plugin, and I can clearly see from which instance it comes.
But only 1 of the receivers get the send data, even though the "dead" instances can send back to the "main" plugin.
// Testing communiction between plugins const subdomains = ["/ch1", "/ch2", "/ch3", "/ch4"]; const var rm = Engine.getGlobalRoutingManager(); rm.connectToOSC({ "SourcePort": 6666, "TargetPort": 6667, "Domain": "/ostinarp" }, 0); inline function OSCCallback(id, value) { LogLbl1.set("text", value); }; for (i = 0; i < 4; i++) rm.addOSCCallback(subdomains[i], OSCCallback);
This is how I set up the receiver plugins
const var rm = Engine.getGlobalRoutingManager(); rm.connectToOSC({ "SourcePort": 6667, // Note how the source port and target port are "TargetPort": 6666, // reversed here to allow bidirectional communication "Domain": "/ostinarp" }, 0); inline function OSCCallback(id, value) { local ch = ChannelKnob.getValue(); if (value[0] == ch) { local ev = Synth.addNoteOn(value[0], value[1], value[2], 0); Synth.noteOffDelayedByEventId(ev, value[3]); LogPanel.setValue(value); LogPanel.repaint(); rm.sendOSCMessage(subdomains[ch-1], "Hi there from "+subdomains[ch-1]); } };
What have done wrong?
-
@ulrik and the data sent is an array, and that works great
-
@Christoph-Hart is it possible to send to more than 1 "TargetPort"
const var rm = Engine.getGlobalRoutingManager(); rm.connectToOSC({ "SourcePort": 6666, "TargetPort": several ports, "Domain": "/ostinarp" }, 0);
-
@ulrik Does
rm.connectToOSC({ "SourcePort": 6666, "TargetPort": [1234, 5678], "Domain": "/ostinarp" }, 0);
Work?
-
@ulrik I am not very familiar with OSC but I am assuming this would need a user to install OSC specifically to use this ?
-
@lalalandsynth Nope, OSC is a network protocol and doesn't need any 3rd party software.
However I don't have too much knowledge about OSC, I just implemented a wrapper around the JUCE classes so I can imagine that port numbers need to be exclusive in order to receive messages.
"TargetPort": [1234, 5678],
pretty sure this will not work, because I implemented this and the
TargetPort
property gets parsed as a single integer value, but I can try to take a look at this and create multiple OSC senders which send the same message to multiple target ports here. Not sure when I find the time for that though... -
@Christoph-Hart @lalalandsynth I've tried using an array but it will not work, at least not the way I've set it up
-
@Christoph-Hart Using only 1 sender and 1 receiver works great, also using using different sub domain.
When the first receiver instance has successfully connected and is receiving data, it is like this instance is blocking the senders port so the second instance is not able to connect.
If that is the case, it would be great if the sender could send on several ports.And as I understand it, you can't use
Engine.getGlobalRoutingManager();
for more than one time right?
-
Guys sorry about my ignorance.
What are the use cases of the communication between the plugins?
What does this feature stand for? -
@harris-rosendahl in my case I wan't to send midi information from a multichannel arpeggiator (which will not work in some daws), to several "receiver! plugins to control multi instruments
-
@ulrik Could I for example control a gain module on track 2, and having my main control module on track 1?
-
@lalalandsynth Be careful about "persistent" states in conjunction with OSC, this is one of the main drawbacks I found in this protocol because restoring these settings from a DAW project will not restore the values (especially because you can't guarantee that the gain module 2 exists already when the gain module 1 is created and restored).
-
@lalalandsynth
If I understand you right, yesIn you main plugin
const var rm = Engine.getGlobalRoutingManager(); rm.connectToOSC({ "SourcePort": 6666, "TargetPort": 6667, "Domain": "/receiver" }, function(printError) { Console.print(printError); }); // In you gain callback inline function onGainControl(component, value) { rm.sendOSCMessage("/gain", value); } Content.getComponent("Gain").setControlCallback(onGainControl);
In you receiver plugin
const var rm = Engine.getGlobalRoutingManager(); rm.connectToOSC({ "SourcePort": 6667, "TargetPort": 6666, "Domain": "/receiver" }, function(printError) { Console.print(printError); }); inline function OSCCallback(id, value) { Track2Gain.setValue(value); Track2Gain.changed(); }; rm.addOSCCallback("/gain", OSCCallback);
-
@Christoph-Hart while searching the juice files for a solution to the "locked port" issue, I found this:
taken from juice_OSCReceiver.h/** Use this struct as the template parameter for Listener and ListenerWithOSCAddress to receive incoming OSC data immediately after it arrives, called directly on the network thread that listens to incoming OSC traffic. This type can be used by OSC callbacks that don't do much, but are realtime-critical, for example, setting real-time audio parameters. */ struct JUCE_API RealtimeCallback {};
If this was implemented in Hise, would it be able to control midi messages accurate, in time?
-
@ulrik I'm using the Realtime callback already (unless you specifically tell the OSC listener to be asynchronous).
-
@Christoph-Hart Great!
-
@ulrik I managed to have several listeners plugins, by forwarding the not consumed data to a new port it works.
The downside is that if I want to listen to ch 4, I need to have ch 1 - 3 also up and running
const var rm = Engine.getGlobalRoutingManager(); inline function onChannelKnobControl(component, value) { rm.connectToOSC({ "SourcePort": 6666+value, // incoming port "TargetPort": 6667+value, // sending port "Domain": "/ostarp" }, function(error) { Console.print(error); }); }; Content.getComponent("ChannelKnob").setControlCallback(onChannelKnobControl); inline function OSCCallback(id, value) { local ch = ChannelKnob.getValue(); if (value[0] == ch) { local ev = Synth.addNoteOn(value[0], value[1], value[2], 0); Synth.noteOffDelayedByEventId(ev, value[3]); LogPanel.setValue(value); LogPanel.repaint(); } else rm.sendOSCMessage(subdomains[ch-1], value); }; for (i = 0; i < 4; i++) rm.addOSCCallback(subdomains[i], OSCCallback);
-
@Christoph-Hart is there a way, in Hise, to count how many instances of the same plugin is loaded in a daw?
The above solution is not optimal because the user will not be able to run more than 1 instance of the "mother plug" before it's get messy.
I'm thinking maybe the second "mother plug" could sense if there is another loaded and automatically change the
domainport and the listeners have a way to change thedomainport (via the user)? -
@Christoph-Hart
I still haven't found a way for instance number 2, 3 etc, to connect to the target port (if already 1 instance is communicating with it).Do you have any suggestions what I, (or you ) could do to make it work?
-
Here is a way to communicate between plugins,
without OSC messages. I found out before I saw this post. ;)HiseSnippet 1092.3ocsV01aaaCDlJILqRacXAX+.zLFJjw5br6KqCHHXNwwtHnMoFSYA6SsiVhxlHTjBRzIwaH.6m79Gjcjh1RNyIcyXUeP.7t6g2yc73cbXtLhVTHyQNtmMKihb9Bb3LgZRuIDl.c7QHmGgGlSKnJzgyxHEEzXjiyluVq0wcKj46u9oCIbhHhVIBgNWxhnukkxTURG18MLNe.IldFKsl0un6wQRQOIWNEXxl31nLRzEjwzSIZy1.ib1teLSIyCUDEs.4r0gx3YgSjWIJs+bVAaDmpWzAEBaTo3ARdrlwZondSX73gyi3BDrKCqh+MKi+uFeBKlsPdUd3qLJ7qPTOe3rwxzayknWm5zqcM5sBJ4TiRaURocvgQ4rLUkFMe9b7wBEMOg.o85TozVzFuZKbOIXgP0JkbAcPNrXAhfm2t8S8geM2yyCR8EJ+KI49GDCG0ET+88mCcLU0SllIEvhfFV8M.TUfdiPNpy8BwnUCvSa6PhZBX5.FmFNqPQS0VaNjxCpI7frriHJBfRCRqP.EB.PKAznBZnnWqZXsADbBnAJY.qZznTHrGTVeQ7TwXszVJvdKQR.AZxXXq9PP6jfEd56pi05hKYzqNCbo0Adl6IsJTjbktZNOncq1uTGn6tqkldLAmIn9ISEQJlT3KEVM5bUtjGDMOQ8THUxmRa58Gdt0hWiv87b+OR2a1y6ib.1pPK2PhdDNeDbcK3trqLVBoh3UDHly0GHLb8bYIA1UttIstJmongpblXbfArlZmq0Gz7gnrs.Z0DtNKzz09UimmJUz2IBLIVua77uqpjjUpytmb3XcUpKOvMZ1c2WSU9l.oJj8+l822OHoEWRhOnvF0Ma5+jmTuRc0FAoKXacWph9tFAkDtkIwh4IwLRdAc.XlJnBpNy5dypis.wzzQz75UdZCg1NK2KCe+8xp2pMp7zqlgRwwBl5cYTw80.FYOx088rrBLUY558k1tdgbFzc.wflaeF1DyHCgqOqA8KGq6WLeafcD7RFMWwzAfyQzKgYQkMScwGQKtPIyfwJKpx.wkN8wVm9VxHJ23SWr8RA55EdrKs6rJ2+scGMd9nK2su81a2QKkvYiEol8daLmlnPI.yBY+dMhGz8JVrZRkf22cBkMdhp9jQTMVt8GM0TQx+77Zjr6uM2UXmqg0ycC14Yl4x+iYNvzNY7TNQs7HP8beqBnVZo4N5YKhBlZV82E7+1bw+sTbG7PlJZxp43FqfiPMymBNZeMwiw8SRnQpJBtEdvu9o4oCneVNUAcGNg.MIf5.7oSSCgpxHJ3cgfx02kc1Peqqbca8ZcFP2h2r.Jdu0pridsiUYm4JQojnb4GhJuqpeuxiLR.NILOUyEehds+hKoXLLVDkBOc5CQQ5v+6gFAqFyyVCLOeMv7h0.yKWCL+vZf4UqAle7Awne05ASUxzxqCffg8MMKcb5KHPkkoJD82PJ0I1n
it works by storing values ββin an external file