Global Cable
Global Cables
can be used in order to send values across HISE projects and even from / to OSC sources. If want to attach scripting callbacks to value changes of a global cable or send values from a script, this object will come in handy.
In order to use it, just create a reference to the global routing manager using Engine.getGlobalRoutingManager()
, then call GlobalRoutingManager.getCable(id)
with a unique ID for the given cable. Then you can send values through it, attach synchronous and asynchronous callbacks, add some range conversion tools etc.
Using a cable as OSC address
If you want to use a cable as OSC address that can send and receive values from external applications, you just need to prepend /
before the id, so any cable that has an ID like this:
/some_osc_id
will automatically be used as OSC address as soon as you start using the global routing system as OSC server.
External C++ communication
The global cable is the preferred way of communicating values back from your C++ node. Take a look here
for a description on how to use it.
Class methods
connectToGlobalModulator
Connects the cable to a global LFO modulation output as source. Edit on GitHub
GlobalCable.connectToGlobalModulator( String lfoId, bool addToMod)
connectToMacroControl
Connects the cable to a macro control.
GlobalCable.connectToMacroControl(int macroIndex, bool macroIsTarget, bool filterRepetitions)
This function connects the macro control system and the global routing system by letting you send / receive value changes from macro controls. In order to use it, just call this method to assign any cable to a macro index.
Parameter | Values | Description |
macroIndex
|
int from 0 to 7 | the macro control that you want to connect to the global cable |
macroIsTarget
|
bool | whether the macro control should control the global cable or vice versa (obviously this can't be bidirectional to prevent feedback loops) |
filterRepetitions
|
bool | whether the cable should filter out repetitions of the same value. This might vastly decrease the CPU usage if you're modulating the cable value and don't want to send a new macro value each block. |
connectToModuleParameter
Connects the cable to a module parameter using a JSON object for defining the range. Edit on GitHub
GlobalCable.connectToModuleParameter( String processorId, var parameterIndexOrId, var targetObject)
deregisterCallback
Deregisteres a callback from the cable. Edit on GitHub
GlobalCable.deregisterCallback(var callbackFunction)
getValue
Returns the value (converted to the input range).
GlobalCable.getValue()
This function will return the current value of the cable after converting it using the range you defined with one of the range methods. If you need the normalised value, check out the getValueNormalised()
function.
getValueNormalised
Returns the normalised value between 0...1 Edit on GitHub
GlobalCable.getValueNormalised()
registerCallback
Registers a function that will be executed whenever a value is sent through the cable.
GlobalCable.registerCallback(var callbackFunction, var synchronous)
This function will register a callable object (either a inline function, a function or a broadcaster) to the cable. It expects a single argument that will contain the value of the cable. You can either register it as synchronous callback or as asynchronous callback (by using either the SyncNotification
or AsyncNotification
constants). The latter will filter out repetitions and will be called on the UI thread at the next timer interval:
Be aware that if you've set a range then the value that will be passed into the callback will be converted from the normalised 0...1 range to whatever range you need.
If you're using a synchronous callback then the function you pass in must be an inline function as this might be executed on the audio thread and normal functions are not realtime safe.
registerDataCallback
Registers a function that will be executed asynchronously when the data receives a JSON data chunk.
GlobalCable.registerDataCallback(var dataCallbackFunction)
This will register a callback that receives any data that was transmitted over this cable. It can come from two sources:
- The scripting method Global Cable
- A external C++ node using the C++ function
The function expects a callable object with a single parameter that will contain the data that is transmitted.
// Create a global routing manager
const var rm = Engine.getGlobalRoutingManager();
// Create the data cable
const var dataCable = rm.getCable("dataCable");
// Register the callback
dataCable.registerDataCallback(function(data)
{
Console.print("DATA: " + trace(data));
});
// Create some arbitrary data
const var bf = Buffer.create(32);
bf[10] = 90.0;
// Send the data over (this will not fire the callback above
// but other targets)
dataCable.sendData([bf, 100, "a string"]);
The function is always being called synchronously and it creates a deep copy of the entire data for each target so this might be not the best solution in a scenario that requires fast communication (eg. UI updates of buffers etc).
sendData
Sends any type of data (JSON, string, buffers) to the target.
GlobalCable.sendData(var dataToSend)
This function can be used to send any kind of arbitrary data to the global cable targets. This can be used for safe communication between different scripts and even external C++ nodes. In order to use this method, just call it with any kind of data and it will be send to all targets that are registered to this cable.
const var rm = Engine.getGlobalRoutingManager();
const var c = rm.getCable("myDataCable");
c.sendData({ someJson: 1234, also: "strings are supported" });
c.sendData([ 1, 2, 3, 4, 5, 6]);
c.sendData(Buffer.create(128));
Note that there is not a data queue for the sender side of this protocol, which means that if you register a target after the data has been sent, it will not be "initialised" with the previously sent value. However if you're using the C++ API in your external node, it will queue the data that is about to be sent if the cable is not connected yet.
Also it will skip its own callbacks, so if you register a callback using Global Cable.registerDataCallback() , it will not be executed:
const var rm = Engine.getGlobalRoutingManager();
// Create a instance of a cable
const var c1 = rm.getCable("myDataCable");
// Create a duplicate instance
const var c2 = rm.getCable("myDataCable");
// Register two callbacks to both objects
c1.registerDataCallback(x => Console.print("C1 executed: " + trace(x)));
c2.registerDataCallback(x => Console.print("C2 executed: " + trace(x)));
Console.print("Send through cable 1");
c1.sendData("some data");
Console.print("Send through cable 2");
c2.sendData("some data");
// Output:
// Interface: Send through cable 1
// Interface: C2 executed: "some data"
// Interface: Send through cable 2
// Interface: C1 executed: "some data"
As you can see if you send a value through the first cable object it will skip the C1 callback and vice versa. This behaviour is also the same on the C++ side.
setRange
Set the input range using a min and max value (no steps / no skew factor).
GlobalCable.setRange(double min, double max)
This function can be used if you want to transmit more complex data than a single number - it accepts any kind of data object (JSON, array, Buffers, Strings) and sends the raw byte to all registered targets.
Note that this involves a deep copy creation for each listener so it might not be the fastest option (and is definitely not realtime safe), but if you want to communicate complex information across modules (and even into C++ nodes), this is the way to do it safely.
setRangeWithSkew
Set the input range using a min and max value and a mid point for skewing the range. Edit on GitHub
GlobalCable.setRangeWithSkew(double min, double max, double midPoint)
setRangeWithStep
Set the input range using a min and max value as well as a step size. Edit on GitHub
GlobalCable.setRangeWithStep(double min, double max, double stepSize)
setValue
Sends the value to all targets (after converting it from the input range.
GlobalCable.setValue(double inputWithinRange)
This will convert the value using the supplied range and send it through the cable.
Be aware that calling this method will not trigger any scripting callbacks attached to itself.
setValueNormalised
Sends the normalised value to all targets. Edit on GitHub
GlobalCable.setValueNormalised(double normalisedInput)