HISE Docs

MidiAutomationHandler

This class is a interface for modifying the MIDI control assignments in HISE through scripting.

You can:

A common practice in plugins is the ability to right click on a control and assign it to a MIDI CC controller so that it can be controlled by hardware controllers (or MIDI clips from the host).

This can be achieved in HISE by setting the enableMidiLearn property of any suitable component (slider / button / combobox) to true (or set the allowMidiAutomation property in the JSON object that you pass into UserPresetHandler.setCustomAutomation() if you're using the custom automation model).

The assignments can be modified using the MidiLearnPanel floating tile which allows you to remove connections, modify the range of how the parameter is mapped and invert the parameter.

However if you need more flexibility you can use this class and implement your own MIDI assignment interface.

Note that MIDI assignments are stored in the user preset system by default, so you don't need to use this class for data management.


Class methods

getAutomationDataObject

Returns an object that contains the MIDI automation data.

MidiAutomationHandler.getAutomationDataObject()


This method returns an array with JSON objects for every MIDI control assignment that is present. The JSON object will have these properties:

Property Type Description
Controller int the CC number (zero based) of the MIDI assignment.
Channel int the MIDI channel of the MIDI assignment (see below). This is one-based(!) and a omni connection that applies to all MIDI channels should have the value -1 .
Processor String the ID of the module that connects to the MIDI control. This is most likely your Interface.
Attribute String the ID (not the index!) of the attribute that the MIDI assignment is supposed to control.
MacroIndex int if the control is mapped to a macro control, this will contain the index.
Start double the current start of the mapped range as it was set in the MidiLearnPanel. By default this is equal to the FullStart property.
End double the current end of the mapped range as it was set in the MidiLearnPanel. By default this is equal to the FullEnd property.
'Inverted' bool whether the MIDI assignment should invert the value range (basically what the Invert button does on the MidiLearnPanel). Note that this does not affect the Start and End properties and it's still expected that Start < End .
FullStart double the lower limit of the range that can be set (in the MidiLearnPanel this would be the min value of the range sliders).
FullEnd double the upper limit of the range that can be set (in the MidiLearnPanel this would be the min value of the range sliders).
Skew double the logarithmic skew of the range that can be used for changing the gamma curve of the MIDI assignment.
Interval double the step size of the MIDI assignments. For discrete controls this can be 1.0 .
Converter String a spurious Base64 string that will contain the encoded text to value converter so that it displays the values correctly.

Note about the Channel property

Starting with HISE 4.5.0 there is the ability of filtering MIDI CC messages by MIDI channel, so that you can eg. assign the modwheel of the MIDI channel 2 to another control than the modwheel of the MIDI channel 1.

By default this is deactivated (so in our example any modwheel message from any channel would control an assigned UI element). If you don't see the Channel property in the JSON object, you have to enable the support for different MIDI channels by adding HISE_USE_MIDI_CHANNELS_FOR_AUTOMATION=1 to your Extra Definitions field (you don't have to recompile HISE for it to be applied though).

Data Example

Here's one JSON object in its full glory:

[{
  "Controller": 1,
  "Channel": 0,
  "Processor": "Interface",
  "MacroIndex": -1,
  "Start": 0.0,
  "End": 1.0,
  "FullStart": 0.0,
  "FullEnd": 1.0,
  "Skew": 1.0,
  "Interval": 0.01,
  "Converter": "37.nT6K8CBGgC..VEFa0U1Pu4lckIGckIG.ADPXiQWZ1UF.ADf...",
  "Attribute": "Knob1",
  "Inverted": false
}]


setAutomationDataFromObject

Sets the MIDI automation from the automation data object.

MidiAutomationHandler.setAutomationDataFromObject(var automationData)


This can be used to modify the list of MIDI assignments programmatically. It expects an array of JSON objects with the exact format as described in the method above and will replace all MIDI assignments with this data and send an update message to the MidiLearnPanel and any attached callback .

function modifySecondController()
{
	// grab the existing list
	var list = mh.getAutomationDataObject();
	
	// set the second range start to 50%
	list[1].Start = 0.5;
	
	// send the list back to the automation handler.
	mh.setAutomationDataObject(list);
}


setConsumeAutomatedControllers

