From dc626710e6c0cb7634c159eebcc5242241f402fb Mon Sep 17 00:00:00 2001 From: Albert Graef Date: Fri, 16 Nov 2018 21:16:00 +0100 Subject: [PATCH] Install midizap-mode automatically if Emacs is found during installation. Update the documentation. --- Makefile | 12 + README.md | 2 +- midizap-mode.el.in | 21 +- midizap.1 | 1937 ++++++++++++++++++++++---------------------- 4 files changed, 990 insertions(+), 982 deletions(-) diff --git a/Makefile b/Makefile index 89b54a0..686403e 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,12 @@ bindir=$(DESTDIR)$(prefix)/bin mandir=$(DESTDIR)$(prefix)/share/man/man1 datadir=$(DESTDIR)/etc +# See whether emacs is installed and try to guess its installation prefix. +emacs_prefix = $(patsubst %/bin/emacs,%,$(shell which emacs 2>/dev/null)) +ifneq ($(strip $(emacs_prefix)),) +elispdir = $(emacs_prefix)/share/emacs/site-lisp +endif + # Check to see whether we have Jack installed. Needs pkg-config. JACK := $(shell pkg-config --libs jack 2>/dev/null) @@ -27,6 +33,12 @@ install: all install -d $(bindir) $(datadir) $(mandir) install midizap $(bindir) install -m 0644 example.midizaprc $(datadir)/midizaprc +ifneq ($(elispdir),) +# If emacs was found, or elispdir was specified manually, install +# midizap-mode.el into the elispdir directory. + install -d $(DESTDIR)$(elispdir) + install -m 0644 midizap-mode.el $(DESTDIR)$(elispdir) +endif # If present, the manual page will be installed along with the program. ifneq ($(findstring midizap.1, $(INSTALL_TARGETS)),) install -m 0644 midizap.1 $(mandir) diff --git a/README.md b/README.md index f945435..9b019eb 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ First, make sure that you have the required dependencies installed. The program Then just run `make` and `sudo make install`. 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 `prefix` variable in the Makefile. Also, package maintainers can use the `DESTDIR` variable to install into a staging directory for packaging purposes. -For users of the Emacs text editor we provide a midizap mode which does syntax-highlighting of midizaprc files and also lets you launch a midizap session in an Emacs buffer. The mode isn't installed automatically, but you can do this manually by copying the midizap-mode.el file to a directory on your Emacs load-path; please check midizap-mode.el in the sources for more detailed instructions. +For users of the Emacs text editor we provide a midizap mode which does syntax-highlighting of midizaprc files and also lets you launch a midizap session in an Emacs buffer. If Emacs was found during installation, the midizap-mode.el file is installed into the share/emacs/site-lisp directory along with the other files. The Makefile tries to guess the proper installation prefix, but if necessary you can also set the `elispdir` variable or copy the file manually to a directory on your Emacs load-path. Please check midizap-mode.el for more detailed instructions. # Configuration File diff --git a/midizap-mode.el.in b/midizap-mode.el.in index e6ddbc2..d6b5321 100644 --- a/midizap-mode.el.in +++ b/midizap-mode.el.in @@ -27,20 +27,17 @@ (require 'comint) (defconst midizap-keywords - (append - (list - "DEBUG_REGEX" "DEBUG_STROKES" "DEBUG_KEYS" "DEBUG_MIDI" - "MIDI_OCTAVE" "JACK_NAME" "JACK_PORTS" - "JACK_IN" "JACK_IN1" "JACK_IN2" - "JACK_OUT" "JACK_OUT1" "JACK_OUT2" - "PASSTHROUGH" "SYSTEM_PASSTHROUGH" - "RELEASE" "SHIFT" "SHIFT1" "SHIFT2" "SHIFT3" "SHIFT4" - "CLASS" "TITLE" - ) - (list + (list + "DEBUG_REGEX" "DEBUG_STROKES" "DEBUG_KEYS" "DEBUG_MIDI" + "MIDI_OCTAVE" "JACK_NAME" "JACK_PORTS" + "JACK_IN" "JACK_IN1" "JACK_IN2" + "JACK_OUT" "JACK_OUT1" "JACK_OUT2" + "PASSTHROUGH" "SYSTEM_PASSTHROUGH" + "RELEASE" "SHIFT" "SHIFT1" "SHIFT2" "SHIFT3" "SHIFT4" + "CLASS" "TITLE" ;; keysyms - ))) + )) ;;;###autoload (define-generic-mode 'midizap-mode diff --git a/midizap.1 b/midizap.1 index 32ecdac..206736c 100644 --- a/midizap.1 +++ b/midizap.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 2.3.1 +.\" Automatically generated by Pandoc 2.4 .\" .TH "midizap" "1" "" "" "" .hy @@ -7,14 +7,12 @@ midizap \[en] control your multimedia applications with MIDI .SH Synopsis .PP -midizap [\-hkn] [\-d[rskmj]] [\-j \f[I]name\f[]] [\-ost[\f[I]n\f[]]] -[\-P[\f[I]prio\f[]]] [[\-r] \f[I]rcfile\f[]] +midizap [\-hkn] [\-d[rskmj]] [\-j \f[I]name\f[R]] [\-ost[\f[I]n\f[R]]] +[\-P[\f[I]prio\f[R]]] [[\-r] \f[I]rcfile\f[R]] .SH Options .TP .B \-h Print a short help message and exit. -.RS -.RE .TP .B \-d[rskmj] Enable various debugging options: r = regex (print matched translation @@ -22,86 +20,68 @@ 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 (print information about the Jack MIDI backend). -Just \f[C]\-d\f[] enables all debugging options. -See Section \f[I]Basic Usage\f[]. -.RS -.RE +Just \f[C]\-d\f[R] enables all debugging options. +See Section \f[I]Basic Usage\f[R]. .TP -.B \-j \f[I]name\f[] +.B \-j \f[I]name\f[R] Set the Jack client name. This overrides the corresponding directive in the configuration file. Default: \[lq]midizap\[rq]. -See Section \f[I]Jack\-Related Options\f[]. -.RS -.RE +See Section \f[I]Jack\-Related Options\f[R]. .TP .B \-k Keep track of key (on/off) status. This may occasionally be useful to deal with quirky controllers sending repeated on or off messages. -See Section \f[I]Key and Data Translations\f[]. -.RS -.RE +See Section \f[I]Key and Data Translations\f[R]. .TP .B \-n No automatic feedback. By default, midizap keeps track of controller feedback from the second -input port if it is enabled (\f[C]\-o2\f[]). +input port if it is enabled (\f[C]\-o2\f[R]). This option lets you disable this feature if the second port is being used for other purposes. -See Section \f[I]Automatic Feedback\f[]. -.RS -.RE +See Section \f[I]Automatic Feedback\f[R]. .TP -.B \-o[\f[I]n\f[]] -Enable MIDI output and set the number of output ports \f[I]n\f[] (1 by +.B \-o[\f[I]n\f[R]] +Enable MIDI output and set the number of output ports \f[I]n\f[R] (1 by default). -Use \f[I]n\f[] = 2 for a second pair of MIDI ports, e.g., for controller -feedback, or \f[I]n\f[] = 0 to disable MIDI output. +Use \f[I]n\f[R] = 2 for a second pair of MIDI ports, e.g., for +controller feedback, or \f[I]n\f[R] = 0 to disable MIDI output. This overrides the corresponding directive in the configuration file. -See Section \f[I]Jack\-Related Options\f[]. -.RS -.RE +See Section \f[I]Jack\-Related Options\f[R]. .TP -.B \-P[\f[I]prio\f[]] +.B \-P[\f[I]prio\f[R]] Run with the given real\-time priority (default: 90). -See Section \f[I]Jack\-Related Options\f[]. -.RS -.RE +See Section \f[I]Jack\-Related Options\f[R]. .TP -.B [\-r] \f[I]rcfile\f[] +.B [\-r] \f[I]rcfile\f[R] Set the configuration file name. -The \f[C]\-r\f[] is optional, but still supported for backward +The \f[C]\-r\f[R] is optional, but still supported for backward compatibility. 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 +exists, or \[ti]/.midizaprc if it exists, /etc/midizaprc otherwise. +See Section \f[I]Configuration File\f[R]. .TP -.B \-s[\f[I]n\f[]] -Pass through system messages from MIDI input to output; \f[I]n\f[] +.B \-s[\f[I]n\f[R]] +Pass through system messages from MIDI input to output; \f[I]n\f[R] optionally specifies the port (0 = none, 1 = first, 2 = second port only), default is pass\-through on both ports (if available). This overrides the corresponding directive in the configuration file. -See Section \f[I]Jack\-Related Options\f[]. -.RS -.RE +See Section \f[I]Jack\-Related Options\f[R]. .TP -.B \-t[\f[I]n\f[]] +.B \-t[\f[I]n\f[R]] Pass through untranslated (non\-system) messages from MIDI input to -output; the meaning of the optional parameter \f[I]n\f[] is the same as -with the \f[C]\-s\f[] option. +output; the meaning of the optional parameter \f[I]n\f[R] is the same as +with the \f[C]\-s\f[R] option. This overrides the corresponding directive in the configuration file. -See Section \f[I]Jack\-Related Options\f[]. -.RS -.RE +See Section \f[I]Jack\-Related Options\f[R]. .SH Description .PP midizap lets you control your multimedia applications using MIDI (https://www.midi.org/), the venerable \[lq]Musical Instrument Digital Interface\[rq] protocol which has been around since the 1980s. -Modern MIDI controllers are usually USB class devices which don't +Modern MIDI controllers are usually USB class devices which don\[cq]t require any special interface or driver, and they are often much cheaper than more specialized gear. With midizap you can leverage these devices to control just about any @@ -112,7 +92,7 @@ It does this by matching the class and title of the focused window 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 +If a matching section cannot be found, or if it doesn\[cq]t define a suitable translation, the program falls back to a set of default translations. .PP @@ -125,9 +105,9 @@ An example.midizaprc file is included in the sources to get you started, and you can find more examples of configuration files for various purposes in the examples subdirectory. .PP -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. +Even if your target application already supports MIDI, midizap\[cq]s +MIDI output option will be useful if your controller can\[cq]t work +directly with the application because of protocol incompatibilities. In particular, you can use midizap to turn any MIDI controller with enough faders and buttons into a Mackie\-compatible device ready to be used with most DAW (digital audio workstation) programs. @@ -145,29 +125,32 @@ 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: +everything that\[cq]s needed by running this command: .IP .nf \f[C] -sudo\ apt\ install\ build\-essential\ libx11\-dev\ libxtst\-dev\ libjack\-dev -\f[] +sudo apt install build\-essential libx11\-dev libxtst\-dev libjack\-dev +\f[R] .fi .PP -Then just run \f[C]make\f[] and \f[C]sudo\ make\ install\f[]. +Then just run \f[C]make\f[R] and \f[C]sudo make install\f[R]. 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 to +be changed with the \f[C]prefix\f[R] variable in the Makefile. +Also, package maintainers can use the \f[C]DESTDIR\f[R] variable to install into a staging directory for packaging purposes. .PP For users of the Emacs text editor we provide a midizap mode which does syntax\-highlighting of midizaprc files and also lets you launch a midizap session in an Emacs buffer. -The mode isn't installed automatically, but you can do this manually by -copying the midizap\-mode.el file to a directory on your Emacs -load\-path; please check midizap\-mode.el in the sources for more -detailed instructions. +If Emacs was found during installation, the midizap\-mode.el file is +installed into the share/emacs/site\-lisp directory along with the other +files. +The Makefile tries to guess the proper installation prefix, but if +necessary you can also set the \f[C]elispdir\f[R] variable or copy the +file manually to a directory on your Emacs load\-path. +Please check midizap\-mode.el for more detailed instructions. .SH Configuration File .PP After installation the system\-wide default configuration file will be @@ -177,15 +160,16 @@ We recommend copying this file to your home directory, renaming it to .IP .nf \f[C] -cp\ /etc/midizaprc\ ~/.midizaprc -\f[] +cp /etc/midizaprc \[ti]/.midizaprc +\f[R] .fi .PP -The ~/.midizaprc file, if it exists, takes priority over /etc/midizaprc, -so it becomes your personal default midizap configuration. +The \[ti]/.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. +example; you\[cq]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 name of the midizaprc file on the command @@ -196,8 +180,8 @@ E.g., to try one of the sample configurations in the sources: .IP .nf \f[C] -midizap\ examples/APCmini.midizaprc -\f[] +midizap examples/APCmini.midizaprc +\f[R] .fi .PP The program automatically reloads the midizaprc file whenever it notices @@ -212,14 +196,14 @@ below to see exactly how your translations are being processed. 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. -If you're an Emacs user, you can conveniently edit and launch midizap -configurations using midizap's Emacs mode; please check the +(see \f[I]Jack\-Related Options\f[R] below) or from your desktop +environment\[cq]s startup files once you\[cq]ve set up everything to +your liking. +If you\[cq]re an Emacs user, you can conveniently edit and launch +midizap configurations using midizap\[cq]s Emacs mode; please check the midizap\-mode.el file included in the sources for details. .PP -Try \f[C]midizap\ \-h\f[] for a brief summary of the available options +Try \f[C]midizap \-h\f[R] 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 @@ -227,8 +211,8 @@ and output, so you need to be able to run Jack and connect the Jack MIDI inputs and outputs of the program. We recommend using a Jack front\-end and patchbay program like QjackCtl (https://qjackctl.sourceforge.io/) for this purpose. -In QjackCtl's setup, make sure that you have selected \f[C]seq\f[] as -the MIDI driver. +In QjackCtl\[cq]s setup, make sure that you have selected \f[C]seq\f[R] +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. @@ -236,27 +220,27 @@ As an alternative, you can also run a2jmidid (http://repo.or.cz/a2jmidid.git) as a separate ALSA\-Jack MIDI bridge. The latter method works well with both Jack1 and Jack2. -Jack's built\-in bridge also does the job in Jack1, but in Jack2 it -doesn't list the ALSA ports by their name, so it's better to use +Jack\[cq]s built\-in bridge also does the job in Jack1, but in Jack2 it +doesn\[cq]t list the ALSA ports by their name, so it\[cq]s better to use a2jmidid in that case. When in doubt, just use a2jmidid. You can have QJackCtl autostart a2jmidid by placing the command -\f[C]a2jmidid\ \-e\ &\f[] into the \[lq]Execute script after -Startup\[rq] field which can be found under \[lq]Options\[rq] in -QJackctl's Setup dialog. +\f[C]a2jmidid \-e &\f[R] into the \[lq]Execute script after Startup\[rq] +field which can be found under \[lq]Options\[rq] in QJackctl\[cq]s Setup +dialog. .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 +connected, and try running \f[C]midizap\f[R] 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 (or the \f[C]a2j\f[] client, if you're using -a2jmidid). +\f[C]midizap\f[R] with one MIDI input port named \f[C]midi_in\f[R]. +That\[cq]s the one you need to connect to your MIDI controller, whose +output port should be visible under the \f[C]alsa_midi\f[R] client on +the left side of the dialog (or the \f[C]a2j\f[R] client, if you\[cq]re +using a2jmidid). .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 @@ -268,69 +252,70 @@ Here is the relevant excerpt from that section: \f[C] [Default] -\ C5\ \ \ \ XK_Button_1 -\ D5\ \ \ \ XK_Button_2 -\ E5\ \ \ \ XK_Button_3 + C5 XK_Button_1 + D5 XK_Button_2 + E5 XK_Button_3 -\ F5\ \ \ \ XK_Left -\ G5\ \ \ \ XK_Up -\ A5\ \ \ \ XK_Down -\ B5\ \ \ \ XK_Right + F5 XK_Left + G5 XK_Up + A5 XK_Down + B5 XK_Right -\ CC1+\ \ XK_Scroll_Up -\ CC1\-\ \ XK_Scroll_Down -\f[] + CC1+ XK_Scroll_Up + CC1\- XK_Scroll_Down +\f[R] .fi .PP -We refer to Section \f[I]Translation Syntax\f[] below for a discussion +We refer to Section \f[I]Translation Syntax\f[R] 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. +\f[C]C5\f[R] thru \f[C]B5\f[R]) 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. +Also, moving the modulation wheel (\f[C]CC1\f[R]) on your keyboard +should scroll the window contents up and down. .PP You can invoke the program with various debugging options to get more verbose output. -E.g., try running \f[C]midizap\ \-drk\f[] to have the program print the +E.g., try running \f[C]midizap \-drk\f[R] 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'll see something like: +You\[cq]ll 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[] +$ midizap \-drk +Loading configuration: /home/user/.midizaprc +translation: Default for emacs\[at]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[R] .fi .PP The debugging output tells you pretty much everything you need to know -about what's going on inside midizap, and helps you along when you start -developing your own configurations. -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[] +about what\[cq]s going on inside midizap, and helps you along when you +start developing your own configurations. +The \f[C]\-d\f[R] option can be combined with various option characters +to choose exactly which kinds of debugging output you want; \f[C]r\f[R] (\[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[] +with the window name and class of the focused window; \f[C]s\f[R] (\[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[] +in a human\-readable form whenever the file is loaded; \f[C]k\f[R] (\[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[] received MIDI input, so that you +executes them, in the same format as \f[C]s\f[R]; \f[C]m\f[R] +(\[lq]MIDI\[rq]) prints \f[I]any\f[R] received 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 useful information about +for your controller; and \f[C]j\f[R] adds some useful information about the Jack backend, so that you see when the Jack client is ready, and which MIDI ports it gets connected to. -You can also just use \f[C]\-d\f[] to enable all debugging output. +You can also just use \f[C]\-d\f[R] to enable all debugging output. Moreover, most of these options are also available as directives in the midizaprc file, so that you can turn them on and off as needed without having to exit the program; please check the comments at the beginning @@ -348,14 +333,14 @@ and favorite applications. .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[]. +MIDI output is enabled by running the program as \f[C]midizap \-o\f[R]. 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). +\f[C]midi_out\f[R] (visible on the left side of QjackCtl\[cq]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[] +special \f[C][MIDI]\f[R] default section for illustration purposes. +This section is only active if the program is run with the \f[C]\-o\f[R] option. It allows MIDI output to be sent to any connected applications, no matter which window currently has the keyboard focus. @@ -365,15 +350,15 @@ 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[] +You can try it and test that it works by running \f[C]midizap \-o\f[R] 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 +Use QjackCtl to connect FluidSynth\[cq]s MIDI input to midizap\[cq]s +output port. +In the sample configuration, the notes \f[C]C4\f[R] thru \f[C]F4\f[R] in the small octave have been set up so that you can use them to operate a -little drumkit, and a binding for the volume controller (\f[C]CC7\f[]) +little drumkit, and a binding for the volume controller (\f[C]CC7\f[R]) has been added as well. The relevant portion from the configuration entry looks as follows: .IP @@ -381,89 +366,90 @@ The relevant portion from the configuration entry looks as follows: \f[C] [MIDI] -\ C4\ \ \ \ C3\-10 -\ D4\ \ \ \ C#3\-10 -\ E4\ \ \ \ D3\-10 -\ F4\ \ \ \ D#3\-10 + C4 C3\-10 + D4 C#3\-10 + E4 D3\-10 + F4 D#3\-10 -\ CC7=\ \ CC7\-10 -\f[] + CC7= CC7\-10 +\f[R] .fi .PP -Note the \f[C]\-10\f[] suffix on the output messages in the above +Note the \f[C]\-10\f[R] 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. -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[]), +E.g., the input note \f[C]C4\f[R] is mapped to \f[C]C3\-10\f[R], 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[R]) at the end of the +entry sends volume changes to the same drum channel (\f[C]CC7\-10\f[R]), so that you can use the volume control on your keyboard to change the volume on the drum channel. .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[] +Besides MIDI notes and control change (\f[C]CC\f[R]) messages, the +midizap program also recognizes key and channel pressure (\f[C]KP\f[R], +\f[C]CP\f[R]), program change (\f[C]PC\f[R]), and pitch bend +(\f[C]PB\f[R]) messages, which should cover most common use cases. +These are discussed in more detail in the \f[I]Translation Syntax\f[R] section below. In addition, unrecognized MIDI messages can be simply passed through -with the \f[C]\-t\f[] option. +with the \f[C]\-t\f[R] option. Also, while midizap cannot translate system messages such as system -exclusive, you can pass them through as well with the \f[C]\-s\f[] +exclusive, you can pass them through as well with the \f[C]\-s\f[R] option, see the following section for details. .SH Jack\-Related Options .PP There are some additional directives (and corresponding command line -options) to configure midizap's Jack setup in various ways. +options) to configure midizap\[cq]s Jack setup in various ways. If both the command line options and directives in the midizaprc file -are used, the former take priority, so that it's possible to override -the configuration settings from the command line. +are used, the former take priority, so that it\[cq]s possible to +override the configuration settings from the command line. Note that all these options can only be set at program startup. If you later edit the corresponding directives in the configuration -file, the changes won't take effect until you restart the program. +file, the changes won\[cq]t take effect until you restart the program. .SS Jack Client Name and MIDI Port Setup .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. +Firstly, there\[cq]s the \f[C]\-j\f[R] option and the +\f[C]JACK_NAME\f[R] directive which change the Jack client name from the +default (\f[C]midizap\f[R]) 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 +\f[C]midizap \-j client\-name\f[R], or put the following directive into your midizaprc file: .IP .nf \f[C] -JACK_NAME\ "client\-name" -\f[] +JACK_NAME \[dq]client\-name\[dq] +\f[R] .fi .PP -This option is useful, in particular, if you're running multiple +This option is useful, in particular, if you\[cq]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 differently, so that they can be identified more easily. .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 +Secondly, we\[cq]ve already seen the \f[C]\-o\f[R] 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[R] directive in the midizaprc file, as follows: .IP .nf \f[C] -JACK_PORTS\ 1 -\f[] +JACK_PORTS 1 +\f[R] .fi .PP The given number of output ports must be 0, 1 or 2. Zero means that MIDI output is disabled (which is the default). -You may want to use \f[C]JACK_PORTS\ 1\f[] if the configuration is -primarily aimed at doing MIDI translations, so you'd like to have MIDI -output enabled by default. -\f[C]JACK_PORTS\ 2\f[] or the \f[C]\-o2\f[] option indicates that -\f[I]two\f[] pairs of input and output ports are to be created. +You may want to use \f[C]JACK_PORTS 1\f[R] if the configuration is +primarily aimed at doing MIDI translations, so you\[cq]d like to have +MIDI output enabled by default. +\f[C]JACK_PORTS 2\f[R] or the \f[C]\-o2\f[R] option indicates that +\f[I]two\f[R] pairs of input and output ports are to be created. The second port is typically used to deal with controller feedback from -the application, see the \f[I]MIDI Feedback\f[] section for details. +the application, see the \f[I]MIDI Feedback\f[R] section for details. .PP Not very surprisingly, at least one output port is needed if you want to output any MIDI at all; otherwise MIDI messages on the right\-hand side @@ -473,23 +459,23 @@ of translations will be silently ignored. Setting up all the required connections for the Jack MIDI ports can be a tedious and error\-prone task, especially if you have to deal with complex setups involving feedback and/or multiple midizap instances. -It's all to easy to mess this up when doing it manually, and end up with -a dysfunctional setup or, even worse, MIDI feedback loops crashing your -Jack MIDI clients. -While it's possible to automatize the MIDI connections, e.g., with -QjackCtl's persistent MIDI patchbay facility, this is often inconvenient -if you need to accommodate multiple midizap configurations and you -already have a complicated studio setup which you don't want to mess -with. +It\[cq]s all to easy to mess this up when doing it manually, and end up +with a dysfunctional setup or, even worse, MIDI feedback loops crashing +your Jack MIDI clients. +While it\[cq]s possible to automatize the MIDI connections, e.g., with +QjackCtl\[cq]s persistent MIDI patchbay facility, this is often +inconvenient if you need to accommodate multiple midizap configurations +and you already have a complicated studio setup which you don\[cq]t want +to mess with. .PP As a remedy, midizap offers its own built\-in patchbay functionality -using the \f[C]JACK_IN\f[] and \f[C]JACK_OUT\f[] directives, which let +using the \f[C]JACK_IN\f[R] and \f[C]JACK_OUT\f[R] directives, which let you specify the required connections in the configuration itself and be done with it. The port number is tacked on to the directive, so, e.g., -\f[C]JACK_IN2\f[] connects the second input port. +\f[C]JACK_IN2\f[R] connects the second input port. If the port number is omitted then it defaults to 1, so both -\f[C]JACK_OUT1\f[] and just \f[C]JACK_OUT\f[] connect the first output +\f[C]JACK_OUT1\f[R] and just \f[C]JACK_OUT\f[R] connect the first output port. The directive is followed by a regular expression to be matched against the Jack MIDI ports of your devices and applications. @@ -505,24 +491,25 @@ This also works dynamically, as new devices get added and new applications are launched at runtime. .PP For instance, the following lines (from the XTouchONE.midizaprc example) -connect midizap to an X\-Touch One device on one side and Ardour's +connect midizap to an X\-Touch One device on one side and Ardour\[cq]s Mackie control port on the other: .IP .nf \f[C] -JACK_IN1\ \ X\-Touch\ One\ MIDI\ 1 -JACK_OUT1\ ardour:mackie\ control\ in -JACK_IN2\ \ ardour:mackie\ control\ out -JACK_OUT2\ X\-Touch\ One\ MIDI\ 1 -\f[] +JACK_IN1 X\-Touch One MIDI 1 +JACK_OUT1 ardour:mackie control in +JACK_IN2 ardour:mackie control out +JACK_OUT2 X\-Touch One MIDI 1 +\f[R] .fi .PP To break this down, the X\-Touch One device will be connected to -midizap's first input port, midizap's first output port to Ardour's -Mackie control input, Ardour's Mackie control output to midizap's second -input port, and midizap's second output port back to the device. +midizap\[cq]s first input port, midizap\[cq]s first output port to +Ardour\[cq]s Mackie control input, Ardour\[cq]s Mackie control output to +midizap\[cq]s second input port, and midizap\[cq]s second output port +back to the device. This is a typical setup for bidirectional communication between -controller and application as described in the \f[I]MIDI Feedback\f[] +controller and application as described in the \f[I]MIDI Feedback\f[R] section. The sample configurations in the examples folder in the sources have all been set up in this manner, so that they will create the required @@ -535,38 +522,38 @@ Also, only one directive can be specified for each port, but since midizap will connect to all ports matching the given regular expression, you can connect to more than one application or device by just listing all the alternatives. -For instance, to have midizap's output connected to both Ardour and Pd, -you might use a directive like: +For instance, to have midizap\[cq]s output connected to both Ardour and +Pd, you might use a directive like: .IP .nf \f[C] -JACK_OUT1\ ardour:MIDI\ control\ in|Pure\ Data\ Midi\-In\ 1 -\f[] +JACK_OUT1 ardour:MIDI control in|Pure Data Midi\-In 1 +\f[R] .fi .PP All matches are done against full port names including the -\f[I]client\-name\f[]\f[C]:\f[] prefix, so you can specify exactly which -ports of which clients should be connected. +\f[I]client\-name\f[R]\f[C]:\f[R] prefix, so you can specify exactly +which ports of which clients should be connected. However, note that in contrast to the QJackCtl patchbay, midizap does -substring matches by default, so that, e.g., \f[C]MIDI\ control\f[] will -match \f[I]any\f[] Ardour MIDI control port, in any instance of the +substring matches by default, so that, e.g., \f[C]MIDI control\f[R] will +match \f[I]any\f[R] Ardour MIDI control port, in any instance of the program (and also ports with the same name in other programs). -If you want to specify an exact match, you need to use the \f[C]^\f[] -and \f[C]$\f[] anchors as follows: +If you want to specify an exact match, you need to use the +\f[C]\[ha]\f[R] and \f[C]$\f[R] anchors as follows: .IP .nf \f[C] -JACK_OUT1\ ^ardour:MIDI\ control\ in$ -\f[] +JACK_OUT1 \[ha]ardour:MIDI control in$ +\f[R] .fi .SS Pass\-Through .PP If at least one output port is available then it also becomes possible to pass through MIDI messages from input to output unchanged. -Two options are available for this: \f[C]\-t\f[] which passes through +Two options are available for this: \f[C]\-t\f[R] which passes through any ordinary (non\-system) message for which there are no translations -(not even in the default section), and \f[C]\-s\f[] which passes through -all system messages. +(not even in the default section), and \f[C]\-s\f[R] which passes +through all system messages. The former is convenient if the incoming MIDI data only needs to be modified in a few places to deal with slight variations in the protocol. The latter may be needed when the input data may contain system @@ -575,32 +562,32 @@ unchanged when necessary. You can find examples for both use cases in the examples folder in the sources. .PP -The corresponding directives are named \f[C]PASSTHROUGH\f[] and -\f[C]SYSTEM_PASSTHROUGH\f[], respectively. +The corresponding directives are named \f[C]PASSTHROUGH\f[R] and +\f[C]SYSTEM_PASSTHROUGH\f[R], respectively. In either case, you can optionally specify which port the pass\-through should apply to (0 means none, 1 the first, 2 the second port; if no number is given, both ports are used). For instance, if you only need system pass\-through on the feedback -port, you might write \f[C]SYSTEM_PASSTHROUGH\ 2\f[], or use the -\f[C]\-s2\f[] option on the command line; and to have unrecognized MIDI +port, you might write \f[C]SYSTEM_PASSTHROUGH 2\f[R], or use the +\f[C]\-s2\f[R] option on the command line; and to have unrecognized MIDI messages passed through in either direction, simply use -\f[C]PASSTHROUGH\f[], or \f[C]\-t\f[]. +\f[C]PASSTHROUGH\f[R], or \f[C]\-t\f[R]. .SS Jack Sessions .PP -midizap also supports \f[I]Jack session management\f[] which provides a +midizap also supports \f[I]Jack session management\f[R] which provides a convenient alternative way to launch your midizap instances. -Once you've finished a configuration, instead of running midizap +Once you\[cq]ve finished a configuration, instead of running midizap manually each time you need it, you just invoke it once with the right command line options, and use a Jack session management program to record the session. The session manager can then be used to relaunch the program with the same options later. .PP -Various Jack session managers are available for Linux, but if you're +Various Jack session managers are available for Linux, but if you\[cq]re running QjackCtl already, you might just as well use it to record your sessions, too. -QjackCtl's built\-in Jack session manager is available in its Session -dialog. +QjackCtl\[cq]s built\-in Jack session manager is available in its +Session dialog. To use it, 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] button in the Session dialog to @@ -612,13 +599,13 @@ menu from where they can be launched quickly. .SS Realtime Priorities .PP Finally, midizap also offers an option to run the program with -\f[I]real\-time priorities\f[]. -Jack itself usually does that anyway where needed, but midizap's main -thread won't unless you run it with the \f[C]\-P\f[] option. +\f[I]real\-time priorities\f[R]. +Jack itself usually does that anyway where needed, but midizap\[cq]s +main thread won\[cq]t unless you run it with the \f[C]\-P\f[R] option. Using this option, midizap should be able to get down to MIDI latencies in the 1 msec ballpark which should be good enough for most purposes. -(Note that there's no need to use this option unless you actually notice -high latencies or jitter in the MIDI output.) +(Note that there\[cq]s no need to use this option unless you actually +notice high latencies or jitter in the MIDI output.) .SH Translation Syntax .PP The midizap configuration file consists of sections defining translation @@ -629,73 +616,73 @@ the window class or title, and a list of translations: .IP .nf \f[C] -[name]\ regex -<#b><0..12>\ output\ \ #\ note -KP:\ 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[] +[name] regex +<#b><0..12> output # note +KP: 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[R] .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. +The \f[C]#\f[R] 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 -Lines beginning with a \f[C][\f[]\f[I]name\f[]\f[C]]\f[] header are also -special. -Each such line introduces a translation class \f[I]name\f[], which may -be followed by an extended regular expression \f[I]regex\f[] to be +Lines beginning with a \f[C][\f[R]\f[I]name\f[R]\f[C]]\f[R] header are +also special. +Each such line introduces a translation class \f[I]name\f[R], which may +be followed by an extended regular expression \f[I]regex\f[R] to be matched against window class and title. -A \f[C]CLASS\f[] or \f[C]TITLE\f[] token may precede \f[I]regex\f[] to -indicate that \f[I]only\f[] the class or title is to be matched, +A \f[C]CLASS\f[R] or \f[C]TITLE\f[R] token may precede \f[I]regex\f[R] +to indicate that \f[I]only\f[R] the class or title is to be matched, respectively; otherwise both are matched. -Note that the \f[I]regex\f[] part is always taken verbatim, ignoring +Note that the \f[I]regex\f[R] part is always taken verbatim, ignoring leading and trailing whitespace, but including embedded whitespace and -\f[C]#\f[] characters (so you can't place a comment on such lines). +\f[C]#\f[R] characters (so you can\[cq]t place a comment on such lines). .PP To find a set of eligible translations, midizap matches class and/or title of the window with the keyboard focus against each section, in the order in which they are listed in the configuration file. -If neither \f[C]CLASS\f[] nor \f[C]TITLE\f[] is specified, then both are -tried; in this case, midizap first tries to match the window class (the -\f[C]WM_CLASS\f[] property), then the window title (the \f[C]WM_NAME\f[] -property). +If neither \f[C]CLASS\f[R] nor \f[C]TITLE\f[R] is specified, then both +are tried; in this case, midizap first tries to match the window class +(the \f[C]WM_CLASS\f[R] property), then the window title (the +\f[C]WM_NAME\f[R] property). The first section which matches determines the translations to be used for that window. -An empty \f[I]regex\f[] for the last class will always match, allowing +An empty \f[I]regex\f[R] for the last class will always match, allowing default translations. If a translation cannot be found in the matched section, it will be loaded from the default section if possible. In addition, there are two special default sections labeled -\f[C][MIDI]\f[] and \f[C][MIDI2]\f[] which are used specifically for -MIDI translations, please see the \f[I]MIDI Output\f[] and \f[I]MIDI -Feedback\f[] sections for details. +\f[C][MIDI]\f[R] and \f[C][MIDI2]\f[R] which are used specifically for +MIDI translations, please see the \f[I]MIDI Output\f[R] and \f[I]MIDI +Feedback\f[R] sections for details. If these sections are present, they should precede the main default section. All other sections, including the main default section, can be named any -way you like; the given \f[I]name\f[] is only used for debugging output -and diagnostics, and needn't be unique. +way you like; the given \f[I]name\f[R] is only used for debugging output +and diagnostics, and needn\[cq]t be unique. .PP This means that when you start writing a section for a new application, -the first thing you'll have to do is determine its window class and +the first thing you\[cq]ll have to do is determine its window class and title, so that you can figure out a regular expression to use in the corresponding section header. -The easiest way to do this is to run midizap with the \f[C]\-dr\f[] +The easiest way to do this is to run midizap with the \f[C]\-dr\f[R] option. Make sure that your controller is hooked up to midizap, click on the window and wiggle any control on your device. -You'll get a message like the following, telling you both the title and -the class name of the window (as well as the name of the translation +You\[cq]ll get a message like the following, telling you both the title +and the class name of the window (as well as the name of the translation class if the window is already recognized): .IP .nf \f[C] -translation:\ Default\ for\ mysession\ \-\ Ardour\ (class\ ardour_ardour) -\f[] +translation: Default for mysession \- Ardour (class ardour_ardour) +\f[R] .fi .PP Here, the class name is \[lq]ardour_ardour\[rq] and the window title @@ -706,28 +693,28 @@ So we might begin a translation section for Ardour as follows: .IP .nf \f[C] -[Ardour]\ CLASS\ ^ardour_ardour$ -\f[] +[Ardour] CLASS \[ha]ardour_ardour$ +\f[R] .fi .PP Here we explicitly specified that only the window class is to be matched -and we employed the \f[C]^\f[] and \f[C]$\f[] anchors to ensure that the -entire string is matched, so this section will match precisely Ardour -windows and nothing else. +and we employed the \f[C]\[ha]\f[R] and \f[C]$\f[R] anchors to ensure +that the entire string is matched, so this section will match precisely +Ardour windows and nothing else. We could also write, rather sloppily: .IP .nf \f[C] -[Ardour]\ [Aa]rdour -\f[] +[Ardour] [Aa]rdour +\f[R] .fi .PP This will match any window which has the string \[lq]Ardour\[rq] or -\[lq]ardour\[rq] \f[I]anywhere\f[] in its class or title, so it will +\[lq]ardour\[rq] \f[I]anywhere\f[R] in its class or title, so it will match Ardour windows, but also, say, the window of a text editor which happens to have a file named \[lq]Ardour.txt\[rq] loaded. So while regular expressions give you a lot of leeway in identifying -windows, it's always a good idea to be as specific with the regex as +windows, it\[cq]s always a good idea to be as specific with the regex as possible. .PP The header is followed by a list of translations which define what @@ -738,21 +725,22 @@ message to be translated. The corresponding right\-hand side (the rest of the line) is a sequence of zero or more tokens, separated by whitespace, indicating MIDI and X11 keyboard and mouse events to be output. -The output sequence may be empty, or just the special token \f[C]NOP\f[] -(which doesn't produce any output), to indicate that the translation -outputs nothing at all; this suppresses the default translation for this -input. +The output sequence may be empty, or just the special token +\f[C]NOP\f[R] (which doesn\[cq]t produce any output), to indicate that +the translation outputs nothing at all; this suppresses the default +translation for this input. Translation classes may be empty as well (i.e., not provide any -translations), in which case \f[I]only\f[] the default translations are +translations), in which case \f[I]only\f[R] the default translations are active, even if a later non\-default section matches the same window. .PP -\f[B]NOTE:\f[] Translations may be listed in any order, but they -\f[I]must be determined uniquely\f[], i.e., each input message may be +\f[B]NOTE:\f[R] Translations may be listed in any order, but they +\f[I]must be determined uniquely\f[R], i.e., each input message may be bound to at most one output sequence in each translation class. Otherwise, the parser will print an error message, and the extra translations will be ignored. This restriction makes it easier to detect inconsistencies, and it also -ensures that midizap's operation is completely \f[I]deterministic\f[]. +ensures that midizap\[cq]s operation is completely +\f[I]deterministic\f[R]. That is, for each input sequence on a given window the program will always generate exactly the same output sequence. .PP @@ -760,45 +748,46 @@ Example: .IP .nf \f[C] -[Terminal]\ CLASS\ ^(.*\-terminal.*|konsole|xterm)$ -\ F5\ \ \ \ XK_Up -\ F#5\ \ \ "pwd" -\ G5\ \ \ \ XK_Down -\ G#5\ \ \ "ls" -\ A5\ \ \ \ XK_Return -\f[] +[Terminal] CLASS \[ha](.*\-terminal.*|konsole|xterm)$ + F5 XK_Up + F#5 \[dq]pwd\[dq] + G5 XK_Down + G#5 \[dq]ls\[dq] + A5 XK_Return +\f[R] .fi .PP This binds a few keys in the middle octave to the Up, Down and Return keys as well as some frequently used shell commands, in a section named -\f[C]Terminal\f[] which matches some common types of terminal windows by -their class names. +\f[C]Terminal\f[R] which matches some common types of terminal windows +by their class names. The bindings in this translation class will let you operate the shell from your MIDI keyboard when the keyboard focus is on a terminal window. .SS MIDI Message Notation .PP -There's no real standard for symbolic designations of MIDI messages, but -we hope that most users will find midizap's notation easy to understand -and remember. +There\[cq]s no real standard for symbolic designations of MIDI messages, +but we hope that most users will find midizap\[cq]s notation easy to +understand and remember. Notes are specified using a format which musicians will find familiar: a -note name \f[C]A\f[], \f[C]B\f[], \&..., \f[C]G\f[] is followed by an -(optional) accidental (\f[C]#\f[] or \f[C]b\f[]), and a (mandatory) 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 (you can change this if you -want, see \f[I]Octave Numbering\f[] below). -Enharmonic spellings are equivalent, so, e.g., \f[C]D#5\f[] and -\f[C]Eb5\f[] denote exactly the same MIDI note. +note name \f[C]A\f[R], \f[C]B\f[R], \&..., \f[C]G\f[R] is followed by an +(optional) accidental (\f[C]#\f[R] or \f[C]b\f[R]), and a (mandatory) +MIDI octave number. +Note that all MIDI octaves start at the note C, so \f[C]B0\f[R] comes +before \f[C]C1\f[R]. +By default, \f[C]C5\f[R] denotes middle C (you can change this if you +want, see \f[I]Octave Numbering\f[R] below). +Enharmonic spellings are equivalent, so, e.g., \f[C]D#5\f[R] and +\f[C]Eb5\f[R] denote exactly the same MIDI note. .PP The other messages are denoted using short mnemonics: -\f[C]KP:\f[]\f[I]note\f[] (aftertouch a.k.a.\ key pressure for the given -note); \f[C]CC\f[]\f[I]n\f[] (control change for the given controller -number); \f[C]PC\f[]\f[I]n\f[] (program change for the given program -number); \f[C]CP\f[] (channel pressure); and \f[C]PB\f[] (pitch bend). +\f[C]KP:\f[R]\f[I]note\f[R] (aftertouch a.k.a.\ key pressure for the +given note); \f[C]CC\f[R]\f[I]n\f[R] (control change for the given +controller number); \f[C]PC\f[R]\f[I]n\f[R] (program change for the +given program number); \f[C]CP\f[R] (channel pressure); and \f[C]PB\f[R] +(pitch bend). 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. +designations later, but it\[cq]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 @@ -808,79 +797,80 @@ entire configuration language.) .IP .nf \f[C] -token\ ::=\ msg\ [\ "["\ number\ "]"\ ]\ [\ "\-"\ number\ ]\ [\ flag\ ] -msg\ \ \ ::=\ (\ note\ |\ other\ )\ [\ number\ ] -note\ \ ::=\ (\ "A"\ |\ ...\ |\ "G"\ )\ [\ "#"\ |\ "b"\ ] -other\ ::=\ "CH"\ |\ "PB"\ |\ "PC"\ |\ "CC"\ |\ "CP"\ |\ "KP:"\ note -flag\ \ ::=\ "\-"\ |\ "+"\ |\ "="\ |\ "<"\ |\ ">"\ |\ "~" -\f[] +token ::= msg [ \[dq][\[dq] number \[dq]]\[dq] ] [ \[dq]\-\[dq] number ] [ flag ] +msg ::= ( note | other ) [ number ] +note ::= ( \[dq]A\[dq] | ... | \[dq]G\[dq] ) [ \[dq]#\[dq] | \[dq]b\[dq] ] +other ::= \[dq]CH\[dq] | \[dq]PB\[dq] | \[dq]PC\[dq] | \[dq]CC\[dq] | \[dq]CP\[dq] | \[dq]KP:\[dq] note +flag ::= \[dq]\-\[dq] | \[dq]+\[dq] | \[dq]=\[dq] | \[dq]<\[dq] | \[dq]>\[dq] | \[dq]\[ti]\[dq] +\f[R] .fi .PP -Case is ignored here, so \f[C]CC\f[], \f[C]cc\f[] or even \f[C]Cc\f[] +Case is ignored here, so \f[C]CC\f[R], \f[C]cc\f[R] or even \f[C]Cc\f[R] 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 \f[C]msg\f[] number depends on the context (octave +The meaning of the \f[C]msg\f[R] number depends on the context (octave number for notes and key pressure, controller or program number in the range 0..127 for other messages, MIDI channel number in the range 1..16 -for the special \f[C]CH\f[] token). +for the special \f[C]CH\f[R] token). This can optionally be followed by a number in brackets, denoting a nonzero step size. Also optionally, a suffix with a 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 the \f[C]CH\f[] token). +right\-hand side with the \f[C]CH\f[R] token). The optional \[lq]increment\[rq] 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 Translations\f[] -below. +changes rather than key presses, cf.\ \f[I]Key and Data +Translations\f[R] 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 +E.g., there\[cq]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 -seems intuitive to mathematically inclined and computer\-savvy people, -and is also what is used by default in the midizaprc file. +There\[cq]s not really a single \[lq]best\[rq] standard here, but the +latter seems intuitive 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 +However, you may want to change this, e.g., if you\[cq]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 +with the special \f[C]MIDI_OCTAVE\f[R] directive in the configuration file. For instance: .IP .nf \f[C] -MIDI_OCTAVE\ \-1\ #\ ASA\ pitches\ (middle\ C\ is\ C4) -\f[] +MIDI_OCTAVE \-1 # ASA pitches (middle C is C4) +\f[R] .fi .PP -Note that this transposes \f[I]all\f[] existing notes in translations +Note that this transposes \f[I]all\f[R] 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 Translations .PP Translations come in two flavors or \[lq]modes\[rq], \f[I]key -translations\f[] and \f[I]data translations\f[], 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. +translations\f[R] and \f[I]data translations\f[R], which differ in the +way the extra data payload of the input message, called the +\f[I]parameter value\f[R] (or just \f[I]value\f[R] 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. +Program changes (\f[C]PC\f[R]) have no value at all. +For notes, as well as key and channel pressure messages (\f[C]CP\f[R], +\f[C]KP\f[R]), it is a velocity value; for control changes +(\f[C]CC\f[R]), a controller value; and for pitch bend messages +(\f[C]PB\f[R]), a pitch bend value. The latter is 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. @@ -888,22 +878,22 @@ 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 must be determined uniquely in each -translation class, you can't have both key \f[I]and\f[] data -translations for the same input in the same section; it's either one or -the other. +translation class, you can\[cq]t have both key \f[I]and\f[R] data +translations for the same input in the same section; it\[cq]s either one +or the other. .PP -\f[I]Key mode\f[] is the default mode and is available for all message +\f[I]Key mode\f[R] 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 +For pitch bends, any positive \f[I]or\f[R] 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. +don\[cq]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. @@ -911,286 +901,288 @@ afterwards. Key mode can optionally keep track of the current key (on/off) status, so that a key translation is only triggered when its status actually changes. -Normally this shouldn't be necessary and thus it is disabled by default. -You usually want to keep it that way, unless you're dealing with a +Normally this shouldn\[cq]t be necessary and thus it is disabled by +default. +You usually want to keep it that way, unless you\[cq]re dealing with a quirky controller or an unreliable transmission line. -In such cases it may useful to enable this option with the \f[C]\-k\f[] +In such cases it may useful to enable this option with the \f[C]\-k\f[R] option on the command line, so that, e.g., repeated note\-ons or \-offs are filtered out automatically. .PP -\f[I]Data mode\f[] is available for all messages with a parameter value, -i.e., anything but \f[C]PC\f[]. +\f[I]Data mode\f[R] is available for all messages with a parameter +value, i.e., anything but \f[C]PC\f[R]. 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[]). +rule should apply to: increment (\f[C]+\f[R]), decrement (\f[C]\-\f[R]), +or both (\f[C]=\f[R]). 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 \f[I]incremental\f[] data mode +In the following, we concentrate on \f[I]incremental\f[R] data mode messages, i.e., the kind which has 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 more specialized uses, so we'll have a look at it later in -the \f[I]Mod Translations\f[] section. +intended for more specialized uses, so we\[cq]ll have a look at it later +in the \f[I]Mod Translations\f[R] section. .PP -Data mode usually tracks changes in the \f[I]absolute\f[] value of a +Data mode usually tracks changes in the \f[I]absolute\f[R] value of a control. -However, for \f[C]CC\f[] messages there's also an alternative mode for -so\-called \f[I]relative\f[] controllers which can found on some +However, for \f[C]CC\f[R] messages there\[cq]s also an alternative mode +for so\-called \f[I]relative\f[R] controllers which can found on some devices. These usually take the form of jog wheels or rotary encoders which can be turned endlessly in either direction, therefore we also just call -them \f[I]encoders\f[] for short in the following. +them \f[I]encoders\f[R] for short in the following. There are various kinds of these which differ in the way they represent relative changes, but these days most encoders found on MIDI controllers -employ the \f[I]sign bit\f[] format; this is also the only kind +employ the \f[I]sign bit\f[R] format; this is also the only kind supported by midizap in the present implementation. In the sign\-bit representation, a value <64 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, sign\-bit values 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 flags are only permitted with \f[C]CC\f[] messages. +suffixes \f[C]<\f[R], \f[C]>\f[R] and \f[C]\[ti]\f[R] in lieu of +\f[C]\-\f[R], \f[C]+\f[R] and \f[C]=\f[R], respectively. +These flags are only permitted with \f[C]CC\f[R] messages. .SS Keyboard and Mouse Events .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 syntax of these items, as well as the special \f[C]RELEASE\f[R] and +\f[C]SHIFT\f[R] tokens which will be discussed later, are described by the following grammar: .IP .nf \f[C] -token\ \ \ ::=\ "RELEASE"\ |\ "SHIFT"\ [\ number\ ]\ | -\ \ \ \ \ \ \ \ \ \ \ \ keycode\ [\ "/"\ keyflag\ ]\ |\ 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) -keyflag\ ::=\ "U"\ |\ "D"\ |\ "H" -string\ \ ::=\ \[aq]"\[aq]\ {\ character\ }\ \[aq]"\[aq] -\f[] +token ::= \[dq]RELEASE\[dq] | \[dq]SHIFT\[dq] [ number ] | + keycode [ \[dq]/\[dq] keyflag ] | string +keycode ::= \[dq]XK_Button_1\[dq] | \[dq]XK_Button_2\[dq] | \[dq]XK_Button_3\[dq] | + \[dq]XK_Scroll_Up\[dq] | \[dq]XK_Scroll_Down\[dq] | + \[dq]XK_...\[dq] (X keysyms, see /usr/include/X11/keysymdef.h) +keyflag ::= \[dq]U\[dq] | \[dq]D\[dq] | \[dq]H\[dq] +string ::= \[aq]\[dq]\[aq] { character } \[aq]\[dq]\[aq] +\f[R] .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 +Here, case \f[I]is\f[R] significant (except in character strings, see +the remarks below), so the special \f[C]RELEASE\f[R] and \f[C]SHIFT\f[R] +tokens must be in all caps, and the \f[C]XK\f[R] 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 and scroll wheel -events (\f[C]XK_Button_1\f[], \f[C]XK_Scroll_Up\f[], etc.). +events (\f[C]XK_Button_1\f[R], \f[C]XK_Scroll_Up\f[R], etc.). .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 +Any keycode can be followed by an optional \f[C]/D\f[R], \f[C]/U\f[R], +or \f[C]/H\f[R] 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[R], 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[]. +keycodes, \f[C]/U\f[R] can be used to release a modifier that was +previously pressed with \f[C]/D\f[R]. Sequences may also have separate press and release sequences, separated -by the special word \f[C]RELEASE\f[]. +by the special word \f[C]RELEASE\f[R]. 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[] +C5 \[dq]qwer\[dq] +D5 XK_Right +E5 XK_Alt_L/D XK_Right +F5 \[dq]V\[dq] XK_Left XK_Page_Up \[dq]v\[dq] +G5 XK_Alt_L/D \[dq]v\[dq] XK_Alt_L/U \[dq]x\[dq] RELEASE \[dq]q\[dq] +\f[R] .fi .PP Translations are handled differently depending on the input mode -(cf.\ \f[I]Key and Data Translations\f[] above). -In \f[I]key mode\f[], there are separate press and release sequences. +(cf.\ \f[I]Key and Data Translations\f[R] above). +In \f[I]key mode\f[R], 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. +by \f[C]/D\f[R] will be released, and the last key not marked by +\f[C]/D\f[R], \f[C]/U\f[R], or \f[C]/H\f[R] 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 +marked with \f[C]/D\f[R] will be repressed before continuing the sequence. -Keycodes marked with \f[C]/H\f[] remain held between the press and +Keycodes marked with \f[C]/H\f[R] remain held between the press and release sequences. -For instance, let's take a look at one of the more conspicuous +For instance, let\[cq]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[] +G5 XK_Alt_L/D \[dq]v\[dq] XK_Alt_L/U \[dq]x\[dq] RELEASE \[dq]q\[dq] +\f[R] .fi .PP -This translation has the following meaning: 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 +This translation has the following meaning: When the \f[C]G5\f[R] key is +pressed on the MIDI keyboard, the key sequence \f[C]Alt+v x\f[R] is +initiated, keeping the \f[C]x\f[R] 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 +translations) until you release the \f[C]G5\f[R] key again, at which +point the \f[C]x\f[R] key is released and the \f[C]q\f[R] key is pressed (and released). .PP One pitfall here 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 +Thus, e.g., \f[C]\[dq]abc\[dq]\f[R] actually denotes the keysym sequence +\f[C]XK_a XK_b XK_c\f[R], as does \f[C]\[dq]ABC\[dq]\f[R]. +So in either case the \f[I]lowercase\f[R] string \f[C]abc\f[R] 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 +E.g., \f[C]XK_Shift_L/D \[dq]abc\[dq]\f[R] will output \f[C]ABC\f[R] in uppercase. .PP -In \f[I]data mode\f[] only a single sequence is output whenever the +In \f[I]data mode\f[R] only a single sequence is output whenever the message value changes. -So there's no separate \[lq]release\[rq] sequence, and at the end of the -sequence, \f[I]all\f[] down keys will be released. -Instead, data mode distinguishes between \f[I]increments\f[] and -\f[I]decrements\f[] of the input value and outputs the corresponding +So there\[cq]s no separate \[lq]release\[rq] sequence, and at the end of +the sequence, \f[I]all\f[R] down keys will be released. +Instead, data mode distinguishes between \f[I]increments\f[R] and +\f[I]decrements\f[R] of the input value and outputs the corresponding sequence for each unit change. For instance, the following translations move the cursor left or right -whenever the volume controller (\f[C]CC7\f[]) decreases and increases, +whenever the volume controller (\f[C]CC7\f[R]) 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 in close +Thus, if in the example \f[C]CC7\f[R] increases by 4, say, the program +will press (and release) \f[C]XK_Right\f[R] four times in close succession, moving the cursor in the focused window four positions to the right. .IP .nf \f[C] -CC7\-\ XK_Left -CC7+\ XK_Right -\f[] +CC7\- XK_Left +CC7+ XK_Right +\f[R] .fi .PP Sign\-bit encoders 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 big jog wheel -(\f[C]CC60\f[]) on some Mackie devices, 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 increment flag of the \f[C]CC\f[] message): +(\f[C]CC60\f[R]) on some Mackie devices, which can be processed as +follows (using \f[C]<\f[R] and \f[C]>\f[R] in lieu of \f[C]\-\f[R] and +\f[C]+\f[R] as the increment flag of the \f[C]CC\f[R] message): .IP .nf \f[C] -CC60<\ XK_Left -CC60>\ XK_Right -\f[] +CC60< XK_Left +CC60> XK_Right +\f[R] .fi .PP The corresponding \[lq]bidirectional\[rq] translations, which are -indicated with the \f[C]=\f[] and \f[C]~\f[] flags, are mostly used with -MIDI output; the same goes for the special \f[C]SHIFT\f[] token. -Thus we'll discuss these in later sections, see \f[I]MIDI Events\f[] and -\f[I]Shift State\f[] below. +indicated with the \f[C]=\f[R] and \f[C]\[ti]\f[R] flags, are mostly +used with MIDI output; the same goes for the special \f[C]SHIFT\f[R] +token. +Thus we\[cq]ll discuss these in later sections, see \f[I]MIDI +Events\f[R] and \f[I]Shift State\f[R] below. .PP -In data mode, input messages can also have a \f[I]step size\f[] +In data mode, input messages can also have a \f[I]step size\f[R] 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 flag. -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. +A step size \f[I]k\f[R] indicates that the translation is executed +whenever the input value has changed by \f[I]k\f[R] 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[] +CC7[4]\- XK_Left +CC7[4]+ XK_Right +\f[R] .fi .PP The same goes for sign\-bit encoders: .IP .nf \f[C] -CC60[4]<\ XK_Left -CC60[4]>\ XK_Right -\f[] +CC60[4]< XK_Left +CC60[4]> XK_Right +\f[R] .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. +Note that since there\[cq]s no persistent absolute controller state in +this case, this simply scales down the actual increment value in the +message itself. .SS MIDI Events .PP Most of the notation for MIDI messages on the left\-hand side of a translation rule also carries over to the output side. -The only real difference is that the increment flags \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[] flag \f[I]is\f[] allowed, however, to indicate output in -sign\-bit encoder format in data translations, see below. -Step sizes are permitted as well on the output side, in \f[I]both\f[] +The only real difference is that the increment flags \f[C]+\-=<>\f[R] +aren\[cq]t permitted here, as they are only used to determine the input +mode (key or data) of the entire translation. +The \f[C]\[ti]\f[R] flag \f[I]is\f[R] allowed, however, to indicate +output in sign\-bit encoder format in data translations, see below. +Step sizes are permitted as well on the output side, in \f[I]both\f[R] 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). +effect of \f[I]upscaling\f[R] 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 -also need to invoke the midizap program with the \f[C]\-o\f[] option to -make MIDI output work. +However, as already discussed in Section \f[I]MIDI Output\f[R] above, +you also need to invoke the midizap program with the \f[C]\-o\f[R] +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 +There is one special MIDI token \f[C]CH\f[R] 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 +This token doesn\[cq]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[R], which outputs a C major chord on MIDI channel 2, can also be abbreviated as -\f[C]CH2\ C5\ E5\ G5\f[]. +\f[C]CH2 C5 E5 G5\f[R]. .PP Key mode is a lot simpler for MIDI output than with key events; there is -no magic involving \[lq]held\[rq] keys here, and no \f[C]/D\f[], -\f[C]/U\f[] or \f[C]/H\f[] flags (these are only valid with keyboard +no magic involving \[lq]held\[rq] keys here, and no \f[C]/D\f[R], +\f[C]/U\f[R] or \f[C]/H\f[R] flags (these are only valid with keyboard output). By default, the press and release sequences will have exactly the same \[lq]on\[rq] and \[lq]off\[rq] MIDI messages, in the same order as they appear in the given output sequence. -If there's an explicit \f[C]RELEASE\f[] section, however, then the +If there\[cq]s an explicit \f[C]RELEASE\f[R] section, however, then the \[lq]off\[rq] messages in this sequence will be output for the release sequence instead. This allows you to output the \[lq]off\[rq] messages in a different order, or output a completely different release sequence if you want. -(This case arises rarely, though; usually you'll just specify the press -sequence and be done with it.) In either case, the messages will be -output exactly as written. +(This case arises rarely, though; usually you\[cq]ll just specify the +press sequence and be done with it.) In either case, the messages will +be output exactly as written. .PP -For instance, the following rule outputs a \f[C]CC64\f[] (hold pedal) -message with controller value 127 each time \f[C]C3\f[] is pressed, and -another \f[C]CC64\f[] message with value 0 when the note is released +For instance, the following rule outputs a \f[C]CC64\f[R] (hold pedal) +message with controller value 127 each time \f[C]C3\f[R] is pressed, and +another \f[C]CC64\f[R] message with value 0 when the note is released again: .IP .nf \f[C] -C3\ CC64\ #\ hold\ pedal\ on/off -\f[] +C3 CC64 # hold pedal on/off +\f[R] .fi .PP The value for the \[lq]on\[rq] state can also be denoted explicitly with @@ -1198,8 +1190,8 @@ a step size: .IP .nf \f[C] -C3\ CC64[64]\ #\ hold\ pedal\ with\ an\ "on"\ value\ of\ 64 -\f[] +C3 CC64[64] # hold pedal with an \[dq]on\[dq] value of 64 +\f[R] .fi .PP For pitch bends, the step size can also be negative. @@ -1208,30 +1200,30 @@ the maximum amount possible: .IP .nf \f[C] -C2\ PB[\-8192]\ #\ bend\ down -D2\ PB[8191]\ \ #\ bend\ up -\f[] +C2 PB[\-8192] # bend down +D2 PB[8191] # bend up +\f[R] .fi .PP Rules similar to the ones above may be useful if your MIDI keyboard -doesn't have a hold pedal or pitch bend wheel, as they let you set aside -some keys to emulate those functions. +doesn\[cq]t have a hold pedal or pitch bend wheel, as they let you set +aside some keys to emulate those functions. .PP -Let's now have a look at data mode. -There are two additional flags \f[C]=\f[] and \f[C]~\f[] for data +Let\[cq]s now have a look at data mode. +There are two additional flags \f[C]=\f[R] and \f[C]\[ti]\f[R] for data translations which are most useful with MIDI output, which is why we deferred their discussion until now. In pure MIDI translations not involving any key or mouse output, the increment and decrement sequences are usually identical, in which case -the \f[C]=\f[] suffix can be used to indicate that the output is to be -used 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[]): +the \f[C]=\f[R] suffix can be used to indicate that the output is to be +used for \f[I]both\f[R] increments and decrements. +For instance, to map the modulation wheel (\f[C]CC1\f[R]) to the volume +controller (\f[C]CC7\f[R]): .IP .nf \f[C] -CC1=\ CC7 -\f[] +CC1= CC7 +\f[R] .fi .PP Which is more convenient to write, but is really just a shorthand for @@ -1239,63 +1231,63 @@ the two separate translations: .IP .nf \f[C] -CC1+\ CC7 -CC1\-\ CC7 -\f[] +CC1+ CC7 +CC1\- CC7 +\f[R] .fi .PP -The same goes for \f[C]<\f[], \f[C]>\f[] and \f[C]~\f[] with sign\-bit -encoders: +The same goes for \f[C]<\f[R], \f[C]>\f[R] and \f[C]\[ti]\f[R] with +sign\-bit encoders: .IP .nf \f[C] -CC60~\ CC7 -\f[] +CC60\[ti] CC7 +\f[R] .fi .PP Which is equivalent to: .IP .nf \f[C] -CC60<\ CC7 -CC60>\ CC7 -\f[] +CC60< CC7 +CC60> CC7 +\f[R] .fi .PP -The \f[C]~\f[] flag can be used to denote encoders in output messages, -too. +The \f[C]\[ti]\f[R] flag can be used to denote encoders in output +messages, too. E.g., to translate a standard (absolute) MIDI controller to a sign\-bit encoder value, you might use a rule like: .IP .nf \f[C] -CC48=\ CC16~ -\f[] +CC48= CC16\[ti] +\f[R] .fi .PP -Of course, this won't magically turn a standard controller into a -\f[I]real\f[] encoder; its range will still be limited. +Of course, this won\[cq]t magically turn a standard controller into a +\f[I]real\f[R] encoder; its range will still be limited. One way to properly emulate the endless range of an encoder is to expend -\f[I]two\f[] absolute controllers, one for reducing and another one for +\f[I]two\f[R] absolute controllers, one for reducing and another one for increasing the value. For instance: .IP .nf \f[C] -CC1\-\ CC60~ -CC2+\ CC60~ -\f[] +CC1\- CC60\[ti] +CC2+ CC60\[ti] +\f[R] .fi .PP -Note that the \[lq]down\[rq] controller (\f[C]CC1\f[] in this example) -only reacts to negative, and the \[lq]up\[rq] controlller (\f[C]CC2\f[]) -only to positive changes. -Therefore it's possible to \[lq]rewind\[rq] each control when getting to -the end of its range, so that you can continue to change its value as -much as you want. +Note that the \[lq]down\[rq] controller (\f[C]CC1\f[R] in this example) +only reacts to negative, and the \[lq]up\[rq] controlller +(\f[C]CC2\f[R]) only to positive changes. +Therefore it\[cq]s possible to \[lq]rewind\[rq] each control when +getting to the end of its range, so that you can continue to change its +value as much as you want. Admittedly, this solution is a bit quirky, but hey \[en] if you -absolutely need to emulate a real encoder on a device which doesn't have -one, that's one way to do it. +absolutely need to emulate a real encoder on a device which doesn\[cq]t +have one, that\[cq]s one way to do it. .PP Step sizes work on the right\-hand side of data translations as well. You might use these to scale up value changes, e.g., when translating @@ -1303,8 +1295,8 @@ from control changes to pitch bends: .IP .nf \f[C] -CC1=\ PB[128] -\f[] +CC1= PB[128] +\f[R] .fi .PP The step size can also be negative, which allows you to reverse the @@ -1314,18 +1306,18 @@ values go up from 0 to 127: .IP .nf \f[C] -CC1=\ CC1[\-1] -\f[] +CC1= CC1[\-1] +\f[R] .fi .PP -Note that you can also place step sizes on \f[I]both\f[] the left\-hand +Note that you can also place step sizes on \f[I]both\f[R] the left\-hand and right\-hand side of a rule, in order to approximate a rational scaling factor: .IP .nf \f[C] -CC1[3]=\ CC1[2] -\f[] +CC1[3]= CC1[2] +\f[R] .fi .PP The above translation will only be triggered when the input value @@ -1336,42 +1328,43 @@ doubled again, so that the net effect is to scale the input value by the method works best if the input and output step sizes are reasonably small.) .PP -\f[B]NOTE:\f[] All data translations we've seen so far handle -\f[I]incremental\f[] value changes. +\f[B]NOTE:\f[R] All data translations we\[cq]ve seen so far handle +\f[I]incremental\f[R] value changes. In order to be able to detect these changes and, in the case of MIDI output, change the output values accordingly, midizap has to keep track of all the current parameter values of all messages on all MIDI channels, for both input and output. This is easy enough, but midizap usually has no way of knowing the -\f[I]actual\f[] state of your controllers and MIDI applications, so when -the program starts up, it simply assumes all these values to be zero. -This means that midizap's \[lq]shadow\[rq] values of controllers, pitch -bends etc.\ may initially well be out of sync with your input devices -and applications, and you may have to wiggle a control in order to -\[lq]calibrate\[rq] it. +\f[I]actual\f[R] state of your controllers and MIDI applications, so +when the program starts up, it simply assumes all these values to be +zero. +This means that midizap\[cq]s \[lq]shadow\[rq] values of controllers, +pitch bends etc.\ may initially well be out of sync with your input +devices and applications, and you may have to wiggle a control in order +to \[lq]calibrate\[rq] it. .PP This becomes most apparent when using negative step sizes, as in the -translation \f[C]CC1=\ CC1[\-1]\f[] from above. +translation \f[C]CC1= CC1[\-1]\f[R] from above. In this case, you will first have to move the control all the way up and then down again to get it working properly. There are some ways to mitigate these issues, however. In particular, midizap can utilize controller feedback from the -application, please check the \f[I]MIDI Feedback\f[] section below for +application, please check the \f[I]MIDI Feedback\f[R] section below for details. Also, encoders need no calibration as they represent incremental changes -anyway, and there's an alternative form of data translation, to be -discussed in Section \f[I]Mod Translations\f[], which always works with +anyway, and there\[cq]s an alternative form of data translation, to be +discussed in Section \f[I]Mod Translations\f[R], which always works with absolute values and thus needs no calibration either. .SS Shift State .PP -Like the \f[C]CH\f[] token, the special \f[C]SHIFT\f[] token doesn't -generate any output by itself; it merely toggles an internal shift state -which can then be tested by other translations to generate alternative -output sequences. -The \f[C]^\f[] prefix denotes a rule which is active only in shifted -state, while unprefixed rules are active in \f[I]both\f[] shifted and -unshifted state. -Also, a prefixed rule \f[I]always\f[] overrides an unprefixed one (no +Like the \f[C]CH\f[R] token, the special \f[C]SHIFT\f[R] token +doesn\[cq]t generate any output by itself; it merely toggles an internal +shift state which can then be tested by other translations to generate +alternative output sequences. +The \f[C]\[ha]\f[R] prefix denotes a rule which is active only in +shifted state, while unprefixed rules are active in \f[I]both\f[R] +shifted and unshifted state. +Also, a prefixed rule \f[I]always\f[R] overrides an unprefixed one (no matter in which order they appear in the configuration file), so if you specify both, the former will be used in shifted, the latter in unshifted state. @@ -1381,72 +1374,74 @@ prefixed ones. 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 on an AKAI APCmini controller (\f[C]D8\f[]): +E.g., to bind the shift key on an AKAI APCmini controller +(\f[C]D8\f[R]): .IP .nf \f[C] -D8\ SHIFT -\f[] +D8 SHIFT +\f[R] .fi .PP -This rule doesn't have a prefix, 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: +This rule doesn\[cq]t have a prefix, so it is used to turn shift state +both on and off, giving a \[lq]Caps Lock\[rq]\-style of toggle key. +If you\[cq]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] -D8\ SHIFT\ RELEASE\ SHIFT -\f[] +D8 SHIFT RELEASE SHIFT +\f[R] .fi .PP -Note that in either case \f[C]SHIFT\f[] works as a \f[I]toggle\f[]; when -executed, it turns the shift status from off to on, and vice versa from -on to off. +Note that in either case \f[C]SHIFT\f[R] works as a \f[I]toggle\f[R]; +when executed, it turns the shift status from off to on, and vice versa +from on to off. .PP Having set up the translation for the shift key itself, we can now assign, depending on the shift state, different functions to buttons and faders. -Here's a typical example which maps a control change to either +Here\[cq]s a typical example which maps a control change to either Mackie\-style fader values encoded as pitch bends, or sign\-bit encoder values: .IP .nf \f[C] -\ CC48=\ PB[128]\ \ #\ default:\ translate\ to\ pitch\ bend -^CC48=\ CC16~\ \ \ \ #\ shifted:\ translate\ to\ encoder -\f[] + CC48= PB[128] # default: translate to pitch bend +\[ha]CC48= CC16\[ti] # shifted: translate to encoder +\f[R] .fi .PP -It's also possible to explicitly denote a rule which is active -\f[I]only\f[] in unshifted state. -Unshifted state is specified with the \f[C]0^\f[] (zero\-caret) prefix, -so you can write: +It\[cq]s also possible to explicitly denote a rule which is active +\f[I]only\f[R] in unshifted state. +Unshifted state is specified with the \f[C]0\[ha]\f[R] (zero\-caret) +prefix, so you can write: .IP .nf \f[C] -0^CC56=\ PB[128]\-9\ #\ unshifted:\ translate\ to\ pitch\ bend -\f[] +0\[ha]CC56= PB[128]\-9 # unshifted: translate to pitch bend +\f[R] .fi .PP -The syntax is a bit awkward, but the case arises rarely (usually, you'll -just write an unprefixed rule instead). +The syntax is a bit awkward, but the case arises rarely (usually, +you\[cq]ll just write an unprefixed rule instead). .PP midizap actually supports up to four different shift states, which are -denoted \f[C]SHIFT1\f[] to \f[C]SHIFT4\f[], with the corresponding -prefixes being \f[C]1^\f[] to \f[C]4^\f[]. +denoted \f[C]SHIFT1\f[R] to \f[C]SHIFT4\f[R], with the corresponding +prefixes being \f[C]1\[ha]\f[R] to \f[C]4\[ha]\f[R]. Unprefixed rules are enabled by default in all of these. -The \f[C]SHIFT\f[] token and \f[C]^\f[] prefix we've seen above are in -fact just shortcuts for \f[C]SHIFT1\f[] and \f[C]1^\f[], respectively. +The \f[C]SHIFT\f[R] token and \f[C]\[ha]\f[R] prefix we\[cq]ve seen +above are in fact just shortcuts for \f[C]SHIFT1\f[R] and +\f[C]1\[ha]\f[R], respectively. So our first example above is equivalent to: .IP .nf \f[C] -D8\ SHIFT1\ RELEASE\ SHIFT1 -CC48=\ PB[128] -1^CC48=\ CC16~ -\f[] +D8 SHIFT1 RELEASE SHIFT1 +CC48= PB[128] +1\[ha]CC48= CC16\[ti] +\f[R] .fi .PP We might add another shift key and use it to assign yet another function @@ -1454,14 +1449,14 @@ to the same input message: .IP .nf \f[C] -F7\ SHIFT2\ RELEASE\ SHIFT2 -2^CC48\-\ XK_Left -2^CC48+\ XK_Right -\f[] +F7 SHIFT2 RELEASE SHIFT2 +2\[ha]CC48\- XK_Left +2\[ha]CC48+ XK_Right +\f[R] .fi .PP Another way to look at this is that translations are organized in -\f[I]layers\f[]. +\f[I]layers\f[R]. Layer 0 contains the unshifted translations, layer 1 to 4 the translations prefixed with the corresponding shift level. Unprefixed translations are available in all of these layers, unless @@ -1471,142 +1466,142 @@ To keep things simple, only one layer can be active at any one time; if you press a shift key while another layer is still active, it will be deactivated automatically before activating the new layer. .PP -Also note that the status of internal shift keys is \f[I]only\f[] +Also note that the status of internal shift keys is \f[I]only\f[R] available to the midizap program; the host application never gets to see them. -If your host software does its own handling of shift keys, 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 doesn't have -enough buttons and faders, since it makes it possible to multiply the -amount of controls available on the device. +If your host software does its own handling of shift keys, it\[cq]s +usually more convenient to simply pass those keys on to the application. +However, \f[C]SHIFT\f[R] comes in handy if your controller doesn\[cq]t +have enough buttons and faders, since it makes it possible to multiply +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, simply by assigning the shifted faders to the encoders, as shown in the first example above. .SH 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[]. +Some MIDI controllers need a more elaborate setup than what we\[cq]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[R] option of midizap, +or the \f[C]JACK_PORTS 2\f[R] directive in the midizaprc file, to create +a second pair of MIDI input and output ports, named \f[C]midi_in2\f[R] +and \f[C]midi_out2\f[R]. 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 +midizaprc file, labeled \f[C][MIDI2]\f[R], 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. +Typically, the translations in the \f[C][MIDI2]\f[R] section will be the +inverse of those in the \f[C][MIDI]\f[R] 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. +You then wire up midizap\[cq]s \f[C]midi_in\f[R] and \f[C]midi_out\f[R] +ports to controller and application as before, but in addition you also +connect the application back to midizap\[cq]s \f[C]midi_in2\f[R] port, +and the \f[C]midi_out2\f[R] 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. -(The \f[C]\-s\f[] option a.k.a.\ \f[C]SYSTEM_PASSTHROUGH\f[] directive +(The \f[C]\-s\f[R] option a.k.a.\ \f[C]SYSTEM_PASSTHROUGH\f[R] directive also works on the feedback port, passing through all system messages from the second input port to the second output port unchanged.) .PP 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. +It shows how to emulate a Mackie controller with AKAI\[cq]s APCmini +device, so that it readily works with DAW software such as Ardour. .SS Automatic Feedback .PP If done right, MIDI feedback will eliminate the problem of controls being out of sync with the application. midizap has some built\-in logic to help with this. Specifically, the current state of controls received from the host -application via the \f[C]midi_in2\f[] port will be recorded, so that +application via the \f[C]midi_in2\f[R] port will be recorded, so that subsequent MIDI output for incremental data translations on the first output port will use the proper values for determining the required relative changes. (The same goes for the reverse path, recording the values from -\f[C]midi_in\f[] so that data translations feeding back to the +\f[C]midi_in\f[R] so that data translations feeding back to the controller will work correctly.) .PP -We refer to this as \f[I]automatic feedback\f[]. -Some devices may provide you with sign\-bit encoders which don't need -any kind of feedback for themselves. -In this case the automatic feedback will be all that's needed to keep -controller and application in sync, and you don't even have to write any -translation rules for the feedback; just enabling the second input port -and hooking it up to the application will be enough. +We refer to this as \f[I]automatic feedback\f[R]. +Some devices may provide you with sign\-bit encoders which don\[cq]t +need any kind of feedback for themselves. +In this case the automatic feedback will be all that\[cq]s needed to +keep controller and application in sync, and you don\[cq]t even have to +write any translation rules for the feedback; just enabling the second +input port and hooking it up to the application will be enough. Other controllers may provide faders with motors or LEDs on them, however, in which case additional translation rules for the feedback will be needed. .PP -\f[B]NOTE:\f[] Automatic feedback is enabled automatically whenever you -create a second pair of ports using \f[C]\-o2\f[]. -If you're using the second pair for more esoteric purposes, you may want -to disable this feature, which can be done with the \f[C]\-n\f[] option -or the \f[C]NO_FEEDBACK\f[] directive in the configuration file. -Use this option \f[I]only\f[] if feedback isn't needed with your +\f[B]NOTE:\f[R] Automatic feedback is enabled automatically whenever you +create a second pair of ports using \f[C]\-o2\f[R]. +If you\[cq]re using the second pair for more esoteric purposes, you may +want to disable this feature, which can be done with the \f[C]\-n\f[R] +option or the \f[C]NO_FEEDBACK\f[R] directive in the configuration file. +Use this option \f[I]only\f[R] if feedback isn\[cq]t needed with your application. .SS Direct Feedback .PP Translations can also provide feedback themselves. To these ends, any MIDI message on the right\-hand side of a translation -can be prefixed with the \f[C]!\f[] character. +can be prefixed with the \f[C]!\f[R] character. This outputs the message as usual, but flips the output ports, so that the message will go to port 2 in a forward translation destined for port 1, and vice versa to port 1 in a feedback translation (in the -\f[C][MIDI2]\f[] section) destined for port 2. +\f[C][MIDI2]\f[R] section) destined for port 2. .PP -We call this \f[I]direct feedback\f[]. +We call this \f[I]direct feedback\f[R]. For instance, suppose that on our MIDI controller we have a fader taking -the form of a touchstrip \f[C]CC1\f[] that has some LEDs for conveying +the form of a touchstrip \f[C]CC1\f[R] that has some LEDs for conveying its current value. -We might like to translate that message to a \f[C]CC7\f[] message for +We might like to translate that message to a \f[C]CC7\f[R] message for the application, while also providing feedback to the controller. The following translation will do this: .IP .nf \f[C] -CC1=\ CC7\ !CC1 -\f[] +CC1= CC7 !CC1 +\f[R] .fi .PP Now, whenever you touch that fader, the corresponding value will be sent -as \f[C]CC7\f[] to the application, while the same value is sent back as -\f[C]CC1\f[] to the controller (which presumably will light the +as \f[C]CC7\f[R] to the application, while the same value is sent back +as \f[C]CC1\f[R] to the controller (which presumably will light the appropriate LEDs on the fader). .PP -Another example are internal shift buttons (cf.\ \f[I]Shift State\f[] +Another example are internal shift buttons (cf.\ \f[I]Shift State\f[R] above). -The host application never gets to see these, so chances are that we'll -have to provide suitable feedback ourselves in order to light the -buttons. +The host application never gets to see these, so chances are that +we\[cq]ll have to provide suitable feedback ourselves in order to light +the buttons. E.g., the following should usually turn on the LED of the button when pressed, and turn it off again when released: .IP .nf \f[C] -D8\ SHIFT\ !D8\ RELEASE\ SHIFT\ !D8 -\f[] +D8 SHIFT !D8 RELEASE SHIFT !D8 +\f[R] .fi .PP This will work for simple cases involving only a single shift key whose state always matches the button state. However, for more complicated setups possibly involving multiple shift -keys, it's better to use the \f[C]^\f[] prefix instead: +keys, it\[cq]s better to use the \f[C]\[ha]\f[R] prefix instead: .IP .nf \f[C] -D8\ SHIFT\ ^D8\ RELEASE\ SHIFT\ ^D8 -\f[] +D8 SHIFT \[ha]D8 RELEASE SHIFT \[ha]D8 +\f[R] .fi .PP This variation of direct feedback is tailored to shift keys, and it -\f[I]only\f[] works with key translations. +\f[I]only\f[R] works with key translations. It also operates under the following two assumptions: .IP \[bu] 2 -Feedback messages come \f[I]after\f[] the corresponding \f[C]SHIFT\f[] +Feedback messages come \f[I]after\f[R] the corresponding \f[C]SHIFT\f[R] token in the translation, so that midizap knows which shift state the message belongs to. .IP \[bu] 2 @@ -1616,20 +1611,20 @@ midizap has some built\-in machinery to deal with shift key feedback which handles direct feedback for shift keys in an automatic fashion, provided that these conditions are met. In particular, midizap ensures that the feedback message reflects the -\f[I]shift\f[] (rather than the button) state, which is needed to make +\f[I]shift\f[R] (rather than the button) state, which is needed to make \[lq]Caps Lock\[rq]\-style toggle keys like the following work correctly: .IP .nf \f[C] -D8\ SHIFT\ ^D8 -\f[] +D8 SHIFT \[ha]D8 +\f[R] .fi .PP This turns the key on when pushed, and toggles it off again when pushed a second time. -Note that you can't get this behavior with the basic direct feedback -facility, since there's no way to keep track of the required status +Note that you can\[cq]t get this behavior with the basic direct feedback +facility, since there\[cq]s no way to keep track of the required status information across different translations. Moreover, midizap also maintains the current status of all shift keys and automatically turns them off when switching from one shift status to @@ -1638,8 +1633,8 @@ shift keys in your configuration. .PP midizap still has a few more tricks up its sleeves, but they require the use of a special kind of data translation. -These are a separate topic in their own right, so we'll introduce them -in the next section. +These are a separate topic in their own right, so we\[cq]ll introduce +them in the next section. .SH Mod Translations .PP Most of the time, MIDI feedback uses just the standard kinds of MIDI @@ -1648,18 +1643,18 @@ buttons light up in different colors, or control change messages which set the positions of motor faders. However, there are some encodings of feedback messages 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. +or even impossible to translate using the simple kinds of rules +we\[cq]ve seen so far. midizap offers a special variation of data mode to help decoding such messages. -We call them \f[I]mod translations\f[] (a.k.a.\ \[lq]modulus\[rq] or +We call them \f[I]mod translations\f[R] (a.k.a.\ \[lq]modulus\[rq] or \[lq]modifier\[rq] translations), because they involve operations with integer moduli which enable you to both calculate output from input -values in a direct fashion, \f[I]and\f[] modify the output messages +values in a direct fashion, \f[I]and\f[R] modify the output messages themselves along the way. .PP -One important task, which we'll use as a running example below, is the -decoding of meter (RMS level) data in the Mackie protocol. +One important task, which we\[cq]ll use as a running example below, is +the decoding of meter (RMS level) data in the Mackie protocol. There, each meter value is represented as a channel 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 @@ -1667,7 +1662,7 @@ nibble\[rq] (bits 4..6) and the corresponding meter value in the We will show how to map these values to notes indicating buttons on the AKAI APCmini (please check examples/APCmini.midizaprc in the sources for details about this device). -Mod translations aren't limited to this specific use case, however; +Mod translations aren\[cq]t limited to this specific use case, however; similar rules will apply to other kinds of \[lq]scrambled\[rq] MIDI data. .PP @@ -1675,36 +1670,37 @@ In its simplest form, the translation looks as follows: .IP .nf \f[C] -CP[16]\ C0 -\f[] +CP[16] C0 +\f[R] .fi .PP -In contrast to standard data translations, there's no increment flag -here, so the translation does \f[I]not\f[] indicate an incremental +In contrast to standard data translations, there\[cq]s no increment flag +here, so the translation does \f[I]not\f[R] indicate an incremental change of the input value. -Instead, mod translations always work with \f[I]absolute\f[] values, and -the step size on the left\-hand side is treated as a \f[I]modulus\f[] to -decompose the input value into two separate quantities, -\f[I]quotient\f[] and \f[I]remainder\f[]. +Instead, mod translations always work with \f[I]absolute\f[R] values, +and the step size on the left\-hand side is treated as a +\f[I]modulus\f[R] to decompose the input value into two separate +quantities, \f[I]quotient\f[R] and \f[I]remainder\f[R]. 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 ignored. -\f[C]PC\f[] messages, on the other hand, lack the parameter value, so in -this case the remainder value will be disregarded instead.) +former is used as an \f[I]offset\f[R] to modify the output message. +(Note that \f[C]CP\f[R] and \f[C]PB\f[R] messages don\[cq]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 ignored. +\f[C]PC\f[R] messages, on the other hand, lack 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 quotient (offset) -\f[I]q\f[] = \f[I]v\f[] div \f[I]k\f[] and the remainder (value) -\f[I]r\f[] = \f[I]v\f[] mod \f[I]k\f[]. -E.g., with \f[I]k\f[] = 16 and \f[I]v\f[] = 21, you'll get \f[I]q\f[] = -1 and \f[I]r\f[] = 5 (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 above the output would be the note \f[C]C#0\f[] -(\f[C]C0\f[] offset by 1) with a velocity of 5. +In order to describe more precisely how this works, let\[cq]s assume an +input value \f[I]v\f[R] and a modulus \f[I]k\f[R]. +We divide \f[I]v\f[R] by \f[I]k\f[R], yielding the quotient (offset) +\f[I]q\f[R] = \f[I]v\f[R] div \f[I]k\f[R] and the remainder (value) +\f[I]r\f[R] = \f[I]v\f[R] mod \f[I]k\f[R]. +E.g., with \f[I]k\f[R] = 16 and \f[I]v\f[R] = 21, you\[cq]ll get +\f[I]q\f[R] = 1 and \f[I]r\f[R] = 5 (21 divided by 16 yields 1 with a +remainder of 5). +The calculated offset \f[I]q\f[R] is then applied to the note itself, +and the remainder \f[I]r\f[R] becomes the velocity of that note. +So in the example above the output would be the note \f[C]C#0\f[R] +(\f[C]C0\f[R] 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 @@ -1712,77 +1708,77 @@ This transformation is surprisingly versatile, and there are some extensions of the MIDI syntax which make it even more flexible. These extensions are only available in mod translations. They are described by the following grammar rules (please also refer to -Section \f[I]MIDI Message Notation\f[] for the rest of the grammar rules -for the MIDI syntax): +Section \f[I]MIDI Message Notation\f[R] for the rest of the grammar +rules for the MIDI syntax): .IP .nf \f[C] -token\ ::=\ msg\ [\ mod\ ]\ [\ steps\ ]\ [\ "\-"\ number]\ [\ flag\ ] -mod\ \ \ ::=\ "["\ [\ number\ ]\ "]" -steps\ ::=\ "["\ number\ "]"\ |\ "{"\ list\ "}" -list\ \ ::=\ number\ {\ ","\ number\ |\ ":"\ number\ |\ "\-"\ number\ } -flag\ \ ::=\ "\[aq]"\ |\ "?"\ |\ "\[aq]?"\ |\ "?\[aq]" -\f[] +token ::= msg [ mod ] [ steps ] [ \[dq]\-\[dq] number] [ flag ] +mod ::= \[dq][\[dq] [ number ] \[dq]]\[dq] +steps ::= \[dq][\[dq] number \[dq]]\[dq] | \[dq]{\[dq] list \[dq]}\[dq] +list ::= number { \[dq],\[dq] number | \[dq]:\[dq] number | \[dq]\-\[dq] number } +flag ::= \[dq]\[aq]\[dq] | \[dq]?\[dq] | \[dq]\[aq]?\[dq] | \[dq]?\[aq]\[dq] +\f[R] .fi .PP There are a couple of new elements in the syntax: an empty modulus -bracket \f[C][]\f[], the transposition flag \f[C]\[aq]\f[], the change -flag \f[C]?\f[], and lists of numbers enclosed in curly braces. +bracket \f[C][]\f[R], the transposition flag \f[C]\[aq]\f[R], the change +flag \f[C]?\f[R], and lists of numbers enclosed in curly braces. They have the following meaning: .IP \[bu] 2 -The \f[I]empty modulus\f[] bracket, denoted \f[C][]\f[] on the +The \f[I]empty modulus\f[R] bracket, denoted \f[C][]\f[R] on the left\-hand side of a mod translation, indicates a default modulus large -enough (16384 for \f[C]PB\f[], 128 for other messages) so that the -offset \f[I]q\f[] always becomes zero and the translation passes on the +enough (16384 for \f[C]PB\f[R], 128 for other messages) so that the +offset \f[I]q\f[R] always becomes zero and the translation passes on the entire input value as is. .IP \[bu] 2 -The \f[I]transposition\f[] flag, denoted with the \f[C]\[aq]\f[] +The \f[I]transposition\f[R] flag, denoted with the \f[C]\[aq]\f[R] (apostrophe) suffix on an output message, reverses the roles of -\f[I]q\f[] and \f[I]r\f[], so that the remainder becomes the offset and -the quotient the value of the output message. +\f[I]q\f[R] and \f[I]r\f[R], so that the remainder becomes the offset +and the quotient the value of the output message. .IP \[bu] 2 -The \f[I]change\f[] flag, denoted with the \f[C]?\f[] suffix on an +The \f[I]change\f[R] flag, denoted with the \f[C]?\f[R] suffix on an output message, only outputs the message if there are any changes in offset or value. .IP \[bu] 2 -\f[I]Value lists\f[], denoted as lists of numbers separated by commas +\f[I]Value lists\f[R], denoted as lists of numbers separated by commas and enclosed in curly braces, provide a way to describe \f[I]discrete -mappings\f[] of input to output values. +mappings\f[R] of input to output values. The input value is used as an index into the list to give the corresponding output value, and the last value in the list will be used for any index which runs past the end of the list. There are also some convenient shortcuts which let you construct these -lists more easily: repetition \f[I]a\f[]\f[C]:\f[]\f[I]b\f[] (denoting -\f[I]b\f[] consecutive \f[I]a\f[]'s) and enumeration -\f[I]a\f[]\f[C]\-\f[]\f[I]b\f[] (denoting -\f[I]a\f[]\f[C],\f[]\f[I]a\f[]±1\f[C],\f[]\&...\f[C],\f[]\f[I]b\f[], +lists more easily: repetition \f[I]a\f[R]\f[C]:\f[R]\f[I]b\f[R] +(denoting \f[I]b\f[R] consecutive \f[I]a\f[R]\[cq]s) and enumeration +\f[I]a\f[R]\f[C]\-\f[R]\f[I]b\f[R] (denoting +\f[I]a\f[R]\f[C],\f[R]\f[I]a\f[R]\[t+-]1\f[C],\f[R]\&...\f[C],\f[R]\f[I]b\f[R], which ramps either up or down depending on whether -\f[I]a\f[]<=\f[I]b\f[] or \f[I]a\f[]>\f[I]b\f[], respectively). +\f[I]a\f[R]<=\f[I]b\f[R] or \f[I]a\f[R]>\f[I]b\f[R], respectively). .PP These are often used in concert. We will introduce value lists in a moment, and cover the other options in due course. .PP -\f[B]NOTE:\f[] In the context of mod translations, pitch bend values are -interpreted as \f[I]unsigned\f[] quantities in the range 0..16383 (with -8192 denoting the center value), which corresponds to the way they are -actually encoded in MIDI. +\f[B]NOTE:\f[R] In the context of mod translations, pitch bend values +are interpreted as \f[I]unsigned\f[R] quantities in the range 0..16383 +(with 8192 denoting the center value), which corresponds to the way they +are actually encoded in MIDI. This makes the modular arithmetic work consistently across all types of MIDI messages, and also facilitates conversions between the different types of absolute parameter values. -Normally you shouldn't have to worry about this, but the change in +Normally you shouldn\[cq]t have to worry about this, but the change in representation needs to be taken into account when transforming pitch bend values with value lists. .PP -Let's return to our example. +Let\[cq]s return to our example. As usual in data translations, you can also specify a step size on the right\-hand side to upscale the output value (which is the remainder -\f[I]r\f[] here): +\f[I]r\f[R] here): .IP .nf \f[C] -CP[16]\ C0[2] -\f[] +CP[16] C0[2] +\f[R] .fi .PP More complicated transformations can be specified as value lists @@ -1793,8 +1789,8 @@ can map the meter values to different colors as follows: .IP .nf \f[C] -CP[16]\ C0{0,1,1,1,1,1,1,1,1,5,5,5,3} -\f[] +CP[16] C0{0,1,1,1,1,1,1,1,1,5,5,5,3} +\f[R] .fi .PP Using the shorthand for repetitions, this can be written more succinctly @@ -1802,8 +1798,8 @@ Using the shorthand for repetitions, this can be written more succinctly .IP .nf \f[C] -CP[16]\ C0{0,1:8,5:3,3} -\f[] +CP[16] C0{0,1:8,5:3,3} +\f[R] .fi .PP Thus 0 will be mapped to 0 (off), 1..8 to 1 (green), 9..11 to 5 @@ -1815,47 +1811,48 @@ Your mileage may vary, though, so you may have to experiment with these values to make this rule work with your DAW.) .PP The quotient here is the mixer channel index in the high\-nibble of the -\f[C]CP\f[] message, which will be used as an offset for the \f[C]C0\f[] -note on the right, so the above rule shows the meters as a single row of -colored buttons at the bottom of the 8x8 grid on the APCmini (first -value on \f[C]C0\f[], second value on \f[C]C#0\f[], etc.). -To get a different layout, you can also scale the \f[I]offset\f[] value, -by adding a second step size to the left\-hand side: +\f[C]CP\f[R] message, which will be used as an offset for the +\f[C]C0\f[R] note on the right, so the above rule shows the meters as a +single row of colored buttons at the bottom of the 8x8 grid on the +APCmini (first value on \f[C]C0\f[R], second value on \f[C]C#0\f[R], +etc.). +To get a different layout, you can also scale the \f[I]offset\f[R] +value, by adding a second step size to the left\-hand side: .IP .nf \f[C] -CP[16][8]\ C0{0,1:8,5:3,3} -\f[] +CP[16][8] C0{0,1:8,5:3,3} +\f[R] .fi .PP Even though the extra step size appears on the left\-hand side of a mod translation, it is applied to all messages on the \f[I]right\-hand -side\f[], scaling \f[I]up\f[] the offsets of all output messages by the -same factor. +side\f[R], scaling \f[I]up\f[R] the offsets of all output messages by +the same factor. Thus, in the example above, the buttons are now in the first -\f[I]column\f[] of the grid (first value on \f[C]C0\f[], second value on -\f[C]G#0\f[], etc.). -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. +\f[I]column\f[R] of the grid (first value on \f[C]C0\f[R], second value +on \f[C]G#0\f[R], etc.). +Instead of a single step size, it\[cq]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. E.g., the following rule places every other meter value in the second row: .IP .nf \f[C] -CP[16]{0,9,2,11,4,13,6,15}\ C0{0,1:8,5:3,3} -\f[] +CP[16]{0,9,2,11,4,13,6,15} C0{0,1:8,5:3,3} +\f[R] .fi .PP You might also output several notes at once, in order to display a -horizontal or vertical meter \f[I]strip\f[] instead of just a single +horizontal or vertical meter \f[I]strip\f[R] instead of just a single colored button for each value. For instance: .IP .nf \f[C] -CP[16]\ C0{0,1}\ G#0{0:8,5}\ E1{0:11,3} -\f[] +CP[16] C0{0,1} G#0{0:8,5} E1{0:11,3} +\f[R] .fi .PP Note that each of the output notes will be offset by the same amount, so @@ -1867,51 +1864,51 @@ mapping the meter values to the five topmost button rows.) Another example from the Mackie protocol is time feedback. The following rule (also from the APCmini.midizaprc example) decodes the least significant digit of the beat number in the time display -(\f[C]CC69\f[]) to count off time on some of the scene launch buttons of -the APCmini. +(\f[C]CC69\f[R]) to count off time on some of the scene launch buttons +of the 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[]\ F7{0:49,1,0}\ E7{0:50,1,0}\ Eb7{0:51,1,0}\ D7{0:52,1,0} -\f[] +CC69[] F7{0:49,1,0} E7{0:50,1,0} Eb7{0:51,1,0} D7{0:52,1,0} +\f[R] .fi .PP Also note the use of an empty modulus bracket on the left\-hand side, which means that we always have a zero offset here and thus the output -notes aren't modified in this example. +notes aren\[cq]t modified in this example. .SS Basic Mod Translations .PP While mod translations are often employed for MIDI feedback, they can also be used as an alternative to \[lq]ordinary\[rq] (incremental) data translations in various contexts. -We discuss some of these use cases below and show how they're +We discuss some of these use cases below and show how they\[cq]re implemented. .PP For more basic uses we often want to simply pass on (and possibly -transform) the input value \f[I]without\f[] using an offset, so we +transform) the input value \f[I]without\f[R] using an offset, so we employ a default modulus in most of the following examples to ensure that the offset becomes zero and thus inconsequential. -We also call such translations \f[I]basic\f[] mod translations. +We also call such translations \f[I]basic\f[R] mod translations. They are useful, in particular, if we want to simply preserve the parameter value in a data translation. For instance: .IP .nf \f[C] -CC1[]\ C5 -\f[] +CC1[] C5 +\f[R] .fi .PP -This translates the \f[C]CC1\f[] (modulation wheel) controller to a -\f[C]C5\f[] (middle C) note message in such a way that the controller +This translates the \f[C]CC1\f[R] (modulation wheel) controller to a +\f[C]C5\f[R] (middle C) note message in such a way that the controller value becomes the velocity of the note. Note that this is different from both the key translation -\f[C]CC1\ C5\f[] (which only preserves the \[lq]on\[rq]/\[lq]off\[rq] +\f[C]CC1 C5\f[R] (which only preserves the \[lq]on\[rq]/\[lq]off\[rq] status but looses the actual parameter value) and the incremental data -translation \f[C]CC1=\ C5\f[] (which usually preserves the value, but +translation \f[C]CC1= C5\f[R] (which usually preserves the value, but executes the translation in a step\-wise fashion). A mod translation always maps messages in a single step, which reproduces leaps in the input values on the output side (and, as a side @@ -1924,43 +1921,43 @@ translation is often preferable. You also need to use a mod translation if your binding involves discrete value lists, because these are not available in other kinds of translations. -Value lists can represent \f[I]any\f[] discrete mapping from input to +Value lists can represent \f[I]any\f[R] discrete mapping from input to output values, and thus offer much more flexibility than simple step sizes. -For instance, here's how to map controller values to the first few +For instance, here\[cq]s how to map controller values to the first few Fibonacci numbers: .IP .nf \f[C] -CC1[]\ CC1{0,1,1,2,3,5,8,13,21,34,55,89} -\f[] +CC1[] CC1{0,1,1,2,3,5,8,13,21,34,55,89} +\f[R] .fi .PP Value lists offer some conveniences to facilitate their use, -\f[I]repetitions\f[] (which we've already discussed above) and -\f[I]enumerations\f[]. +\f[I]repetitions\f[R] (which we\[cq]ve already discussed above) and +\f[I]enumerations\f[R]. Enumerations are used to denote an ascending or descending range of values. E.g., to reverse the values of a controller you may write: .IP .nf \f[C] -CC1[]\ CC1{127\-0} -\f[] +CC1[] CC1{127\-0} +\f[R] .fi .PP -Contrast this with the \f[I]incremental\f[] reversed controller rule -that we've seen earlier: +Contrast this with the \f[I]incremental\f[R] reversed controller rule +that we\[cq]ve seen earlier: .IP .nf \f[C] -CC1=\ CC1[\-1] -\f[] +CC1= CC1[\-1] +\f[R] .fi .PP As mentioned, this rule requires that you first move the controller up to its maximum position to make it work. -The mod translation above uses absolute values and thus doesn't have +The mod translation above uses absolute values and thus doesn\[cq]t have this defect. .PP The values in a list may be in any order, and you can throw in any @@ -1969,15 +1966,15 @@ For instance: .IP .nf \f[C] -CC1[]\ CC1{0:2\-5,7:5\-0} -\f[] +CC1[] CC1{0:2\-5,7:5\-0} +\f[R] .fi .PP The value list in this example starts with two zeros, then ramps up to 5 followed by five 7s, before finally fading back to 0. It goes without saying that this is much easier to read and also much less error\-prone to write than -\f[C]{0,0,1,2,3,4,5,7,7,7,7,7,6,5,4,3,2,1,0}\f[]. +\f[C]{0,0,1,2,3,4,5,7,7,7,7,7,6,5,4,3,2,1,0}\f[R]. .PP Values in lists may also be negative. In general, if mapping any input value using a value list results in an @@ -1987,54 +1984,54 @@ We can use this, e.g., to suppress note\-off messages in the output: .IP .nf \f[C] -C0[]\ C0{\-1,1\-127} -\f[] +C0[] C0{\-1,1\-127} +\f[R] .fi .PP -This rule will translate a zero velocity to \-1, which isn't in the +This rule will translate a zero velocity to \-1, which isn\[cq]t in the valid range, so the output message will be dropped. For all other velocities, the input message will be output unchanged, -because the \f[C]1\-127\f[] enumeration maps the positive velocities to +because the \f[C]1\-127\f[R] enumeration maps the positive velocities to themselves. -If you'd rather output a key\-style fixed velocity for the note\-ons +If you\[cq]d rather output a key\-style fixed velocity for the note\-ons instead, you can do that as follows: .IP .nf \f[C] -C0[]\ C0{\-1,127} -\f[] +C0[] C0{\-1,127} +\f[R] .fi .PP This kind of translation may look a bit odd, but can be useful at times if the application interprets note inputs, e.g., as radio or toggle buttons, and may get confused by note\-off messages. -Note that it's impossible to do this kind of mapping with key or -incremental data translations, because these don't allow you to suppress -the note\-off messages. +Note that it\[cq]s impossible to do this kind of mapping with key or +incremental data translations, because these don\[cq]t allow you to +suppress the note\-off messages. .PP Last but not least, you can also use a modulus of 1 to cancel the -\f[I]remainder\f[] instead, if you want to use the input value solely as -an offset. -For instance, here's how you can map controller values to note -\f[I]numbers\f[] (rather than velocities): +\f[I]remainder\f[R] instead, if you want to use the input value solely +as an offset. +For instance, here\[cq]s how you can map controller values to note +\f[I]numbers\f[R] (rather than velocities): .IP .nf \f[C] -CC1[1]\ C0 -\f[] +CC1[1] C0 +\f[R] .fi .PP This outputs 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, \f[C]D0\f[] for value -2, etc. +\f[C]C0\f[R] for value 0, \f[C]C#0\f[R] for value 1, \f[C]D0\f[R] for +value 2, etc. In fact, this is just a basic mod translation in disguise, because -employing the \f[C]\[aq]\f[] flag on the output message to transpose +employing the \f[C]\[aq]\f[R] flag on the output message to transpose quotient and remainder, we can also write it as: .IP .nf \f[C] -CC1[]\ C0\[aq] -\f[] +CC1[] C0\[aq] +\f[R] .fi .PP Note that the quotient, which becomes the velocity of the output note, @@ -2043,8 +2040,8 @@ To get a nonzero velocity, you specify it in a value list: .IP .nf \f[C] -CC2[]\ C0{127}\[aq] -\f[] +CC2[] C0{127}\[aq] +\f[R] .fi .SS Extracting Sub\-Values .PP @@ -2055,44 +2052,45 @@ zero: .IP .nf \f[C] -CC1[16]{0}\ CC1 -\f[] +CC1[16]{0} CC1 +\f[R] .fi .PP -Extracting the \f[I]high\f[] nibble is just as easy (this is another +Extracting the \f[I]high\f[R] nibble is just as easy (this is another case where the transposition flag comes in handy): .IP .nf \f[C] -CC1[16]{0}\ CC2\[aq] -\f[] +CC1[16]{0} CC2\[aq] +\f[R] .fi .PP -Note that this works because the output mapping \f[C]{0}\f[] (which -forces the offset to 0) is in fact applied \f[I]after\f[] the +Note that this works because the output mapping \f[C]{0}\f[R] (which +forces the offset to 0) is in fact applied \f[I]after\f[R] the transposition. -Thus the quotient becomes the value of the \f[C]CC2\f[] message, while +Thus the quotient becomes the value of the \f[C]CC2\f[R] message, while the remainder is canceled out and becomes a zero offset. -You can also output \f[I]both\f[] the low and high nibbles at the same +You can also output \f[I]both\f[R] the low and high nibbles at the same time that way: .IP .nf \f[C] -CC1[16]{0}\ CC1\ CC2\[aq] -\f[] +CC1[16]{0} CC1 CC2\[aq] +\f[R] .fi .PP Using similar rules, you can extract almost any part of an input value, -down to every single bit if needed (see the \f[I]Macro Translations\f[] +down to every single bit if needed (see the \f[I]Macro Translations\f[R] section below for another example). .SS Detecting Changes .PP -Let's have another look at the high\-nibble extraction rule from above: +Let\[cq]s have another look at the high\-nibble extraction rule from +above: .IP .nf \f[C] -CC1[16]{0}\ CC2\[aq] -\f[] +CC1[16]{0} CC2\[aq] +\f[R] .fi .PP Note that if the input value changes gradually then many output values @@ -2100,44 +2098,44 @@ will be identical. E.g., if the input values are 0, 10, 19, 32, 64 then the first four high nibbles are all zero, so the output will be 0, 0, 0, 0, 1, with the zero value repeated four times. -If this is not desired, you can add the \f[C]?\f[] flag to indicate that -the message should be output only if the value has changed: +If this is not desired, you can add the \f[C]?\f[R] flag to indicate +that the message should be output only if the value has changed: .IP .nf \f[C] -CC1[16]{0}\ CC2\[aq]? -\f[] +CC1[16]{0} CC2\[aq]? +\f[R] .fi .PP Now, repeated values are suppressed, so with the same inputs the output will be just 0, 1. -Note that we used the \f[C]?\f[] flag in combination with transposition +Note that we used the \f[C]?\f[R] flag in combination with transposition and the offset forced to zero here, but of course it will work for any kind of change (offset or value, transposed or not). Also note that change detection always considers the \[lq]post\-transform\[rq] values as they would be output, i.e., changes -are detected \f[I]after\f[] transposition and all mappings of input and +are detected \f[I]after\f[R] transposition and all mappings of input and output values have been performed. .PP Change detection is often useful when input values are projected, as in the above example, but also in many other situations in which you simply want to prevent repeated values. -For instance, suppose that we'd like to turn the modulation wheel -(\f[C]CC1\f[]) into a kind of on/off switch. +For instance, suppose that we\[cq]d like to turn the modulation wheel +(\f[C]CC1\f[R]) into a kind of on/off switch. Using a basic mod translation with a value list and change detection, this can be done quite easily: .IP .nf \f[C] -CC1[]\ CC1{0,127}? -\f[] +CC1[] CC1{0,127}? +\f[R] .fi .PP This emits a single 127 value as soon as the input value becomes nonzero, and a single 0 value when it drops to zero again. -Note that without the \f[C]?\f[] flag, the 127 value might be repeated +Note that without the \f[C]?\f[R] flag, the 127 value might be repeated any number of times while you keep turning the modulation wheel, which -isn't the behavior we want here. +isn\[cq]t the behavior we want here. .SS Macro Translations .PP There are some situations in which it is hard or even impossible to @@ -2145,96 +2143,96 @@ construct a translation in a single step, but it may become much easier if we can recursively invoke other translations. midizap allows you to do this by \[lq]calling\[rq] the mod translation for a MIDI message on the right\-hand side of a translation. -This is done by prefixing the message to be expanded with the \f[C]$\f[] -character: +This is done by prefixing the message to be expanded with the +\f[C]$\f[R] character: .IP .nf \f[C] -CC0[]\ $CC1 -\f[] +CC0[] $CC1 +\f[R] .fi .PP -Note that you can \f[I]only\f[] call mod translations this way, so the -message to be expanded (\f[C]CC1\f[] in this example) must be bound in a -mod translation somewhere; otherwise you'll get a warning about the -message being undefined and no output will be generated. -On the other hand, the translation \f[I]containing\f[] the call may also -be a key or incremental data translation instead, so we might just as -well have written, e.g.: +Note that you can \f[I]only\f[R] call mod translations this way, so the +message to be expanded (\f[C]CC1\f[R] in this example) must be bound in +a mod translation somewhere; otherwise you\[cq]ll get a warning about +the message being undefined and no output will be generated. +On the other hand, the translation \f[I]containing\f[R] the call may +also be a key or incremental data translation instead, so we might just +as well have written, e.g.: .IP .nf \f[C] -CC0=\ $CC1 -\f[] +CC0= $CC1 +\f[R] .fi .PP -Before we proceed, let's introduce a few terms which will make it easier -to talk about these things. +Before we proceed, let\[cq]s introduce a few terms which will make it +easier to talk about these things. We refer to a mod translation being called in this manner as a -\f[I]macro translation\f[], and we also call the left\-hand side of the -translation a \f[I]macro\f[], and the invocation of a macro using the -dollar symbol a \f[I]macro call\f[]. +\f[I]macro translation\f[R], and we also call the left\-hand side of the +translation a \f[I]macro\f[R], and the invocation of a macro using the +dollar symbol a \f[I]macro call\f[R]. .PP -To continue our example, let's define the \f[C]CC1\f[] macro so that it -outputs just a single note message: +To continue our example, let\[cq]s define the \f[C]CC1\f[R] macro so +that it outputs just a single note message: .IP .nf \f[C] -CC0[]\ $CC1\ \ #1 -CC1[]\ C5\ \ \ \ #2 -\f[] +CC0[] $CC1 #1 +CC1[] C5 #2 +\f[R] .fi .PP On a conceptual level, the macro expansion process works pretty much like the production rules of a grammar, with the \[lq]dollar\[rq] tokens playing the role of the nonterminals. -Thus, with the definitions above a \f[C]CC0\f[] message will be +Thus, with the definitions above a \f[C]CC0\f[R] message will be processed as follows: .IP \[bu] 2 Rule #1 is applied, constructing the output sequence with the -\f[C]CC1\f[] message as usual. +\f[C]CC1\f[R] message as usual. .IP \[bu] 2 -Instead of outputting the resulting \f[C]CC1\f[] message directly, the +Instead of outputting the resulting \f[C]CC1\f[R] message directly, the program now looks for a mod translation of that message which can be applied recursively. .IP \[bu] 2 -Rule #2 is applied, yielding a \f[C]C5\f[] message which is substituted -for the \f[C]$CC1\f[] token in rule #1. +Rule #2 is applied, yielding a \f[C]C5\f[R] message which is substituted +for the \f[C]$CC1\f[R] token in rule #1. .PP -Unsurprisingly, the end result is a \f[C]C5\f[] message with the same -velocity as the value of the \f[C]CC1\f[] message, which in turn comes -from the original \f[C]CC0\f[] message being translated. +Unsurprisingly, the end result is a \f[C]C5\f[R] message with the same +velocity as the value of the \f[C]CC1\f[R] message, which in turn comes +from the original \f[C]CC0\f[R] message being translated. .PP -Of course, we could also just have written \f[C]CC0[]\ C5\f[] here and +Of course, we could also just have written \f[C]CC0[] C5\f[R] here and be done with it. -So let's try something slightly more complicated which really -\f[I]needs\f[] recursive translations to work. -For instance, suppose that we'd like to output \f[I]two\f[] messages -instead: the note message \f[C]C5\f[] as before, followed by a -\f[C]CC1\f[] message with just the low nibble of the controller value. +So let\[cq]s try something slightly more complicated which really +\f[I]needs\f[R] recursive translations to work. +For instance, suppose that we\[cq]d like to output \f[I]two\f[R] +messages instead: the note message \f[C]C5\f[R] as before, followed by a +\f[C]CC1\f[R] message with just the low nibble of the controller value. Now each of these translations is easy to define: .IP .nf \f[C] -CC0[]\ C5 -CC0[16]{0}\ CC1 -\f[] +CC0[] C5 +CC0[16]{0} CC1 +\f[R] .fi .PP -But we can't just put these two rules into the same section, because -we're not allowed to bind \f[C]CC0\f[] in two different translations at -once (if you try this, the parser will complain and just ignore the -second rule). -And the single rule \f[C]CC0[16]{0}\ C5\ CC1\f[] won't work either, -because it only passes the low nibble to the \f[C]C5\f[] message. +But we can\[cq]t just put these two rules into the same section, because +we\[cq]re not allowed to bind \f[C]CC0\f[R] in two different +translations at once (if you try this, the parser will complain and just +ignore the second rule). +And the single rule \f[C]CC0[16]{0} C5 CC1\f[R] won\[cq]t work either, +because it only passes the low nibble to the \f[C]C5\f[R] message. However, using a macro call we can massage those rules into an eligible form: .IP .nf \f[C] -CC0[]\ C5\ $CC1 -CC1[16]{0}\ CC1 -\f[] +CC0[] C5 $CC1 +CC1[16]{0} CC1 +\f[R] .fi .PP This does exactly what we set out to do, and the transformation of the @@ -2246,35 +2244,35 @@ transformations. If you know C, you will have realized by now that macro translations work pretty much like macros in the C programming language. The same caveats apply here, too. -Specifically, you usually do \f[I]not\f[] want to have a macro invoke +Specifically, you usually do \f[I]not\f[R] want to have a macro invoke itself (either directly or indirectly), because that will almost certainly lead to infinite recursion. E.g.: .IP .nf \f[C] -CC0[128]\ $CC1 -CC1[128]\ $CC0\ #\ don\[aq]t\ do\ this! -\f[] +CC0[128] $CC1 +CC1[128] $CC0 # don\[aq]t do this! +\f[R] .fi .PP -midizap \f[I]will\f[] catch such mishaps after a few iterations, but -it's better to avoid them in the first place. +midizap \f[I]will\f[R] catch such mishaps after a few iterations, but +it\[cq]s better to avoid them in the first place. We mention in passing that in theory, recursive macro calls in conjunction with value lists and change detection make the configuration language Turing\-complete. -However, there's a quite stringent limit on the number of recursive +However, there\[cq]s a quite stringent limit on the number of recursive calls, and there are no variables and no iteration constructs, so these -facilities aren't really suitable for general\-purpose programming. +facilities aren\[cq]t really suitable for general\-purpose programming. .PP -But there's still a lot of fun to be had with macros despite their +But there\[cq]s still a lot of fun to be had with macros despite their limitations. -Here's another instructive example which spits out the individual bits -of a controller value, using the approach that we discussed earlier in -the context of nibble extraction. -Input comes from \f[C]CC7\f[] in the example, and bit #\f[I]i\f[] of the -controller value becomes \f[C]CC\f[]\f[I]i\f[] in the output, where -\f[I]i\f[] runs from 0 to 6. +Here\[cq]s another instructive example which spits out the individual +bits of a controller value, using the approach that we discussed earlier +in the context of nibble extraction. +Input comes from \f[C]CC7\f[R] in the example, and bit #\f[I]i\f[R] of +the controller value becomes \f[C]CC\f[R]\f[I]i\f[R] in the output, +where \f[I]i\f[R] runs from 0 to 6. Note that each of these rules uses a successively smaller power of 2 as modulus and passes on the remainder to the next rule, while transposition is used to extract and output the topmost bit in the @@ -2284,80 +2282,80 @@ exactly is going on there.) .IP .nf \f[C] -CC7[64]{0}\ $CC6\ CC6\[aq] -CC6[32]{0}\ $CC5\ CC5\[aq] -CC5[16]{0}\ $CC4\ CC4\[aq] -CC4[8]{0}\ \ $CC3\ CC3\[aq] -CC3[4]{0}\ \ $CC2\ CC2\[aq] -CC2[2]{0}\ \ CC0\ \ CC1\[aq] -\f[] +CC7[64]{0} $CC6 CC6\[aq] +CC6[32]{0} $CC5 CC5\[aq] +CC5[16]{0} $CC4 CC4\[aq] +CC4[8]{0} $CC3 CC3\[aq] +CC3[4]{0} $CC2 CC2\[aq] +CC2[2]{0} CC0 CC1\[aq] +\f[R] .fi .PP In principle, any message which can occur on the left\-hand side of a -mod translation (i.e., everything but \f[C]PC\f[]) can also be used as a -macro. -Unfortunately, in general you can't be sure which messages might show up -in \f[I]real\f[] MIDI input. +mod translation (i.e., everything but \f[C]PC\f[R]) can also be used as +a macro. +Unfortunately, in general you can\[cq]t be sure which messages might +show up in \f[I]real\f[R] MIDI input. For instance, in the example above the macro translations for -\f[C]CC2\f[] to \f[C]CC6\f[] might also be triggered by real MIDI input -instead of macro calls. +\f[C]CC2\f[R] to \f[C]CC6\f[R] might also be triggered by real MIDI +input instead of macro calls. While this may be useful at times, e.g., for testing purposes, it is most likely going to confuse unsuspecting end users. As a remedy, midizap also provides a special kind of \f[I]macro -event\f[], denoted \f[C]M0\f[] to \f[C]M127\f[]. -These \[lq]synthetic\[rq] messages work exactly like \f[C]CC\f[] +event\f[R], denoted \f[C]M0\f[R] to \f[C]M127\f[R]. +These \[lq]synthetic\[rq] messages work exactly like \f[C]CC\f[R] messages, but they are guaranteed to never occur as real input, and they -can \f[I]only\f[] be used in macro calls and on the left\-hand side of +can \f[I]only\f[R] be used in macro calls and on the left\-hand side of mod translations. We can rewrite the previous example using macro events as follows: .IP .nf \f[C] -CC7[64]{0}\ $M6\ CC6\[aq] -M6[32]{0}\ \ $M5\ CC5\[aq] -M5[16]{0}\ \ $M4\ CC4\[aq] -M4[8]{0}\ \ \ $M3\ CC3\[aq] -M3[4]{0}\ \ \ $M2\ CC2\[aq] -M2[2]{0}\ \ \ CC0\ CC1\[aq] -\f[] +CC7[64]{0} $M6 CC6\[aq] +M6[32]{0} $M5 CC5\[aq] +M5[16]{0} $M4 CC4\[aq] +M4[8]{0} $M3 CC3\[aq] +M3[4]{0} $M2 CC2\[aq] +M2[2]{0} CC0 CC1\[aq] +\f[R] .fi .PP -Let's conclude with another, slightly more practical example for the use -of macros, which turns the pitch wheel of a MIDI keyboard into a simple -kind of \[lq]shuttle control\[rq]. -To illustrate how this works, let's emit an \f[C]XK_Left\f[] key event -when the pitch wheel is pushed down, and an \f[C]XK_Right\f[] event when -it's pushed up. +Let\[cq]s conclude with another, slightly more practical example for the +use of macros, which turns the pitch wheel of a MIDI keyboard into a +simple kind of \[lq]shuttle control\[rq]. +To illustrate how this works, let\[cq]s emit an \f[C]XK_Left\f[R] key +event when the pitch wheel is pushed down, and an \f[C]XK_Right\f[R] +event when it\[cq]s pushed up. This can be done as follows: .IP .nf \f[C] -PB[]\ $M0{0:8192,1,2}? -M0[]\ $M1{1,\-1}\ $M2{\-1:2,1,\-1} -M1[]\ XK_Left -M2[]\ XK_Right -\f[] +PB[] $M0{0:8192,1,2}? +M0[] $M1{1,\-1} $M2{\-1:2,1,\-1} +M1[] XK_Left +M2[] XK_Right +\f[R] .fi .PP -Note that the \f[C]M0\f[] macro will be invoked with a value of 0, 1 and -2 if the pitch wheel is down, centered, and up, respectively. -Also, we use the change flag here, so the \f[C]M0\f[] macro is only +Note that the \f[C]M0\f[R] macro will be invoked with a value of 0, 1 +and 2 if the pitch wheel is down, centered, and up, respectively. +Also, we use the change flag here, so the \f[C]M0\f[R] macro is only invoked when this value actually changes. -The value lists in the definition of \f[C]M0\f[] are then used to filter -these values and call the appropriate macro which handles the key -output: \f[C]M1\f[] for value 0, \f[C]M2\f[] for value 2. +The value lists in the definition of \f[C]M0\f[R] are then used to +filter these values and call the appropriate macro which handles the key +output: \f[C]M1\f[R] for value 0, \f[C]M2\f[R] for value 2. .PP -Flipping the pitch wheel just to move the cursor left and right isn't -much fun after a while, but it's easy to adjust the \f[C]M1\f[] and -\f[C]M2\f[] macros for more sensible purposes. +Flipping the pitch wheel just to move the cursor left and right +isn\[cq]t much fun after a while, but it\[cq]s easy to adjust the +\f[C]M1\f[R] and \f[C]M2\f[R] macros for more sensible purposes. E.g., we might output the keyboard shortcuts for \[lq]Rewind\[rq] and \[lq]Fast Forward\[rq] for a video editor like Kdenlive or Shotcut: .IP .nf \f[C] -M1[]\ "j" -M2[]\ "l" -\f[] +M1[] \[dq]j\[dq] +M2[] \[dq]l\[dq] +\f[R] .fi .PP We could also substitute the corresponding MIDI messages of the Mackie @@ -2365,9 +2363,9 @@ protocol to control a DAW program like Ardour: .IP .nf \f[C] -M1[]\ G7[127]\ \ #\ Rewind -M2[]\ G#7[127]\ #\ Fast\ Forward -\f[] +M1[] G7[127] # Rewind +M2[] G#7[127] # Fast Forward +\f[R] .fi .SH Configuration Language Grammar .PP @@ -2378,11 +2376,11 @@ permitted in comments, however). The language is line\-oriented; each directive, section header, and translation must be on a separate line. Empty lines and lines containing nothing but whitespace are generally -ignored, as are comments, which are introduced with \f[C]#\f[] at the +ignored, as are comments, which are introduced with \f[C]#\f[R] at the beginning of a line or after whitespace, and continue until the end of the line. (The section name and regex in header lines is always taken verbatim, -though, so whitespace and \f[C]#\f[] have no special significance +though, so whitespace and \f[C]#\f[R] have no special significance there.) .PP Regular expressions must follow the usual syntax for extended regular @@ -2394,35 +2392,35 @@ Numbers are always integers written in decimal notation. .IP .nf \f[C] -config\ \ \ \ \ \ ::=\ {\ directive\ |\ header\ |\ translation\ } -header\ \ \ \ \ \ ::=\ "["\ name\ "]"\ [\ "CLASS"\ |\ "TITLE"\ ]\ regex -translation\ ::=\ midi\-token\ {\ key\-token\ |\ midi\-token\ } +config ::= { directive | header | translation } +header ::= \[dq][\[dq] name \[dq]]\[dq] [ \[dq]CLASS\[dq] | \[dq]TITLE\[dq] ] regex +translation ::= midi\-token { key\-token | midi\-token } -directive\ \ \ ::=\ "DEBUG_REGEX"\ |\ "DEBUG_STROKES"\ |\ "DEBUG_KEYS"\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "DEBUG_MIDI"\ |\ "MIDI_OCTAVE"\ number\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "JACK_NAME"\ string\ |\ "JACK_PORTS"\ number\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "JACK_IN"\ [number]\ regex\ |\ "JACK_OUT"\ [number]\ regex\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "PASSTHROUGH"\ [\ number\ ]\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "SYSTEM_PASSTHROUGH"\ [\ number\ ] +directive ::= \[dq]DEBUG_REGEX\[dq] | \[dq]DEBUG_STROKES\[dq] | \[dq]DEBUG_KEYS\[dq] | + \[dq]DEBUG_MIDI\[dq] | \[dq]MIDI_OCTAVE\[dq] number | + \[dq]JACK_NAME\[dq] string | \[dq]JACK_PORTS\[dq] number | + \[dq]JACK_IN\[dq] [number] regex | \[dq]JACK_OUT\[dq] [number] regex | + \[dq]PASSTHROUGH\[dq] [ number ] | + \[dq]SYSTEM_PASSTHROUGH\[dq] [ number ] -midi\-token\ \ ::=\ msg\ [\ mod\ ]\ [\ steps\ ]\ [\ "\-"\ number]\ [\ flag\ ] -msg\ \ \ \ \ \ \ \ \ ::=\ (\ note\ |\ other\ |\ "M"\ )\ [\ number\ ] -note\ \ \ \ \ \ \ \ ::=\ (\ "A"\ |\ ...\ |\ "G"\ )\ [\ "#"\ |\ "b"\ ] -other\ \ \ \ \ \ \ ::=\ "CH"\ |\ "PB"\ |\ "PC"\ |\ "CC"\ |\ "CP"\ |\ "KP:"\ note -mod\ \ \ \ \ \ \ \ \ ::=\ "["\ [\ number\ ]\ "]" -steps\ \ \ \ \ \ \ ::=\ "["\ number\ "]"\ |\ "{"\ list\ "}" -list\ \ \ \ \ \ \ \ ::=\ number\ {\ ","\ number\ |\ ":"\ number\ |\ "\-"\ number\ } -flag\ \ \ \ \ \ \ \ ::=\ "\-"\ |\ "+"\ |\ "="\ |\ "<"\ |\ ">"\ |\ "~"\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "\[aq]"\ |\ "?"\ |\ "\[aq]?"\ |\ "?\[aq]" +midi\-token ::= msg [ mod ] [ steps ] [ \[dq]\-\[dq] number] [ flag ] +msg ::= ( note | other | \[dq]M\[dq] ) [ number ] +note ::= ( \[dq]A\[dq] | ... | \[dq]G\[dq] ) [ \[dq]#\[dq] | \[dq]b\[dq] ] +other ::= \[dq]CH\[dq] | \[dq]PB\[dq] | \[dq]PC\[dq] | \[dq]CC\[dq] | \[dq]CP\[dq] | \[dq]KP:\[dq] note +mod ::= \[dq][\[dq] [ number ] \[dq]]\[dq] +steps ::= \[dq][\[dq] number \[dq]]\[dq] | \[dq]{\[dq] list \[dq]}\[dq] +list ::= number { \[dq],\[dq] number | \[dq]:\[dq] number | \[dq]\-\[dq] number } +flag ::= \[dq]\-\[dq] | \[dq]+\[dq] | \[dq]=\[dq] | \[dq]<\[dq] | \[dq]>\[dq] | \[dq]\[ti]\[dq] | + \[dq]\[aq]\[dq] | \[dq]?\[dq] | \[dq]\[aq]?\[dq] | \[dq]?\[aq]\[dq] -key\-token\ \ \ ::=\ "RELEASE"\ |\ "SHIFT"\ [\ number\ ]\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ keycode\ [\ "/"\ keyflag\ ]\ |\ string -keycode\ \ \ \ \ ::=\ "XK_Button_1"\ |\ "XK_Button_2"\ |\ "XK_Button_3"\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "XK_Scroll_Up"\ |\ "XK_Scroll_Down"\ | -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "XK_..."\ (see\ /usr/include/X11/keysymdef.h) -keyflag\ \ \ \ \ ::=\ "U"\ |\ "D"\ |\ "H" -string\ \ \ \ \ \ ::=\ \[aq]"\[aq]\ {\ character\ }\ \[aq]"\[aq] -\f[] +key\-token ::= \[dq]RELEASE\[dq] | \[dq]SHIFT\[dq] [ number ] | + keycode [ \[dq]/\[dq] keyflag ] | string +keycode ::= \[dq]XK_Button_1\[dq] | \[dq]XK_Button_2\[dq] | \[dq]XK_Button_3\[dq] | + \[dq]XK_Scroll_Up\[dq] | \[dq]XK_Scroll_Down\[dq] | + \[dq]XK_...\[dq] (see /usr/include/X11/keysymdef.h) +keyflag ::= \[dq]U\[dq] | \[dq]D\[dq] | \[dq]H\[dq] +string ::= \[aq]\[dq]\[aq] { character } \[aq]\[dq]\[aq] +\f[R] .fi .SH Bugs .PP @@ -2430,12 +2428,12 @@ 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 +In particular, we\[cq]re looking for interesting configurations to be included in the distribution. .PP The names of some of the debugging options are rather idiosyncratic. -midizap inherited them from Eric Messick's ShuttlePRO program, and we -decided to keep them for backward compatibility. +midizap inherited them from Eric Messick\[cq]s ShuttlePRO program, and +we decided to keep them for backward compatibility. .PP midizap tries to keep things simple, which implies that it has its limitations. @@ -2452,28 +2450,29 @@ using a more comprehensive tool such as Pd (http://puredata.info/) instead. .PP 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 +support is tailored to X11, i.e., it\[cq]s pretty much tied to Unix/X11 systems right now. -Native Mac or Windows support certainly seems possible, but it's not -going to happen until someone steps in who's in the know about suitable -Mac and Windows replacements for the X11 XTest extension. +Native Mac or Windows support certainly seems possible, but it\[cq]s not +going to happen until someone steps in who\[cq]s in the know about +suitable Mac and Windows replacements for the X11 XTest extension. .SH See Also .PP midizap is based on a fork (https://github.com/agraef/ShuttlePRO) of -Eric Messick's ShuttlePRO +Eric Messick\[cq]s ShuttlePRO program (https://github.com/nanosyzygy/ShuttlePRO), which provides similar functionality for the Contour Design Shuttle devices. .PP -Spencer Jackson's osc2midi utility (https://github.com/ssj71/OSC2MIDI) -makes for a great companion to midizap if you also need to convert -between MIDI and Open Sound Control (http://opensoundcontrol.org/). +Spencer Jackson\[cq]s osc2midi +utility (https://github.com/ssj71/OSC2MIDI) 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. +It is proprietary software and isn\[cq]t available for Linux, but it +should be worth a look if you need a midizap alternative which runs on +these systems. .SH Authors, License and Credits .PP midizap is free and open source software licensed under the GPLv3, @@ -2492,6 +2491,6 @@ 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. +The Jack MIDI backend is based on code from Spencer Jackson\[cq]s +osc2midi utility, and on the simple_session_client.c example available +in the Jack git repository.