/ VST Home / Technical Documentation
[3.8.0] MIDI Learn 2 (MIDI 2.0 support)
On this page:
Related pages:
- [3.0.1] Parameter MIDI Mapping (MIDI 1.0 support)
- [3.6.12] MIDI Learn (MIDI 1.0 support)
- [3.8.0] Parameter MIDI Mapping 2 (MIDI 2.0 support)
Introduction
MIDI Learn Interface: Vst:: IMidiLearn2.
- [plug imp]
- [extends Vst:: IEditController]
- [released: 3.8.0]
- [optional]
- [replaces Vst::IMidiLearn]
If this interface is implemented by the edit controller, the host will call this method whenever there is live MIDI-CC input for the plug-in. This way, the plug-in can change its MIDI-CC parameter mapping and notify the host using the Vst:: IComponentHandler::restartComponent with the kMidiCCAssignmentChanged flag.
Use this if you want to implement custom MIDI-Learn functionality in your plug-in.
Note: The struct Midi2Controller refers to MIDI 2 Registered and Assignable Controllers. These UMP MIDI 2 message types are specified by the MIDI Association to map and translate directly to MIDI 1 RPN and NRPN. In that regard, they are both MIDI 1 and MIDI 2.
Generally, plug-ins should avoid allowing n-to-m mappings of controllers and parameters, as this could lead to inconsistent states in how controllers and parameters are represented within the host, which could confuse users. Nevertheless, there may be special situations where such mappings are intended, e.g., when layering sounds within a multitimbral plug-in. Therefore, such mappings are allowed.
Example
In mycontroller.h
//------------------------------------------------------------------------
// here an example of how a VST 3 plug-in could support this IMidiLearn2 interface.
// we need to define somewhere the iids:
//in MyController class declaration
class MyController : public Vst::EditController, public Vst::IMidiLearn2
{
// ...
//--- IMidiLearn2 ---------------------------------
tresult PLUGIN_API onLiveMidi2ControllerInput (BusIndex index, MidiChannel channel,
Midi2Controller midiCC) SMTG_OVERRIDE;
tresult PLUGIN_API onLiveMidi1ControllerInput (BusIndex index, MidiChannel channel,
CtrlNumber midiCC) SMTG_OVERRIDE;
// ...
OBJ_METHODS (MyController, Vst::EditController)
DEFINE_INTERFACES
// ...
DEF_INTERFACE (Vst::IMidiLearn2)
END_DEFINE_INTERFACES (Vst::EditController)
//...
}
In mycontroller.cpp
#include "pluginterfaces/vst/ivstmidimapping2.h
namespace Steinberg {
namespace Vst {
DEF_CLASS_IID (IMidiLearn2)
}
}
//------------------------------------------------------------------------
tresult PLUGIN_API MyController::onLiveMidi2ControllerInput (BusIndex index, MidiChannel channel, Midi2Controller midiCC)
{
// if we are not in doMIDILearn (triggered by a UI button for example) or wrong channel then return
if (!doMIDILearn || index != 0 || channel != 0 || midiLearnParamID == InvalidParamID)
return kResultFalse;
auto currentMapping = midiCCMapping.find ({CCType::CC, midiCC});
if (currentMapping == midiCCMapping.end () || currentMapping->second != midiLearnParamID)
{
removeCurrentMidiLearnParamAssignment ();
midiCCMapping[{CCType::CC, midiCC}] = midiLearnParamID;
if (auto _componentHandler = getComponentHandler ())
_componentHandler->restartComponent (kMidiCCAssignmentChanged);
}
return kResultTrue;
}
//------------------------------------------------------------------------
tresult PLUGIN_API MyController::onLiveMidi1ControllerInput (BusIndex index, MidiChannel channel, CtrlNumber midiCC)
{
// if we are not in doMIDILearn (triggered by a UI button for example) or wrong channel then return
if (!doMIDILearn || index != 0 || channel != 0 || midiLearnParamID == InvalidParamID)
return kResultFalse;
CCKey key { midiCC.registered ? CCType::RPN : CCType::NRPN, (midiCC.bank << 7) | midiCC.index };
auto currentMapping = midiCCMapping.find (key);
if (currentMapping == midiCCMapping.end () || currentMapping->second != midiLearnParamID)
{
removeCurrentMidiLearnParamAssignment ();
midiCCMapping[key] = midiLearnParamID;
if (auto _componentHandler = getComponentHandler ())
_componentHandler->restartComponent (kMidiCCAssignmentChanged);
}
return kResultTrue;
}