Vendor helgoboss/helgobox (ReaLearn) as basis for custom UI fork

Stripped upstream git history; starting point for replacing the native
SWELL/Win32 mapping UI with something more suited to bulk editing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Paul Lipscomb
2026-07-15 17:38:29 -04:00
parent 583ed77a67
commit e58f06d9fa
2232 changed files with 685575 additions and 1 deletions
@@ -0,0 +1,106 @@
= Best practices
[[best-practices-input-output,Best practices for setting input and output]]
== Setting input and output
Prefer output to a specific device over xref:user-interface/main-panel/input-output-section.adoc#fx-output[]!::
It's usually better to select a specific output device because sending MIDI feedback to the FX output has drawbacks.
+
First, it doesn't participate in ReaLearn's multi-unit feedback orchestration.
That means you might experience misbehaving LEDs/faders/displays when using multiple units.
+
Second, it doesn't work if ReaLearn FX is suspended, e.g. in the following cases:
* ReaLearn FX is disabled.
* Project is paused and ReaLearn track is not armed.
* ReaLearn FX is on input FX chain and track is not armed.
[[using-the-controller-compartment]]
== Using the controller compartment
The xref:key-concepts.adoc#controller-compartment[] lets you describe a xref:key-concepts.adoc#controller[] simply by adding xref:key-concepts.adoc#mapping[mappings].
When you do that, each xref:key-concepts.adoc#controller-mapping[] represents a xref:key-concepts.adoc#control-element[] on your xref:key-concepts.adoc#controller[], e.g. a xref:further-concepts/mapping.adoc#momentary-button[] or xref:further-concepts/mapping.adoc#fader[].
Describing your controller is optional but it brings benefits:
* You can use the xref:further-concepts/unit.adoc#projection[] feature to project your controller mapping to a smartphone or tablet (link:https://www.youtube.com/watch?v=omuYBznEShk&feature=youtu.be[watch video]).
* You can use xref:further-concepts/compartment.adoc#controller-preset[controller presets] either built-in ones or those made by other users ... and thereby save precious setup time.
Or you can contribute them yourself!
* You can make your xref:key-concepts.adoc#main-mapping[main mappings] independent of the actually used xref:key-concepts.adoc#controller[].
This is done using xref:further-concepts/source.adoc#virtual-source[virtual sources] and xref:further-concepts/target.adoc#virtual-target[virtual targets].
* It allows you to give your knobs, buttons etc. descriptive and friendly names instead of just e.g. "CC 15".
* You don't need to learn your xref:key-concepts.adoc#control-element[control elements] again and again.
Although the process of learning an element is easy in ReaLearn, it can take some time in case the xref:further-concepts/source.adoc#midi-source-character[] is not guessed correctly.
Just do it once and be done with it!
If you want to make ReaLearn "learn" about your nice controller device, all you need to do is to create a suitable controller mapping for each of its control elements.
Let's first look at the "slow" way to do this - adding and editing each controller mapping one by one:
. Press the xref:user-interface/main-panel/mappings-toolbar.adoc#add-one[].
. Learn the xref:key-concepts.adoc#source[] by pressing the xref:user-interface/main-panel/mapping-row.adoc#learn-source[] and touching the control element.
. Press the xref:user-interface/main-panel/mapping-row.adoc#row-edit[].
. Enter a descriptive name for the xref:key-concepts.adoc#control-element[].
+
TIP: This name will appear in many places so you want it to be short, clear and unique!
. Assign a unique xref:further-concepts/target.adoc#virtual-target[].
** At this point we don't want to assign a xref:further-concepts/target.adoc#real-target[] yet.
The point of xref:further-concepts/compartment.adoc#controller-preset[controller presets] is to make them as reusable as possible, that's why we choose a xref:further-concepts/target.adoc#virtual-target[].
** In the _Category_ dropdown, choose _Virtual_.
** As _Type_, choose xref:further-concepts/compartment.adoc#virtual-control-element-type[] if your control element is a sort of button (something which you can press) or xref:further-concepts/compartment.adoc#virtual-control-element-type-multi[] in all other cases.
** Use for each xref:key-concepts.adoc#control-element[] a unique combination of xref:further-concepts/compartment.adoc#virtual-control-element-type[] and xref:further-concepts/compartment.adoc#virtual-control-element-id[], starting with number *1* and counting.
+
TIP: It's okay and desired to have one control element mapped to "Multi 1" and one to "Button 1".
** Just imagine the "8 generic knobs + 8 generic buttons" layout which is typical for lots of popular controllers.
You can easily model that by assigning 8 multis and 8 buttons.
** Maybe you have realized that the xref:user-interface/mapping-panel/glue-section.adoc[] is available for controller mappings as well!
That opens up all kinds of possibilities.
You could for example restrict the target range for a certain control element.
Or make an encoder generally slower or faster.
Or you could simulate a rotary encoder by making two buttons on your controller act as -/+ buttons emitting relative values.
This is possible by mapping them to the same xref:further-concepts/compartment.adoc#virtual-control-element[] in xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[].
Before you go ahead and do that for each control element, you might want to check out what this is good for: Navigate back to the xref:key-concepts.adoc#main-compartment[], learn the xref:key-concepts.adoc#source[] of some xref:key-concepts.adoc#main-mapping[] and touch the xref:key-concepts.adoc#control-element[] that you have just mapped: Take note how ReaLearn will assign a xref:further-concepts/source.adoc#virtual-source[] this time, not a xref:sources/midi.adoc[MIDI source]!
It will also display the name of the xref:further-concepts/compartment.adoc#virtual-control-element[] as source label.
Now, let's say at some point you swap your xref:key-concepts.adoc#controller[] with another one that has a similar layout, all you need to do is to switch the xref:further-concepts/compartment.adoc#controller-preset[] and you are golden!
You have decoupled your xref:key-concepts.adoc#main-mapping[] from the actual xref:key-concepts.adoc#controller[].
Plus, you can now take full advantage of the xref:further-concepts/unit.adoc#projection[] feature.
All of this might be a bit of an effort, but it's well worth it!
Plus, there's a way to do this _a lot_ faster by using _batch learning_:
. Press the xref:user-interface/main-panel/mappings-toolbar.adoc#learn-many[].
. Choose whether you want to learn all the xref:further-concepts/compartment.adoc#virtual-control-element-type-multi[] elements on your xref:key-concepts.adoc#controller[] or all the xref:further-concepts/compartment.adoc#virtual-control-element-type[] elements.
. Simply touch all relevant xref:key-concepts.adoc#control-element[control elements] in the desired order.
ReaLearn will take care of automatically incrementing the xref:further-concepts/compartment.adoc#virtual-control-element-id[].
. Press btn:[Stop].
. Done!
** At this point it's recommended to recheck the learned mappings.
** ReaLearn's xref:further-concepts/source.adoc#midi-source-character[] detection for MIDI CCs is naturally just a guess, so it can be wrong.
If so, just adjust the character in the corresponding xref:user-interface/mapping-panel.adoc[].
You can share your preset with other users by sending them to link:mailto:&#105;&#110;&#102;&#x6f;&#x40;&#104;&#101;&#108;&#103;&#x6f;&#98;&#111;&#115;&#x73;&#46;&#111;&#x72;&#103;[&#105;&#110;&#102;&#x6f;&#x40;&#104;&#101;&#108;&#103;&#x6f;&#98;&#111;&#115;&#x73;&#46;&#111;&#x72;&#103;].
I will add it to https://github.com/helgoboss/helgobox/tree/master/resources/controller-presets[this
list].
== Naming compartment parameters
Because ReaLearn's xref:further-concepts/compartment.adoc#compartment-parameter[compartment parameters] are freely assignable, they have very generic names by default.
However, as soon as you give them meaning by using them in a specific way, it can be very helpful to give them a name by using the xref:user-interface/main-panel/menu-bar.adoc#compartment-parameters[].
[[troubleshooting-luau-import]]
== Troubleshooting Luau import
The way Luau import works in ReaLearn is:
. ReaLearn attempts to execute the Luau script in the clipboard.
. ReaLearn attempts to interpret the returned value as ReaLearn API object.
. ReaLearn loads the API object
If step 1 fails, ReaLearn displays an error messages that hopefully contains a line number.
If step 2 fails, ReaLearn shows a validation error message.
If importing Luau code fails and the displayed error message is not helpful, you can try xref:user-interface/main-panel/menu-bar.adoc#dry-run-lua-script[].
This action enables you to just execute step 1 and see the "expanded" result.
This can help to make sense of a possible validation error message in step 2.
@@ -0,0 +1,11 @@
= Configuration files
In addition to the xref:helgobox::configuration-files.adoc[general configuration files], ReaLearn maintains the following ones:
`Data/helgoboss/auto-load-configs/fx.json`:: Contains global FX-to-preset links, see xref:further-concepts/unit.adoc#auto-load[]
`Data/helgoboss/presets/controller`:: Contains preset for the controller compartment
`Data/helgoboss/presets/main`:: Contains preset for the main compartment
`Helgoboss/ReaLearn/osc.json`:: Global OSC device configurations, see xref:user-interface/main-panel/input-output-section.adoc#manage-osc-devices[]
@@ -0,0 +1,4 @@
= Further concepts
This section describes further concepts.
You may or may not need to understand them, it depends on which ReaLearn features you are going to use and how complex your control scenarios are.
@@ -0,0 +1,484 @@
= Compartment concepts
[[compartment-preset]]
== Compartment preset
=== Main presets vs. controller presets
[[main-preset]]
==== Main preset
The term _main preset_ is just a shortcut for saying "compartment preset in the main compartment".
The number of factory _main_ presets is relatively small because ReaLearn is all about enabling you to quickly come up with your own customized main mappings. However, a few interesting main presets are available link:https://github.com/helgoboss/helgobox/wiki/ReaLearn-Interesting-Presets[in the Wiki].
[[controller-preset]]
==== Controller preset
The term _controller preset_ is just a shortcut for saying "compartment preset in the controller compartment".
.Mix and match!
TIP: The big advantage of separating controller presets from main presets is that you can freely combine them on a mix-and-match basis.
This enables you to get out-of-the-box access to all kinds of interesting control scenarios with potentially very different controllers.
=== Factory preset vs. User preset
[[factory-compartment-preset]]
==== Factory preset
Factory presets are built-in compartment presets.
Characteristics:
* You can't change them.
* If you want to change a factory preset, you can make a copy of it, either by pressing btn:[Save as...] or by <<writing-presets-with-luau, creating your personal Lua workspace>>.
* It's always possible that factory presets are changed in future ReaLearn versions.
+
.No worries
NOTE: This is not a problem for existing compartments. A changed preset will *only* be applied to the compartment if you select the preset again!
+
.Preset stability
TIP: Whenever you like a certain factory preset and want it to remain the same, even if you select it again, it's best if you make your own copy of it. The simplest way to do this is to press btn:[Save as...].
[[user-compartment-preset]]
==== User preset
User presets are made by users, for example by you.
* Saving your mappings as a preset is optional.
All controller mappings are saved together with your current ReaLearn unit anyway, no worries.
But as soon as you want to reuse these mappings in other ReaLearn unit or for xref:further-concepts/unit.adoc#auto-load[], it makes of course sense to save them as a preset!
* All of your presets end up in the REAPER resource directory (REAPER → Options → Show REAPER resource path in explorer/finder) at
`Data/helgoboss/realearn/presets` followed by `main` (for main compartment presets) or `controller` (for controller compartment presets).
They are JSON files and very similar to what you get when you press
_Export to clipboard_.
* They can even be in a subdirectory.
Please note that the subdirectory name becomes a part of the preset ID, so better don't move existing presets around if you want preset references of existing ReaLearn units to stay intact.
* JSON files can also contain <<custom-data>>.
[#writing-presets-with-luau]
=== Writing presets with Luau
It is possible to write compartment presets with the link:https://luau.org/[Luau language] instead of building them via the user interface.
Many of the more complex ReaLearn factory presets are written in Lua, e.g. the "DAW control" preset.
A good way to get started writing Luau presets is to create your personal compartment preset user workspace.
A preset workspace is a subdirectory within the compartment preset parent directory that may contain a bunch of presets and other files.
Important facts about preset workspaces/namespaces:
* It may contain both Luau presets (`.preset.luau`) and conventional JSON presets (`.json`)!
* The name of the workspace (subdirectory) is at the same time the first part of the preset ID.
For example, if the subdirectory name is `helgoboss` and it contains a preset file `my-preset.json`, the final ID of that preset will be `helgoboss/my-preset`.
* That also means that presets from different workspaces never conflict with each other.
* Therefore, a preset "workspace" is at the same time a preset "namespace".
Those terms are sometimes used interchangeably.
* It's important that the ID of a preset doesn't change, especially if you want to use that preset with xref:further-concepts/unit.adoc#auto-load[].
If you change the ID, it's another preset from ReaLearn's perspective!
* Conversely, the name of the workspace directory and the name/path of the preset file within the workspace directory should not change!
* The only thing that is allowed to change is the file extension.
This makes it possible to convert a preset from JSON to Luau and vice versa.
* Preset workspaces are self-contained.
What does that mean?
Luau presets can use the `require` statement to share common Luau code.
However, this is only possible within one preset workspace.
* As a result, it is safe to have multiple completely different preset workspace, and it's guaranteed that they don't conflict with each other.
This makes preset sharing easy (it's just a matter of copying the preset workspace directory).
* There's one special preset workspace: The _user workspace_.
It's the workspace whose directory has the same name as your macOS/Windows/Linux user.
Special features:
** The user workspace is where ReaLearn puts your presets when you save them via the user interface (as `.json` files).
** All `require` statements in Luau code imported via *Import from clipboard* are resolved against this user workspace.
You can create a preset workspace by pressing *Menu → Compartment presets → Create compartment preset workspace (including factory presets)* (done for each compartment type separately).
This will create a randomly-named preset workspace directory within the compartment preset parent directory.
If this is your first preset workspace, it is best practice to turn it into your personal _user workspace_ by renaming the generated directory to your macOS/Windows/Linux username (name must match exactly!).
Maybe the user workspace directory exists already.
Most likely because you have saved presets from the user interface, in which case it should contain only JSON files.
In that case you can safely move all files and directories from the generated preset workspace directory into that existing directory.
The generated workspace contains:
* A README file with some general information and tips.
* A copy of all ReaLearn factory presets for that compartment.
** Mainly Luau presets (ending with `.preset.luau`).
** You can use them as inspiration for your own ones.
** Most of the factory presets in the main compartment are quite advanced.
One of the easier ones is
`generic/numbered/fx-paraameters.preset.luau`.
* A bunch of Luau SDK files in the first directory level of the workspace.
** They contain Luau types and utility functions.
** You can require them within your own Luau files in that workspace and use them to build presets.
** However, the usage of the SDK files is completely optional!
The only important thing about building ReaLearn presets is that the returned table conforms to the ReaLearn compartment API (= has the structure that you get when you do *Export from clipboard → Export ... compartment as Lua*).
It doesn't matter if you use Luau's type system to build that table or the provided utility functions or your own or none.
** The SDK files can change in incompatible ways in newer ReaLearn versions.
Only ReaLearn's built-in compartment API is guaranteed to stay backward-compatible!
Luau presets have a YAML frontmatter comment section right at the top of the file that contain meta information about the preset.
The following properties are possible:
[cols="m,1,3"]
|===
|
name
|
required
|
Preset display name
|
realearn_version
|
required
|
The ReaLearn version for which this preset was built.
This can effect the way the preset is loaded, e.g. it can lead to different interpretation
or migration of properties. So care should be taken to set this correctly!
|
author
|
|
Preset author
|
description
|
|
Preset description.
Preferably in link:https://en.wikipedia.org/wiki/Markdown[Markdown] format, but can also be plain text.
|
setup_instructions
|
|
Setup instructions.
Preferably in link:https://en.wikipedia.org/wiki/Markdown[Markdown] format, but can also be plain text.
|
device_manufacturer
|
controller compartment only
|
Manufacturer of the device represented by the controller preset.
|
device_name
|
controller compartment only
|
Name of the device represented by the controller preset.
|
midi_identity_pattern
|
controller compartment only
|
MIDI identity compatibility pattern.
Will be used for auto-adding controllers and for finding the correct controller preset when calculating auto-units.
|
midi_output_port_patterns
|
controller compartment only
|
Possible MIDI identity compatibility patterns.
Will be used for auto-adding controllers and for finding the correct controller preset when calculating auto-units.
It should only be provided if the device in question doesn't reply to device queries or if it exposes
multiple ports which all respond with the same device identity and only one of the ports is the correct one.
Example: APC Key 25 mk2, which exposes a "Control" and a "Keys" port.
ReaLearn will match any in the list. OS-prefixes are alowed, e.g. `macos:` will only match on macOS.
|
provided_schemes
|
controller compartment only
|
Provided virtual control schemes.
Will be used for finding the correct controller preset when calculating auto units.
The order matters! It directly influences the choice of the best-suited main presets. In particular, schemes that are more specific to this particular controller (e.g. "novation/launchpad-mk3") should come first. Generic schemes (e.g. "grid") should come last. When auto-picking a main preset, matches of more specific schemes will be favored over less specific ones.
|
used_schemes
|
main compartment only
|
Used virtual control schemes.
Will be used for finding the correct controller preset when calculating auto units.
|
required_features
|
main compartment only
|
A set of features that a Helgobox instance needs to provide for the preset to make sense.
Will be used for determining whether an auto unit should be created for a specific instance or not. Example: If the required feature is "playtime" and a controller is configured with
this main preset but the instance doesn't contain a Playtime Matrix, this instance will not load the main preset.
Currently, only feature `playtime` is supported, which matches if the Helgobox instance contains a Playtime Matrix.
|===
[#compartment-parameter]
== Compartment parameter
Each ReaLearn compartment contains 100 freely assignable parameters.
Compartment parameters can be used in the following ways:
* For xref:further-concepts/mapping.adoc#conditional-activation[] (lets the parameter value influence which mappings are active)
* For xref:further-concepts/target.adoc#dynamic-selector[] (lets the parameter value influence which object, such as track or FX, is targeted for a specific mapping)
* As xref:sources/reaper/realearn-parameter.adoc[] (lets the parameter value control any ReaLearn target)
They can be customized as described in xref:user-interface/main-panel/menu-bar.adoc#compartment-parameters[].
Parameter customizations are saved together with the compartment preset.
Parameter values will be reset whenever you load a preset (just the ones in that compartment).
[[continuous-vs-discrete-compartment-parameters]]
=== Continuous vs. discrete compartment parameters
By default, <<compartment-parameter,compartment parameters>> have a xref:further-concepts/target.adoc#continuous-value-range[].
Although that makes them very versatile, it's often easier to work with a xref:further-concepts/target.adoc#discrete-value-range[].
Entering a value count (see xref:user-interface/main-panel/menu-bar.adoc#set-compartment-parameter-value-count[]) turns this into a parameter with a xref:further-concepts/target.adoc#discrete-value-range[], with the given number of integer values.
For example, a value count of 10 means that the parameter can represent exactly 10 values (0 to 9).
[CAUTION]
====
*Choose the value count wisely and think twice before changing it to a different value at a later point in time!*
You probably want to refer to values of this parameter in certain parts of ReaLearn, e.g. in xref:user-interface/mapping-panel/glue-section.adoc#target-min-max[].
If you do that and later change the value count, these value references will not be valid anymore.
They will point to other integers than you intended to.
So if you are not sure, better pick a large value count and stick to it!
====
[[compartment-wide-lua-code]]
== Compartment-wide Lua code
Each compartment may contain arbitrary Luau code to be reused by multiple mapping MIDI source and feedback scripts.
This avoids code duplication and decreases memory usage.
It even allows the usage of shared state.
You can set the compartment-wide Lua code using xref:user-interface/main-panel/menu-bar.adoc#edit-compartment-wide-lua-code[].
The code that you provide here is treated as a module that xref:further-concepts/source.adoc#midi-source-script[MIDI source scripts] and xref:further-concepts/glue.adoc#dynamic-feedback[Feedback scripts] can import using `require("compartment")`.
That means you need to export everything that you want the MIDI source and feedback scripts to see, simply by returning it.
.Compartment-wide Lua code
====
The following compartment-wide Lua code exports 2 functions named `get_text` and `get_number`:
[source,lua]
----
local module = {}
local function private_function()
return "i'm private"
end
function module.get_text()
return "hello world"
end
function module.get_number()
return 5
end
return module
----
These functions can then be reused in MIDI source and feedback scripts:
[source,lua]
----
local compartment = require("compartment")
local text = compartment.get_text()
local number = compartment.get_number()
----
====
Compartment-wide Lua code is part of the compartment, that means it's also saved as part of a compartment preset!
[[virtual-control]]
== Virtual control
_Virtual control_ makes it possible to create <<main-preset,main presets>>
that can be reused with many different xref:key-concepts.adoc#controller[controllers].
The idea is simple:
1. You define a <<controller-preset>> for a DAW controller, mapping each <<real-control-element>> (e.g. its first fader, which emits MIDI CC7 messages) to a corresponding <<virtual-control-element>> (e.g. named `ch1/fader`) by using a xref:further-concepts/target.adoc#virtual-target[].
2. You define a <<main-preset>>, mapping each <<virtual-control-element>> to some xref:further-concepts/target.adoc#real-target[] by using a xref:further-concepts/source.adoc#virtual-source[].
For example, you map `ch1/fader` to the xref:targets/track/set-volume.adoc[].
3. ReaLearn creates a sort of wire between the xref:key-concepts.adoc#controller-compartment[] and the xref:key-concepts.adoc#main-compartment[].
So you can now control the track volume by moving the first fader.
4. Most importantly, the main preset is now generic because it's not built for a specific controller anymore!
See xref:best-practices.adoc#using-the-controller-compartment[] for more information how to do this in detail!
[[virtual-feedback]]
== Virtual feedback
_Virtual feedback_ is just like <<virtual-control>>, but in the opposite direction (from REAPER to your xref:key-concepts.adoc#controller[]).
== Real vs. virtual control elements
Wait ... control elements that are not real!?
Yes!
In ReaLearn, they exist.
We can distinguish between <<real-control-element>> and <<virtual-control-element>>.
[[real-control-element]]
=== Real control element
A _real_ control element is an element that really exists on a xref:key-concepts.adoc#controller[], e.g. a fader that you can touch.
[[virtual-control-element]]
=== Virtual control element
A _virtual_ control element is an abstraction of a <<real-control-element>>.
It enables <<virtual-control>> and <<virtual-feedback>>.
Each virtual control element has a _type_ and an _ID_.
[[virtual-control-element-id]]
==== Virtual control element ID
A number or name that uniquely identifies the control element on the device.
Numbers are especially suited for the 8-knobs/8-buttons layouts.
In a row of 8 knobs one would typically assign number 1 to the leftmost and number 8 to the rightmost one.
It's your choice.
For more advanced virtual control scenarios it can be useful to think in names instead of numbers.
You can use up to 32 alphanumeric and punctuation characters (no exotic characters, e.g. no umlauts).
[[virtual-control-element-type]]
==== Virtual control element type
If you want to define a virtual control element, you should first decide which type is should have: _Multi_ or _Button_.
This distinction is used by ReaLearn to optimize its user interface.
IMPORTANT: For numbered control elements, the type is even part of the <<virtual-control-element-id>>.
For example, "Multi 1" is considered a different virtual control element than "Button 1".
For named control elements, this is not the case. `col1/row1/pad` defined as Multi is considered the same as `col1/row1/pad` defined as Button.
[[virtual-control-element-type-multi]] Multi::
Represents a control element that you can "move", that is, something that allows you to choose between more than 2 values.
Usually everything which is _not_ a simple on/off button :) Here's a list of typical _multis_:
* Fader
* Knob
* Pitch wheel
* Mod wheel
* Endless encoder
* XY pad (1 axis)
* Touch strip
* Rotary (endless) encoder
* Velocity-sensitive pads or keys
[[virtual-control-element-type-button]] Button::
Represents a control element that distinguishes between two possible states only (e.g. on/off), or even just one ("trigger").
Usually it has the form factor of a button that you can "press".
Here's a list of typical _buttons_:
* Play button
* Switch
* Sustain pedal (a simple on/off one, not a half-pedaling one!)
Please note that velocity-sensitive keys should be exposed as <<virtual-control-element-type-button>> - unless you know for sure that you are not interested in the velocity sensitivity.
[[virtual-control-scheme]]
==== Virtual control scheme
===== Introduction
Mixing and matching controller and main presets only works as long as controller and main presets share the same philosophy and virtual control element naming/numbering.
IMPORTANT: A main preset is not automagically compatible with any controller preset!
As you can imagine, there are far too many types of controllers and control scenarios out there to make this work in all cases.
However, ReaLearn provides many means to get close to this ideal.
To make it easier for users to know which main presets are compatible with which controller presets, ReaLearn has the concept of _virtual control schemes_. At the moment, ReaLearn uses the following schemes:
DAW control (`daw`)::
Control elements that are typically used for controlling a DAW.
The control elements names available in this scheme are heavily inspired by the wording used on Mackie Control devices, e.g. `ch1/fader`.
Grid (`grid`)::
Control elements that are laid out in columns and rows, as for example found on the Novation Launchpad. Typical control element names are `col1/row2/pad`.
Numbered (`numbered`)::
Control elements that are laid out as a simple row or column. The names available in this scheme are simply numbers, e.g. from 1 to 8.
The general idea is:
* A **controller preset** _provides_ an arbitrary number of schemes.
** E.g. the Akai APC Key 25 provides control elements of all the mentioned schemes.
** A controller should not double-expose one single control element under different virtual control element names.
* A **main preset** _uses_ an arbitrary number of schemes.
** E.g. they could assign a track volume change to both the numbered multi control element 5 (_Numbered_ scheme) and to the named multi control element `ch5/fader` (_DAW_ scheme) by using 2 mappings with the same target.
Then we say this preset uses both schemes.
===== How main presets can leverage virtual control schemes
There are roughly 3 kinds of main presets:
. **Controller-specific main presets without virtual sources:** They are built for one specific controller and use MIDI/OSC sources directly.
. **Controller-specific main presets with virtual sources:** They are built for one specific controller but primarily use virtual sources (e.g. in order to take advantage of ReaLearn's projection feature).
. **Reusable main presets:** Thy are built for all controllers that provide a specific control scheme.
===== Usage
If you want your main preset to be compatible with as many controller presets as possible, try to use predefined control element names instead of coming up with your own way of naming things!
When you define a virtual source or virtual target, there's a convenient picker that provides names for the following standardized virtual control schemes.
[[custom-data]]
== Custom compartment data
Each xref:key-concepts.adoc#compartment[] in ReaLearn can carry _custom data_. That is arbitrary structured (JSON-like) data which can be used in certain ways.
I know that's a quite generic description. It's best to give some examples:
* ReaLearn's xref:further-concepts/unit.adoc#projection[projection feature] uses custom compartment data within the xref:key-concepts.adoc#controller-compartment[] in order to memorize the positions and shapes of all control elements.
* Playtime's xref:playtime::further-concepts/matrix.adoc#control-unit[] feature reads custom compartment data within the xref:key-concepts.adoc#main-compartment[] in order to know the size of the connected xref:playtime::key-concepts.adoc#grid-controller[].
Such custom data can't directly be edited in ReaLearn's xref:user-interface.adoc[]. But you can read it when dealing with JSON or Lua chunks, e.g. when <<writing-presets-with-luau>>.
== Order in which mappings are processed
Since ReaLearn 2.10.0, mappings are processed from top to button, exactly in the order in which they are defined within the corresponding compartment.
This matters if you want to map multiple targets to one button and the order of execution matters.
*Important:* There's an exception.
ReaLearn's processing of its own VST parameters is always deferred.
- That means changing a ReaLearn parameter in one mapping and relying on it in the next one (in terms of conditional activation or in a `<Dynamic>` expression), will not work!
- You can work around that by delaying execution of the next mapping via xref:user-interface/mapping-panel/glue-section.adoc#fire-mode[fire mode] but that's a dirty hack.
ReaLearn's parameters are not supposed to be used that way!
- Imagine a railway: ReaLearn's targets can be considered as trains.
Triggering a target means moving the train forward.
ReaLearn's parameters can be considered as railway switches.
Changing a parameter means setting a course.
The course needs to be set in advance, at least one step before!
Not at the same time as moving the train over the switch.
@@ -0,0 +1,55 @@
= General concepts
[[import-export]]
== Import/export
ReaLearn can import and export data in 2 formats:
link:https://www.json.org/json-en.html[JSON]::
A wide-spread data exchange format.
It's a text format, so if you are familiar with the search & replace feature of your favorite link:https://en.wikipedia.org/wiki/Text_editor[text editor], this is one way to do batch editing.
link:https://luau.org/[Luau]::
A full-blown programming language derived from the famous Lua language that is also used in REAPER itself.
[TIP]
====
For the programmers and script junkies out there: It's perfectly possible to program ReaLearn from outside by passing it a snippet of JSON via https://www.reaper.fm/sdk/reascript/reascripthelp.html#TrackFX_SetNamedConfigParm[`TrackFX_SetNamedConfigParm()`].
Parameter name is `set-state`.
This mechanism is implemented on ReaLearn side using https://www.reaper.fm/sdk/vst/vst_ext.php[REAPER's named parameter mechanism] (search for `named_parameter_name`).
Example that assumes that the first FX of the first track is a ReaLearn instance:
[source,lua]
----
local track = reaper.GetTrack(0, 0)
local state = [[
{
"controlDeviceId": "62",
"feedbackDeviceId": "fx-output",
"mappings": [
{
"name": "1",
"source": {
"type": 1,
"channel": 0,
"number": 64
},
"mode": {},
"target": {
"type": 2
}
}
]
}
]]
reaper.TrackFX_SetNamedConfigParm(track, 0, "set-state", state)
----
====
[#feedback-relay]
== Feedback relay
Feedback _relay_ happens when a feedback-enabled mapping becomes inactive and another feedback-enabled mapping with the same xref:key-concepts.adoc#source[] becomes active. In that case, ReaLearn has to swap the displayed value of the previous mapping target with the displayed value of the new mapping target.
@@ -0,0 +1,257 @@
= Glue concepts
[[target-value-sequence]]
== Target value sequence
A target value sequence represents a list of possible target values.
It can be entered using into the xref:user-interface/mapping-panel/glue-section.adoc#value-sequence[].
The mapping will set the target only to values contained in that sequence.
Such a sequence doesn't just support single values but also ranges with customizable step sizes.
All values are entered comma-separated using the target unit specified with the xref:user-interface/mapping-panel/target-section.adoc#display-unit[].
.Single values
====
Enter this sequence for a volume target with target unit switched to *dB*:
`-20, -14, -12, -6, -3.5, 0`
When you move your knob or rotary encoder or press a button using xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[], ReaLearn will step through the entered dB values for you.
====
.Value ranges
====
Enter this sequence for a target with a continuous value range and target unit switched to *%*:
`10 - 30, 50 - 70 (5), 80 - 90 (2)`
It will first step in 1% steps from 10% to 30%, then in 2% steps from 50% to 70% and finally from 80% to 90% in 2% steps.
It's important that the numbers and the range dash are separated by spaces!
====
.Non-monotonic or non-strict-monotonic sequences
====
Let's look at this sequence:
`20, 10, 10, -5, 8`
It's non-monotonic: It decreases, and then increases again.
Even if it would just decrease, it would be non-strict monotonic because it contains duplicates (value 10).
When using xref:further-concepts/mapping.adoc#absolute-control[], it's no problem stepping through such sequences.
However, xref:further-concepts/mapping.adoc#relative-control[] only supports strictly increasing or strictly decreasing sequences.
So if you control this sequence e.g. via xref:further-concepts/mapping.adoc#rotary-endless-encoder[] or via xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[], the sequence will be stepped through like this: -5, 8, 10, 20.
Alternative: Use xref:user-interface/mapping-panel/glue-section.adoc#make-absolute[]!
====
[#feedback-type]
== Feedback type
The _feedback type_ determines whether to send numeric, text or dynamic feedback to the source.
It can be set using the xref:user-interface/mapping-panel/glue-section.adoc#feedback-type-controls[].
[[numeric-feedback-type]]
=== Numeric feedback: EEL transformation
Sends numeric feedback to the source.
This is the default.
Numeric feedback can be combined with an EEL feedback transformation formula.
This is similar to xref:user-interface/mapping-panel/glue-section.adoc#control-transformation[] but used for translating a target value back to a source value for feedback purposes.
Be aware: Here `x` is the desired source value (= output value) and `y` is the current target value (= input value), so you must assign the desired source value to `x`.
.Simple feedback transformation formula
====
`x = y * 2`
====
ReaLearn's feedback processing order is:
. Apply target interval.
. Apply reverse.
. Apply transformation.
. Apply source interval.
[[text-feedback]]
=== Text feedback: Text expression
With this option, ReaLearn will send text feedback values to the source.
This only works with sources that are capable of displaying text: That is any xref:sources/osc.adoc[] with argument type _String_, xref:sources/midi/display.adoc[] and xref:sources/midi/midi-script.adoc[].
Text feedback can be combined with a _text expression_, which lets you define which text is going to be sent to the source _whenever the target value changes_ and immediately when entering the text.
Whatever text you enter here, will be sent verbatim to the source.
Of course, entering a fixed text here is not very exciting.
Most likely you want to display dynamic text such as the name of the currently selected track or the current target value, nicely formatted!
You can do that by using placeholders, delimited by double braces.
.Simple text expression
====
`{{target.text_value}}`
====
See xref:further-concepts/target.adoc#target-property[] for a list of properties that you can use in placeholders.
[#dynamic-feedback]
=== Dynamic feedback: Lua script
This feedback type puts you fully in charge about which feedback to send to the source.
It does so by letting you define a Luau script that builds numeric, textual or even arbitrarily structured feedback.
==== General mechanics
ReaLearn executes your script whenever one of the ReaLearn-provided properties used in your script might have changed its value.
The script receives an input and must produce an output.
Script input::
* The input is a function `context.prop` which you can use to query arbitrary properties, e.g. target or mapping properties.
Those properties are the very same properties that you can use in <<text-feedback,textual feedback>>.
+
.How to use `context.prop()`
====
[source,lua]
----
local preset_name = context.prop("target.preset.name")
local param_name = context.prop("target.fx_parameter.name")
----
====
+
* Values returned by this function can be `nil`!
E.g. target-related properties return a `nil` value whenever the mapping or target turns inactive, which is a very common situation.
So it's important to prepare your Luau code for that, otherwise script execution fails and no feedback will be sent.
One way to deal with a `nil` value returned by `context.prop` is to also return `nil` as `value` (see below).
Script output::
* The output that the script is supposed to return is a table which looks as in the following example.
+
.Result table structure
====
[source,lua]
----
return {
feedback_event = {
-- The feedback value <1>
value = "Arbitrary text",
-- An optional color <2>
color = { r = 0, g = 255, b = 0 },
-- An optional background color <3>
background_color = nil,
}
}
----
<1> In this example it's a text value, but it can be anything!
<2> Has the same effect as color in xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[]
<3> Has the same effect as background color in xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[]
====
+
* The most important thing here is `value`.
It can either be ...
** ... a string (ideal for display sources)
** ... a number (ideal for LEDs and motor faders)
** ... `nil` (which means "turn the source off", e.g. turn off the LED, turn down the motorfader, clear the display text)
** ... or anything else (`true`, `false` or an arbitrary table ... at the moment, this is only useful for the xref:sources/midi/midi-script.adoc[] because other sources don't know how to deal with it)
.`global.realearn.time`
====
Displays the number of milliseconds passed since ReaLearn was loaded:
[source,lua]
----
local millis = context.prop("global.realearn.time") or 0
return {
feedback_event = {
value = "" .. millis .. "ms"
},
}
----
====
.Animation
====
Creates an animation to make a long FX name visible on a tiny screen:
[source,lua]
----
function create_left_right_animation(global_millis, max_char_count, frame_length, text)
if text == nil then
return nil
end
if #text > max_char_count then
local frame_count = #text - max_char_count
local frame_index = math.floor(global_millis / frame_length) % (frame_count * 2)
local text_offset
if frame_index < frame_count then
text_offset = frame_index
else
local distance = frame_index - frame_count
text_offset = frame_count - distance
end
return text:sub(text_offset + 1, text_offset + max_char_count)
else
return text
end
end
-- The maximum number of characters we want to display at once
local max_char_count = 10
-- How many milliseconds to remain in one position
local frame_length = 150
local millis = context.prop("global.realearn.time")
local fx_name = context.prop("target.fx.name")
local animation = create_left_right_animation(millis, 10, frame_length, fx_name)
return {
feedback_event = {
value = animation
},
}
----
====
.Structured feedback values
====
Returns a structured feedback value ...
[source,lua]
----
return {
feedback_event = {
value = {
available = context.prop("target.available"),
more_info = {
index = context.prop("target.discrete_value"),
count = context.prop("target.discrete_value_count"),
},
}
},
}
----
+...+ which can then be processed by a xref:sources/midi/midi-script.adoc[]:
[source,lua]
----
return {
address = 0x4bb0,
messages = {
{ 0xb0, 0x4b, y.more_info.index, y.more_info.count }
}
}
----
This example is not realistic, it just shows how you can access the value table returned by the glue section feedback script.
====
You can share code between multiple feedback scripts by using xref:further-concepts/compartment.adoc#compartment-wide-lua-code[], with the following limitations (which hopefully will be lifted over time):
* The shared code is not yet available to the Lua code editor window.
That means writing `require("compartment")` will evaluate to `nil` in the editor.
You might see a corresponding error message when the editor tries to compile your code.
* When ReaLearn queries the script in advance to know which target properties it needs, the shared code is also not available yet.
Currently, you need to make sure that the target properties are queried even if `require("compartment")` evaluates to `nil`.
@@ -0,0 +1,38 @@
= Instance concepts
[[instance-tag]]
== Instance tag
Each instance can have arbitrarily many tags.
Tags are important if you want to dynamically enable or disable instances using the xref:targets/realearn/enable-disable-instances.adoc[].
[[auto-units]]
== Auto units
Each xref:key-concepts.adoc#instance[] optionally supports the automatic addition and configuration of a xref:key-concepts.adoc#unit[] with a user-defined xref:further-concepts/compartment.adoc#main-preset[] if a certain type of controller is connected, and automatic removal if it is disconnected.
The general procedure is:
. Globally define once what controllers you have at your disposal and choose which main preset you want to use for which controller (in the xref:user-interface/settings-dialog.adoc[] of the xref:helgobox::app.adoc[])
. Enable global control for one xref:key-concepts.adoc#instance[] using xref:user-interface/main-panel/menu-bar.adoc#enable-global-control[].
=== Global control
If global control is enabled for an instance, all connected controllers that are configured in the xref:realearn::user-interface/settings-dialog.adoc[ReaLearn settings dialog] will load their corresponding main preset.
You can configure controllers using the xref:helgobox::app/user-interface/title-bar.adoc#title-bar-settings[] button in the window title bar of the xref:helgobox::app.adoc[].
If global control is disabled for an instance, global controllers will be ignored in this instance.
This gives you the freedom to create a custom control experience using ReaLearn.
TIP: It's a good idea to enable global control for a Helgobox instance on the monitoring FX chain.
Such an instance will be around permanently as long as REAPER is running, even if you open and close different projects.
Perfect for project-spanning control scenarios!
=== Overrides
If you decide to use a specific device for something else in a certain project, all you need to do is to set use the device as input and/or output in a project-specific ReaLearn unit!
If you do that, the project-specific instance "wins" over the monitoring FX instance.
You got a project-specific override.
If you close the project, the monitoring FX instance takes over again.
@@ -0,0 +1,523 @@
= Mapping concepts
== Absolute vs. relative control
We can distinguish between two fundamentally different ways of xref:key-concepts.adoc#control[]: _Absolute_ and _relative_ control.
[[absolute-control]]
=== Absolute control
Imagine someone tells you: "Change the volume to -6 dB!" You go ahead and move the fader to -6 dB.
That's absolute control in a nutshell!
Absolute control uses <<absolute-control-value, absolute control values>>.
[TIP]
====
Often, absolute control involves an <<absolute-control-element>>, but it doesn't have to!
ReaLearn can simulate absolute control even with a <<relative-control-element>> (see xref:user-interface/mapping-panel/glue-section.adoc#make-absolute[]).
====
[[relative-control]]
=== Relative control
Imagine someone tells you: "Raise the volume by 2 dB!" You go ahead and move the fader up by 2 dB.
Before it was -6 dB, that means it's -4 dB now.
That's relative control!
Relative control uses <<relative-control-value, relative control values>>.
[TIP]
====
Often, relative control involves a <<relative-control-element>>, but it doesn't have to!
ReaLearn masters multiple ways of turning absolute control into relative one:
* Buttons or keys naturally emit absolute control values.
But using xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[], they can be used for relative control (previous/next style buttons).
* Knobs naturally emit absolute control values.
But using xref:user-interface/mapping-panel/glue-section.adoc#make-relative[] or xref:user-interface/mapping-panel/glue-section.adoc#performance-control[], they can be used for relative control.
====
== Absolute vs. relative control elements
We can distinguish between control elements with regard to what sort of <<control-value>> they emit: In this dimension, we have <<absolute-control-element>> and <<relative-control-element>>.
[[absolute-control-element]]
=== Absolute control element
A xref:key-concepts.adoc#control-element[] is _absolute_ if it emits absolute values.
You can think of an absolute value as a percentage: The value is something between 0% and 100%, where 0% represents the minimum possible value and 100% the maximum.
.Typical absolute control elements
[[fader]] Fader::
A fader is a vertical or horizontal element with a thumb that you can move.
When moving a fader up from bottom to top, it will continuously emit values from 0% to 100%.
[[knob]] Knob::
A knob is a circular element with boundaries on the left and right.
When moving a knob clockwise, it will continuously emit values from 0% (at the left boundary) to 100% (at the right boundary).
[[momentary-button]] Momentary button::
A momentary button is a button that emits 100% when pressed and 0% when released.
ReaLearn can easily use momentary buttons to toggle a target.
See xref:user-interface/mapping-panel/glue-section.adoc#toggle-button-mode[].
[[toggle-button]] Toggle button::
A toggle button is a button that emits 100% when pressed and 0% when pressed again.
+
IMPORTANT: You don't want toggle buttons on the hardware side!
They are much less flexible than momentary buttons!
Momentary buttons can be turned into toggle buttons by ReaLearn, but not vice versa!
If you have to put up with a hardware toggle button, use xref:further-concepts/source.adoc#midi-source-character[] xref:further-concepts/source.adoc#toggle-only-button[].
[[velocity-sensitive-key]] Velocity-sensitive key:: A key emits a value between 0% and 100% when pressed, depending on the velocity with which the key was hit.
When released, it will emit 0%.
[[aftertouch]] Aftertouch:: When pressing the key a bit more into the keybed after it has already been pressed, it will continuously emit increasing values starting at 0%.
When releasing pressure, it will continuously emit decreasing values until reaching 0% again.
[[pitch-wheel]] Pitch wheel:: When moving a pitch wheel up, it will continuously emit increasing values starting at 50%.
When letting it snap back, it will continuously emit decreasing value until reaching 50% again.
When moving it down, it will continuously emit decreasing values, and so on.
[[touch-strip]] Touch strips:: When touching the strip somewhere in the middle, it will emit a value around 50%.
When dragging upward, it will continuously emit increasing values starting from where you touched it first.
[[relative-control-element]]
=== Relative control element
A xref:key-concepts.adoc#control-element[] is _relative_ if it emits relative values.
You can think of a relative value as an _instruction_.
It can be one of the following two instructions:
Please decrease!:: We call such a value a *decrement*.
Please increase!:: We call such a value an *increment*.
.Typical relative control elements
[[rotary-endless-encoder]] Rotary endless encoder::
A rotary endless encoder (or just _encoder_) is a circular, like a knob.
But unlike a knob, it doesn't have boundaries.
When moving a rotary endless encoder clockwise, it will continuously emit increments.
When moving it counter-clockwise, it will continuously emit decrements.
+
IMPORTANT: It happens very often that controllers have rotary endless encoders, but they will act like knobs by default, sending absolute messages.
That is a great waste, and you should change that setting as soon as possible on the hardware side.
[[control-value]]
== Control value
A _control value_ is the signal that travels through a ReaLearn xref:key-concepts.adoc#mapping[] from xref:key-concepts.adoc#source[] to xref:key-concepts.adoc#target[] when it receives an event from an xref:key-concepts.adoc#input-port[].
A control value can be absolute or relative.
[[feedback-value]]
== Feedback value
A _feedback value_ is the signal that travels through a ReaLearn xref:key-concepts.adoc#mapping[] back from xref:key-concepts.adoc#target[] to xref:key-concepts.adoc#source[] when the target changes its value.
A feedback value is always absolute.
== Absolute vs. relative control values
[[absolute-control-value]]
=== Absolute control value
An _absolute_ control value is conceptually a percentage between 0.0% and 100.0%.
Internally, it is represented by a high-precision floating point number between 0.0 and 1.0. E.g. 0.25 is 25%.
[[relative-control-value]]
=== Relative control value
A _relative_ control value is a number of increments or decrements.
Internally, it is represented as a positive or negative integer.
E.g. control value -2 means a decrement of 2.
[[mapping-tag]]
== Mapping tag
Each mapping can have arbitrarily many tags.
Such tags can be used to organize mappings in a way that is much more flexible than groups.
Tags are not just something for people that love to keep things tidy!
They also get meaning in combination with certain ReaLearn targets such as xref:targets/realearn/enable-disable-mappings.adoc[].
[[group]]
== Mapping group
Mapping groups are part of the currently shown compartment and enable you to divide the list of mappings into multiple groups.
Groups can be useful …
* To apply an activation condition to multiple mappings at once.
* To enable/disable control/feedback for multiple mappings at once.
* To keep track of mappings if there are many of them.
You can decide which group is displays using xref:user-interface/main-panel/mapping-group-section.adoc#mapping-group[].
You can move existing mappings between groups by opening the context menu (accessible via right-click on Windows and Linux, control-click on macOS) of the corresponding mapping row and choosing "Move to group".
Groups are saved as part of the project, VST plug-in preset and compartment preset.
[[mapping-activation-state]]
== Mapping activation state
A mapping is considered as *on* or *active* (terms are used interchangeably) only if all following criteria are fulfilled:
. The mapping is complete, that is, both source and target are completely specified
. The mapping is enabled as a whole
. The mapping has control and/or feedback enabled
. The <<mapping-activation-condition>> is fulfilled
. The xref:further-concepts/target.adoc#target-activation-condition[] is fulfilled
. The target is valid
+
====
Example: A track target can be invalid when it's using xref:further-concepts/target.adoc#selected-selector[] but no track is currently selected).
====
In all other cases, mapping is *off* or *inactive*.
In that case, it doesn't have any effect!
(Controller) mappings with xref:further-concepts/target.adoc#virtual-target[] are always considered active as long as the feedback checkbox is ticked.
[[mapping-signal-flow]]
== Mapping signal flow
Here's how ReaLearn processes an incoming control event that matches a mapping source.
1. ReaLearn converts the event coming from the xref:key-concepts.adoc#input-port[] to a <<control-value>>.
2. ReaLearn feeds the <<control-value>> to the mapping's xref:key-concepts.adoc#glue[].
The glue section is responsible for transforming control values before they reach the xref:key-concepts.adoc#target[].
This transformation can change the type of the control value, e.g. from relative to absolute - it depends on the settings in the glue section and the mapping's target.
The glue section can even "eat" control values so that they don't arrive at the target at all.
3. Finally, ReaLearn converts the transformed <<control-value>> into some target instruction (e.g. "set volume to -6.0 dB") and executes it.
Feedback (from target to source) works in a similar fashion but is restricted to absolute control values.
Even if the source is relative (e.g. an encoder), ReaLearn will always emit absolute feedback, because relative feedback doesn't make sense.
[[conditional-activation]]
== Conditional activation
Conditional activation is a powerful feature that allows you to dynamically activate or deactivate a mapping depending on its <<mapping-activation-condition>>.
.Control A when a button is not pressed, control B when it is
====
Here's how you would implement a typical use case.
You want your rotary encoder to control target A when the button is not pressed and control target B when it's pressed.
. Create a mapping for the button
** As "Target", you need to choose ReaLearn itself (Type: xref:targets/fx-parameter/set-value.adoc[], Track: `<This>`, FX: "… VSTi: ReaLearn (Helgoboss)").
As "Parameter", choose an arbitrary ReaLearn parameter, e.g. "Parameter 1".
** As "Mode", choose either "Absolute" (if you want to switch the encoder function just momentarily) or "Toggle" (if you want the button to toggle between the two encoder functions).
. Create a mapping with target A
** Set "Active" to "When modifiers on/off", "Modifier A" to "Parameter 1" and disable the checkbox beside it.
Set "Modifier B" to `<None>`.
** This basically means "Hey, ReaLearn!
Please activate this mapping only if ReaLearn Parameter 1 is *off*!" (remember, we control ReaLearn Parameter 1 using the button).
** At this point, turning your encoder should control target A, but only if you don't press the button!
. Create a mapping with target B
** Just as in step 2, set "Active" to "When modifiers on/off" and "Modifier A" to "Parameter 1". *But*: Now *enable* the checkbox beside it.
Set "Modifier B" to `<None>`.
** This basically means "Hey, ReaLearn!
Please activate this mapping only if ReaLearn Parameter 1 is *on*!"
** At this point, turning your encoder should control target A if you don't press the button and control target B if you press the button.
====
[[mapping-activation-condition]]
== Mapping activation condition
The activation condition of a mapping determines under which circumstances a mapping is active or inactive, based on the value of a xref:further-concepts/compartment.adoc#compartment-parameter[] or based on the state of arbitrary xref:key-concepts.adoc#target[targets].
It is especially practical if your controller has a limited amount of control elements and you want to give control elements several responsibilities.
It lets you easily implement use cases such as:
* "This knob should control the track pan, but only when my sustain pedal is pressed, otherwise it should control track volume!" (modifier use cases)
* "I want to have two buttons for switching between different banks where each bank represents a group of mappings." (bank use cases)
* "I want to control the volume of this track only if it's not muted." (target-state based use cases)
TIP: Since ReaLearn 2.11.0, xref:targets/realearn/enable-disable-mappings.adoc[] provides a slightly less powerful but more straightforward way to implement use cases that were before only achievable with parameter-based conditional activation.
There are 6 different activation modes:
* *Always:* Mapping is always active (the default)
* *When modifiers on/off:* Mapping becomes active only if something is pressed / not pressed
* *When bank selected:* Allows you to step through different groups of mappings (sometimes also called "pages")
* *When EEL met* Let an EEL formula decide (total freedom)
* *When expression met:* Let an expression decide (total freedom)
* *When target value met:* Let the current value of the target of another mapping decide
[NOTE]
====
At this occasion, some words about ReaLearn's own freely assignable FX parameters.
ReaLearn itself isn't just able to control parameters of other FX, it also offers FX parameters itself.
At the moment it offers 200 FX parameters, 100 for the main compartment and 100 for the controller compartment.
You can control them just like parameters in other FX:
- Via automation envelopes,
- via track controls,
- via REAPER's own MIDI/OSC learn
- … and of course via ReaLearn itself.
Initially, they don't do anything at all.
First, you need to give meaning to them by referring to them in activation conditions or `<Dynamic>` selector expressions.
====
=== When modifiers on/off
This mode is comparable to modifier keys on a computer keyboard.
For example, when you press `Ctrl+V`
for pasting text, `Ctrl` is a modifier because it modifies the meaning of the `V` key.
When this modifier is "on" (= pressed), it activates the "paste text" and deactivates the "write the letter V" functionality of the `V` key.
In ReaLearn, the modifier is one of the FX parameters.
It's considered to be "on" if the parameter has a value greater than 0 and "off" if the value is 0.
You can choose up to 2 modifier parameters, "Modifier A" and "Modifier B".
If you select "<None>", the modifier gets disabled (it won't have any effect on activation).
The checkbox to the right of the dropdown lets you decide if the modifier must be "on" for the mapping to become active or "off".
Example: The following setting means that this mapping becomes active _only_ if both "Parameter 1" and "Parameter 2" are "on".
* *Modifier A:* "Parameter 1"
* *Checkbox A:* Checked
* *Modifier B:* "Parameter 2"
* *Checkbox B:* Checked
Now you just have to map 2 controller buttons to "Parameter 1" and "Parameter 2" via ReaLearn (by creating 2 additional mappings - in the same ReaLearn instance or another one, up to you) et voilà, it works.
The beauty of this solution lies in how you can compose different ReaLearn features to obtain exactly the result you want.
For example, the _absolute mode_ of the mapping that controls the modifier parameter decides if the modifier button is momentary (has to be pressed all the time) or toggled (switches between on and off everytime you press it).
You can also be more adventurous and let the modifier on/off state change over time, using REAPER's automation envelopes.
=== When bank selected
This is the correct activation mode if you want control surface "bank-style" mapping.
TIP: For this kind of use cases you should consider the new xref:targets/realearn/enable-disable-mappings.adoc[], which is available since ReaLearn 2.11.0 as an alternative.
It's slightly less powerful than conditional activation but probably easier to use, partly because you can dictate which mappings should be active "from outside", not from the perspective of the mapping itself.
You can tell ReaLearn to only activate your mapping if a certain parameter has a particular value.
The particular value is called "Bank".
Why?
Let's assume you mapped 2 buttons "Previous" and "Next" to increase/decrease the value of the parameter (by using "Incremental button" mode, you will learn how to do that further below).
And you have multiple mappings where each one uses "When bank selected" with the same parameter but a different "Bank".
Then the result is that you can press "Previous" and "Next" and it will switch between different mappings within that parameter.
If you assign the same "Bank" to multiple mappings, it's like putting those mappings into one group which can be activated/deactivated as a whole.
Switching between different programs via "Previous" and "Next" buttons is just one possibility.
Here are some other ones:
* *Browse banks using a rotary encoder:* Just map the rotary encoder to the "Bank" parameter and restrict the target range as desired.
* *Activate each bank with a separate button:* Map each button to the "Bank" parameter (with absolute mode "Normal") and set "Target Min/Max" to a distinct value.
E.g. set button 1 min/max both to 0% and button 2 min/max both to 1%.
Then pressing button 1 will activate bank 0 and pressing button 2 will activate bank 1.
In previous versions of ReaLearn you could use other methods to achieve a similar behavior, but it always involved using multiple ReaLearn instances:
* *By enabling/disabling other ReaLearn instances:* You can use one main ReaLearn instance containing a bunch of mappings with xref:targets/fx/enable-disable.adoc[] in order to enable/disable other ReaLearn FX instances.
Then each of the other ReaLearn instances acts as one mapping bank/group.
* *By switching between presets of another ReaLearn instance:* You can use one main ReaLearn instance containing a mapping with xref:targets/fx/browse-presets.adoc[] in order to browse presets of another ReaLearn FX instance.
Then each preset in the other ReaLearn instance acts as one mapping bank/group.
However, that method is pretty limited and hard to maintain because presets are something global (not saved together with your REAPER project).
With _Conditional activation_ you can do the same (and more) within just one ReaLearn unit.
TIP: If you want to adjust the number of banks and improve bank handling in general, set a discrete value count for the corresponding bank parameter (see xref:further-concepts/compartment.adoc#compartment-parameter[]).
=== When EEL met
This is for experts.
It allows you to write a formula in https://www.cockos.com/EEL2/[EEL2] language that determines if the mapping becomes active or not, based on potentially all parameter values.
This is the most flexible of all parameter-based activation modes.
The other modes can be easily simulated.
The example modifier condition scenario mentioned above written as formula would be:
----
y = p1 > 0 && p2 > 0
----
`y` represents the result.
If `y` is greater than zero, the mapping will become active, otherwise it will become inactive. `p1` to `p100` contain the current parameter values.
Each of them has a value between 0.0 (= 0%) and 1.0 (= 100%).
This activation mode accounts for ReaLearn's philosophy to allow for great flexibility instead of just implementing one particular use case.
If you feel limited by the other activation modes, just use EEL.
TIP: For most activation conditions which need this amount of freedom, the newer activation mode <<expression-based-activation-condition>> is a slightly better choice because it's easier to use and generally performs a bit better.
[#expression-based-activation-condition]
=== When expression met
This is very similar to the previous EEL activation mode.
But instead of EEL, it lets you use the same expression language as used in xref:further-concepts/target.adoc#dynamic-selector[dynamic selectors] to express the activation condition.
The equivalent expression to above EEL example is:
`p[0] > 0 && p[1] > 0`
[#target-based-activation-condition]
=== When target value met
This is different from all the other activation condition types in that it doesn't look at ReaLearn's internal parameter values.
Instead, it looks at the target of another mapping (the so-called "lead mapping") and switches our mapping (the so-called "follow mapping") on or off depending on the target value of the lead mapping.
It works like this:
. Create the lead mapping and give it a target, e.g. xref:targets/track/select-unselect.adoc[].
* This lead mapping doesn't need to have a source.
It can even be completely disabled!
. In the **Mapping** dropdown, pick this newly created mapping.
. In the **Expression** text field to the right, enter `y > 0`.
* This means you want the follow mapping to be active whenever the target value of the lead mapping is greater than 0.0. Or in other words, when it's "switched on".
You can detect an inactive target by using `y == none`.
[[raw-midi-pattern]]
== Raw MIDI pattern
xref:sources/midi/raw-midi-sysex.adoc[] and xref:targets/midi/send-message.adoc[] allow to enter so-called MIDI patterns, an advanced ReaLearn concept.
=== Pattern basics
In its most basic form, the pattern is a sequence of bytes notated as hexadecimal numbers.
This is typical notation, especially for system-exclusive MIDI messages.
.A SysEx pattern
====
----
F0 00 20 6B 7F 42 02 00 10 77 00 F7
----
If you enter this and ReaLearn receives this system-exclusive message from the input, it will fire a 100% value.
If feedback is set up correctly, this message will be sent to the device whenever the target value changes.
====
Remarks:
* You can check if the correct feedback messages are sent to the device by enabling xref:further-concepts/unit.adoc#logging-of-real-feedback-messages[].
* Each byte is written using 2 hexadecimal digits.
* Spaces between the bytes can be omitted.
* You can express all types of MIDI messages using this raw notation (e.g. pitch wheel), not just system-exclusive ones.
If you do this, it will work as expected for the _feedback_ direction.
Please note that it will not work for the _control_ direction at the moment (I don't think this is needed).
* If you want a system-exclusive MIDI message, you _must_ include its start (`F0`) and end status byte (`F7`)!
=== Binary notation
ReaLearn also supports binary notation of a byte.
You need to enclose the binary digits of one byte in brackets.
.Binary notation
====
----
F0 00 20 [0110 1011] 7F 42 02 00 10 77 00 F7
----
This is equivalent to the previous example (`6B` in hexadecimal notation is the same as `0110 1011` in binary notation).
====
Remarks:
* Between the brackets, each digit represents one bit.
The left bit is the most significant one.
* Spaces between the two nibbles (4 bits) can be omitted.
=== Variable patterns (extracting and encoding a value)
For the xref:key-concepts.adoc#feedback[] direction, the examples I've shown you so far aren't real-world examples, because there's no point in sending the same MIDI message to the device over and over again!
If you really would want to send a constant MIDI message to the device, you would be much better off using a xref:user-interface/mapping-panel/advanced-settings-dialog.adoc#mapping-lifecycle-actions[Mapping lifecycle action], which allow you to send raw MIDI messages once when a mapping is initialized, not on every target value change.
But even for the xref:key-concepts.adoc#control[] direction, you might want to react to a whole _range_ of system-exclusive messages, not just a fixed one.
One part of your message might represent a variable value.
You might want to extract it and control the target with it.
Fortunately, ReaLearn offers a uniform way to extract a variable value from the raw MIDI message (control) or encode the current target value into the raw MIDI message (feedback).
Bytes which contain a variable value (or a part of it) _must_ be expressed using binary notation.
.Variable pattern
====
----
F0 00 20 6B 7F 42 02 00 10 77 [0000 dcba] F7
----
The second nibble of the second last byte contains the lowercase letters `dcba`.
This is the portion of the byte that denotes the variable value.
====
Each letter represents one bit of the variable value:
[horizontal]
`a`:: Bit 1 (least significant bit of the variable value)
`b`:: Bit 2
`c`:: Bit 3
`d`:: Bit 4
`m`:: Bit 13
`n`:: Bit 14
`o`:: Bit 15
`p`:: Bit 16 (most significant bit of the variable value)
=== Resolution of variable patterns
The resolution of the variable value always corresponds to the letter in the whole pattern which represents the highest bit number.
In the example above, the resolution is 4 bit because there's no letter greater than `d` in the pattern.
.Another variable pattern
====
In this example, the resolution is 7 bit because `n` is the greatest letter in the whole pattern.
----
F0 00 20 6B 7F 42 02 00 10 [00nm lkji] [hgfe dcba] F7
----
====
Remarks:
* The highest resolution currently supported is 16 bit (= 65536 different values).
* You can put these letter bits anywhere in the pattern (but only within bytes that use binary notation).
=== Byte order
This form of notation is slightly unconventional, but I think it's very flexible because it gives you much control over the resulting MIDI message.
This amount of control seems appropriate considering the many different ways hardware manufacturers used and still use to encode their MIDI data.
When a number is expressed within more than one byte, manufacturers sometimes put the most significant byte first and sometimes the least significant one, there's no rule.
This notation supports both because you decide where the bits end up:
.Most significant byte first
====
----
F0 00 20 6B 7F 42 02 00 10 [ponm lkji] [hgfe dcba] F7
----
====
.Least significant byte first
====
----
F0 00 20 6B 7F 42 02 00 10 [hgfe dcba] [ponm lkji] F7
----
====
=== More examples
."Romeo and Juliet" bits (separated by 2 bytes)
====
----
F0 [1111 000b] [a101 0100] F7
----
====
.Simple on/off value (1 bit only)
====
----
F0 A0 [1111 010a] F7
----
====
.Pitch wheel simulation
====
This behaves like pitch wheel because the pattern describes exactly the way how pitch wheel messages are encoded.
----
E0 [0gfe dcba] [0nml kjih]
----
====
@@ -0,0 +1,318 @@
= Source concepts
== Real vs. virtual sources
We distinguish between _virtual_ and _real_ sources.
[[virtual-source]]
=== Virtual source
A _virtual_ source refers to a xref:further-concepts/compartment.adoc#virtual-control-element[] and can only be used in the xref:key-concepts.adoc#main-compartment[].
Examples: `ch1/fader`
[[real-source]]
=== Real source
A _real_ source refers to a xref:further-concepts/compartment.adoc#real-control-element[].
[[midi-source-character]]
== MIDI source character
MIDI control-change messages serve a very wide spectrum of MIDI control use cases.
Even though some control-change controller numbers have a special purpose according to the MIDI specification (e.g. CC 7 = channel volume), nothing prevents one from using them for totally different purposes.
In practice that happens quite often, especially when using general-purpose controllers.
Also, there's no strict standard whatsoever that specifies how relative values (increments/decrements) shall be emitted and which controller numbers emit them.
Therefore, you explicitly need to tell ReaLearn about it by setting the _source character_.
The good news is: If you use "Learn source", ReaLearn will try to guess the source character for you by looking at the emitted values.
Naturally, the result is not always correct.
The best guessing result can be achieved by turning the knob or encoder quickly and "passionately" into clockwise direction.
Please note that guessing doesn't support encoder type 3.
The possible source characters are:
Range element (knob, fader, etc.)::
A control element that emits continuous absolute values.
Examples: Fader, knob, modulation wheel, pitch bend, ribbon controller.
Would also include a endless rotary encoder which is (maybe unknowingly) configured to transmit absolute values.
Button (momentary)::
A control element that can be pressed and emits absolute values.
It emits a > 0% value when pressing it and optionally a 0% value when releasing it.
Examples: Damper pedal.
Encoder (relative type _x_)::
A control element that emits relative values, usually an endless rotary encoder.
The _x_ specifies _how_ the relative values are sent.
This 1:1 corresponds to the relative modes in REAPER's built-in MIDI learn:
Type 1:::
* 127 = decrement; 0 = none; 1 = increment
* 127 > value > 63 results in higher decrements (64 possible decrement amounts)
* 1 < value +<=+ 63 results in higher increments (63 possible increment amounts)
Type 2:::
* 63 = decrement; 64 = none; 65 = increment
* 63 > value >= 0 results in higher decrements (64 possible decrement amounts)
* 65 < value +<=+ 127 results in higher increments (63 possible increment amounts)
Type 3:::
* 65 = decrement; 0 = none; 1 = increment
* 65 < value +<=+ 127 results in higher decrements (63 possible decrement amounts)
* 1 < value +<=+ 64 results in higher increments (64 possible increment amounts)
[[toggle-only-button,Toggle-only button]] Toggle-only button (avoid!):: A control element that can be pressed and emits absolute values.
ReaLearn will simply emit 100%, no matter what the hardware sends.
+
This is a workaround for controllers that don't have momentary buttons!
You should only use this character if there's absolutely no way to configure this control element as a momentary button.
+
[NOTE]
.Background
====
ReaLearn can make a momentary hardware button work like a full-blown toggle button.
Its toggle mode is inherently more powerful than your controller's built-in toggle mode!).
However, the opposite is not true.
It can't make a toggle hardware button act like a momentary button.
====
+
[CAUTION]
.Combination with xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[]
====
If you use the toggle-only source character in combination with mode xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[], you must leave source max at the (default) theoretical maximum value for that source (e.g. 127 for MIDI CC).
Even if your controller device only sends 0 and 1 and in all other mappings you would enter the controller's concrete (instead of theoretically possible) maximum value.
Otherwise, for this special case, a fixed out-of-range-behavior will set in that will just ignore all button presses.
====
[[midi-source-script]]
== MIDI source script
MIDI source scripts are EEL or Luau scripts to configure the xref:sources/midi/midi-script.adoc[].
=== General mechanics
Each script receives an input and must produce an output.
Script input::
* The main input is the current feedback value, which the script can access as a variable.
Script output::
* The main output that the script is supposed to return is the MIDI message to be sent to the MIDI device.
* Additionally, the script can provide a so-called _feedback address_, which is supposed to uniquely identify the LED, motor fader or display.
+
It's important to provide an address if you want ReaLearn to handle feedback relay correctly, e.g. that it switches off the LED when not in use anymore and doesn't switch it off if another mapping "takes over" the same LED.
By convention, the constant (non-variable) bytes of the MIDI message should be used as address.
The examples below might help to understand.
=== EEL script specifics
Scripts written in EEL work as follows.
Script input::
* EEL scripts can access numeric feedback values only.
The current numeric feedback value is available as variable `y`, a floating point number between 0.0 and 1.0. This is essentially the current normalized target value after being processed by the "Glue" section of the mapping.
Script output::
* In order to provide the output MIDI message, you must assign the raw bytes of that message to subsequent slots of the EEL script's virtual local address space (by indexing via brackets) *and*
set the variable `msg_size` to the number of bytes to be sent.
If you forget the latter step, nothing will be sent because that variable defaults to zero!
* In order to provide the address, simply assign an appropriate number to the `address` variable.
.Creating a 3-byte MIDI message
====
[source,eel]
----
address = 0x4bb0;
msg_size = 3;
0[] = 0xb0;
1[] = 0x4b;
2[] = y * 64;
----
====
=== Luau script specifics
Scripts written in Luau work as follows.
Script input::
* Luau scripts can access numeric, text and dynamic feedback values.
* Here's the list of input variables:
`y`::: The feedback value, either numeric (`type(y) == "number"`) or text (`type(y) == "string")`.
`context.feedback_event.color`::: The color as set in the xref:user-interface/mapping-panel/glue-section.adoc[] section.
Either the default color (`== nil`) or an RGB color (table with properties `r`, `g` and `b`).
`context.feedback_event.background_color`::: The background color.
Script output::
* A Luau script can even generate multiple output messages.
* You need to return a table which contains the following keys:
`address`::: The feedback address.
`messages`::: An array containing all the messages, where each message itself is an array contaning the message bytes.
.Creating a 3-byte MIDI message, assuming that `y` is a numeric normalized value.
====
[source,lua]
----
return {
address = 0x4bb0,
messages = {
{ 0xb0, 0x4b, math.floor(y * 10) }
}
}
----
====
.Creating a MIDI sys-ex message that changes the color of some fictional device LED/display.
====
[source,lua]
----
local color = context.feedback_event.color
if color == nil then
-- This means no specific color is set. Choose whatever you need.
color = { r = 0, g = 0, b = 0 }
end
return {
address = 0x4b,
-- Whatever messages your device needs to set that color.
messages = {
{ 0xf0, 0x02, 0x4b, color.r, color.g, color.b, 0xf7 }
}
}
----
====
.Creating a 3-byte MIDI message, assuming that `y` is a text value.
====
[source,lua]
----
local lookup_table = {
playing = 5,
stopped = 6,
paused = 7,
}
return {
messages = {
{ 0xb0, 0x4b, lookup_table[y] or 0 }
}
}
----
====
[TIP]
====
Please note that this kind of simple mapping from text values to integer numbers doesn't need a script.
You can use the `feedback_value_table` xref:user-interface/mapping-panel/glue-section.adoc[] property instead, which can only be set via API though.
Do a full-text search for `feedback_value_table` in directory `resources/controller-presets` of the link:https://github.com/helgoboss/realearn[ReaLearn source code] to find usage examples.
====
You can share code between multiple MIDI scripts by using xref:further-concepts/compartment.adoc#compartment-wide-lua-code[], with the following limitations (which hopefully will be lifted over time):
* The shared code is not yet available to the Lua code editor window.
That means writing `require("compartment")` will evaluate to `nil` in the editor.
You might see a corresponding error message when the editor tries to compile your code.
[[osc-feedback-arguments-expression]]
== OSC feedback arguments expression
This expression is used to enable for more flexible feedback for the xref:sources/osc.adoc[].
It allows you to define exactly which feedback value is sent at which argument position.
If this field is non-empty, the argument type will be ignored for the xref:key-concepts.adoc#feedback[] direction.
The format of this field is very simple: You enter feedback value property keys separated by spaces.
Each entered property key corresponds to one argument position.
.Custom feedback with 2 arguments
====
If you want ReaLearn to send the current feedback value in text form at argument 1 and the color (see xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[]) as RRGGBB string at argument 2, you would enter:
----
value.string style.color.rrggbb
----
====
The following properties are available:
[cols="m,m,1"]
|===
| Property | Type | Description
|
value.float
|
Float
|
Numeric feedback value interpreted as float
|
value.double
|
Double
|
Numeric feedback value interpreted as double
|
value.bool
|
Bool
|
Numeric feedback interpreted as bool (on/off only)
|
value.string
|
String
|
Numeric or textual feedback value formatted as string
|
style.color.rrggbb
|
String
|
Feedback value color formatted as RRGGBB string
|
style.background_color.rrggbb
|
String
|
Feedback value background color formatted as RRGGBB string
|
style.color
|
Color
|
Feedback value color as native OSC color
|
style.background_color
|
Color
|
Feedback value background color as native OSC color
|
nil
|
Nil
|
Nil value
|
inf
|
Infinity
|
Infinity value
|===
@@ -0,0 +1,539 @@
= Target concepts
== Real vs. virtual targets
We distinguish between _virtual_ and _real_ targets.
[[virtual-target]]
=== Virtual target
A _virtual_ target controls a xref:further-concepts/compartment.adoc#virtual-control-element[] and can only be used in the xref:key-concepts.adoc#controller-compartment[].
Example: `ch1/fader`
It's then picked up by a xref:further-concepts/source.adoc#virtual-source[]] in the xref:key-concepts.adoc#main-compartment[].
[[real-target]]
=== Real target
All others targets are real.
Examples: xref:targets/track/set-volume.adoc[]
[[target-object-selectors]]
== Target object selectors
Many ReaLearn xref:key-concepts.adoc#target[targets] work on some kind of _object_:
* A track
* An FX
* An FX parameter
* A send or receive
All of those objects need to be _addressed_ somehow.
For this purpose, ReaLearn uses so-called _object selectors_.
=== Common object selectors
This section describes commonly available object selectors.
NOTE: The descriptions below are somewhat tailored to track objects.
However, the same concepts can easily be applied to other objects that support these selectors.
[#unit-selector]
==== Unit selector
This selector makes the target work on the current xref:further-concepts/unit.adoc#unit-track[] or current xref:further-concepts/unit.adoc#unit-fx[] of this particular ReaLearn xref:key-concepts.adoc#unit[].
[#particular-selector]
==== Particular selector
Lets you pick a specific object (e.g. track) and refer to it by its unique ID.
This is the default.
Choose this if you want ReaLearn to always control that very particular track even in case you move it somewhere else or rename it.
Please note that this is an extremely <<sticky-selectors,sticky>> selector.
It's
_not possible_ with this setting to create a ReaLearn preset that is reusable among different projects.
Because a track ID is globally unique, even across projects.
That also means it doesn't make sense to use this setting in a ReaLearn xref:key-concepts.adoc#unit[] on the monitoring FX chain.
[#at-position-selector]
==== At position selector
This is the most straightforward selector.
It lets you refer to a track by its position in the track list.
This is great if you want to build a preset that you are going to reuse among multiple projects.
However, this selector has the disadvantage that things fall apart if you reorder, insert or delete tracks.
This is why it's not the default.
Next to the dropdown you will find a text field.
Here you should enter the position as number, starting with number `1`.
[#named-selector]
==== Named selector
Allows you to choose a track depending on its name.
In case there are multiple tracks with the same name, it will always prefer the first one.
This will allow you to use one ReaLearn preset across multiple projects that have similar naming schemes, e.g. as monitoring FX.
In the name field next to the dropdown, you can enter a name.
If you don't want exact matching, you can use wildcards:
[horizontal]
`*`:: for matching zero or arbitrary many characters
`?`:: for matching exactly one arbitrary character.
.Wildcards in named selectors
====
`Violin *` would match `Violin 1` or `Violin 12` but not `12th Violin`.
====
[#dynamic-selector]
==== Dynamic selector
This selector allows you to _calculate_ which object (e.g. track) you want to use.
When you choose this option, a text field will appear next to it.
This lets you enter a mathematical expression whose result should be the object's _index_.
E.g. the first track in the project has index 0, the master track -1. For your convenience, you will find a small text label next to the expression text field that always shows the current result of your formula (clamped to the target value range).
NOTE: Please note that the expression language is _not_ EEL - this is a notable difference to ReaLearn's control/feedback transformation text fields!
The expression language used here just provides very basic mathematical operations like addition (`+/-`), multiplication (`*`) etc. and it also doesn't allow or need any assignment to an output variable.
The dynamic selector is a very powerful tool because you can use some special variables:
[cols="m,1,1,3"]
|===
| Variable | Type | Applicable to | Description
| none | - | All selectors |
Special value that represents a "not set" value. See below for examples.
| p | Array of floating-point numbers | All selectors |
Allows you to access the values of ReaLearn's internal parameters. E.g. you can get the number of the first parameter by writing `p[0]`.
By default, parameter values are normalized floating point values, that means they are decimal numbers between 0.0 and 1.0. This can be changed by customizing the parameter with a specific integer value count (see xref:further-concepts/compartment.adoc#compartment-parameter[]).
| p1 ... p100 | Floating-point numbers | All selectors |
Values of ReaLearn's internal parameters as single variables.
_Deprecated_: Recent ReaLearn versions offer the `p` array instead. Better use that one.
| selected_track_index | Integer >= -1 | Track selectors |
Resolves to the zero-based index of the first currently selected track within the containing project.
If no track is selected, this resolves to `none`. If the master track is selected, `-1`.
| selected_track_tcp_index | Integer >= -1 | Track selectors |
Like `selected_track_index` but counts only tracks that are visible in the track control panel.
| selected_track_mcp_index | Integer >= -1 | Track selectors |
Like `selected_track_index` but counts only tracks that are visible in the mixer control panel.
| selected_track_indexes | Array of integers >= -1 | Track selectors |
Lets you access the indexes of multiple selected tracks.
E.g. if 2 tracks are selected, `selected_track_indexes[0]` gives you the index of the first selected track whereas `selected_track_indexes[1]` gives you the index of the second selected track. `selected_track_indexes[2]` would resolve to `none`.
| this_track_index | Integer >= -1 | Track selectors |
Resolves to the zero-based index of the track on which this ReaLearn instance is located.
| instance_track_index | Integer >= -1 | Track selectors |
Resolves to the zero-based index of the instance track of this ReaLearn instance.
| instance_track_tcp_index | Integer >= -1 | Track selectors |
Like `instance_track_index` but counts only tracks that are visible in the track control panel.
| instance_track_mcp_index | Integer >= -1 | Track selectors |
Like `instance_track_index` but counts only tracks that are visible in the mixer control panel.
| this_fx_index | Integer >= 0 | FX selectors |
Resolves to the zero-based index of this ReaLearn FX instance.
| instance_fx_index | Integer >= 0 | FX selectors |
Resolves to the zero-based index of the instance FX of this ReaLearn instance.
| tcp_fx_indexes | Array of integers >= 0 | FX selectors |
Lets you access the indexes of FXs in a track control panel.
E.g. `tcp_fx_indexes[2]` will resolve to the index of the third FX displayed in the track control panel.
| tcp_fx_parameter_indexes | Array of integers >= 0 | FX parameter selectors |
Lets you access the indexes of FX parameters in a track control panel.
E.g. `selected_fx_parameter_indexes[2]` will resolve to the index of the third FX parameter displayed in the track control panel.
This only makes sense if used in conjunction with `tcp_fx_indexes`.
|===
.Simple example
====
`p1 * 99`
* Will point to track with index 0 (first track) if xref:further-concepts/compartment.adoc#compartment-parameter[] 1 is set to the minimum and to track with index 99 (= track number 100) if it's set to the maximum.
* If you use a formula like that, you should make sure that xref:further-concepts/compartment.adoc#compartment-parameter[] 1 is controlled with a step size that allows for exactly 100 different values.
This conforms to ReaLearn's default step size 0.01 = 1%.
* Since ReaLearn 2.13, this is easier because it adds support for integer parameters:
** Set the xref:user-interface/main-panel/menu-bar.adoc#set-compartment-parameter-value-count[] of the parameter to 100
** You can now treat the parameter in the formula as an integer (just `p1` instead of `p1 * 99`).
** Most importantly, ReaLearn will take care of using the correct step size automatically when setting up a mapping for controlling that parameter.
====
.More complex example
====
`p1 * 3 * 100 + p2 * 99`
This will treat xref:further-concepts/compartment.adoc#compartment-parameter[] 1 as a kind of bank selector that allows you to choose between exactly 4 banks (0, 1, 2, 3) of 100 tracks each.
xref:further-concepts/compartment.adoc#compartment-parameter[] 2 will select the track number within the bank.
You see, this is very flexible.
====
=== Additional object selectors for tracks
==== <This> selector
Track which hosts this ReaLearn instance.
If ReaLearn is on the monitoring FX chain, this resolves to the master track of the current project.
[#selected-selector]
==== <Selected> selector
Currently selected track.
If multiple tracks are selected, refers only to the first one.
==== <All selected> selector
All currently selected tracks.
This makes track targets (not FX target and not send targets) do their job on _all_ selected tracks.
The feedback value always corresponds to the highest value among all selected tracks.
CAUTION: If you select many tracks, things can become quite slow!
==== <Master> selector
Master track of the project which hosts this ReaLearn instance.
* If ReaLearn is on the monitoring FX chain, this resolves to the master track of the current project.
* If you don't have ReaLearn on the monitoring FX chain, but you want to control an FX on the monitoring FX chain, this option is the right choice as well.
Make sure to enable the "Monitoring FX" checkbox.
==== All named selector
Allows you to use wildcards (see <<named-selector>>) to make track targets do their thing on all matching tracks instead of only the first one.
==== At TCP position selector
Like <<at-position-selector>> but just considers tracks that are visible in the track control panel.
==== At MCP position selector
Like <<at-position-selector>> but just considers tracks that are visible in the mixer control panel.
==== Dynamic (TCP) selector
Like <<dynamic-selector>> but the result should be an index counting only tracks visible in the track control panel.
==== Dynamic (MCP) selector
Like <<dynamic-selector>> but the result should be an index counting only tracks visible in the mixer control panel.
==== By ID or name (legacy) selector
This lets you refer to a track by its unique ID and name as fallback.
This was the default behavior for ReaLearn versions up to 1.11.0 and is just kept for compatibility reasons.
IMPORTANT: **This selector is deprecated!** You shouldn't use it anymore.
=== Additional target selectors for FXs
==== <This> selector
Always points to the own ReaLearn FX xref:helgobox:ROOT:key-concepts.adoc#instance[].
Perfect for changing own parameters, e.g. for usage of the conditional activation or <<dynamic-selector>> features (especially important if you want to create reusable presets that make use of these features).
[[fx-focused-selector]]
==== Focused selector
Currently or last focused FX. _Track_ and _Input FX_ settings are ignored.
[#particular-fx-selector]
==== Particular selector
Lets you pick a specific FX in the FX chain.
Renaming the FX or moving it within the FX chain is fine - ReaLearn will still keep controlling exactly this FX.
Please note that this only makes sense if you address the containing track using <<particular-selector>> as well.
[#named-fx-selector]
==== Named selector
Lets you address the FX by its name in the FX chain.
Just as with tracks, you can use wildcards to have a blurry search.
[#all-named-fx-selector]
==== All named selector
Allows you to use wildcards (see <<named-fx-selector>>) to make FX targets do their thing on all matching FX instances instead of only the first one.
==== By ID or position (legacy) selector
This refers to the FX by its unique ID with its position as fallback.
This was the default behavior for ReaLearn versions up to 1.11.0 and is just kept for compatibility reasons.
IMPORTANT: **This selector is deprecated!** You shouldn't use it anymore.
=== Sticky vs. non-sticky selectors
We call object selectors _sticky_ if they refer to a particular object (e.g. a track).
[[sticky-selectors]] Sticky selectors:: `<Master>`, `<This>`, `Particular`
[[non-sticky-selectors]] Non-sticky selectors:: `<Dynamic>`, `<Focused>`, `<Selected>`, `<Unit>`, `<All selected>`, `Named`, `All named`, `At position`, `From Playtime column`
[[target-property]]
== Target property
Targets can expose properties, which you can use for xref:further-concepts/glue.adoc#text-feedback[] or xref:further-concepts/glue.adoc#dynamic-feedback[].
Which properties are available, depends very much on the type of the target type.
There are some properties which are available for (almost) any target (for very target-specific properties, please look up the corresponding target in xref:targets.adoc[]):
.Common target properties
[cols="m,1,3"]
|===
|Name | Type | Description
|
global.realearn.time
|
Decimal
|
Time in milliseconds since ReaLearn has been loaded (the first instance).
|
mapping.name
|
String
|
Name of the mapping. Contains the explicitly assigned mapping name, never an automatically generated one.
|
target.text_value
|
String
|
Short text representing the current target value, including a possible unit.
If the target value can be represented using some kind of name, this name is preferred over a possibly alternative numeric representation. Example: Let's assume the 4th track in our project is called "Guitar" and the mapping target is xref:targets/project/browse-tracks.adoc[]. Then `target.text_value` contains the text _Guitar_, not the text _4_.
This is the default value shown if textual feedback is enabled and the textual feedback
expression is empty.
|
target.available
|
Boolean
|
A boolean value indicating whether the target is currently available or not.
Most targets that are _active_ are also _available_. But some targets can be _active_ and _unavailable_. Example: xref:targets/pot/preview-preset.adoc[] is not _available_ if no preview is available for the preset currently selected in Pot browser. But the target is still considered _active_ in this case!
Usually used together with xref:further-concepts/glue.adoc#dynamic-feedback[], for example in order to display different things on displays depending on the target's availability.
|
target.discrete_value
|
Integer
|
The current target value as zero-based integer. This only works for discrete targets.
|
target.discrete_value_count
|
Integer
|
The number of possible values in the current target. This only works for discrete targets.
|
target.numeric_value
|
Decimal
|
The current target value as a "human-friendly" number without its unit.
The purpose of this placeholder is to allow for more freedom in formatting numerical target values than
when using `target.text_value`. This can be done using xref:further-concepts/glue.adoc#dynamic-feedback[].
|
target.numeric_value.unit
|
String
|
Contains the unit of `target.numeric_value` (e.g. _dB_).
|
target.normalized_value
|
Decimal
|
The current target value as normalized number, that is, a value between 0.0 and 1.0 (the so-called unit interval). You can think of this number as a percentage, and indeed, it's currently always formatted as percentage.
This value is available for most targets and good if you need a totally uniform and predictable representation of the target value that doesn't differ between target types.
By default, this number is formatted as percentage _without_ the percent sign. Future versions of ReaLearn might offer user-defined
formatting. This will also be the preferred form to format on/off states in a
custom way (where 0% represents _off_).
|
target.type.name
|
String
|
Short name representing the type of the mapping target.
|
target.type.long_name
|
String
|
Long name representing the type of the mapping target.
|
target.track.index
|
Integer
|
Zero-based index of the first resolved target track (if supported).
|
target.track.name
|
String
|
Name of the first resolved target track (if supported).
|
target.track.color
|
Color
|
Custom color of the first resolved target track (if supported).
|
target.fx.index
|
Integer
|
Zero-based index of the first resolved target FX (if supported).
|
target.fx.name
|
String
|
Name of the first resolved target FX (if supported).
|
target.route.index
|
Integer
|
Zero-based index of the first resolved target send/receive/output (if supported).
|
target.route.name
|
String
|
Name of the first resolved target send/receive/output (if supported).
|===
[[target-value-polling]]
== Target value polling
Target value polling makes ReaLearn query the current value of a target every few milliseconds as part of the main application loop in order to send up-to-date feedback to your controller at all times.
IMPORTANT: Target value polling is not necessary for most targets because usually ReaLearn takes advantage of REAPER's internal notification system to get notified about target value changes (which is good for performance).
For the few targets for which it is, this option is enabled by default in order to give you the best feedback experience out-of-the-box.
Remarks:
* For most targets that support polling, if you disable polling, automatic feedback for that target will simply stop working.
This means you will not receive up-to-date feedback anymore whenever you change the target value within REAPER itself (not using ReaLearn).
* The xref:targets/fx-parameter/set-value.adoc[] is an exception.
Automatic feedback will still work, even without _Poll for feedback_ enabled.
But in the following corner cases it might not:
** If the FX is on the monitoring FX chain.
** If you change a preset from within the FX GUI.
[[target-activation-condition]]
== Target activation condition
xref:key-concepts.adoc#target[Targets] can have activation conditions as well.
They are very specific to the type of the target.
.Typical target conditions
====
* xref:user-interface/mapping-panel/target-section.adoc#track-must-be-selected[]
* xref:user-interface/mapping-panel/target-section.adoc#fx-must-have-focus[]
====
[[continuous-vs-discrete-value-range]]
== Continuous vs. discrete value range
ReaLearn xref:key-concepts.adoc#target[targets] can have a _continuous_ or _discrete_ value range.
[[continuous-value-range]]
=== Continuous value range
A _continuous_ value range is a range of arbitrary floating point numbers between 0.0 and 1.0. You can also think of them as _percentages_ between 0.0% and 100.0%.
Continuous value ranges don't have steps.
.Some targets with a continuous value range.
====
* xref:targets/track/set-volume.adoc[]
* xref:targets/project/set-tempo.adoc[]
====
[[discrete-value-range]]
=== Discrete value range
A _discrete_ value range is a range of integers, e.g. 0 to 9. That would be 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. That's it!
No other values are possible.
Discrete value ranges have steps.
.Some targets with a discrete value range.
====
* xref:targets/fx/browse-presets.adoc[]
* xref:targets/project/browse-tracks.adoc[]
====
[[group-properties]]
== Group properties
A group doesn't just have a name.
It has a few properties that are also available for mappings and thus affect all mappings in that group:
Tags::
Tags defined in the group will be merged with the tags in each mapping.
Control/feedback-enabled::
Lets you switch off control and/or feedback off for all mappings in that group.
Activation condition::
The activation condition that you provide here is combined with the one that you provide in the mapping.
Only if both, the group activation conditions and the mapping activation condition are satisfied, the corresponding mapping will be active.
Read more about
xref:further-concepts/mapping.adoc#conditional-activation[conditional activation] in the section about the xref:user-interface/mapping-panel.adoc[].
@@ -0,0 +1,187 @@
= Unit concepts
[[letting-through-events]]
== Letting through MIDI events
ReaLearn by default "eats" incoming MIDI events for which there's at least one active mapping with that source.
In other words, it doesn't forward MIDI events which are used to control a target parameter.
However, unmatched MIDI events are forwarded!
You can change this using xref:user-interface/main-panel/let-through-section.adoc[].
The exact behavior differs depending on what you choose as xref:user-interface/main-panel/input-output-section.adoc#input[]:
* If input is set to xref:user-interface/main-panel/input-output-section.adoc#fx-input[]
** MIDI events arrive from ReaLearn's FX input.
If they get forwarded, they get forwarded to the FX output, usually to the plug-in which is located right below ReaLearn FX.
The default setting often makes much sense here, especially if you put ReaLearn right above another instrument plug-in.
* If input is set to a MIDI hardware device
** MIDI events arrive directly from the MIDI hardware device.
If they get forwarded, they get forwarded to REAPER's tracks as they would usually do without ReaLearn.
If they don't get forwarded, it means they get filtered and will never make it to the tracks.
ReaLearn completely eats them, globally!
That means, ReaLearn can act as global MIDI filter.
** Please note, with input set to a real MIDI device, MIDI events coming from _FX input_ are _always_ forwarded to the FX output.
** Also, MIDI events captured from a real MIDI device input are *never* forwarded to ReaLearn's FX output.
+
TIP: This global MIDI filter feature is only available in REAPER v6.36+.
* The checkboxes don't have any effect on computer keyboard input or OSC.
Keys are always passed through when doing text entry and never passed through if a mapping matches.
[[auto-load]]
== Auto-load
If you activate xref:user-interface/main-panel/preset-section.adoc#auto-load-based-on-unit-fx[], ReaLearn will start to observe the <<unit-fx>> of this ReaLearn unit and keep loading xref:further-concepts/compartment.adoc#main-preset[main presets] according to which <<fx-to-preset-link, FX-to-preset links>> you have defined.
By default, the unit FX is set to `<Focused>`, which means, it will reflect whatever FX is currently focused.
Whenever the unit FX changes, it will check if you have linked a compartment preset to it and will automatically load it.
Whenever the unit FX switches to an unlinked FX or the FX loses focus, ReaLearn falls back to the mapping list or preset that was active before activating auto-load.
Of course this makes sense only if you actually have linked some presets.
Section <<unit-fx-to-preset-link>> describes how to do that.
[[fx-to-preset-link]]
== FX-to-preset link
A link between a FX and a xref:further-concepts/compartment.adoc#main-preset[].
Used in <<auto-load>>.
[[unit-fx-to-preset-link]]
=== Unit FX-to-preset link
A link saved as part of a xref:key-concepts.adoc#unit[].
[[global-fx-to-preset-link]]
=== Global FX-to-preset link
This is like a <<unit-fx-to-preset-link>> but the link is saved globally.
This is useful if you have only one controller or if you have x controllers (= and therefore x ReaLearn units) and want both of them to always auto-load the same preset if the unit FX points to the same plug-in.
* All links will be saved _globally_, not just within this project!
* Location: REAPER resource directory (menu:Options[Show REAPER resource path in explorer/finder]) at `Data/helgoboss/realearn/auto-load-configs/fx.json`.
[[unit-key]]
== Unit key
Each ReaLearn unit has a key that's used to address this particular ReaLearn unit when using the <<projection>> feature.
By default, the unit key is a random cryptic string which ensures that every unit is uniquely addressable.
The result is that scanning the QR code of this ReaLearn unit will let your mobile device connect for sure with this unique unit, not with another one - remember, you can use many units of ReaLearn in parallel.
This is usually what you want.
But a side effect is that with every new ReaLearn unit that you create, you first have to point your mobile device to it in order to see its
<<projection>> (by scanning the QR code).
Let's assume you have in many of your projects exactly one ReaLearn unit that lets your favorite MIDI controller control track volumes.
By customizing the unit key, you can tell your mobile device that it should always show the <<projection>> of this very ReaLearn unit - no matter in which REAPER project you are and even if they control the volumes of totally different tracks.
You can achieve this by setting the unit key of each volume-controlling ReaLearn unit to exactly the same value, in each project, using xref:user-interface/main-panel/bottom-section.adoc#set-unit-data[].
Ideally it's a descriptive name without spaces, such as "track-volumes".
You have to do the pairing only once et voilà, you have a dedicated device for monitoring your volume control ReaLearn units in each project.
[CAUTION]
====
Make sure to not have more than one ReaLearn unit with the same unit key active at the same time because then it's not clear to which your mobile device will connect!
====
*At the moment, the unit key is part of the ReaLearn preset!* That means, opening a preset, copying/cutting a ReaLearn FX, importing from clipboard - all of that will overwrite the unit key.
This might change in future in favor of a more nuanced approach!
[#unit-track]
== Unit track
The second line of the bottom panel shows the current track chosen as **Unit track** for this unit of ReaLearn.
This can be something like "Track 3" or "The currently selected track".
Mappings in this ReaLearn unit can refer to this track by choosing the track selector xref:further-concepts/target.adoc#unit-selector[].
The unit track can be changed via xref:targets/track/track.adoc[].
[#unit-fx]
== Unit FX
The second line of the bottom panel also shows the current FX chosen as **Unit FX** for this unit of ReaLearn.
This can be something like "FX 5 on track 3" or "The currently focused track".
Mappings in this ReaLearn unit can refer to this FX by choosing the FX selector xref:further-concepts/target.adoc#unit-selector[].
The unit FX can be changed via xref:targets/fx/fx.adoc[].
[[unit-tag]]
== Unit tag
Each unit can have arbitrarily many tags.
Tags are important if you want to dynamically enable or disable units using the xref:targets/realearn/enable-disable-units.adoc[].
[[projection]]
== Projection
Projection is a quite unique feature that allows you to project a schematic representation of your currently active controller to a mobile device (e.g. a tablet computer).
You can put this device close to your controller in order to see immediately which control element is mapped to which parameter.
This is an attempt to solve an inherent problem with generic controllers: That it's easy to forget which control element is mapped to which target parameter.
See xref:user-interface/projection.adoc[].
== Logging
Logging can be enabled or disabled via xref:user-interface/main-panel/menu-bar.adoc#logging[].
[[logging-of-real-control-messages]]
=== Logging of real control messages
Each log entry contains the following information:
* Timestamp in seconds
* Helgobox xref:helgobox:ROOT:key-concepts.adoc#instance-id[]
* Message purpose
** *Real control:* A message used for controlling targets.
** *Real learn:* A message used for learning a source.
* Actual message (MIDI messages will be shown as hexadecimal byte sequence, short MIDI messages also as decimal byte sequence and decoded)
* Match result
** *unmatched:* The message didn't match any mappings.
** *matched:* The message matched at least one of the mappings.
** *consumed:* Only for short MIDI messages.
This short message is part of a (N)RPN or 14-bit CC message and there's at least one active mapping that has a (N)RPN or 14-bit CC source.
That means it will not be processed.
The complete (N)RPN or 14-bit CC message will be.
[[logging-of-real-feedback-messages]]
=== Logging of real feedback messages
The log entries look similar to the ones described above, with the following notable differences.
* Message purpose
** *Feedback output:* A message sent to your controller as response to target value changes.
** *Lifecycle output:* A message sent to your controller as response to mapping activation/deactivation (see xref:user-interface/mapping-panel/advanced-settings-dialog.adoc#mapping-lifecycle-actions[Mapping lifecycle actions]).
** *Target output:* A message sent because of either the xref:targets/midi/send-message.adoc[] or xref:targets/osc/send-message.adoc[].
[[superior-units]]
== Superior units
When a unit is made superior via menu entry xref:user-interface/main-panel/menu-bar.adoc#make-unit-superior[], this unit is allowed to suspend other units which share the same input and/or output device (hardware devices only, not FX input or output!).
[TIP]
====
Making units superior is **rarely needed**!
This option was initially introduced in order to add more flexibility to the <<auto-load>> feature.
The idea was to let a controller _fall back_ to some default behavior if the currently focused FX is closed.
Multiple instances were necessary to make this work with one of them (the auto-load instance) being superior.
However, since ReaLearn 2.14.0, falling back to initial mappings when the FX loses focus in auto-load mode became much easier and doesn't require multiple units anymore!
Your initial mappings or initial preset will be memorized and reloaded once the FX loses focus.
See <<auto-load>> for more information.
====
Behavior:
* By default, ReaLearn units are not superior, just normal.
This is most of the time okay, even if you have multiple units that share the same input and output ... as long as you don't have any conflicting mappings active at the same time.
* For example, if 2 units use the same input or output device, and they use different control elements, they can peacefully coexist.
And even if they share a control element for the _control direction_, they are still fine with it.
The same control element will control 2 mappings, why not!
* Things start to get hairy as soon as 2 units want to send _feedback_ to the same control elements at the same time.
You should avoid this.
You should not even do this within one ReaLearn unit.
This can't work.
* Sometimes you want one unit to suspend/cover/cancel/mute another one!
You can do this by making this unit _superior_.
Then, whenever this unit has at least one active mapping, all non-superior units with the same control and/or feedback device will be disabled for control and/or feedback.
* You can have multiple superior units.
Make sure they get along with each other :)
@@ -0,0 +1,3 @@
= Glue signal flow
The diagrams in this section illustrate how signals travel through the xref:key-concepts.adoc#glue[] section of a mapping.
@@ -0,0 +1,59 @@
= Control direction
The diagrams in this section illustrate how control values travel through the xref:key-concepts.adoc#glue[] section of a mapping, from source to target.
== Absolute control values
The following diagrams apply whenever the source emits xref:further-concepts/mapping.adoc#absolute-control-value[absolute] control values.
=== Absolute mode "Normal"
See xref:user-interface/mapping-panel/glue-section.adoc#absolute-mode-normal[].
image::realearn/diagrams/control-flow/target/control-flow-absolute-normal.svg[]
=== Absolute mode "Toggle button"
See xref:user-interface/mapping-panel/glue-section.adoc#toggle-button-mode[].
image::realearn/diagrams/control-flow/target/control-flow-absolute-toggle.svg[]
=== Absolute mode "Incremental button"
See xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[].
include::partial$under-construction.adoc[]
image::realearn/diagrams/control-flow/target/control-flow-absolute-incremental.svg[]
=== Absolute mode "Performance control"
See xref:user-interface/mapping-panel/glue-section.adoc#performance-control[].
include::partial$under-construction.adoc[]
image::realearn/diagrams/control-flow/target/control-flow-absolute-performance.svg[]
=== Absolute mode "Make relative"
See xref:user-interface/mapping-panel/glue-section.adoc#make-relative[].
include::partial$under-construction.adoc[]
image::realearn/diagrams/control-flow/target/control-flow-absolute-make-relative.svg[]
== Relative control values
The following diagrams apply whenever the source emits xref:further-concepts/mapping.adoc#relative-control-value[relative] control values.
=== "Make absolute" disabled
image::realearn/diagrams/control-flow/target/control-flow-relative-normal.svg[]
=== "Make absolute" enabled
See xref:user-interface/mapping-panel/glue-section.adoc#make-absolute[].
include::partial$under-construction.adoc[]
image::realearn/diagrams/control-flow/target/control-flow-relative-make-absolute.svg[]
@@ -0,0 +1,5 @@
= Feedback direction
The diagrams in this section illustrate how feedback values travel through the xref:key-concepts.adoc#glue[] section of a mapping, from target to source.
include::partial$under-construction.adoc[]
@@ -0,0 +1,3 @@
= Installation
See xref:helgobox::installation.adoc[installation instructions for Helgobox], the plug-in that contains ReaLearn.
@@ -0,0 +1,24 @@
= Introduction
include::helgobox::partial$intro-header.adoc[]
|===
|Last update of text: |`2026-01-28 (v2.18.3-pre.1)`
|Last update of screenshots: |`2025-03-15 (v2.18.0)`
|===
link:https://www.helgoboss.org/projects/realearn[ReaLearn] is a versatile controller integration tool for link:https://www.reaper.fm[REAPER].
It is part of the link:https://www.helgoboss.org/projects/helgobox[Helgobox] plug-in.
This reference provides a detailed description of ReaLearn's user interface, concepts and functionalities.
Use it whenever you need an in-depth exploration of a specific feature or functionality in ReaLearn.
[IMPORTANT]
====
**If you are a beginner, please use the link:https://github.com/helgoboss/helgobox/wiki/ReaLearn-Home[ReaLearn Wiki] instead!**
This reference is targeted at users who are already familiar with the ReaLearn basics and want to look up specific information.
The Wiki is perfect if you are just starting off.
It guides you through the very basics and contains links to easily digestible video tutorials.
====
@@ -0,0 +1,169 @@
= Key concepts
This section offers brief descriptions of ReaLearn's key concepts.
A solid understanding of these concepts is essential for effectively using ReaLearn, regardless of which features you plan to utilize.
[[control]]
== Control
In ReaLearn, the term _control_ typically refers to the process of triggering or adjusting something in REAPER, such as executing an action or modifying an FX parameter.
[[feedback]]
== Feedback
In ReaLearn, the term _feedback_ refers to controlling LEDs, motorized faders, or displays on your device in response to events in REAPER, such as a track volume change.
== Controller
Most of the time, when talking about _controllers_ in the documentation, we are talking about controllers in the _general_ sense.
[[controller,Controller]]
=== Controller in the general sense
A _controller_ in the general sense is the device you use to control REAPER.
It is usually a hardware device, such as a MIDI keyboard or control surface, but it can also be software, like an OSC app.
Controllers are normally not specifically managed within ReaLearn, because you just need to set an <<input-port>> and and <<output-port>>, and that's all ReaLearn needs to know. An exception are <<managed-controller,managed controllers>>.
[[managed-controller]]
=== Managed controller
Only recently, ReaLearn introduced the concept of xref:further-concepts/instance.adoc#auto-units[], in which controllers can actually be managed in a xref:user-interface/settings-dialog.adoc#controllers[list]. ReaLearn then automatically creates <<unit,units>> depending on which of these controllers are connected. Such controllers are called _managed controllers_.
[[control-element]]
== Control element
A control element is any component you can use to control something.
In most cases, it's a physical part of your hardware <<controller>>.
Examples include knobs, encoders, faders, buttons, keys, pads, pitch wheels and acceleration sensors.
[[control-element-interaction]]
== Control element interaction
A control element _interaction_ is the act of using a <<control-element>>.
Typically, each control element has one primary interaction type:
* _Turning_ a knob
* _Pressing/releasing_ a button
* _Moving_ a fader
However, some control elements allow multiple interactions:
* _Moving_ a touch-sensitive fader
* _Touching/releasing_ a touch-sensitive fader
In this reference, <<control-element>> often implies <<control-element-interaction>>, as they are usually synonymous.
[[feedback-element]]
== Feedback element
A _feedback element_ is any part of your <<controller>> that can indicate or display information.
Examples includes LEDs, motor faders and displays.
Very frequently, control elements and feedback elements are combined:
- Button with an integrated LED
- Encoder with an LED ring
- Motorized fader
For this reason, this reference sometimes uses <<control-element>> to refer to both the <<control-element>> and the corresponding <<feedback-element>>.
[[input-port]]
== Input port
To enable control, ReaLearn needs to respond to events from your <<controller>>.
It achieves this by listening to events from an _input port_, which can be a MIDI device port, an OSC port or your computer keyboard.
You can change the input port using the xref:user-interface/main-panel/input-output-section.adoc#input[].
[[output-port]]
== Output port
To send <<feedback>> back to your <<controller>>, ReaLearn transmits instructions through an _output port_, which can be a MIDI device port or an OSC port.
You can change the output port using the xref:user-interface/main-panel/input-output-section.adoc#output[].
[[instance]]
== ReaLearn Instance
The terms _ReaLearn Instance_ and xref:helgobox:ROOT:key-concepts.adoc#instance[Helgobox instance] are interchangeable — they both refer to the same concept.
[[unit]]
== Unit
Each ReaLearn <<instance>> contains at least one _unit_, known as the _main unit_, but it can also contain an arbitrary number of additional units.
Units function like "mini instances" within a single ReaLearn <<instance>>, allowing that instance to manage multiple controllers simultaneously.
Each unit has its own <<input-port>>, <<output-port>>, <<controller-compartment>>, <<main-compartment>>, xref:further-concepts/compartment.adoc#controller-preset[], xref:further-concepts/compartment.adoc#main-preset[], and more.
[[compartment]]
== Compartment
Each unit consists of two compartments.
A compartment is a self-contained list of mappings that can be saved as an independent preset.
The two compartments in each unit are:
[[main-compartment]] Main compartment::
This is the primary compartment.
Its purpose is to define what the controller device should do, e.g., allowing a fader to control track volume or displaying the name of an FX parameter on a hardware display.
+
We refer to the mappings in this compartment as [[main-mapping,Main mapping]] _main mappings_ and to the presets as _main presets_.
[[controller-compartment]] Controller compartment::
The controller compartment is optional and serves two main purposes: Describing all control elements of the controller, assigning them descriptive names and enabling xref:further-concepts/compartment.adoc#virtual-control[].
+
We refer to the mappings in this compartment as [[controller-mapping,Controller mapping]] _controller mappings_ and to the presets as _controller presets_.
[#mapping]
== Mapping
Each compartment contains a list of mappings.
A _mapping_ connects a <<control-element>> and/or <<feedback-element>> on your <<controller>> with an action or parameter in REAPER.
Each mapping consists of <<source>>, <<glue>> and <<target>>.
[[source]]
== Source
A _source_ is the part of a <<mapping>> that typically describes a <<control-element>> and/or <<feedback-element>> on the <<controller>>.
More generally, it can be anything that emits xref:further-concepts/mapping.adoc#control-value[control values].
Examples: MIDI source, OSC source
[[glue]]
== Glue
A _glue_ is the part of a <<mapping>> that sits between <<source>> and <<target>>, filtering and transforming <<control>> and <<feedback>> streams.
This is a very powerful feature of ReaLearn, as can be seen by looking at the xref:glue-signal-flow.adoc[].
[[target]]
== Target
A _target_ is the part of the <<mapping>> that describes the thing which should be controlled and/or provides feedback data.
Examples: Track volume, cursor position, REAPER action
[[learning]]
== Learning
This section wouldn't be complete without mentioning the concept that inspired ReaLearn's name: _Learning_.
Learning simply means that you press a btn:[Learn] button instead of performing manual setup, saving you valuable time!
In ReaLearn, you can learn <<source, sources>> and <<target, targets>>.
[[learn-source]]
=== Learn source
Sources can be learned by pressing the xref:user-interface/main-panel/mapping-row.adoc#learn-source[] and then touching a <<control-element>> on your controller.
This saves you from the tedious job of setting up MIDI or OSC sources manually.
[[learn-target]]
=== Learn target
Targets can be learned by pressing the xref:user-interface/main-panel/mapping-row.adoc#learn-target[] and then invoking a <<target>> within REAPER.
This saves you from choosing xref:further-concepts/target.adoc#target-object-selectors[] and other stuff manually.
@@ -0,0 +1,26 @@
= REAPER actions
ReaLearn provides the following REAPER actions in addition to the xref:helgobox::reaper-actions.adoc[general actions].
Helgobox/ReaLearn: Find first mapping by source:: This action will ask you to touch some control element.
As soon as you touch a control element which is mapped, it will open the mapping panel for the corresponding mapping.
It will search within all ReaLearn instances/units loaded in your current project as well as the ones on the monitoring FX chain.
Helgobox/ReaLearn: Find first mapping by target:: This action is similar to _Find first mapping by source_.
It asks you to touch some (learnable) REAPER parameter.
As soon as you touch one that is mapped, it will open its mapping panel.
Helgobox/ReaLearn: Learn single mapping (reassigning source):: Asks you to touch a control element and target and adds a new mapping in the first ReaLearn unit that it encounters.
It prefers units in the current project over monitoring FX.
It automatically chooses the unit with the correct MIDI/OSC input.
If there's a unit which already has that source assigned, it will be reassigned to the new target that you touched.
Helgobox/ReaLearn: Learn single mapping (reassigning source) and open it:: Like _Learn single mapping_ but additionally opens the mapping panel after having learned the mapping.
This is great for subsequent fine-tuning.
Helgobox/ReaLearn: Learn source for last touched target (reassigning target):: This behaves similar to REAPER's built-in MIDI learn in that it always relates to the target that has been touched last.
[[send-feedback-for-all-instances]] Helgobox/ReaLearn: Send feedback for all instances:: Makes each ReaLearn instance/unit in all project tabs send feedback for all mappings.
That shouldn't be necessary most of the time because ReaLearn usually sends feedback automatically, but there are situations when it might come in handy.
[[auto-detect-controllers-with-logging]] Helgobox/ReaLearn: Auto-detect controllers (with logging):: Looks at each currently connected MIDI device and automatically creates a xref:key-concepts.adoc#managed-controller[] if the device is known and a suitable preset exists. Also logs information that helps troubleshoot controller detection issues.
@@ -0,0 +1,3 @@
= Sources
ReaLearn supports the following xref:key-concepts.adoc#source[] types.
@@ -0,0 +1,22 @@
= Source "Keyboard"
This source reacts to pressing or releasing a key on your computer keyboard.
It emits a value of 100% when the key is pressed and 0% when released.
In order to set the key, simply click the btn:[Learn] button and press the key of your choice.
In addition to the key label, ReaLearn might show some warnings regarding the portability of your keystroke.
This helps you to avoid keyboard shortcuts that don't reliably work cross-platform (in other operating systems) or on other keyboard layouts.
You can ignore portability warnings if you use just this operating system and don't plan to share your keyboard presets with other users.
[TIP]
====
* This only works if xref:user-interface/main-panel/input-output-section.adoc#computer-keyboard[] is enabled in the xref:user-interface/main-panel/input-output-section.adoc#input[].
* If you hold a key, it will not keep firing.
This is by design!
Use xref:user-interface/mapping-panel/glue-section.adoc#fire-after-timeout-keep-firing[] instead.
* Key combinations are not supported.
This is by design!
Use xref:further-concepts/mapping.adoc#conditional-activation[] instead.
* Matching keys are automatically consumed by ReaLearn, so that they will not reach the rest of REAPER (unless a text field is focused). Check out xref:user-interface/main-panel/menu-bar.adoc#match-even-inactive-mappings[] to fine-tune matching behavior.
====
@@ -0,0 +1,9 @@
= MIDI sources
Most types in the MIDI category have the following UI elements in common.
Channel menu::
Optionally restricts this source to messages from a certain MIDI channel.
Only available for sources that emit MIDI channel messages.
The remaining UI elements in this section depend on the chosen source type.
@@ -0,0 +1,17 @@
= Source "CC value"
This source reacts to incoming MIDI control-change messages.
== CC menu
Optionally restricts this source to messages with a certain MIDI control-change controller number.
== Character menu
See xref:further-concepts/source.adoc#midi-source-character[].
== 14-bit values checkbox
If unchecked, this source reacts to MIDI control-change messages with 7-bit resolution (usually the case).
If checked, it reacts to MIDI control-change messages with 14-bit resolution.
This is not so common but sometimes used by controllers with high-precision faders.
@@ -0,0 +1,4 @@
= Source "Channel after touch"
This source reacts to incoming MIDI channel-pressure messages.
The higher the pressure, the higher the absolute control value.
@@ -0,0 +1,33 @@
= Source "Display"
This is a feedback-only source used to display text on MIDI-controllable hardware displays (LCDs, OLED displays, 7-segment displays, ...).
== Protocol menu
Lets you choose the display protocol, which tells ReaLearn how it should communicate with the hardware display and which options it supports.
Mackie LCD:: Use this for MCU-compatible LCDs.
Depending on your particular control surface, there can be up to 8 LCDs, each of which has up to 2 lines.
Mackie XT LCD:: Use this to control the displays of MCU XT devices (= control surface extenders, which provide additional faders and displays).
X-Touch Mackie LCD:: Like _Mackie LCD_ but also supports colors on certain X-Touch devices.
X-Touch Mackie XT LCD:: Like _Mackie LCD XT_ but also supports colors on certain X-Touch devices.
Mackie 7-segment display:: Use this for MCU-compatible 7-segment displays (you know, the ones which only show digits).
There's usually one small assignment display and a larger one for showing the time code.
SiniCon E24:: Use this with the https://www.sinicon.io/[SiniCon E24 controller].
Launchpad Pro - Scrolling text:: Displays looped scrolling text on a Novation Launchpad Pro.
Only seems to work if you set _Output_ to `MIDIOUT2 (Launchpad Pro)`.
Studiologic SL Keyboard display:: Displays text on the display of Studiologic SL keyboards (tested with SL88).
== Display menu
Choose the particular display or display portion to which you want to send text.
== Line menu
Choose the line number.
CAUTION: For controllers with multiple displays and lines, ReaLearn allows you to spread your text over all available displays and lines.
This is great if you need to display a lot of text but one display doesn't provide enough space.
But be aware: xref:further-concepts/general.adoc#feedback-relay[] doesn't work nicely anymore if you make use of this feature.
If you want to know how to define which text shall be sent to the displays, please see xref:further-concepts/glue.adoc#text-feedback[textual feedback] in the xref:user-interface/mapping-panel/glue-section.adoc[].
@@ -0,0 +1,14 @@
= Source "MIDI clock tempo"
This source reacts to incoming MIDI clock (MTC) tempo messages.
These are metronome-beat-like messages which can be regularly transmitted by some DAWs and MIDI devices.
The frequency with which this message is sent dictates the tempo.
The higher the calculated tempo, the higher the absolute control value.
A tempo of 1 bpm will be translated to a control value of 0%, a tempo of 960 bpm to 100% (this corresponds to REAPER's supported tempo range).
This source can be used in combination with the xref:targets/project/set-tempo.adoc[] to obtain a "poor man's" tempo synchronization.
Be aware: MIDI clock naturally suffers from certain inaccuracies and latencies - that's an issue inherent to the nature of the MIDI clock protocol itself.
E.g. it's not really suitable if you need super accurate and instant tempo synchronization.
Additionally, ReaLearn's algorithm for calculating the tempo could probably be improved (that's why this source is marked as experimental).
@@ -0,0 +1,8 @@
= Source "MIDI clock transport"
This source reacts to incoming MIDI clock (MTC) transport messages.
These are simple start, continue and stop messages which can be sent by some DAWs and MIDI devices.
== Message menu
The specific transport message to which this source should react.
@@ -0,0 +1,23 @@
= Source "MIDI Script"
[[source-midi-script]]
This source is feedback-only and exists for enabling more complex feedback use cases such as controlling LCDs that are not yet supported by the xref:sources/midi/display.adoc[].
It lets you write an EEL or Luau script that will be executed whenever ReaLearn "feels" like it needs to send some feedback to the MIDI device.
== Kind menu
Whether to use the EEL or Luau language.
== Script field
The script.
Is disabled if the script contains more than one line.
See xref:further-concepts/source.adoc#midi-source-script[] for details.
== More button (…)
Opens the script in a separate window (for multi-line scripts).
TIP: Prefer the xref:sources/midi/display.adoc[] over this one whenever possible.
It's easier to use.
@@ -0,0 +1,6 @@
= Source "Note number"
This source reacts to incoming MIDI note-on messages.
The higher the note number (= key on a MIDI keyboard), the higher the absolute control value.
This essentially turns your MIDI keyboard into a "huge fader" with the advantage that you can jump to any value at any time.
@@ -0,0 +1,9 @@
= Source "Note velocity"
This source reacts to incoming MIDI note-on and note-off messages.
The higher the velocity of the incoming note-on message, the higher the absolute control value.
Note-off messages are always translated to 0%, even if there's a note-off velocity.
== Note menu
Optionally restricts this source to messages with a certain note number (note numbers represent keys on the MIDI keyboard, e.g. 60 corresponds to C4).
@@ -0,0 +1,28 @@
= Source "(N)RPN value"
This source reacts to incoming non-registered (NRPN) or registered (RPN) MIDI parameter-number messages.
The higher the emitted value, the higher the absolute control value.
(N)RPN messages are not widely used.
If they are, then mostly to take advantage of their ability to transmit 14-bit values (up to 16384 different values instead of only 128), resulting in a higher resolution.
== RPN checkbox
If unchecked, this source reacts to unregistered parameter-number messages (NRPN).
If checked, it reacts to registered ones (RPN).
== Number field
The number of the registered or unregistered parameter-number message.
This is a value between 0 and 16383.
== 14-bit values checkbox
If unchecked, this source reacts to (N)RPN messages with 7-bit resolution, including increment/decrement messages.
If checked, it reacts to those with 14-bit resolution.
In practice, this if often checked.
== Character menu
See xref:further-concepts/source.adoc#midi-source-character[].
@@ -0,0 +1,5 @@
= Source "Pitch wheel"
This source reacts to incoming MIDI pitch-bend change messages.
The higher the pitch-wheel position, the higher the absolute control value.
The center position corresponds to an absolute control value of 50%.
@@ -0,0 +1,8 @@
= Source "Polyphonic after touch"
This source reacts to incoming MIDI polyphonic-key-pressure messages.
The higher the pressure, the higher the absolute control value.
== Note menu
Optionally restricts this source to messages with a certain note number.
@@ -0,0 +1,4 @@
= Source "Program change"
This source reacts to a range of incoming MIDI program-change messages.
The higher the program number, the higher the absolute control value.
@@ -0,0 +1,10 @@
= Source "Raw MIDI / SysEx"
[[source-midi-raw]]
This source primarily deals with system-exclusive MIDI messages.
It supports both control and feedback direction!
== Pattern field
Pattern describing the raw MIDI message.
See xref:further-concepts/mapping.adoc#raw-midi-pattern[].
@@ -0,0 +1,5 @@
= Source "Specific program change"
This source reacts to MIDI program-change messages with a specific program.
This is a trigger-only source, that means it always fires 100% (whenever the program number corresponds to the configured one).
@@ -0,0 +1,6 @@
= Source "None"
A special kind of source that will never emit any events.
It's intended to be used on mappings which are not supposed to be controlled directly but only via xref:user-interface/mapping-panel/glue-section.adoc#group-interaction[].
[split=1]
@@ -0,0 +1,66 @@
= Source "OSC"
OSC sources allow configuration of the following aspects:
== Address field
This needs to correspond exactly to the address of the corresponding control element on your OSC device.
Example: `/1/fader1`
You don't need to figure that out yourself, just use the btn:[Learn] button.
== Argument section
Each OSC message consists of an arbitrary number of arguments.
In most cases, e.g. with faders, knobs or buttons, it's just one argument.
X/Y controls often send 2 arguments, one for each axis.
There are rare cases in which messages have even more arguments.
=== Argument number menu
The first dropdown menu allows you to choose the number of the argument that ReaLearn should look at and process. `1` denotes the first argument, `2` the second one, and so on.
=== Argument type menu
The second dropdown menu lets you choose the argument type which ReaLearn should use to construct a proper feedback message.
This is usually the same type as the one used for control direction.
For control direction, choosing an explicit type is irrelevant because ReaLearn handles whatever type arrives automatically in the best possible way.
If you use _Learn_, the type is filled automatically.
* The value to be sent will be derived from the type (see <<feedback-arguments>>):
[cols="m,m"]
|===
| Type | Property
| Float | value.float
| Double | value.double
| Int | value.int
| Long | value.long
| Bool | value.bool
| Nil | nil
| Inf | inf
| String | value.string
| Color | style.color
|===
If you want more control over what feedback values are sent, use the <<feedback-arguments>> field.
== Range field
Values of argument types _Float_ and _Double_ are by default interpreted as decimal values between 0.0 and 1.0. You can change that by entering a different value range here.
Even negative numbers are allowed.
Customizing the value range is especially important for argument types _Int_ and _Long_ because they don't have a standard value range.
== Is relative checkbox
Some messages transmitted by OSC devices are meant to be interpreted as relative increments/decrements instead of absolute values, e.g. jog wheels.
When you enable this checkbox, ReaLearn will treat each received _1_ value as an increment and _0_ value a decrement.
[#feedback-arguments]
== Feedback arguments field
Allows you to modify the xref:further-concepts/source.adoc#osc-feedback-arguments-expression[].
@@ -0,0 +1 @@
= REAPER sources
@@ -0,0 +1,4 @@
= Source "MIDI device changes"
This source emits a value of 100% whenever any MIDI device is connected and 0% whenever any MIDI device is disconnected.
You can map this to the REAPER action "Reset all MIDI devices" to achieve true plug and play of MIDI devices (provided the corresponding device has been enabled at least once in REAPER's MIDI device preferences).
@@ -0,0 +1,8 @@
= Source "ReaLearn parameter"
This source fires whenever a selected xref:further-concepts/compartment.adoc#compartment-parameter[] changes its value.
One of many ways to use this is to create macro parameters which control multiple parameters of multiple other plug-ins.
CAUTION: This is one of the sources that can't participate in rendering.
So it's important to write down automation *before* rendering.
@@ -0,0 +1,4 @@
= Source "ReaLearn unit start"
This source fires (emits a value of 100%) when ReaLearn starts.
It can be used to execute an actions or restore certain states on REAPER startup or project load.
@@ -0,0 +1,11 @@
= Source "Speech"
This source works for xref:key-concepts.adoc#feedback[] only.
It uses the native Windows or macOS text-to-speech engine to speak out any feedback value.
== Troubleshooting
If you don't hear anything, check the xref:user-interface/main-panel/bottom-section.adoc[] if unit-wide feedback is currently off.
If yes, maybe xref:user-interface/main-panel/menu-bar.adoc#send-feedback-only-if-track-armed[] is enabled but your track is not armed.
Also keep in mind that ReaLearn only resends feedback when it changed. Therefore, the speech source will only say something when the target value actually changes.
@@ -0,0 +1,3 @@
= Source "Timer"
This source fires (emits a value of 100%) repeatedly every _n_ milliseconds.
@@ -0,0 +1,156 @@
= Source "Stream Deck"
With this source, you can leverage your Stream Deck with ReaLearn, for example the link:https://www.elgato.com/en/en/p/stream-deck-mk2-black[Elgato Stream Deck MK.2].
This includes reacting to buttons and sending xref:key-concepts.adoc#feedback[] to the button displays.
CAUTION: This source is experimental. Behavioral changes are still possible!
== Supported devices
The following StreamDeck devices are currently supported:
* Original
* Original v2
* Mini
* Revised Mini
* XL
* MK.2
== Setup
=== General
**Make sure that the official Stream Deck software is not running!**
ReaLearn connects to your Stream Deck directly via USB.
Only one software can connect to the device, so it's _either_ ReaLearn _or_ the Stream Deck software.
[[linux]]
=== Linux
If you use Stream Deck on Linux, you also need to explicitly allow normal users access to the device, otherwise ReaLearn won't be able to connect to it.
==== 1. Find the Vendor and Product ID
Plug in the Stream Deck and identify its vendor and product IDs:
[source,bash]
----
lsusb
----
Look for a line similar to:
`Bus 001 Device 002: ID 0fd9:0080 Elgato Systems GmbH`
In this example, `0fd9` is the vendor ID, and `0080` is the product ID (these may vary).
==== 2. Create a udev Rule
Create a new udev rule file in `/etc/udev/rules.d/`:
[source,bash]
----
sudo nano /etc/udev/rules.d/99-streamdeck.rules
----
Add the following rule, replacing `0fd9` and `0080` with the correct vendor and product IDs if necessary:
[source]
----
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0080", MODE="0660", GROUP="plugdev"
KERNEL=="hidraw*", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0080", MODE="0660", GROUP="plugdev"
----
This rule sets permissions to `0660`, allowing the device owner and users in the `plugdev` group access to the device with the specified vendor and product IDs.
==== 3. Reload udev Rules
Reload the udev rules to apply changes:
[source,bash]
----
sudo udevadm control --reload-rules
----
==== 4. Unplug and Replug the Device
Unplug the Stream Deck and plug it back in to apply the new rule.
Alternatively, you can execute `sudo udevadm trigger`.
== User interface
=== Button menu
Select the button that you want to use to control or display something.
=== Back menu
Allows you to choose the desired button backgrounds.
Unlike the button foreground, the button background is always static.
It doesn't react to feedback value changes.
Color::
Uses a solid color as button background, by default black.
You can change the color via xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[], that means the background color can even be dynamic, e.g. reflect the currently selected track's color.
Image::
Uses a PNG image as button background.
+
The image should ideally be a square.
If not, some parts of the image will not be visible.
The ideal dimensions of that square depends on your specific device.
On most Stream Decks, it's 72x72 pixels.
But ReaLearn will automatically scale the image.
If in doubt, prefer _larger_ image sizes.
Scaling down gives you a better quality than scaling up.
+
If the image has transparent parts, the color defined in xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[] will shine through.
TIP: When picking images to be displayed on your Stream Deck, prefer images that are somewhere within your REAPER resource path (REAPER → Options → Show REAPER resource path in explorer/finder), e.g. toolbar icons.
That makes ReaLearn save it as relative path, so your mapping becomes more portable (which is important if you want to share presets).
=== Front menu
Allows you to choose the desired button foreground, if desired.
A foreground is usually dynamic, that means it can change depending on the target value.
None::
No foreground.
Choose this if all you want to display is a static background.
Color fade::
Paints a color over the background with an opacity that depends on the target value.
For example, if the target value is at 10%, the color will be almost transparent.
It will fade depending The color is defined in xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[].
Image fade::
Paints an image over the background with an opacity that depends on the target value.
In terms of sizing, it behaves exactly like a background image.
Image slide::
Paints the portion of an image over the background.
Which portion, depends on the target value.
Landscape images slide horizontally, portrait images slide vertically.
+
This type of foreground is perfect for making use of REAPER's toolbar images.
They are actually sprites, that means they contain multipe images in one file, at different horizontal positions.
Full bar::
Paints a full-sized bottom-up half-transparent bar over the background, indicating the current target value.
+
Good in combination with targets that have a continuous range, such as xref:targets/track/set-volume.adoc[] or xref:targets/track/peak.adoc[].
Knob::
Paints a knob over the background, indicating the current target value.
=== Default text field
Here you can enter static text that should be displayed over the background and foreground.
ReaLearn will automatically choose a contrast color or dim the background so that the text always stays readable.
You can press btn:[...] to enter multi-line text.
ReaLearn supports up to 4 lines of text.
You can also display dynamic text from the target!
See xref:user-interface/mapping-panel/glue-section.adoc#feedback-style[].
@@ -0,0 +1,20 @@
= Source "Virtual"
See xref:further-concepts/source.adoc#virtual-source[].
== Type menu
See xref:further-concepts/compartment.adoc#virtual-control-element-type[].
== ID section
See xref:further-concepts/compartment.adoc#virtual-control-element-id[].
=== Pick menu
The convenient picker provides IDs from standardized xref:further-concepts/compartment.adoc#virtual-control-scheme[virtual control schemes].
It also contains a category for accessing the virtual control elements that are currently exposed by the xref:key-concepts.adoc#controller-compartment[].
=== ID field
Lets you enter the ID manually.
@@ -0,0 +1 @@
= Targets
@@ -0,0 +1 @@
= FX chain targets
@@ -0,0 +1,8 @@
= Target "FX chain: Browse FXs"
Steps through the FX instances in the FX chain by always having exactly one FX instance visible.
To be used with endless rotary encoders or previous/next-style "Incremental buttons".
== Display menu
Here you can decide if you want to display the FX as part of the FX chain or in a dedicated floating window.
@@ -0,0 +1,2 @@
= FX parameter targets
@@ -0,0 +1,9 @@
= Target "FX parameter: Set automation touch state"
This is similar to xref:targets/track/set-automation-touch-state.adoc[] but for FX parameter value changes.
IMPORTANT: There's one difference.
This target currently only reacts to _release_ events, not _press_ events.
So you can't start writing automation by touching the fader.
You can only end writing automation by releasing it.
The reason is that REAPER doesn't provide a function `TrackFX_BeginParamEdit`, it only provides link:https://www.reaper.fm/sdk/reascript/reascripthelp.html#TrackFX_EndParamEdit[TrackFX_EndParamEdit].
@@ -0,0 +1,97 @@
= Target "FX parameter: Set value"
Sets the value of a particular track FX parameter.
== Parameter controls
Use them to set the parameter to be controlled.
Please note that both xref:further-concepts/target.adoc#particular-fx-selector[] and xref:further-concepts/target.adoc#at-position-selector[] address the FX by its position in the FX chain.
The difference between the two is that xref:further-concepts/target.adoc#particular-selector[] shows a dropdown containing the available parameters and xref:further-concepts/target.adoc#at-position-selector[] lets you enter the position as a number in a text field.
The latter is useful if at the time of choosing the position, the FX is not available.
== Retrigger checkbox
By default, ReaLearn doesn't set the parameter if it already has the desired value. That prevents unnecessary invocations.
However, some FX parameters are more like triggers. They don't actually have a value and are just used to trigger some action within that FX. In this case, it's important to enable _Retrigger_, which sets the parameter no matter what.
== Real-time checkbox
=== Main thread vs. real-time thread
By default, ReaLearn does FX parameter value adjustments from the so-called _main_ thread instead of the _real-time_ thread. That means, in the worst case, we get latency as long as one main loop cycle. One main loop cycle is usually around 30 ms.
In many control scenarios, this is completely acceptable. Basically, all control surface solutions including REAPER's built-in control surfaces, CSI and DrivenByMoss adjust FX parameters in the _main_ thread. Imagine you adjust a volume with a knob for mixing purposes. Such adjustments are usually rather slow and gradual, so it won't matter if the effect comes in 5 ms or 30 ms later.
However, ReaLearn is a tool not just for mixing, also for performing. And in performing, there's sometimes demand for low latencies and fast responses, even when controlling FX parameters.
=== Enabling real-time
If you enable this checkbox, ReaLearn will **under certain conditions** control the FX parameter from a _real-time_ thread, enabling much lower latencies. In particular, the latency will correspond to the configured audio device block size -- the same thing that influences how fast virtual instruments respond when you press a note.
The conditions are as follows:
Condition 1: Same track:: The controlled FX must be on the **same track** as the ReaLearn instance.
Condition 2: FX input:: The xref:key-concepts.adoc#input-port[] must be set to xref:user-interface/main-panel/input-output-section.adoc#fx-input[], **not** to a particular device.
In all other circumstances, ReaLearn will fall back to adjusting the FX parameter from the _main_ thread.
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|
target.fx_parameter.index
|
Integer
|
Zero-based index of the resolved FX parameter.
|
target.fx_parameter.name
|
String
|
Name of the resolved FX parameter.
|
target.fx_parameter.macro.name
|
String
|
Name of the corresponding Pot macro parameter. Only works if this parameter is part of a preset loaded via Pot.
|
target.fx_parameter.macro.section.name
|
String
|
Name of the corresponding Pot macro parameter section. Only works if this parameter is part of a preset loaded via Pot.
|
target.fx_parameter.macro.section.index
|
Integer
|
Zero-based index of the corresponding Pot macro parameter section (within the current bank). Only works if this parameter is part of a preset loaded via Pot.
|
target.fx_parameter.macro.new_section.name
|
String
|
Name of the corresponding Pot macro parameter section, but only if this parameter marks the start of a new section. Only works if this parameter is part of a preset loaded via Pot.
|
target.fx_parameter.macro.bank.name
|
String
|
Name of the corresponding Pot macro parameter bank. Only works if this parameter is part of a preset loaded via Pot.
|===
@@ -0,0 +1,2 @@
= FX targets
@@ -0,0 +1,12 @@
= Target "FX: Browse presets"
Steps through FX presets.
This target is suited for use with xref:further-concepts/mapping.adoc#knob[knobs], xref:further-concepts/mapping.adoc#rotary-endless-encoder[encoders] and xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[] because it allows you to step through the complete preset list.
The minimum value always represents _No preset_ whereas the maximum value always represents the last available preset.
It's _not_ suited for activating a particular preset (e.g. by setting xref:user-interface/mapping-panel/glue-section.adoc#target-min-max[] to the same value), because the preset list of an FX is usually not constant.
As soon as you modify the preset list, this value will might suddenly point to a completely different preset.
Even worse, the actual preset might have been deleted.
If you want to activate a particular preset, please use the xref:targets/fx/load-snapshot.adoc[] instead.
@@ -0,0 +1,3 @@
= Target "FX: Enable/disable"
Enables the FX instance if the incoming absolute control value is greater than 0%, otherwise disables it.
@@ -0,0 +1,8 @@
= Target "FX"
A target that allows you to define an FX, in its basic variant perfect for acquiring feedback for a specific FX.
== Act/Tags controls
The setting **Act/Tags** allows you to optionally set/pin the declared FX as xref:further-concepts/unit.adoc#unit-fx[].
This works pretty much the same as described in xref:targets/track/track.adoc[].
@@ -0,0 +1,13 @@
= Target "FX: Load snapshot"
Restores a certain state of a particular FX.
Before using this target, you need to take a snapshot of the desired FX state using the btn:[Take!] button.
This snapshot will be saved as part of ReaLearn's state itself and as a direct consequence as a part of your project.
This makes your project nicely self-contained.
It's perfect for activating particular FX presets because it will always restore the desired state, even if the preset list has changed.
This target supports feedback, but only if the snapshot is loaded via ReaLearn itself.
Please note that some plug-ins have _very large_ states.
Therefore, you should keep an eye on the snapshot size, which will be displayed once you take the snapshot.
ReaLearn's own state will grow with every new snapshot mapping, so this can quickly add up and make REAPER/ReaLearn slow!
@@ -0,0 +1,7 @@
= Target "FX: Open/close"
Makes the FX instance visible if the incoming control value is greater than 0%, otherwise hides it.
== Display menu
Here you can decide if you want to display the FX as part of the FX chain or in a dedicated floating window.
@@ -0,0 +1,3 @@
= Target "FX: Set online/offline"
Sets the FX instance online if the incoming absolute control value is greater than 0%, otherwise sets it offline.
@@ -0,0 +1,2 @@
= Global targets
@@ -0,0 +1,13 @@
= Target "Global: Last touched"
This will control whatever target has been last touched in REAPER.
It's similar to the built-in REAPER action "Adjust last touched FX parameter" but provides the following benefits:
. It's applicable to all ReaLearn targets that are learnable, not just FX parameters.
. It offers feedback.
. It can distinguish between parameter modifications caused by ReaLearn (i.e. hardware control) and those caused in other ways (e.g. via mouse).
== Pick button
This opens a window that lets you pick all considered target types and types of invocations (only macOS and Windows so far).
Last-touched targets not checked in this window will be ignored.
@@ -0,0 +1,36 @@
= Target "Global: Mouse"
This will control the mouse.
== Action menu
Move cursor to:: Moves the mouse cursor on the given axis in an absolute manner.
This is a good choice for absolute mouse movement, that is, if you want to position the mouse cursor to a specific screen position.
Although it's also possible to move the mouse cursor relatively with this action by controlling the target with relative messages, it's usually better to use _Move cursor by_ instead.
Move cursor by:: Moves the mouse cursor on the given axis in a relative manner.
This is a good choice if you want to move the cursor e.g. up a bit, starting from its current position.
This only works with relative control elements such as encoders or features such as xref:user-interface/mapping-panel/glue-section.adoc#make-relative[].
Press or release button:: Presses or releases a certain mouse button, depending on the incoming control value (0% = release, anything else = press).
[[turn-scroll-wheel]] Turn scroll wheel:: Simulates the scroll wheel.
== Axis menu
Determines the direction of movement or scrolling.
X (horizontal):: Horizontal movement or scrolling
[[mouse-axis-y]] Y (vertical):: Vertical movement or scrolling
== Button menu
Determines which mouse button to use.
TIP: One popular use of this target is to adjust the FX parameter under the mouse cursor.
For this, it's usually best to use action <<turn-scroll-wheel>> and <<mouse-axis-y>>.
TIP: You can unfold the magic of this target by combining multiple mappings.
E.g. one can simulate mouse dragging by using one mapping to press/release the left button and another mapping to move the cursor. link:https://raw.githubusercontent.com/helgoboss/realearn/master/resources/test-projects/issue-686-mouse-target.RPP[This example project] contains multiple examples (one per group).
WARNING: Feedback for this target is not fully implemented.
@@ -0,0 +1,11 @@
= Target "Global: Set automation mode override"
Sets the global automation mode override to the desired value if the incoming control value is greater than 0%, otherwise removes the override.
== Behavior menu
Lets you decide between not overriding anything, bypassing all envelopes or overriding with a specific automation mode.
== Mode menu
Here you can pick the desired automation mode if _Behavior_ is _Override_.
@@ -0,0 +1,2 @@
= Marker/region targets
@@ -0,0 +1,64 @@
= Target "Marker/region: Go to"
Navigates to a specific marker or region.
Here's the behavior in detail:
Regions::
* If the project is stopped, the editor cursor immediately jumps to the start position of the given region.
* If the project is playing, playback will continue with the given region as soon as the currently playing region (or measure if not within a region) has finished playing.
This is called "smooth seek".
* *Attention:* This currently doesn't work if the project containing ReaLearn is not the active project tab.
Markers::
* If the project is stopped, the editor cursor immediately jumps to the given marker.
* If the project is playing, playback will immediately be continued at the given marker.
The advantage over REAPER's built-in actions is that this target allows to target arbitrarily many markers/regions (either by position or by ID) … and that it supports visual feedback!
If you assign this target to a button which has an LED, you will see which marker/region is currently playing just by looking at your controller.
Please note that this doesn't work when recording!
== Marker/region selector menu
This dropdown lets you choose if you want to refer to a marker/region by its user-assigned ID or by its position on the timeline.
== Marker/region menu
This dropdown displays the markers or regions (depending on the _Regions_ checkbox state).
== Now! button
This sets the target to the currently playing (or currently focused, if stopped) marker/region.
== Behavior menu
Determines whether to use immediate or smooth seeking.
== Regions checkbox
Switches between markers and regions.
== Set loop points checkbox
For regions, this will additionally set the loop points to the region start and end position.
== Set time selection checkbox
For regions, this will additionally set the time selection to the region start and end position.
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|target.bookmark.id | Intger | (Numeric) ID of the bookmark
|target.bookmark.index | Integer | Index of the bookmark (counting both markers and regions)
|target.bookmark.index_within_type | Integer | Index of the bookmark (counting only markers or regions, respectively)
|target.bookmark.name | String | Name of the bookmark
| target.bookmark.color | Color | Custom color of the resolved marker or region.
|===
@@ -0,0 +1,2 @@
= MIDI targets
@@ -0,0 +1,50 @@
= Target "MIDI: Send message"
[[target-midi-send-message]]
Sends arbitrary MIDI messages (also sys-ex!) in response to incoming messages.
This target turns ReaLearn into a capable and convenient MIDI/OSC/Keyboard-to-MIDI converter.
== Output menu
Where to send the MIDI message.
FX output:: Sends the MIDI message to the output of this ReaLearn instance - which usually means it flows into the FX below ReaLearn, e.g. a VST instrument.
Feedback output:: Sends the MIDI message to the device which is set as _output_.
[[midi-send-output-input-device]] Input device:: Injects the MIDI message into the current MIDI input device buffer.
Enables a unique feature called "Global MIDI transformation", as shown in link:https://www.youtube.com/watch?v=WJiwmlJSsi8&list=PL0bFMT0iEtAgKY2BUSyjEO1I4s20lZa5G&index=11[tutorial video 11].
== Device menu
When choosing output <<midi-send-output-input-device>>, you can choose into which MIDI input device buffer the message will be injected.
<Same as input device>:: Injects the message into the same buffer of the MIDI input device chosen as xref:user-interface/main-panel/input-output-section.adoc#input[].
_Specific input device_:: Injects the message into another specific MIDI input device.
This can be useful for doing global MIDI transformation with controllers that expose multiple MIDI input ports.
A practical example is shown in link:https://www.youtube.com/watch?v=WJiwmlJSsi8&list=PL0bFMT0iEtAgKY2BUSyjEO1I4s20lZa5G&index=11[tutorial video 11].
== Pattern field
Defines the MIDI message to be sent as xref:further-concepts/mapping.adoc#raw-midi-pattern[].
It allows you to encode the incoming _absolute_ control value as part of the message (after it has been processed by xref:key-concepts.adoc#glue[]).
== Pre-defined patterns menu (...)
Provides predefined patterns.
[NOTE]
.This is a target capable of real-time control!
====
This target is a bit special in that it carries out its processing logic exclusively in the audio thread if it's controlled by a MIDI source.
This has the big advantage that receiving and producing MIDI messages happens in one go (without inter-thread-communication latency), which is often important when using MIDI message conversion.
However, this also means that the following things won't work when controlling this target using MIDI:
* It can't take the lead in xref:user-interface/mapping-panel/glue-section.adoc#group-interaction[].
* It won't work with timed xref:user-interface/mapping-panel/glue-section.adoc#fire-mode[fire modes].
* If _output_ is set to xref:user-interface/main-panel/input-output-section.adoc#fx-output[], additional limitations apply:
** It can't act as a follower in xref:user-interface/mapping-panel/glue-section.adoc#group-interaction[], either.
** It can't participate in xref:targets/realearn/load-mapping-snapshot.adoc[].
====
@@ -0,0 +1,2 @@
= OSC targets
@@ -0,0 +1,15 @@
= Target "OSC: Send message"
Sends OSC messages with up to one argument in response to incoming messages.
This target turns ReaLearn into a capable and convenient MIDI → OSC and OSC → OSC converter.
If an argument number is entered (e.g. `1`), it will encode the incoming absolute control value as that argument (after it has been processed by the glue section).
== Output menu
Where to send the OSC message.
<Feedback output>:: Sends the OSC message to the device which is set as _Output_.
Of course this only works if it's an OSC device.
_Specific device:_:: Sends the OSC message to a specific device.
Address, Argument and Range:: These correspond to the identically named settings of xref:sources/osc.adoc[].
Check that section for details.
@@ -0,0 +1,69 @@
= Playtime targets
The targets in this section are made for controlling xref:playtime::introduction.adoc[Playtime], the clip launcher contained in Helgobox.
[[column-selector]]
== Column selector
Column-related targets use a _column selector_ to define what xref:playtime::key-concepts.adoc#column[] the target should be applied to.
The following kinds of column selectors are available:
Active::
The xref:playtime::further-concepts/matrix.adoc#active-cell[currently active] column.
At position::
Here you can refer to a fixed column by entering the column number, e.g. 2.
Dynamic::
Allows you to dynamically refer to a certain column. See <<dynamic-selector-variables>>.
[[row-selector]]
== Row selector
Row-related targets use a _row selector_ to define what xref:playtime::key-concepts.adoc#row[] the target should be applied to.
The following kinds of row selectors are available:
Active::
The xref:playtime::further-concepts/matrix.adoc#active-cell[currently active] row.
At position::
Here you can refer to a fixed column by entering the row number, e.g. 2.
Dynamic::
Allows you to dynamically refer to a certain row. See <<dynamic-selector-variables>>.
[[slot-selector]]
== Slot selector
Slot-related targets use a _slot selector_ to define what xref:playtime::key-concepts.adoc#slot[] the target should be applied to.
The following kinds of slot selectors are available:
Active::
The xref:playtime::further-concepts/matrix.adoc#active-cell[currently active] slot.
At coordinates::
Here you can refer to a fixed slot by entering the slot address, e.g. 2 and 4. The first number is the number of the xref:playtime::key-concepts.adoc#column[], the second one the number of the xref:playtime::key-concepts.adoc#row[].
Dynamic::
Allows you to dynamically refer to a certain slot. There are two expressions, the first one should evaluate to the column index and the second one to the row index. As always, expressions must evaluate to zero-based indexes! See <<dynamic-selector-variables>>.
[[dynamic-selector-variables]]
== Dynamic selector variables
In addition to the general variables described in xref:further-concepts/target.adoc#dynamic-selector[], the dynamic selectors mentioned above grants access to the following variables:
[cols="m,1,3"]
|===
| Variable | Type | Description
| control_unit_column_index
| Integer >= 0
| Column index of the current top-left scroll position within the xref:playtime::further-concepts/matrix.adoc#control-unit[Playtime control unit] represented by this xref:key-concepts.adoc#unit[ReaLearn unit].
| control_unit_row_index
| Integer >= 0
| Row index of the current top-left scroll position within the xref:playtime::further-concepts/matrix.adoc#control-unit[Playtime control unit] represented by this xref:key-concepts.adoc#unit[ReaLearn unit].
|===
@@ -0,0 +1,9 @@
= Target "Playtime: Browse cells"
Changes the currently xref:playtime::further-concepts/matrix.adoc#active-cell[].
Best uses with xref:further-concepts/mapping.adoc#rotary-endless-encoder[encoders] or previous/next-style buttons.
== Axis
Sets the direction into which to browse.
@@ -0,0 +1,23 @@
= Target "Playtime: Column action"
Invokes a xref:playtime::key-concepts.adoc#column[]-related action.
== Action menu
The kind of action to be executed.
Stop::
Stops all slots in this column.
Arm/disarm::
When hit with an _on_ value, arms the associated xref:playtime::key-concepts.adoc#column-track[], otherwise disarms it.
Arm/disarm () exclusive::
When hit with an _on_ value, arms the associated xref:playtime::key-concepts.adoc#column-track[] and disarms all other column tracks, otherwise disarms it.
Activate::
Makes this column the xref:playtime::further-concepts/matrix.adoc#active-cell[] .
== Column menu
The xref:playtime::key-concepts.adoc#column[] on which to carry out this action. See xref:targets/playtime.adoc#column-selector[].
@@ -0,0 +1,7 @@
= Target "Playtime: Control unit scroll"
Controls the current xref:playtime::further-concepts/matrix.adoc#control-unit-scroll-position[] of the xref:playtime::further-concepts/matrix.adoc#control-unit[] represented by this xref:key-concepts.adoc#unit[ReaLearn unit].
== Axis
Sets the direction into which to scroll.
@@ -0,0 +1,52 @@
= Target "Playtime: Matrix action"
Invokes a xref:playtime::key-concepts.adoc#matrix[]-related action.
== Action menu
The kind of action to be executed.
Stop::
Stops all clips in the matrix. See xref:playtime::user-interface/matrix-area.adoc#column-cell-stop[]. Supports real-time operation.
Undo::
When hit with an _on_ value, undoes the last matrix operation. See xref:helgobox::app/user-interface/title-bar.adoc#title-bar-undo[].
Redo::
When hit with an _on_ value, redoes the last matrix operation. See xref:helgobox::app/user-interface/title-bar.adoc#title-bar-redo[].
Build scene::
When hit with an _on_ value, builds a xref:playtime::key-concepts.adoc#scene[] of all currently playing xref:playtime::key-concepts.adoc#clip[clips] in the first empty xref:playtime::key-concepts.adoc#row[].
Set record length mode::
Switches to a specific record-length mode. At the moment, only two possible modes exist: *Open end* and *Custom length* are supported. They correspond to the off and on state of xref:playtime::user-interface/inspector/matrix/recording.adoc#inspector-matrix-recording-length[].
Set custom record length in bars::
Sets the xref:playtime::user-interface/inspector/matrix/recording.adoc#inspector-matrix-recording-length[] to the desired number of bars.
Enable/disable click::
When hit with an _on_ value, enables the xref:playtime::user-interface/toolbar.adoc#toolbar-metronome[], otherwise disables it.
Enable/disable MIDI auto-quantize::
When hit with an _on_ value, enables xref:playtime::user-interface/inspector/matrix/recording.adoc#inspector-matrix-recording-auto-quantize[], otherwise disables it.
Smart record::
When hit with an _on_ value, triggers the xref:playtime::user-interface/toolbar.adoc#toolbar-smart-record[] function. If this leads to the stop of a xref:playtime::further-concepts/matrix.adoc#feature-tempo-detection[], the operation can be carried out in real-time.
Start or stop playback::
When hit with an _on_ value, this starts Playtime playback and plays all xref:playtime::further-concepts/slot.adoc#ignited-slot[ignited] slots. Otherwise, this stops Playtime playback. This basically resembles the xref:playtime::user-interface/toolbar.adoc#toolbar-start-stop-playback[] button. This action supports real-time invocation.
Enable/disable silence mode::
When hit with an _on_ value, this stops Playtime playback. Otherwise, it starts playback _without_ playing xref:playtime::further-concepts/slot.adoc#ignited-slot[ignited] slots. This action supports real-time invocation.
Panic::
This abruptly stops all clips in the matrix. This resembles a double click on the xref:playtime::user-interface/matrix-area.adoc#matrix-cell-stop[] button. This action supports real-time invocation.
Enable/disable sequencer recording::
When hit with an _on_ value, this starts recording a new xref:playtime::key-concepts.adoc#matrix-sequence[], otherwise it stops recording.
Enable/disable sequencer playing::
When hit with an _on_ value, this starts playting the currently active xref:playtime::key-concepts.adoc#matrix-sequence[], otherwise it stops playing.
Tap tempo::
Invokes the tap-tempo function. This action supports real-time invocation. See xref:playtime::user-interface/toolbar.adoc#toolbar-tap-tempo[].
@@ -0,0 +1,26 @@
= Target "Playtime: Row action"
== Action menu
The kind of action to be executed.
Most of the actions only execute when the target is hit with an _on_ value. In all other cases, it's specifically mentioned.
Play::
Acts like the xref:playtime::user-interface/matrix-area.adoc#row-cell-play-scene[] button. This action supports real-time invocation.
Build scene::
Acts like the xref:playtime:ROOT:user-interface/menus/row-menu.adoc#row-build-scene-from-currently-playing-clips[] function.
Clear::
Acts like the xref:playtime:ROOT:user-interface/menus/row-menu.adoc#row-clear[] function.
Copy or paste::
If the row contains clips, copies them to a matrix-internal clipboard. If the row is empty, attempts to paste clips from the matrix-internal clipboard into that row, replacing existing ones.
Activate::
Makes this row the xref:playtime::further-concepts/matrix.adoc#active-cell[].
== Row menu
The xref:playtime::key-concepts.adoc#row[] on which to carry out this action. See xref:targets/playtime.adoc#row-selector[].
@@ -0,0 +1,56 @@
= Target "Playtime: Slot management action"
Invokes a xref:playtime::key-concepts.adoc#slot[]-related action that has something to do with modifying slots.
== Action menu
The kind of action to be executed.
Most of the actions only execute when the target is hit with an _on_ value. In all other cases, it's specifically mentioned.
Clear slot::
See xref:playtime:ROOT:user-interface/menus/slot-menu.adoc#slot-clear[].
Fill slot with selected item::
See xref:playtime:ROOT:user-interface/menus/slot-menu.adoc#slot-import-selected-item[].
Edit first clip::
When hit with an _on_ value, opens the MIDI editor for the primary clip in the slot, otherwise close its. Works for MIDI clips only.
Copy or paste clip::
If the slot contains clips, copies them to a matrix-internal clipboard. If the slot is empty, attempts to paste clips from the matrix-internal clipboard into that slot, replacing existing ones.
Double clip section length::
Doubles the xref:playtime::user-interface/inspector/clip.adoc#inspector-clip-length[] of each clip contained in the slot.
Halve clip section length::
Halves the xref:playtime::user-interface/inspector/clip.adoc#inspector-clip-length[] of each clip contained in the slot.
Quantization on/off state::
When hit with an _on_ value, quantizes the first MIDI clip in this slot, otherwise un-quantizes it.
Duplicate::
Duplicates the clips of this slot to the slot below. If the slot below already contains clips, they will get replaced.
Activate::
Makes this slot the xref:playtime::further-concepts/matrix.adoc#active-cell[].
include::partial$targets/playtime/slot-menu.adoc[]
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|
target.clip.name
|
String
|
Name of the first clip in the slot.
|===
@@ -0,0 +1,14 @@
= Target "Playtime: Slot seek"
This target exists mainly to provide xref:key-concepts.adoc#feedback[] about the current playback position of the xref:playtime::key-concepts.adoc#slot[].
For example, you can use it to make an LED ring, motor fader or text display indicate the current playback position.
[CAUTION]
====
This also works in xref:key-concepts.adoc#control[control direction], changing the current play position of the clips in that slot. But this is **experimental**.
====
include::partial$targets/feedback-frequency-menu.adoc[]
include::partial$targets/playtime/slot-menu.adoc[]
@@ -0,0 +1,52 @@
= Target "Playtime: Slot transport action"
Invokes a xref:playtime::key-concepts.adoc#slot[]-related action that has something to do with transport.
All actions that are about starting and stopping slots are real-time capable, which means they can be executed in real-time when controlled via xref:sources/midi.adoc[].
== Action menu
The kind of action to be executed.
[[trigger]] Trigger::
xref:playtime::further-concepts/matrix.adoc#trigger-slot[Triggers] the slot.
Play/stop::
When hit with an _on_ value, starts slot playback, otherwise stops it.
Play/pause::
When hit with an _on_ value, starts slot playback, otherwise pauses it.
+
CAUTION: Pausing slots is experimental.
Stop::
When hit with an _on_ value, stops the slot.
Pause::
When hit with an _on_ value, pauses the slot.
+
CAUTION: Pausing slots is experimental.
Record/stop::
When hit with an _on_ value, starts slot recording, otherwise stops it.
Record/play/stop::
When hit with an _on_ value and the slot is empty, starts slot recording.
+
When hit with an _on_ value and the slot contains clips, starts playback.
+
When hit with an _off_ value, stops the slot.
Overdub/play::
When hit with an _on_ value, starts MIDI-overdubbing the slot, otherwise stops it.
Looped::
Controls the xref:playtime::user-interface/inspector/clip.adoc#inspector-clip-looped[] setting of the clip.
include::partial$targets/playtime/slot-menu.adoc[]
== Stop if empty
If this is checked, and you play or trigger empty slots, all slots in that column will be stopped.
In other words, this makes empty slots act as stop button.
@@ -0,0 +1,5 @@
= Target "Playtime: Slot volume"
Sets the xref:playtime::user-interface/inspector/clip.adoc#inspector-clip-volume[volume] property of all clips in a xref:playtime::key-concepts.adoc#slot[].
include::partial$targets/playtime/slot-menu.adoc[]
@@ -0,0 +1,2 @@
= Pot targets
@@ -0,0 +1,32 @@
= Target "Pot: Browse filter items"
This target can be used to filter the potentially very large collection of presets in xref:targets/pot/browse-presets.adoc[].
The idea is to map this target to an endless rotary encoder or previous/next buttons (using xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[] mode) and then navigate within the available filter items, e.g. instruments or banks.
== Kind menu
Choose the kind of filter items that you want to browse.
They correspond to the filters available in xref:helgobox::products.adoc#pot-browser[].
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|
target.item.name
|
String
|
Name of the filter item.
|
target.item.parent.name
|
String
|
Name of the parent filter item if there's any. E.g. the instrument to which a bank belongs or the type to which a subtype belongs.
|===
@@ -0,0 +1,60 @@
= Target "Pot: Browse presets"
Use this target to browse a collection of presets.
By default, this is the complete collection of presets available in all supported databases, so potentially thousands of presets.
If you want to browse just a subset, see xref:targets/pot/browse-filter-items.adoc[].
The idea is to map this target to an endless rotary encoder or previous/next buttons (using xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[] mode) and then navigate within the available presets.
Once you have selected a preset, you can audition it via xref:targets/pot/preview-preset.adoc[] (if it's a sound preset) and load it via xref:targets/pot/load-preset.adoc[].
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|
target.preset.name
|
String
|
Name of the preset.
|
target.preset.product.name
|
String
|
Name of the product to which this preset belongs, if available.
|
target.preset.file_ext
|
String
|
File extension of the preset, in case it's a file-based preset.
|
target.preset.author
|
String
|
Name of the preset author, if available.
|
target.preset.vendor
|
String
|
Name of the preset vendor, if available.
|
target.preset.comment
|
String
|
Preset comment, if available.
|===
@@ -0,0 +1,19 @@
= Target "Pot: Load preset"
Loads a preset selected via xref:targets/pot/browse-presets.adoc[].
NOTE: This needs at least REAPER version 6.69+dev1030! Also, it only works if you have the VST2/VST2i version of the corresponding plug-in installed.
NKS audio file presets will be loaded into ReaSamplOmatic5000.
== Track/FX controls
You must tell the target at which FX slot to load the corresponding plug-in.
The best idea is to use FX selector xref:further-concepts/target.adoc#at-position-selector[].
Selectors such as xref:further-concepts/target.adoc#particular-fx-selector[] or xref:further-concepts/target.adoc#named-fx-selector[] are not suited because the target might replace the plug-in with another one, in which the unique FX ID and the FX name can change.
Then the target would turn inactive and stop working.
== Target-specific properties
This target supports the same additional xref:further-concepts/target.adoc#target-property[target properties] as xref:targets/pot/browse-presets.adoc[].
The only difference is that the ones in this one relate to the currently loaded preset, not the one that's selected in the preset browser.
@@ -0,0 +1,4 @@
= Target "Pot: Preview preset"
Auditions a preset selected via xref:targets/pot/browse-presets.adoc[].
Only works if it's a sound preset and a sound preview file is available.
@@ -0,0 +1,2 @@
= Project targets
@@ -0,0 +1,10 @@
= Target "Project: Any on (solo/mute/...)"
This target is most useful in feedback direction.
Map it to some LED on your controller and the LED will light up if at least one of the tracks in your project is e.g. mute (depending on the track parameter in question).
If the control element is also a button, pressing the button will e.g. unmute all tracks in your project.
== Parameter menu
The track parameter in question.
@@ -0,0 +1,29 @@
= Target "Project: Browse tracks"
Steps through tracks.
To be used with endless rotary encoders or xref:user-interface/mapping-panel/glue-section.adoc#incremental-button[].
== Scroll TCP checkbox
See xref:targets/track/select-unselect.adoc[].
== Scroll mixer checkbox
See xref:targets/track/select-unselect.adoc[].
== Scope menu
Decides which tracks are considered and how.
All tracks:: Considers all tracks even those which are hidden.
Only tracks visible in TCP:: Considers only those tracks which are visible in the track control panel.
Only tracks visible in TCP (allow 2 selections):: Like "Only tracks visible in TCP" but makes it possible to have 2 selections.
One for the MCP and one for the TCP.
These selections can be moved independently.
This can make sense if you have a bunch of tracks that you only show in the TCP and another separate bunch of tracks that you only show in the MCP.
Only tracks visible in MCP:: Considers only those tracks which are visible in the mixer control panel.
Only tracks visible in MCP (allow 2 selections):: See above.
@@ -0,0 +1,80 @@
= Target "Project: Invoke REAPER action"
Triggers or sets the value of a particular REAPER action in the main section.
== Section menu
Specifies in which context the action is going to be invoked.
Main:: Invokes a main action.
Active MIDI editor:: Invokes a MIDI editor action, applied to the currently active MIDI editor.
Active MIDI event list editor:: Invokes a MIDI event list action, applied to the currently active MIDI editor.
Media explorer:: Invokes a media explorer action.
[[invocation-type]]
== Invocation type
Specifies _how_ the picked action is going to be controlled.
Trigger:: Invokes the action with the incoming absolute control value, but only if it's greater than 0%.
Most suitable for simple trigger-like actions that neither have an on/off state nor are annotated with "(MIDI CC/OSC only)" or similar.
Absolute 14-bit:: Invokes the action with the incoming absolute control value, even if it's 0%.
Most suitable for actions which either have an on/off state or are annotated with "(MIDI CC/OSC only)" or similar.
The resolution of the invocation is 14-bit, no matter what's the resolution of your control element).
Absolute 7-bit:: Just like the previous invocation mode but uses 7-bit resolution.
Might be necessary for actions provided by 3rd-party extensions which don't interpret 14-bit control values correctly.
In all other circumstances, 14-bit is probably the better default choice.
Relative:: Invokes the action with the incoming relative control value (absolute ones are ignored).
Only works for actions that are annotated with ("MIDI CC relative only") or similar.
== Pick! button
Opens REAPER's action dialog so you can select the desired action.
== With track checkbox
Allows you to choose a track which ReaLearn will select before executing the action.
This makes it possible to combine ReaLearn's flexible track selection capabilities with the plethora of REAPER actions that work on the currently selected track.
== Limitations
The particular action decides if toggling/feedback works completely, has limitations or is not possible at all.
There are multiple types of actions so it's not possible to settle with one invocation type and be done with it.
The types of actions can roughly be divided into:
Actions that take care of toggling themselves _and_ report on/off state::
* Example: "25. Track: Toggle record arm for track 01"
* If you want toggle behavior, you have 2 options:
** a) Set Invoke to "Absolute" and Mode to "Toggle button" (preferred).
** b) Set Invoke to "Trigger" and Mode to "Normal".
* Feedback is completely supported.
Actions that take care of toggling themselves but _don't_ report on/off state::
* Example: "40175. Item properties: Toggle mute"
* Toggle behavior is achieved as described in (1) but support for toggling and feedback has limitations (explained in (4)).
Actions that don't take care of toggling themselves ("trigger only")::
* Example: "1007. Transport: Play"
* There's no way to make such an action toggle because the action is not designed to do so.
* If the action reports an on/off state, feedback is completely supported though, otherwise not at all!
Actions that have a complete range of values as state::
* Example: "994. View: Adjust vertical zoom (MIDI CC/OSC only)"
* Since ReaLearn 2 and REAPER 6.20, there's special support for this type of actions.
Starting from the first time this action is triggered, ReaLearn will track its current value.
* That's why toggling is supported.
Because ReaLearn itself takes care of toggling, you need to set _Invoke_ to "Absolute" and Mode to "Toggle button".
* Feedback is also supported.
* Toggling/feedback for this type of actions comes with some inherent limitations that are related to the fact that a) REAPER itself doesn't necessarily use actions to invoke its own functions and b) MIDI CC/OSC actions don't have the concept of a "current value" (unlike e.g. toggle actions or FX parameters).
* The bottom line of these limitations is that toggling/feedback will only work if the action itself is used to trigger the change and if the action is an absolute action (not relative).
* Limitations in detail:
+
. In most cases, feedback will not work when changing the value in REAPER directly (e.g. when adjusting vertical zoom directly via the REAPER user interface).
. It will only work for actions that support some kind of absolute value range (usually the case for all non-relative MIDI CC/OSC actions).
. When the action is invoked via ReaLearn, the feedback will only work if "Invoke" is "Trigger" or "Absolute".
It won't work with "Relative".
. When the action is invoked from ReaScript or other extensions, it will only work if the invocation was done via `KBD_OnMainActionEx()` and an absolute value change.
. When the action is invoked via a native REAPER action mapping, it will only work if the invocation is done using absolute MIDI CC/OSC (not relative).
@@ -0,0 +1,16 @@
= Target "Project: Invoke transport action"
Invokes a transport-related action.
== Action menu
Specifies which transport action should be invoked.
Play/stop:: Starts playing the containing project if the incoming absolute control value is greater than 0%, otherwise invokes stop.
Play/pause:: Starts playing the containing project if the incoming absolute control value is greater than 0%, otherwise invokes pause.
Stop:: Stops the containing project if the incoming absolute control value is greater than 0%.
Useful for distinguishing feedback between _paused_ and _stopped_ state.
Pause:: Pauses the containing project if the incoming absolute control value is greater than 0%.
Useful for distinguishing feedback between _paused_ and _stopped_ state.
Record:: Starts/enables recording for the current project if the incoming absolute control value is greater than 0%, otherwise disables recording.
Repeat:: Enables repeat for the containing project if the incoming absolute control value is greater than 0%, otherwise disables it.
@@ -0,0 +1,72 @@
= Target "Project: Seek"
Allows you to use faders, knobs, encoders or incremental buttons to seek within portions of your project … with feedback that indicates the current position!
include::partial$targets/feedback-frequency-menu.adoc[]
== Behavior menu
Determines whether to use immediate or smooth seeking.
== Seek play checkbox
Doesn't just change the edit cursor but also changes the play position when the project is currently being played.
== Move view checkbox
Allow to scroll / change viewport when seeking.
== "Use" checkboxes
The following checkboxes determine which time ranges will be taken into consideration as reference for seeking (control) and feedback.
If you don't tick any "Use" checkbox, ReaLearn will seek within the currently visible viewport.
If you tick multiple options, this is the order of fallbacks:
* If there's no time selection, the loop points will be used.
* If there are no loop points, the current region is used.
* If there's no current region, the project will be used.
* If the project is empty, the viewport will be used.
=== Use time selection checkbox
Can use the currently set time selection as reference.
=== Use loop points checkbox
Can use the currently set loop points as reference.
=== Use regions checkbox
Can use the current region as reference.
=== Use project checkbox
Can use the complete project as reference, from start to end.
== Target-specific properties
This target supports the following additional xref:further-concepts/target.adoc#target-property[target properties].
[cols="m,1,3"]
|===
|Name|Type|Description
|target.position.project_default | String | Position in the current transport time unit
|target.position.time | String | _minute:second.milli_
|target.position.measures_beats_time | String | _measure.beat.milli_
|target.position.measures_beats | String | _measure.beat.milli_
|target.position.seconds | String | _second.milli_
|target.position.samples | String | _sample_
|target.position.hmsf | String | _hour:minute:second:milli_
|target.position.absolute_frames | String | _frames_
|target.position.project_default.mcu | String | Like `target.position.project_default` but tailored to Mackie Control timecode displays
|target.position.time.mcu | String | Like `target.position.time` but tailored to Mackie Control timecode displays
|target.position.measures_beats_time.mcu | String | Like `target.position.measures_beats_time` but tailored to Mackie Control timecode displays
|target.position.measures_beats.mcu | String | Like `target.position.measures_beats` but tailored to Mackie Control timecode displays
|target.position.seconds.mcu | String | Like `target.position.seconds` but tailored to Mackie Control timecode displays
|target.position.samples.mcu | String | Like `target.position.samples` but tailored to Mackie Control timecode displays
|target.position.hmsf.mcu | String | Like `target.position.hmsf` but tailored to Mackie Control timecode displays
|target.position.absolute_frames.mcu | String | Like `target.position.absolute_frames` but tailored to Mackie Control timecode displays
|===
@@ -0,0 +1,5 @@
= Target "Project: Set playrate"
Sets REAPER's master playrate.
CAUTION: This target doesn't currently work if the project containing ReaLearn is not the active project tab.
@@ -0,0 +1,5 @@
= Target "Project: Set tempo"
Sets REAPER's master tempo.
This target is not learnable anymore via the "Learn target" button and also not eligible for the xref:targets/global/last-touched.adoc[] because it causes too many "false positives".
@@ -0,0 +1,2 @@
= ReaLearn targets
@@ -0,0 +1,33 @@
= Target "ReaLearn: Browse group mappings"
This target lets you choose an arbitrary mapping group in this compartment and cycle through it with an encoder/fader/knob or incremental (previous/next) buttons.
"Cycling through" means that you move from one mapping in the group to the next one by hitting the next mapping's target with the _Target Max_ value in its glue section (by default 100%).
== Group menu
The group that you want to browse.
== Exclusivity menu
Non-exclusive:: Really just hits the target of the mapping which is next in the line and doesn't do anything with the other mappings.
In many cases this is enough, e.g. if the targets of the mappings in the cycled group are the same and just "Target Max" is different.
Or if the target itself already takes care of exclusivity.
Exclusive:: Doesn't just hit the target of the mapping which is next in the line but also hits the targets of all other mappings in the cycled group with their respective _Target Min_ value (by default 0%).
Be careful with this, you often won't need it.
Inactive mappings are skipped!
[TIP]
====
A mapping group lends itself perfectly for defining things that should happen _in sequence_.
This target allows you to take advantage of that!
- Combine it with xref:targets/realearn/enable-disable-mappings.adoc[] to browse different banks.
- Combine it with xref:targets/realearn/enable-disable-instances.adoc[] to browse completely different controller setups (or banks).
- Combine it with targets that don't provide a "Browse ..." variant themselves.
- Use it as an alternative to xref:further-concepts/glue.adoc#target-value-sequence[target value sequences] that allows you to have completely different targets within one sequence.
====
[split=0]
@@ -0,0 +1,7 @@
= Target "ReaLearn: Dummy"
This target simply does nothing when invoked and also doesn't provide any meaningful feedback on its own.
It's sometimes useful to have such a dummy target, e.g. combined with xref:user-interface/mapping-panel/glue-section.adoc#group-interaction[].
Or if you want to use ReaLearn as a MIDI filter which just "eats" an incoming MIDI message.
Or if you want to send some text feedback to a hardware display, if the text is just a constant string or uses a placeholder that doesn't need target context.
@@ -0,0 +1,42 @@
= Target "ReaLearn: Enable/disable instances"
This target allows you to flexibly enable or disable other ReaLearn instances based on instance or unit tags.
== Tag kind menu
Instance tags::
A ReaLearn instance matches when at least one of its units is tagged with any of the xref:further-concepts/instance.adoc#instance-tag[instance tags] entered into the **tags** field.
Unit tags::
A ReaLearn instance matches when at least one of its units is tagged with any of the xref:further-concepts/unit.adoc#unit-tag[unit tags] entered into the **tags** field.
+
WARNING: Controlling instances via unit tags can be counter-intuitive, please use instance tags instead! This option is retained for backward compatibility only.
== Exclusivity menu
Non-exclusive:: If the incoming control value is greater than 0%, all matching ReaLearn instances will be enabled (on top of the already enabled instances).
If the value is 0%, all matching ReaLearn instances will be disabled.
Exclusive:: If the incoming control value is greater than 0%, all matching ReaLearn instances will be enabled and all non-matching ones will be disabled.
If the value is 0%, it's exactly the opposite (react to button xref:user-interface/mapping-panel/glue-section.adoc#press-only[press only] if you don't want this to happen).
Exclusive (on only):: Variation of _Exclusive_ that applies exclusivity only if the incoming control value is greater than 0%.
== Tags field
Here you enter the instance or unit tags, separated by commas.
.Comma-separated tags
====
keys, guit, voc
====
== Remarks
* This affects other ReaLearn instances only. It doesn't match against this one.
* ReaLearn instances without tags won't be affected at all.
* Only affects instances in the same project.
If _this_ ReaLearn instance is on the monitoring FX chain, it only affects other instances in the monitoring FX chain.
TIP: This target is great for switching between completely different controller setups!
@@ -0,0 +1,24 @@
= Target "ReaLearn: Enable/disable mappings"
This target allows you to flexibly enable or disable other mappings in this unit based on their tags:
== Exclusivity menu
Non-exclusive:: If the incoming control value is greater than 0%, all matching mappings will be enabled (on top of the already enabled mappings).
If the value is 0%, all matching mappings will be disabled.
Exclusive:: If the incoming control value is greater than 0%, all matching mappings will be enabled and all non-matching ones will be disabled.
If the value is 0%, it's exactly the opposite (react to button xref:user-interface/mapping-panel/glue-section.adoc#press-only[press only] if you don't want this to happen).
Exclusive (on only):: Variation of _Exclusive_ that applies exclusivity only if the incoming control value is greater than 0%.
== Tags field
A mapping matches when it is tagged with any of the xref:further-concepts/mapping.adoc#mapping-tag[mapping tags] entered into this field (comma-separated).
== Remarks
* This affects other mappings only, not _this_ mapping.
* Mappings without tags won't be affected at all.
TIP: This target is a straightforward alternative to xref:further-concepts/mapping.adoc#conditional-activation[] when it comes to bank switching!
@@ -0,0 +1,27 @@
= Target "ReaLearn: Enable/disable units"
This target allows you to flexibly enable or disable other ReaLearn units within the same ReaLearn instance.
== Exclusivity menu
Non-exclusive:: If the incoming control value is greater than 0%, all matching ReaLearn units will be enabled (on top of the already enabled units).
If the value is 0%, all matching ReaLearn units will be disabled.
Exclusive:: If the incoming control value is greater than 0%, all matching ReaLearn units will be enabled and all non-matching ones will be disabled.
If the value is 0%, it's exactly the opposite (react to button xref:user-interface/mapping-panel/glue-section.adoc#press-only[press only] if you don't want this to happen).
Exclusive (on only):: Variation of _Exclusive_ that applies exclusivity only if the incoming control value is greater than 0%.
== Tags field
Here you enter the unit tags, separated by commas.
.Comma-separated tags
====
keys, guit, voc
====
== Remarks
* This affects other ReaLearn units only. It doesn't match against this one.
* ReaLearn units without tags won't be affected at all.
@@ -0,0 +1,35 @@
= Target "ReaLearn: Load mapping snapshot"
Restores target values for all or certain mappings in this ReaLearn unit.
== Snapshot menu
Choose the snapshot that you want to load.
<Initial>:: Restores the initial target values for the mappings.
By ID:: Restores target values contained in a snapshot that was taken via xref:targets/realearn/take-mapping-snapshot.adoc[].
Enter the corresponding ID here.
== Default field
Allows you to define a default target value to restore for each participating mapping whenever the snapshot either doesn't exist or doesn't contain a value for that mapping.
If that participating mapping has reverse checked, the inverse of the default value will be loaded.
== Tags field
Allows you to restrict the set of mappings whose target values will be restored.
* If this field is empty, target values of all mappings will be restored.
* If this field contains tags (comma-separated), target values will be restored only for mappings that are tagged with any of these.
== Active mappings only checkbox
By default, even target values for inactive (but control-enabled) mappings are restored!
If you don't like that, tick this checkbox.
== Remarks
* Mappings for which control is not enabled, never participate in snapshotting.
* Some targets don't report values and therefore don't participate in snapshotting.
* Feedback of this target indicates whether the desired snapshot is the one which has last been loaded (for the given tags).
@@ -0,0 +1,23 @@
= Target "ReaLearn: Modify mapping"
Triggers a modification of another ReaLearn mapping.
== Kind menu
The kind of modification.
Learn target:: Switches "Learn target" on or off for the destination mapping.
Use button btn:[...] to pick the considered target types and invocations to be included in the learning process.
Set target to last touched:: Sets the target of the destination mapping to the last-touched target.
Use button btn:[...] to pick the considered target types and invocations.
== Unit menu
Allows you to pick another ReaLearn unit.
== Mapping menu
Allows you to pick the destination mapping.
TIP: This target is great to "pin" targets to certain control elements on demand.
@@ -0,0 +1,26 @@
= Target "ReaLearn: Take mapping snapshot"
Memorizes target values for all or certain mappings in this ReaLearn units and saves them in a snapshot of your choice.
== Snapshot menu
Choose the snapshot to which you want to save the mapping values.
<Last loaded>:: Always chooses the snapshot which is currently active (was last loaded) for the given tags.
+
Only works if tags are not empty and if all tags have the same last-loaded snapshot.
So the best is if you always enter exactly one tag.
+
By ID:: Enter the unique ID of the snapshot, e.g. `scene_1`.
== Tags field
Allows you to restrict the set of mappings whose target values will be memorized.
* If this field is empty, target values of all mappings will be memorized.
* If this field contains tags (comma-separated), target values will be memorized only for mappings that are tagged with any of these.
== Active mappings only checkbox
By default, even target values of inactive (but control-enabled) mappings end up in the snapshot!
If you don't like that, tick this checkbox.

Some files were not shown because too many files have changed in this diff Show More