1442 lines
57 KiB
Groff
1442 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 the translation denotes the MIDI
|
|
message to be translated.
|
|
The corresponding right\-hand side (the rest of the line) 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
|
|
\f[B]NOTE:\f[] Translations must be determined \f[I]uniquely\f[] in each
|
|
translation class.
|
|
That is, each input message may be bound to at most one output sequence
|
|
in each section.
|
|
Otherwise, the parser will print an error message, and the extra
|
|
translations will be ignored.
|
|
This also ensures that the output sequence completely determines the
|
|
order in which the events for each given input will be output, so that
|
|
midizap's operation is deterministic (i.e., for the same input sequence
|
|
on the same window the program will always generate exactly the same
|
|
output sequence).
|
|
.SS MIDI Message Notation
|
|
.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).
|
|
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
|
|
The other messages are denoted using short mnemonics: \f[C]KP\f[]
|
|
(aftertouch a.k.a.
|
|
key pressure; followed by the colon and a note designation); \f[C]CC\f[]
|
|
(control change, followed by a controller number); \f[C]PC\f[] (program
|
|
change, followed by a program number); \f[C]CP\f[] and \f[C]PB\f[]
|
|
(channel pressure and pitch bend; these don't have a numeric suffix, as
|
|
they apply to the entire MIDI channel).
|
|
.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 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
|
|
Note that since translations are determined uniquely in each translation
|
|
class, you can't have both a key \f[I]and\f[] a data translation for the
|
|
same input in the same section; it's either one or the other.
|
|
.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.
|
|
.SS Keyboard and Mouse Translations
|
|
.PP
|
|
Keyboard and mouse output 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.
|
|
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.
|
|
.PP
|
|
midizap lacks an option to run with real\-time priorities right now.
|
|
Use chrt(1) instead.
|
|
For instance: \f[C]chrt\ 90\ midizap\ \-o\f[].
|
|
This should only be needed when MIDI output is enabled and you
|
|
experience bad latency or jitter in MIDI output.
|
|
With chrt, midizap should be able to get down to MIDI latencies in the 1
|
|
msec ballpark which should be good enough for most purposes (YMMV,
|
|
though).
|
|
.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.
|