Sets whether a automated MIDI CC message should be consumed by the automation handler (default is enabled).

MidiAutomationHandler.setConsumeAutomatedControllers(bool shouldBeConsumed)


This setting specifies whether a MIDI control that is assigned to a UI control should be excempted from further processing. The default value for this is true (so HISE will not forward a MIDI control message to its internal processing chain if it was assigned to a UI control), but for some projects you might want to enable this to be able to process all MIDI messages, regardless of the MIDI assignments.

setControllerNumberNames

Replaces the names in the popup.

MidiAutomationHandler.setControllerNumberNames(var ccName, var nameArray)


This can be used to modify the appearance of the context menu. By default it displays the controller types as "CC #2" , but if you don't like that, you can customize the strings used for the popup menu as well as the text "Add XXX" / "Remove XXX" for the ultimate UX customization!

ccName must be a string and ccNames an array with strings. Note that the length of ccNames must be either 127 or the exact length of the array you passed into MidiAutomationHandler.setControllerNumbersInPopup()

mh.setControllerNumbersInPopup([1, 2, 7]);
mh.setControllerNumberNames("Funky Controller!!!", ["Modwheel", "Breath Controller", "Volume"]);

The context menu will then look like this:


setControllerNumbersInPopup

Sets the numbers that are displayed in the MIDI automation popup.

MidiAutomationHandler.setControllerNumbersInPopup(var numberArray)


This can be used to modify the appearance of the context menu. By default it displays all 127 CC numbers in a submenu, but if you don't like that, you can limit the list of available entries by supplying a list of CC numbers that you want to show.


setExclusiveMode

Enables the "exclusive" mode for MIDI automation (only one active parameter for each controller).

MidiAutomationHandler.setExclusiveMode(bool shouldBeExclusive)


By default you can assign a single MIDI controller to multiple UI controls so if you want to eg. control the volume of multiple channels with your modwheel this can be achieved by assigning it to those controls.

However this might be an unwanted behaviour for your project so if you want to ensure that there is only a single connection for each MIDI control present, call this function with true and it will change the behaviour of the context menu:

  1. It will grey out MIDI assignments that are already connected to another MIDI controller.
  2. When you enable MIDI learn and then assign a controller to a knob, it will remove any existing connection to other controls for this particular MIDI controller. Note that if you are using HISE_USE_MIDI_CHANNELS_FOR_AUTOMATION=1 to support different assignments for MIDI channels, it will retain connections from different MIDI channels, but remove "Omni" connections as well as connections with the same channel.

Note that this logic will not be used to check the data you pass into MidiAutomationHandler.setAutomationDataFromObject() so you must take care of avoiding duplicates in there yourself.

setUpdateCallback

Set a function (with one parameter containing the automation data as JSON) that will be executed whenever the MIDI automation changes.

MidiAutomationHandler.setUpdateCallback(var callback)


This can be used to attach a function (or Broadcaster ) to be notified whenever the MIDI assignments change). The events that cause this call back are:

Note that changing the properties of a connection (eg. the range) in the MIDI learn panel does not send an update message.

Whenever one of these events is happening, it will asynchronously call this function. It expects a callable object with a single parameter which contains the JS array with JSON objects exactly as returned by MidiAutomationHandler.getAutomationDataObject() .

const var mh = Engine.createMidiAutomationHandler();

mh.setUpdateCallback(function(obj)
{
	Console.print(trace(obj));
});

Never call MidiAutomationHandler.setAutomationDataFromObject() inside this function or it will cause an endless loop of callbacks! Note that trying to outsmart this rule by using a simple recursion protection would not work as the update message is asynchronous.

const var mh = Engine.createMidiAutomationHandler();

// This freezes your computer.
mh.setUpdateCallback(function(obj)
{
	obj[0].Start = 0.5;
	mh.setAutomationDataFromObject(obj);
});

var recursion = false;

// Good idea and extra points for using scoped statements,
// but this freezes your computer too because the update message
// will be called asynchronously...
mh.setUpdateCallback(function(obj)
{
	if(!recursion)
	{
		.set(recursion, true);
		
		obj[0].Start = 0.5;
		mh.setAutomationDataFromObject(obj);
	}
});