midizap/midizap.1

1422 lines
57 KiB
Groff

.\" Automatically generated by Pandoc 2.2.3.2
.\"
.TH "midizap" "1" "" "" ""
.hy
.SH Name
.PP
midizap \[en] control your multimedia applications with MIDI
.SH Synopsis
.PP
midizap [\-h] [\-k] [\-o[2]] [\-j \f[I]name\f[]] [\-r \f[I]rcfile\f[]]
[\-d[rskmj]]
.SH Options
.TP
.B \-h
Print a short help message.
.RS
.RE
.TP
.B \-k
Keep track of key (on/off) status of MIDI notes and control switches.
This isn't generally recommended, but may occasionally be useful to deal
with quirky controllers sending note\- or control\-ons without
corresponding off messages.
.RS
.RE
.TP
.B \-o[2]
Enable MIDI output.
Add \[lq]2\[rq] for a second pair of MIDI ports to be used, e.g., for
controller feedback.
See Sections \f[I]MIDI Output\f[] and \f[I]MIDI Feedback\f[].
.RS
.RE
.TP
.B \-j \f[I]name\f[]
Set the Jack client name.
Default: \[lq]midizap\[rq].
See Section \f[I]Jack\-Related Options\f[].
.RS
.RE
.TP
.B \-r \f[I]rcfile\f[]
Set the configuration file name.
Default: taken from the MIDIZAP_CONFIG_FILE environment variable if it
exists, or ~/.midizaprc if it exists, /etc/midizaprc otherwise.
See Section \f[I]Configuration File\f[].
.RS
.RE
.TP
.B \-d[rskmj]
Enable various debugging options: r = regex (print matched translation
sections), s = strokes (print the parsed configuration file in a
human\-readable format), k = keys (print executed translations), m =
midi (MIDI monitor, print all recognizable MIDI input), j = jack
(additional Jack debugging output).
Just \f[C]\-d\f[] enables all debugging options.
See Section \f[I]Basic Usage\f[].
.RS
.RE
.SH Description
.PP
midizap lets you control your favorite multimedia applications using
MIDI (https://www.midi.org/).
To these ends, it translates Jack MIDI input into X keystrokes, mouse
button presses, scroll wheel events, and, as an option, MIDI output.
It does this by matching the \f[C]WM_CLASS\f[] and \f[C]WM_NAME\f[]
properties of the window that has the keyboard focus against the regular
expressions for each application section in its configuration
(midizaprc) file.
If a regex matches, the corresponding set of translations is used.
If a matching section cannot be found, or if it doesn't define a
suitable translation, the program falls back to a set of translations in
a default section at the end of the file, if available.
.PP
The midizaprc file is just an ordinary text file which you can edit to
configure the program.
The format of the configuration file is pretty straightforward,
basically just a list of MIDI messages and their translations divided in
sections for different applications; the language is also described in
detail with lots of examples later in this manual.
Moreover, an example.midizaprc file containing sample configurations for
some applications is included in the sources, and you can find some more
examples of configuration files for various purposes in the examples
directory.
.PP
midizap provides you with a way to hook up just about any MIDI
controller to your applications.
Even if your target application already supports MIDI, midizap's MIDI
output option will be useful if your controller can't work directly with
the application because of protocol incompatibilities.
In particular, you can use midizap to turn pretty much any MIDI
controller with enough faders and buttons into a Mackie\-compatible
mixing device ready to be used with most DAW (digital audio workstation)
programs.
Another common use case is video editing software, which rarely offers
built\-in MIDI support.
midizap allows you to map the faders, encoders and buttons of your MIDI
controller to keyboard commands of your video editor for cutting,
marking, playback, scrolling, zooming, etc.
.PP
In other words, as long as the target application can be controlled with
simple keyboard shortcuts and/or MIDI commands, chances are that midizap
can make it work (at least to some extent) with your controller.
.SH Installation
.PP
First, make sure that you have the required dependencies installed.
The program needs a few X11 libraries and Jack.
And of course you need GNU make and gcc (the GNU C compiler).
On Ubuntu and other Debian\-based systems you should be able to get
everything that's needed by running this command:
.IP
.nf
\f[C]
sudo\ apt\ install\ build\-essential\ libx11\-dev\ libxtst\-dev\ libjack\-dev
\f[]
.fi
.PP
Then just run \f[C]make\f[] and \f[C]sudo\ make\ install\f[].
This installs the example.midizaprc file as /etc/midizaprc, and the
midizap program and the manual page in the default install location.
Usually this will be under /usr/local, but the installation prefix can
be changed with the \f[C]prefix\f[] variable in the Makefile.
Also, package maintainers can use the \f[C]DESTDIR\f[] variable as usual
to install into a staging directory for packaging purposes.
.SH Configuration File
.PP
After installation the system\-wide default configuration file will be
in /etc/midizaprc, where the program will be able to find it.
We recommend copying this file to your home directory, renaming it to
\&.midizaprc:
.IP
.nf
\f[C]
cp\ /etc/midizaprc\ ~/.midizaprc
\f[]
.fi
.PP
The ~/.midizaprc file, if it exists, takes priority over /etc/midizaprc,
so it becomes your personal default midizap configuration.
The midizaprc file included in the distribution is really just an
example; you're expected to edit this file to adjust the bindings for
the MIDI controllers and the applications that you use.
.PP
It is also possible to specify the configuration file to be used, by
invoking midizap with the \f[C]\-r\f[] option on the command line, e.g.:
\f[C]midizap\ \-r\ myconfig.midizaprc\f[].
This is often used with more specialized configurations dealing with
specific applications or MIDI controllers.
.PP
The program automatically reloads the midizaprc file whenever it notices
that the file has been changed.
Thus you can edit the file while the program keeps running, and have the
changes take effect immediately without having to restart the program.
When working on new translations, you may want to run the program in a
terminal, and employ some or all of the debugging options explained
below to see exactly how your translations are being processed.
.SH Basic Usage
.PP
The midizap program is a command line application, so you typically run
it from the terminal.
However, it is also possible to launch it from your Jack session manager
(see \f[I]Jack\-Related Options\f[] below) or from your desktop
environment's startup files once you've set up everything to your
liking.
.PP
Try \f[C]midizap\ \-h\f[] for a brief summary of the available options
with which the program can be invoked.
.PP
midizap uses Jack (http://jackaudio.org/) for doing all its MIDI input
and output, so you need to be able to run Jack and connect the Jack MIDI
inputs and outputs of the program.
While it's possible to do all of that from the command line as well, we
recommend using a Jack front\-end and patchbay program like
QjackCtl (https://qjackctl.sourceforge.io/) to manage Jack and to set up
the MIDI connections.
In QjackCtl's setup, make sure that you have selected \f[C]seq\f[] as
the MIDI driver.
This exposes the ALSA sequencer ports of your MIDI hardware and other
non\-Jack ALSA MIDI applications as Jack MIDI ports, so that they can
easily be connected to midizap.
(Here and in the following, we're assuming that you're using Jack1.
Jack2 works in a very similar way, but may require some more fiddling;
in particular, you may have to use
a2jmidid (http://repo.or.cz/a2jmidid.git) as a separate ALSA\-Jack MIDI
bridge in order to have the ALSA MIDI devices show properly as Jack MIDI
devices.)
.PP
Having that set up, start Jack, make sure that your MIDI controller is
connected, and try running \f[C]midizap\f[] from the command line
(without any arguments).
In QjackCtl, open the Connections dialog and activate the second tab
named \[lq]MIDI\[rq], which shows all available Jack MIDI inputs and
outputs.
On the right side of the MIDI tab, you should now see a client named
\f[C]midizap\f[] with one MIDI input port named \f[C]midi_in\f[].
That's the one you need to connect to your MIDI controller, whose output
port should be visible under the \f[C]alsa_midi\f[] client on the left
side of the dialog.
.PP
To test the waters, you can hook up just about any MIDI keyboard and
give it a try with the default section in the distributed midizaprc
file, which contains some basic translations for mouse and cursor key
emulation.
Here is the relevant excerpt from that section:
.IP
.nf
\f[C]
[Default]
\ C5\ \ \ \ XK_Button_1
\ D5\ \ \ \ XK_Button_2
\ E5\ \ \ \ XK_Button_3
\ F5\ \ \ \ XK_Left
\ G5\ \ \ \ XK_Up
\ A5\ \ \ \ XK_Down
\ B5\ \ \ \ XK_Right
\ CC1+\ \ XK_Scroll_Up
\ CC1\-\ \ XK_Scroll_Down
\f[]
.fi
.PP
We refer to Section \f[I]Translation Syntax\f[] below for a discussion
of the syntax being used here, but it should be fairly obvious that
these translations map the white keys of the middle octave (MIDI notes
\f[C]C5\f[] thru \f[C]B5\f[]) to some mouse buttons and cursor commands.
Switch the keyboard focus to some window with text in it, such as a
terminal or an editor window.
Pressing the keys C, D and E should click the mouse buttons, while F
thru B should perform various cursor movements.
Also, moving the modulation wheel (\f[C]CC1\f[]) on your keyboard should
scroll the window contents up and down.
.PP
One useful feature is that you can invoke the program with various
debugging options to get more verbose output as the program recognizes
events from the device and translates them to corresponding mouse
actions or key presses.
E.g., try running \f[C]midizap\ \-drk\f[] to have the program print the
recognized configuration sections and translations as they are executed.
Now press some of the keys and move the modulation wheel.
You should see something like:
.IP
.nf
\f[C]
$\ midizap\ \-drk
Loading\ configuration:\ /home/user/.midizaprc
translation:\ Default\ for\ emacs\@hostname\ (class\ emacs)
CC1\-1\-:\ XK_Scroll_Down/D\ XK_Scroll_Down/U\
CC1\-1\-:\ XK_Scroll_Down/D\ XK_Scroll_Down/U\
G5\-1[D]:\ XK_Up/D\
G5\-1[U]:\ XK_Up/U\
A5\-1[D]:\ XK_Down/D\
A5\-1[U]:\ XK_Down/U\
\f[]
.fi
.PP
It goes without saying that these debugging options will be very helpful
when you start developing your own bindings.
The \f[C]\-d\f[] option can be combined with various option characters
to choose exactly which kinds of debugging output you want; \f[C]r\f[]
(\[lq]regex\[rq]) prints the matched translation section (if any) along
with the window name and class of the focused window; \f[C]s\f[]
(\[lq]strokes\[rq]) prints the parsed contents of the configuration file
in a human\-readable form whenever the file is loaded; \f[C]k\f[]
(\[lq]keys\[rq]) shows the recognized translations as the program
executes them, in the same format as \f[C]s\f[]; \f[C]m\f[]
(\[lq]MIDI\[rq]) prints \f[I]any\f[] MIDI input, so that you can figure
out which MIDI tokens to use for configuring the translations for your
controller; and \f[C]j\f[] adds some debugging output from the Jack
driver.
You can also just use \f[C]\-d\f[] to enable all debugging output.
(Most of these options are also available as directives in the midizaprc
file; please check the distributed example.midizaprc for details.)
.PP
Have a look at the distributed midizaprc file for more examples.
Most of the other translations in the file assume a Mackie\-like device
with standard playback controls and a jog wheel.
Any standard DAW controller which can be switched into Mackie mode
should work with these out of the box.
There are also some more generic examples, like the one above, which
will work with almost any kind of MIDI keyboard.
The examples are mostly for illustrative and testing purposes, though,
to help you get started.
You will want to edit them and add translations for your own controllers
and favorite applications.
.SH MIDI Output
.PP
As already mentioned, the midizap program can also be made to function
as a MIDI mapper which translates MIDI input to MIDI output.
MIDI output is enabled by running the program as \f[C]midizap\ \-o\f[].
This equips the Jack client with an additional MIDI output port named
\f[C]midi_out\f[] (visible on the left side of QjackCtl's Connection
window).
.PP
The example.midizaprc file comes with a sample configuration in the
special \f[C][MIDI]\f[] default section for illustration purposes.
This section is only active if the program is run with the \f[C]\-o\f[]
option.
It allows MIDI output to be sent to any connected applications, no
matter which window currently has the keyboard focus.
This is probably the most common way to use this feature, but of course
it is also possible to have application\-specific MIDI translations, in
the same way as with X11 key bindings.
In fact, you can freely mix mouse actions, key presses and MIDI messages
in all translations.
.PP
You can try it and test that it works by running \f[C]midizap\ \-o\f[]
along with a MIDI synthesizer such as
FluidSynth (http://www.fluidsynth.org/) or its graphical front\-end
Qsynth (https://qsynth.sourceforge.io/).
Use QjackCtl to connect FluidSynth's MIDI input to midizap's output
port.
In the sample configuration, the notes \f[C]C4\f[] thru \f[C]F4\f[] in
the small octave have been set up so that you can operate a little
drumkit, and a binding for the volume controller (\f[C]CC7\f[]) has been
added as well.
The relevant portion from the configuration entry looks as follows:
.IP
.nf
\f[C]
[MIDI]
\ C4\ \ \ \ C3\-10
\ D4\ \ \ \ C#3\-10
\ E4\ \ \ \ D3\-10
\ F4\ \ \ \ D#3\-10
\ CC7=\ \ CC7\-10
\f[]
.fi
.PP
Note the \f[C]\-10\f[] suffix on the output messages in the above
example, which indicates that output goes to MIDI channel 10.
In midizaprc syntax, MIDI channels are 1\-based, so they are numbered
1..16, and 10 denotes the GM (General MIDI) drum channel.
.PP
E.g., the input note \f[C]C4\f[] is mapped to \f[C]C3\-10\f[], the note
C in the third MIDI octave, which on channel 10 will produce the sound
of a bass drum, at least on GM compatible synthesizers like Fluidsynth.
The binding for the volume controller (\f[C]CC7\f[]) at the end of the
entry sends volume changes to the same drum channel (\f[C]CC7\-10\f[]),
so that you can use the volume control on your keyboard to dial in the
volume on the drum channel that you want.
The program keeps track of the values of both input and output
controllers on all MIDI channels internally, so with the translations
above all that happens automagically.
.PP
Besides MIDI notes and control change (\f[C]CC\f[]) messages, the
midizap program also recognizes key and channel pressure (\f[C]KP\f[],
\f[C]CP\f[]), program change (\f[C]PC\f[]), and pitch bend (\f[C]PB\f[])
messages, which should cover most common use cases.
These are discussed in more detail in the \f[I]Translation Syntax\f[]
section below.
.SH Jack\-Related Options
.PP
There are some additional directives (and corresponding command line
options) to set midizap's Jack client name and the number of input and
output ports it uses.
(If both the command line options and directives in the midizaprc file
are used, the former take priority, so that it's always possible to
override the options in the midizaprc file from the command line.)
.PP
Firstly, there's the \f[C]\-j\f[] option and the \f[C]JACK_NAME\f[]
directive which change the Jack client name from the default
(\f[C]midizap\f[]) to whatever you want it to be.
To use this option, simply invoke midizap as
\f[C]midizap\ \-j\ client\-name\f[], or put the following directive into
your midizaprc file:
.IP
.nf
\f[C]
JACK_NAME\ "client\-name"
\f[]
.fi
.PP
This option is useful, in particular, if you're running multiple
instances of midizap with different configurations for different
controllers and/or target applications, and you want to have the
corresponding Jack clients named appropriately, so that they can be
identified more easily when wiring them up.
If you're using a persistent MIDI patchbay, such as the one available in
QjackCtl, you can then have the right connections automatically set up
for you whenever you launch midizap with that specific configuration.
.PP
Secondly, we've already seen the \f[C]\-o\f[] option which is used to
equip the Jack client with an additional output port.
This can also be achieved with the \f[C]JACK_PORTS\f[] directive in the
midizaprc file, as follows:
.IP
.nf
\f[C]
JACK_PORTS\ 1
\f[]
.fi
.PP
You may want to place this directive directly into a configuration file
if the configuration is primarily aimed at doing MIDI translations, so
you'd like to have the MIDI output enabled by default.
Typically, such configurations will include just a default
\f[C][MIDI]\f[] section and little else.
As explained in the \f[I]MIDI Feedback\f[] section, it's also possible
to have \f[I]two\f[] pairs of input and output ports, in order to deal
with controller feedback from the application.
This is achieved by either invoking midizap with the \f[C]\-o2\f[]
option, or by employing the \f[C]JACK_PORTS\ 2\f[] directive in the
configuration file.
.PP
Last but not least, midizap also supports Jack session management, which
makes it possible to record the options the program was invoked with,
along with all the MIDI connections.
This feature can be used with any Jack session management software.
Specifically, QjackCtl has its own built\-in Jack session manager which
is available in its Session dialog.
To use this, launch midizap and any other Jack applications you want to
have in the session, use QjackCtl to set up all the connections as
needed, and then hit the \[lq]Save\[rq] (or \[lq]Save and Quit\[rq])
button in the Session dialog to have the session recorded.
Now, at any later time you can relaunch the same session with the
\[lq]Load\[rq] (or \[lq]Recent\[rq]) button in the same dialog.
.SH Translation Syntax
.PP
The midizap configuration file consists of sections defining translation
classes.
Each section generally looks like this, specifying the name of a
translation class, optionally a regular expression to be matched against
the window class or title, and a list of translations:
.IP
.nf
\f[C]
[name]\ regex
<A..G><#b><0..12>\ output\ \ #\ note
KP:<note>\ output\ \ \ \ \ \ \ \ \ \ #\ key\ pressure\ (aftertouch)
PC<0..127>\ output\ \ \ \ \ \ \ \ \ #\ program\ change
CC<0..127>\ output\ \ \ \ \ \ \ \ \ #\ control\ change
CP\ output\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ channel\ pressure
PB\ output\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ pitch\ bend
\f[]
.fi
.PP
The \f[C]#\f[] character at the beginning of a line and after whitespace
is special; it indicates that the rest of the line is a comment, which
is skipped by the parser.
Empty lines and lines containing nothing but whitespace are also
ignored.
.PP
Each \f[C][name]\ regex\f[] line introduces the list of MIDI message
translations for the named translation class.
The name is only used for debugging output, and needn't be unique.
When focus is on a window whose class or title matches the regular
expression \f[C]regex\f[], the corresponding translations are in effect.
An empty regex for the last class will always match, allowing default
translations.
Any output sequences not bound in a matched section will be loaded from
the default section if they are bound there.
.PP
The translations define what output should be produced for the given
MIDI input.
Each translation must be on a line by itself.
The left\-hand side (first token) of each translation denotes the MIDI
message to be translated.
MIDI messages are on channel 1 by default; a suffix of the form
\f[C]\-<1..16>\f[] can be used to specify a MIDI channel.
E.g., \f[C]C3\-10\f[] denotes note \f[C]C3\f[] on MIDI channel 10.
.PP
Note messages are specified using the customary notation (note name
\f[C]A..G\f[], optionally followed by an accidental, \f[C]#\f[] or
\f[C]b\f[], followed by the MIDI octave number).
The same notation is used for key pressure (\f[C]KP\f[]) messages.
Note that all MIDI octaves start at the note C, so \f[C]B0\f[] comes
before \f[C]C1\f[].
By default, \f[C]C5\f[] denotes middle C.
Enharmonic spellings are equivalent, so, e.g., \f[C]D#\f[] and
\f[C]Eb\f[] denote exactly the same MIDI note.
.PP
We will go into the other syntactic bits and pieces of MIDI message
designations later, but it's good to have the following grammar in EBNF
notation handy for reference.
(To keep things simple, the grammar is somewhat abridged, but it covers
all the frequently used notation.
There is some additional syntax for some special forms of translations
which will be introduced later.)
.IP
.nf
\f[C]
token\ ::=\ msg\ [\ "["\ number\ "]"\ ]\ [\ "\-"\ number\ ]\ [\ incr\ ]
msg\ \ \ ::=\ (\ note\ |\ other\ )\ [\ number\ ]
note\ \ ::=\ (\ "A"\ |\ ...\ |\ "G"\ )\ [\ "#"\ |\ "b"\ ]
other\ ::=\ "CH"\ |\ "PB"\ |\ "PC"\ |\ "CC"\ |\ "CP"\ |\ "KP:"\ note
incr\ \ ::=\ "\-"\ |\ "+"\ |\ "="\ |\ "<"\ |\ ">"\ |\ "~"
\f[]
.fi
.PP
Case is ignored here, so \f[C]CC\f[], \f[C]cc\f[] or even \f[C]Cc\f[]
are considered to be exactly the same token by the parser, although by
convention we usually write them in uppercase.
Numbers are always integers in decimal.
The meaning of the first number depends on the context (octave number
for notes and key pressure, controller or program number in the range
0..127 for other messages).
This can optionally be followed by a number in brackets, denoting a
nonzero step size.
Also optionally, the suffix with the third number (after the dash)
denotes the MIDI channel in the range 1..16; otherwise the default MIDI
channel is used (which is always 1 on the left\-hand side, but can be
set on the right\-hand side with \f[C]CH\f[]).
The optional incr (increment) flag at the end of a token indicates a
\[lq]data\[rq] translation which responds to incremental (up/down) value
changes rather than key presses, cf.
\f[I]Key and Data Input\f[] below.
.SS Octave Numbering
.PP
A note on the octave numbers in MIDI note designations is in order here.
There are various different standards for numbering octaves, and
different programs use different standards, which can be rather
confusing.
E.g., there's the ASA (Acoustical Society of America) standard where
middle C is C4, also known as \[lq]scientific\[rq] or \[lq]American
standard\[rq] pitch notation.
At least two other standards exist specifically for MIDI octave
numbering, one in which middle C is C3 (so the lowest MIDI octave starts
at C\-2), and zero\-based octave numbers, which start at C0 and have
middle C at C5.
There's not really a single \[lq]best\[rq] standard here, but the latter
tends to appeal to mathematically inclined and computer\-savvy people,
and is also what is used by default in the midizaprc file.
.PP
However, you may want to change this, e.g., if you're working with
documentation or MIDI monitoring software which uses a different
numbering scheme.
To do this, just specify the desired offset for the lowest MIDI octave
with the special \f[C]MIDI_OCTAVE\f[] directive in the configuration
file.
For instance:
.IP
.nf
\f[C]
MIDI_OCTAVE\ \-1\ #\ ASA\ pitches\ (middle\ C\ is\ C4)
\f[]
.fi
.PP
Note that this transposes \f[I]all\f[] existing notes in translations
following the directive, so if you add this option to an existing
configuration, you probably have to edit the note messages in it
accordingly.
.SS Key and Data Input
.PP
Translations come in two flavors, \[lq]key translations\[rq] and
\[lq]data translations\[rq], which differ in the way the extra data
payload of the input message, called the \f[I]parameter value\f[] (or
just \f[I]value\f[] for short), is processed.
The parameter value depends on the type of MIDI message.
Program changes (\f[C]PC\f[]) have no value at all.
For notes, as well as key and channel pressure messages (\f[C]CP\f[],
\f[C]KP\f[]), it is a velocity value; for control changes (\f[C]CC\f[]),
a controller value; and for pitch bend messages (\f[C]PB\f[]), a pitch
bend value.
The latter is actually a 14 bit value composed of the two data bytes in
the message, which is considered as a signed quantity in the range
\-8192..8191, where 0 denotes the center value.
In all other cases, the parameter value consists of a single data byte,
which denotes an unsigned 7 bit quantity in the range 0..127.
.PP
\f[I]Key mode\f[] is the default mode and is available for all message
types.
In this mode, MIDI messages are considered as keys which can be
\[lq]pressed\[rq] (\[lq]on\[rq]) or \[lq]released\[rq] (\[lq]off\[rq]).
Any nonzero data value means \[lq]pressed\[rq], zero \[lq]released\[rq].
Two special cases need to be considered here:
.IP \[bu] 2
For pitch bends, any positive \f[I]or\f[] negative value means
\[lq]pressed\[rq], while 0 (the center value) means \[lq]released\[rq].
.IP \[bu] 2
Since program changes have no parameter value associated with them, they
don't really have an \[lq]on\[rq] or \[lq]off\[rq] status.
But they are treated in the same key\-like fashion anyway, assuming that
they are \[lq]pressed\[rq] and then \[lq]released\[rq] immediately
afterwards.
.PP
\f[I]Data mode\f[] is available for all messages with a parameter value,
i.e., anything but \f[C]PC\f[].
In this mode, the actual value of the message is processed rather than
just the on/off state.
Data mode is indicated with a special suffix on the message token which
denotes a step size and/or the direction of the value change which the
rule should apply to: increment (\f[C]+\f[]), decrement (\f[C]\-\f[]),
or both (\f[C]=\f[]).
The two parts are both optional, but at least one of them must be
present (otherwise the rule is interpreted as a key translation).
.PP
In the following, we concentrate on \[lq]standard\[rq] data mode
messages having an increment suffix.
In this case, the optional step size in brackets indicates the amount of
change required to trigger the translation, so its effect is to
downscale the amount of change in the input value.
(The variant without an increment suffix is more complicated and mostly
intended for rather specialized uses, so we'll have a look at it later
in the \f[I]Advanced Features\f[] section.)
.PP
Data mode usually tracks changes in the \f[I]absolute\f[] value of a
control.
However, for \f[C]CC\f[] messages there's also an alternative mode for
so\-called \f[I]incremental\f[] controllers, or \f[I]encoders\f[] for
short, which can found on some DAW controllers.
These usually take the form of jog wheels or rotary encoders which can
be turned endlessly in either direction.
In contrast, absolute\-valued controllers are usually faders or knobs
which are confined to a range between minimum and maximum values.
.PP
Encoders emit a special \f[I]sign bit\f[] value indicating a
\f[I]relative\f[] change, where a value < 64 usually denotes an
increment (representing clockwise rotation), and a value > 64 a
decrement (counter\-clockwise rotation).
The actual amount of change is in the lower 6 bits of the value.
In the message syntax, these kinds of controls are indicated by using
the suffixes \f[C]<\f[], \f[C]>\f[] and \f[C]~\f[] in lieu of
\f[C]\-\f[], \f[C]+\f[] and \f[C]=\f[], respectively.
These suffixes are only permitted with \f[C]CC\f[] messages.
.PP
Translations must be determined uniquely in each translation class.
That is, there must be at most one translation for each MIDI token in
each translation section.
Note, however, that the MIDI channel is part of the message, so tokens
with different MIDI channels count as different messages here.
Key and (standard) data translations can also be used in concert if
needed (in such a case the key translation is executed first).
.SS Keyboard and Mouse Translations
.PP
The right\-hand side of a translation (i.e., everything following the
first token) is a sequence of one or more tokens, separated by
whitespace, indicating either MIDI messages or X11 keyboard and mouse
events to be output.
.PP
In this section, we first have a look at keyboard and mouse output.
It consists of X key codes with optional up/down indicators, or strings
of printable characters enclosed in double quotes.
The syntax of these items, as well as the special \f[C]RELEASE\f[] and
\f[C]SHIFT\f[] tokens which will be discussed later, are described by
the following grammar:
.IP
.nf
\f[C]
token\ \ \ ::=\ "RELEASE"\ |\ "SHIFT"\ |\ keycode\ [\ "/"\ flag\ ]\ |\ string
keycode\ ::=\ "XK_Button_1"\ |\ "XK_Button_2"\ |\ "XK_Button_3"\ |
\ \ \ \ \ \ \ \ \ \ \ \ "XK_Scroll_Up"\ |\ "XK_Scroll_Down"\ |
\ \ \ \ \ \ \ \ \ \ \ \ "XK_..."\ (X\ keysyms,\ see\ /usr/include/X11/keysymdef.h)
flag\ \ \ \ ::=\ "U"\ |\ "D"\ |\ "H"
string\ \ ::=\ \[aq]"\[aq]\ {\ character\ }\ \[aq]"\[aq]
\f[]
.fi
.PP
Here, case \f[I]is\f[] significant (except in character strings, see the
remarks below), so the special \f[C]RELEASE\f[] and \f[C]SHIFT\f[]
tokens must be in all caps, and the \f[C]XK\f[] symbols need to be
written in mixed case exactly as they appear in the
/usr/include/X11/keysymdef.h file.
Besides the key codes from the keysymdef.h file, there are also some
special additional key codes to denote mouse button
(\f[C]XK_Button_1\f[], \f[C]XK_Button_2\f[], \f[C]XK_Button_3\f[]) and
scroll wheel (\f[C]XK_Scroll_Up\f[], \f[C]XK_Scroll_Down\f[]) events.
.PP
Any keycode can be followed by an optional \f[C]/D\f[], \f[C]/U\f[], or
\f[C]/H\f[] flag, indicating that the key is just going down (without
being released), going up, or going down and being held until the
\[lq]off\[rq] event is received.
So, in general, modifier key codes will be followed by \f[C]/D\f[], and
precede the keycodes they are intended to modify.
If a sequence requires different sets of modifiers for different
keycodes, \f[C]/U\f[] can be used to release a modifier that was
previously pressed with \f[C]/D\f[].
Sequences may also have separate press and release sequences, separated
by the special word \f[C]RELEASE\f[].
Examples:
.IP
.nf
\f[C]
C5\ "qwer"
D5\ XK_Right
E5\ XK_Alt_L/D\ XK_Right
F5\ "V"\ XK_Left\ XK_Page_Up\ "v"
G5\ XK_Alt_L/D\ "v"\ XK_Alt_L/U\ "x"\ RELEASE\ "q"
\f[]
.fi
.PP
One pitfall is that character strings in double quotes are just a
shorthand for the corresponding X key codes, ignoring case.
Thus, e.g., \f[C]"abc"\f[] actually denotes the keysym sequence
\f[C]XK_a\ XK_b\ XK_c\f[], as does \f[C]"ABC"\f[].
So in either case the \f[I]lowercase\f[] string \f[C]abc\f[] will be
output.
To output uppercase letters, it is always necessary to add one of the
shift modifiers to the output sequence.
E.g., \f[C]XK_Shift_L/D\ "abc"\f[] will output \f[C]ABC\f[] in
uppercase.
.PP
Translations are handled differently depending on the input mode (cf.
\f[I]Key and Data Input\f[] above).
In \f[I]key mode\f[], there are separate press and release sequences.
The former is invoked when the input key goes \[lq]down\[rq] (i.e., when
the \[lq]on\[rq] status is received), the latter when the input key goes
\[lq]up\[rq] again (\[lq]off\[rq] status).
More precisely, at the end of the press sequence, all down keys marked
by \f[C]/D\f[] will be released, and the last key not marked by
\f[C]/D\f[], \f[C]/U\f[], or \f[C]/H\f[] will remain pressed.
The release sequence will begin by releasing the last held key.
If keys are to be pressed as part of the release sequence, then any keys
marked with \f[C]/D\f[] will be repressed before continuing the
sequence.
Keycodes marked with \f[C]/H\f[] remain held between the press and
release sequences.
For instance, let's take a look at one of the more conspicuous
translations in the example above:
.IP
.nf
\f[C]
G5\ XK_Alt_L/D\ "v"\ XK_Alt_L/U\ "x"\ RELEASE\ "q"
\f[]
.fi
.PP
When the \f[C]G5\f[] key is pressed on the MIDI keyboard, the key
sequence \f[C]Alt+v\ x\f[] is initiated, keeping the \f[C]x\f[] key
pressed (so it may start auto\-repeating after a while).
The program then sits there waiting (possibly executing other
translations) until you release the \f[C]G5\f[] key again, at which
point the \f[C]x\f[] key is released and the \f[C]q\f[] key is pressed
(and released).
.PP
In contrast, in \f[I]data mode\f[] only a single sequence is output
whenever the message value increases or decreases.
At the end of the sequence, all down keys will be released.
For instance, the following translations move the cursor left or right
whenever the volume controller (\f[C]CC7\f[]) decreases and increases,
respectively.
Also, the number of times one of these keys is output corresponds to the
actual change in the value.
Thus, if in the example \f[C]CC7\f[] increases by 4, say, the program
will press (and release) \f[C]XK_Right\f[] four times, moving the cursor
4 positions to the right.
.IP
.nf
\f[C]
CC7\-\ XK_Left
CC7+\ XK_Right
\f[]
.fi
.PP
Incremental \f[C]CC\f[] messages are treated in an analogous fashion,
but in this case the increment or decrement is determined directly by
the input message.
One example for this type of controller is the jog wheel on the Mackie
MCU, which can be processed as follows (using \f[C]<\f[] and \f[C]>\f[]
in lieu of \f[C]\-\f[] and \f[C]+\f[] as the suffix of the \f[C]CC\f[]
message):
.IP
.nf
\f[C]
CC60<\ XK_Left
CC60>\ XK_Right
\f[]
.fi
.PP
(The corresponding \[lq]bidirectional\[rq] translations, which are
indicated with the \f[C]=\f[] and \f[C]~\f[] suffixes, are rarely used
with keyboard and mouse translations.
Same goes for the special \f[C]SHIFT\f[] token.
Thus we'll discuss these in later sections, see \f[I]MIDI
Translations\f[] and \f[I]Shift State\f[] below.)
.PP
In data mode, input messages can also have a \f[I]step size\f[]
associated with them, which has the effect of downscaling changes in the
parameter value.
The default step size is 1 (no scaling).
To change it, the desired step size is written in brackets immediately
after the message token and before the increment suffix.
A step size \f[I]k\f[] indicates that the translation is executed
whenever the input value has changed by \f[I]k\f[] units.
For instance, to slow down the cursor movement in the example above by a
factor of 4:
.IP
.nf
\f[C]
CC7[4]\-\ XK_Left
CC7[4]+\ XK_Right
\f[]
.fi
.PP
The same goes for incremental \f[C]CC\f[] messages:
.IP
.nf
\f[C]
CC60[4]<\ XK_Left
CC60[4]>\ XK_Right
\f[]
.fi
.PP
Note that since there's no persistent absolute controller state in this
case, this simply scales down the actual increment value in the message
itself.
.SS MIDI Translations
.PP
Most of the notation for MIDI messages on the left\-hand side of a
translation rule also carry over to the output side.
The only real difference is that the increment suffixes \f[C]+\-=<>\f[]
aren't permitted here, as they are only used to determine the input mode
(key or data) of the entire translation.
The \f[C]~\f[] suffix \f[I]is\f[] allowed, however, to indicate output
in incremental bit\-sign format in data translations, see below.
Step sizes are permitted as well on the output side, in \f[I]both\f[]
key and data translations.
Their meaning depends on the kind of translation, however.
In key translations, they denote the (nonzero) value to be used for the
\[lq]on\[rq] state in the press sequence; in data translations, they
indicate the amount of change for each unit input change (which has the
effect of \f[I]upscaling\f[] the value change).
.PP
The output sequence can involve as many MIDI messages as you want, and
these can be combined freely with keyboard and mouse events in any
order.
However, as already discussed in Section \f[I]MIDI Output\f[] above, you
need to invoke the midizap program with the \f[C]\-o\f[] option to make
MIDI output work.
Otherwise, MIDI messages in the output translations will just be
silently ignored.
.PP
There is one special MIDI token \f[C]CH\f[] which can only be used on
the output side.
It is always followed by a MIDI channel number in the range 1..16.
This token doesn't actually generate any MIDI message, but merely sets
the default MIDI channel for subsequent MIDI messages in the same output
sequence, which is convenient if multiple messages are output to the
same MIDI channel.
For instance, the sequence \f[C]C5\-2\ E5\-2\ G5\-2\f[], which outputs a
C major chord on MIDI channel 2, can also be abbreviated as
\f[C]CH2\ C5\ E5\ G5\f[].
.PP
For key mode inputs, the corresponding \[lq]on\[rq] or \[lq]off\[rq]
event is generated for all MIDI messages in the output sequence, where
the \[lq]on\[rq] value defaults to the maximum value (127 for controller
values, 8191 for pitch bends).
Thus, e.g., the following rule outputs a \f[C]CC80\f[] message with
controller value 127 each time middle C (\f[C]C5\f[]) is pressed (and
another \f[C]CC80\f[] message with value 0 when the note is released
again):
.IP
.nf
\f[C]
C5\ CC80
\f[]
.fi
.PP
The value for the \[lq]on\[rq] state can also be denoted explicitly with
a step size:
.IP
.nf
\f[C]
C5\ CC80[64]
\f[]
.fi
.PP
For pitch bends, the step size can also be negative.
For instance, the following rules assign two keys to bend down and up by
the maximum amount possible:
.IP
.nf
\f[C]
C2\ PB[\-8192]\ #\ bend\ down
D2\ PB[8191]\ \ #\ bend\ up
\f[]
.fi
.PP
Let's now have a look at data mode.
There are two additional suffixes \f[C]=\f[] and \f[C]~\f[] for data
translations which are most useful with pure MIDI translations, which is
why we deferred their discussion until now.
If the increment and decrement sequences for a given translation are the
same, the \f[C]=\f[] suffix can be used to indicate that this sequence
should be output for \f[I]both\f[] increments and decrements.
For instance, to map the modulation wheel (\f[C]CC1\f[]) to the volume
controller (\f[C]CC7\f[]):
.IP
.nf
\f[C]
CC1=\ CC7
\f[]
.fi
.PP
Which is exactly the same as the two translations:
.IP
.nf
\f[C]
CC1+\ CC7
CC1\-\ CC7
\f[]
.fi
.PP
The same goes for \f[C]<\f[], \f[C]>\f[] and \f[C]~\f[] with sign\-bit
encoders:
.IP
.nf
\f[C]
CC60~\ CC7
\f[]
.fi
.PP
Which is equivalent to:
.IP
.nf
\f[C]
CC60<\ CC7
CC60>\ CC7
\f[]
.fi
.PP
The \f[C]~\f[] suffix can be used to denote incremental controllers in
output messages, too.
E.g., to translate a standard (absolute) MIDI controller to an
incremental encoder value, you might use a rule like:
.IP
.nf
\f[C]
CC48=\ CC16~
\f[]
.fi
.PP
Step sizes also work on the right\-hand side of data translations.
You might use these to scale up value changes, e.g., when translating
from control changes to pitch bends:
.IP
.nf
\f[C]
CC1=\ PB[128]
\f[]
.fi
.PP
The step size can also be negative, which allows you to reverse the
direction of a controller if needed.
E.g., the following will output values going down from 127 to 0 as input
values go up from 0 to 127:
.IP
.nf
\f[C]
CC1=\ CC1[\-1]
\f[]
.fi
.PP
Another possibility is to place step sizes on \f[I]both\f[] the
left\-hand and right\-hand side of a rule, in order to approximate a
rational scale factor:
.IP
.nf
\f[C]
CC1[3]=\ CC1[2]
\f[]
.fi
.PP
The above translation will only be triggered when the input value
changes by 3 units, and the change in the output value will then be
doubled again, so that the net effect is to scale the amount of change
by 2/3.
Note that this will only work well if the input and output step sizes
are reasonably small, so for most real\-valued scale factors this method
can only provide a very rough approximation.
.SS Shift State
.PP
The special \f[C]SHIFT\f[] token toggles an internal shift state, which
can be used to generate alternative output for certain MIDI messages.
Please note that, like the \f[C]CH\f[] token, the \f[C]SHIFT\f[] token
doesn't generate any output by itself; it merely toggles the internal
shift bit which can then be queried in other translations to distinguish
between shifted and unshifted bindings for the same input message.
.PP
To these ends, there are two additional prefixes which indicate the
shift status in which a translation is active.
Unprefixed translations are active only in unshifted state.
The \f[C]^\f[] prefix denotes a translation which is active only in
shifted state, while the \f[C]?\f[] prefix indicates a translation which
is active in \f[I]both\f[] shifted and unshifted state.
.PP
Many DAW controllers have some designated shift keys which can be used
for this purpose, but the following will actually work with any
key\-style MIDI message.
E.g., to bind the shift key (\f[C]A#5\f[]) on a Mackie controller:
.IP
.nf
\f[C]
?A#5\ SHIFT
\f[]
.fi
.PP
Note the \f[C]?\f[] prefix indicating that this translation is active in
both unshifted and shifted state, so it is used to turn shift state both
on and off, giving a \[lq]Caps Lock\[rq]\-style of toggle key.
If you'd rather have an ordinary shift key which turns on shift state
when pressed and immediately turns it off when released again, you can
do that as follows:
.IP
.nf
\f[C]
?A#5\ SHIFT\ RELEASE\ SHIFT
\f[]
.fi
.PP
Having set up the translation for the shift key itself, we can now
indicate that a translation should be valid only in shifted state with
the \f[C]^\f[] prefix.
This makes it possible to assign, depending on the shift state,
different functions to buttons and faders.
Here's a typical example which maps a control change to either
Mackie\-style fader values encoded as pitch bends, or incremental
encoder values:
.IP
.nf
\f[C]
\ CC48=\ PB[128]\ \ #\ translate\ to\ pitch\ bend\ when\ unshifted
^CC48=\ CC16~\ \ \ \ #\ translate\ to\ encoder\ when\ shifted
\f[]
.fi
.PP
To keep things simple, only one shift status is available in the present
implementation.
Also note that when using a shift key in the manner described above, its
status is \f[I]only\f[] available internally to the midizap program; the
host application never gets to see it.
If your host software does its own handling of shift keys (as most
Mackie\-compatible DAWs do), it's usually more convenient to simply pass
those keys on to the application.
However, \f[C]SHIFT\f[] comes in handy if your controller simply doesn't
have enough buttons and faders to control all the essential features of
your target application.
In this case the internal shift feature makes it possible to double the
amount of controls available on the device.
For instance, you can emulate a Mackie controller with both encoders and
faders on a device which only has a single set of faders, by assigning
the shifted faders to the encoders, as shown above.
.SH Advanced Features
.PP
This section covers some functionality which is a bit more complicated
and used less frequently than the basic features discussed in previous
sections, but will come in handy in some situations.
Specifically, we'll discuss \f[I]MIDI feedback\f[], which is needed to
properly implement bidirectional communication with some controllers, as
well as a special kind of data translations which helps implement some
types of feedback, and also has its uses in \[lq]normal\[rq] processing.
.SS MIDI Feedback
.PP
Some MIDI controllers need a more elaborate setup than what we've seen
so far, because they have motor faders, LEDs, etc.
requiring feedback from the application.
To accommodate these, you can use the \f[C]\-o2\f[] option of midizap,
or the \f[C]JACK_PORTS\ 2\f[] directive in the midizaprc file, to create
a second pair of MIDI input and output ports, named \f[C]midi_in2\f[]
and \f[C]midi_out2\f[].
Use of this option also activates a second MIDI default section in the
midizaprc file, labeled \f[C][MIDI2]\f[], which is used exclusively for
translating MIDI input from the second input port and sending the
resulting MIDI output to the second output port.
Typically, the translations in the \f[C][MIDI2]\f[] section will be the
inverse of those in the \f[C][MIDI]\f[] section, or whatever it takes to
translate the MIDI feedback from the application back to MIDI data which
the controller understands.
.PP
You then wire up midizap's \f[C]midi_in\f[] and \f[C]midi_out\f[] ports
to controller and application as before, but in addition you also
connect the application back to midizap's \f[C]midi_in2\f[] port, and
the \f[C]midi_out2\f[] port to the controller.
This reverse path is what is needed to translate the feedback from the
application and send it back to the controller.
.PP
An in\-depth discussion of controller feedback is beyond the scope of
this manual, but we present a few useful tidbits below.
Also, the distribution includes a full\-blown example of this kind of
setup for your perusal, please check examples/APCmini.midizaprc in the
sources.
It shows how to emulate a Mackie controller with AKAI's APCmini device,
so that it readily works with DAW software such as Ardour.
.SS Mod Translations
.PP
Most of the time, MIDI feedback uses just the standard kinds of MIDI
messages readily supported by midizap, such as note messages which make
buttons light up in different colors, or control change messages which
set the positions of motor faders.
However, there are some encodings of MIDI messages employed in feedback,
such as time and meter displays, which combine different bits of
information in a single message, making them difficult or even
impossible to translate using the simple kinds of rules we've seen so
far.
.PP
midizap offers a special variation of data mode to help decoding at
least some of these special messages.
For reasons which will become obvious in a moment, we also call these
\f[I]mod data translations\f[], or just \f[I]mod translations\f[] for
short.
The extended MIDI syntax being used here is described by the following
grammar rules (please refer to the beginning of Section \f[I]Translation
Syntax\f[] for the parts of the syntax not explicitly defined here):
.IP
.nf
\f[C]
token\ ::=\ msg\ [\ steps\ ]\ [\ "\-"\ number]
steps\ ::=\ "["\ list\ "]"\ |\ "["\ number\ "]"\ "["\ list\ "]"
list\ \ ::=\ number\ {\ ","\ number\ |\ ":"\ number\ }
\f[]
.fi
.PP
In the following, we take the mapping of channel pressure to notes
indicating buttons on the AKAI APCmini as a running example; for further
details see examples/APCmini.midizaprc in the sources.
These translations are useful, in particular, to decode meter messages
in the Mackie protocol.
But they work the same with any kind of message having a parameter value
(i.e., anything but \f[C]PC\f[]) and any kind of MIDI output, so similar
rules should help with other kinds of \[lq]scrambled\[rq] MIDI data.
Some other possible uses will be discussed in the following section.
.PP
In its most basic form, the translation looks as follows:
.IP
.nf
\f[C]
CP[16]\ C0
\f[]
.fi
.PP
In contrast to standard data translations, there's no increment suffix
here, so the translation does \f[I]not\f[] indicate an incremental value
change of some sort.
Rather, the output messages are constructed directly from the input
value by some arithmetic calculations.
To these ends, the step size on the left\-hand side is actually used as
a \f[I]modulus\f[] in order to decompose the input value into two
separate quantities, \f[I]quotient\f[] and \f[I]remainder\f[].
Only the latter becomes the value of the output message, while the
former is used as an \f[I]offset\f[] to modify the output message.
(Note that \f[C]CP\f[] and \f[C]PB\f[] messages don't have a modifiable
offset, so if you use these on the output side of a mod translation, the
offset part of the input value will be simply ignored.
The \f[C]PC\f[] message, in contrast, lacks the parameter value, so in
this case the remainder value will be disregarded instead.)
.PP
In order to describe more precisely how this works, let's assume an
input value \f[I]v\f[] and a modulus \f[I]k\f[].
We divide \f[I]v\f[] by \f[I]k\f[], yielding the offset \f[I]q\f[] =
[\f[I]v\f[]/\f[I]k\f[]] (i.e., \f[I]v\f[]/\f[I]k\f[] rounded down to the
nearest integer towards zero), and the remainder \f[I]r\f[] = \f[I]v\f[]
\- \f[I]kq\f[] of that division.
E.g., with \f[I]k\f[] = 16 and \f[I]v\f[] = 21, we have that 16 + 5 = 21
and thus you'll get \f[I]q\f[] = 1 and \f[I]r\f[] = 5 (i.e., 21 divided
by 16 yields 1 with a remainder of 5).
The calculated offset \f[I]q\f[] is then applied to the note itself, and
the remainder \f[I]r\f[] becomes the velocity of that note.
So in the example the output would be the note \f[C]C#0\f[] (\f[C]C0\f[]
offset by 1) with a velocity of 5.
On the APCmini, this message will light up the second button in the
bottom row of the 8x8 grid in yellow.
.PP
As we mentioned already, there is in fact an important use case for all
this, namely decoding meter information in the Mackie protocol.
There, each meter value is sent by the host application in the form of a
key pressure message whose value consists of a mixer channel index 0..7
in the \[lq]high nibble\[rq] (bits 4..6) and the corresponding meter
value in the \[lq]low nibble\[rq] (bits 0..3), which is why we used 16
as the modulus in this example.
.PP
There are some variations of the syntax which make this kind of
translation more flexible.
In particular, on the right\-hand side of the rule you can specify a
step size if the remainder \f[I]r\f[] needs to be scaled:
.IP
.nf
\f[C]
CP[16]\ C0[2]
\f[]
.fi
.PP
But in many cases the required transformations on \f[I]r\f[] will be
more complicated.
To accommodate these, it is also possible to specify a \f[I]list\f[] of
discrete values instead.
E.g., the APCmini uses the velocities 0, 1, 3 and 5 to denote
\[lq]off\[rq] and the colors green, red and yellow, respectively, so you
can map the meter value to different colors as follows:
.IP
.nf
\f[C]
CP[16]\ C0[0,1,1,1,1,5,5,5,3]
\f[]
.fi
.PP
The remainder \f[I]r\f[] will then be used as an index into the list to
give the translated value.
E.g., in our example 0 will be mapped to 0 (off), 1..4 to 1 (green),
5..7 to 5 (yellow), and 8 to 3 (red), which actually matches the Mackie
protocol specifications.
Also, the last value in the list will be used for any index which runs
past the end of the list.
E.g., if you receive a meter value of 10, which isn't in the list, the
output will still be 3, since it's the last value in the list.
.PP
You probably noticed that there are a lot of repeated values in this
example, which makes the notation a bit untidy and error\-prone.
As a remedy, it's possible to abbreviate repeated values as
\f[I]value\f[]\f[C]:\f[]\f[I]count\f[], which also helps readability.
The following denotes exactly the same list as above:
.IP
.nf
\f[C]
CP[16]\ C0[0,1:4,5:3,3]
\f[]
.fi
.PP
Furthermore, you can also scale the \f[I]offset\f[] value, by adding a
second step size to the left\-hand side:
.IP
.nf
\f[C]
CP[16][8]\ C0[0,1:4,5:3,3]
\f[]
.fi
.PP
With this rule, the buttons for each mixer channel are now spread out
across different \f[I]rows\f[] rather than columns.
E.g., a channel pressure value of 24 (denoting a meter value of 8 on the
second mixer channel) will output the note \f[C]G#0\f[] (\f[C]C0\f[]
offset by 8) with velocity 3, which on the APCmini will light up the
first button in the second row in red.
.PP
Instead of a single step size, it's also possible to specify a list of
discrete offset values, so that you can achieve any regular or irregular
output pattern that you want:
.IP
.nf
\f[C]
CP[16][1,8,17,24]\ C0[0,1:4,5:3,3]
\f[]
.fi
.PP
You might also output several notes at once, in order to display an
entire horizontal or vertical meter \f[I]strip\f[] instead of just a
single colored button for each mixer channel.
For instance:
.IP
.nf
\f[C]
CP[16]\ C0[0,1]\ G#0[0:5,5]\ E1[0:8,3]
\f[]
.fi
.PP
Note that each of the output notes will be offset by the same amount, so
that the green, yellow and red buttons will always be lined up
vertically in this example.
The APCmini.midizaprc configuration uses a similar, albeit more
elaborate translation to handle MCU meter data.
.SS Other Uses of Mod Translations
.PP
Mod translations work with all kinds of output, so that you can also
output X11 key and mouse events along with the transformed MIDI data if
needed, and the input may be any kind of message which has a parameter
value.
So, while mod translations are most commonly employed for MIDI feedback,
they can also be used as a more capable replacement for
\[lq]ordinary\[rq] (incremental) data translations in various contexts.
We discuss some of these use cases below and show how they're
implemented.
.PP
In particular, note you can always choose the modulus large enough (>
8192 for \f[C]PB\f[], > 127 for other messages) so that the offset
becomes zero and thus inconsequential.
This is useful if you just want to employ the discrete value lists
(which are only available in mod translations) for your mappings.
These offer a great deal of flexibility, much more than can be achieved
with simple step sizes.
In fact, they can be used to realize \f[I]any\f[] discrete mapping
between input and output values.
For instance, here's how to map controller values to the first few
Fibonacci numbers:
.IP
.nf
\f[C]
CC1[128]\ CC1[0,1,1,2,3,5,8,13,21,34,55,89]
\f[]
.fi
.PP
The output values don't have to be increasing either; they might be in
any order you want:
.IP
.nf
\f[C]
CC1[128]\ CC1[0,2,1,4,3,6,5,8,7,10,9,...]
\f[]
.fi
.PP
On the other hand, you can also use a modulus of 1 if you're only
interested in the \f[I]offset\f[] and don't care about the output value.
This is useful, e.g., if you want to map controller values to note
\f[I]numbers\f[] (rather than velocities):
.IP
.nf
\f[C]
CC1[1]\ C0
\f[]
.fi
.PP
This will output the note with the same number as the controller value,
\f[C]C0\f[] for value 0, \f[C]C#0\f[] for value 1, etc.
Note that the remainder value, which becomes the velocity of the output
note, will always be zero here, so the above translation turns all notes
off.
To get a nonzero velocity, you have to specify it in a value list:
.IP
.nf
\f[C]
CC2[1]\ C0[127:1]
\f[]
.fi
.PP
Now we can turn notes on with \f[C]CC2\f[] and turn them off again with
\f[C]CC1\f[].
Note the little bit of trickery there on the right\-hand side.
Just \f[C][127]\f[] would be interpreted as a simple step size, which
wouldn't do us much good here since the remainder value to be scaled is
always zero.
Thus we write \f[C][127:1]\f[] instead to make sure that the parser
recognizes this as a value list.
You could also use, e.g., \f[C][127,0]\f[].
Any list which doesn't look like a simple scale factor and maps the 0
value to 127 will do.
.PP
For the sake of a more practical example, let's have another look at
MIDI feedback in the Mackie protocol.
The following rule decodes the lowest digit in the time display
(\f[C]CC69\f[]) to count off time on the scene launch buttons of the
AKAI APCmini.
Note that the digits are actually encoded in ASCII, hence the copious
amount of initial zeros in the value lists below with which we skip over
all the non\-digit characters at the beginning of the ASCII table.
.IP
.nf
\f[C]
CC69[128]\ F7[0:49,1,0]\ E7[0:50,1,0]\ Eb7[0:51,1,0]\ D7[0:52,1,0]
\f[]
.fi
.PP
As you can see, mod data translations in combination with discrete value
lists are really very powerful and let you implement pretty much any
desired mapping with ease.
There \f[I]are\f[] some limitations, though.
In particular, mappings involving multiple different translations of the
same input aren't possible right now, because translations must be
unique.
Also, there's no way to combine the values of several input messages
into a single output message.
.SH Bugs
.PP
There probably are some.
Please submit bug reports and pull requests at the midizap git
repository (https://github.com/agraef/midizap).
Contributions are also welcome.
In particular, we're looking for interesting configurations to be
included in the distribution.
.PP
The names of some of the debugging options are rather peculiar.
midizap inherited them from Eric Messick's ShuttlePRO program on which
midizap is based, so they'll probably last until someone comes up with
something better.
.PP
There's no Mac or Windows support (yet).
midizap has only been tested on Linux so far, and its keyboard and mouse
support is tailored to X11, i.e., it's pretty much tied to Unix/X11
systems right now.
.PP
midizap tries to keep things simple, which implies that it has its
limitations.
In particular, system messages are not supported right now, and midizap
lacks some more interesting ways of mapping, filtering and recombining
MIDI data.
There are other, more powerful utilities which do these things, but they
are also more complicated and usually require at least some programming
skills.
midizap often does the job reasonably well for simple mapping tasks, but
if things start getting fiddly then you should consider using a more
comprehensive tool like Pd (http://puredata.info/) instead.
.SH See Also
.PP
midizap is based on a fork (https://github.com/agraef/ShuttlePRO) of
Eric Messick's ShuttlePRO
program (https://github.com/nanosyzygy/ShuttlePRO), which provides
similar functionality for the Contour Design Shuttle devices.
.PP
Spencer Jackson's osc2midi (https://github.com/ssj71/OSC2MIDI) utility
makes for a great companion to midizap if you also need to convert
between MIDI and Open Sound Control (http://opensoundcontrol.org/).
.PP
The Bome MIDI Translator (https://www.bome.com/products/miditranslator)
seems to be a popular MIDI and keystroke mapping tool for Mac and
Windows.
It is proprietary software and isn't available for Linux, but it should
be worth a look if you need a midizap alternative which runs on these
systems.
.SH Authors
.PP
midizap is free and open source software licensed under the GPLv3,
please check the accompanying LICENSE file for details.
.PP
Copyright 2013 Eric Messick (FixedImagePhoto.com/Contact)
.PD 0
.P
.PD
Copyright 2018 Albert Graef (<aggraef@gmail.com>)
.PP
This is a version of Eric Messick's ShuttlePRO program which has been
redesigned to work with Jack MIDI instead of the Contour Design Shuttle
devices.
ShuttlePRO was written in 2013 by Eric Messick, based on earlier code by
Trammell Hudson and Arendt David.
The MIDI support was added by Albert Graef.
All the key and mouse translation features of the original program still
work as before, but it goes without saying that the configuration
language and the translation code have undergone some substantial
changes to accommodate the MIDI input and output facilities.
The Jack MIDI backend is based on code from Spencer Jackson's osc2midi
utility, and on the simple_session_client.c example available in the
Jack git repository.