Compare commits

...

22 Commits
0.4 ... master

Author SHA1 Message Date
nixo 6d5a3b1ef4 add guix build file 2020-07-25 21:44:33 +02:00
nixo e00ab5e45b Fix jog back on djcontrol instinct 2020-07-25 21:30:17 +02:00
Albert Graef b6068a73c0 Minimal Mackie emulation for the Harley Benton MP-100 a.k.a. MeloAudio MIDI Commander. 2019-12-18 10:56:19 +01:00
Albert Graef dc626710e6 Install midizap-mode automatically if Emacs is found during installation. Update the documentation. 2018-11-16 21:18:54 +01:00
Albert Graef 8c622bd085 midizap-mode: Add keysyms to auto-complete keywords table. 2018-11-16 20:37:58 +01:00
Albert Graef e53e3b3140 Add some snippets for Emacs yasnippets. 2018-11-13 08:31:41 +01:00
Albert Graef 8fef722919 Remove unneeded changes to midizap mode syntax table. 2018-11-11 18:59:24 +01:00
Albert Graef 24e346c733 Comment changes. 2018-11-11 10:12:21 +01:00
Albert Graef 240d30da7d Comment changes. 2018-11-11 00:31:31 +01:00
Albert Graef 951fa8fb17 Update the manual. 2018-11-10 23:46:20 +01:00
Albert Graef 7954230468 Add an Emacs mode for midizaprc files. 2018-11-10 23:45:56 +01:00
Albert Graef 357836a383 Fix glitches in regexes. 2018-11-06 07:31:56 +01:00
Albert Graef c2160b9893 Typo in the manual. 2018-10-16 08:33:48 +02:00
Albert Graef 7ce7f3c30b Fix up the detection of our own ports in the connection callback. 2018-10-16 08:29:22 +02:00
Albert Graef 15b8b574b3 Update the manual. 2018-10-15 06:23:23 +02:00
Albert Graef b39484c0ac Make the -r optional, so that just 'midizap rcfile' will work. 2018-10-15 05:56:47 +02:00
Albert Graef 4947aca50f Fix an obscure bug in copying anyshift mod translations which might errorneously override the modulus in an existing translation. 2018-10-15 03:26:31 +02:00
Albert Graef 70287a7e9f X-Touch Mini example: Move the MIDI CC assignments on the ALT layer to a separate config, so that we don't mix up Mackie and MIDI control messages. 2018-10-14 21:05:19 +02:00
Albert Graef 1898fe74cf X-Touch Mini example: Add some more bindings for the encoders on the ALT layer (experimental). 2018-10-14 10:47:01 +02:00
Albert Graef 9d55ce9651 Cosmetic changes to the other examples. 2018-10-14 10:47:01 +02:00
Albert Graef d0477d27d2 Rework the X-Touch Mini and ONE examples. 2018-10-14 10:47:01 +02:00
Albert Graef 56ea96686a Add a built-in patchbay facility (JACK_IN/JACK_OUT directives). 2018-10-14 10:47:01 +02:00
27 changed files with 1986 additions and 1656 deletions

View File

@ -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)
@ -18,7 +24,7 @@ INSTALL_TARGETS = midizap $(wildcard midizap.1)
.PHONY: all world install uninstall man pdf clean realclean
all: midizap
all: midizap midizap-mode.el
# This also creates the manual page (see below).
world: all man
@ -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)
@ -56,7 +68,7 @@ midizap.pdf: midizap.1
man -Tpdf ./midizap.1 > $@
clean:
rm -f midizap keys.h $(OBJ)
rm -f midizap keys.h keys.el midizap-mode.el $(OBJ)
realclean:
rm -f midizap midizap.1 midizap.pdf keys.h $(OBJ)
@ -64,6 +76,12 @@ realclean:
keys.h: keys.sed /usr/include/X11/keysymdef.h
sed -f keys.sed < /usr/include/X11/keysymdef.h > keys.h
keys.el: keywords.sed /usr/include/X11/keysymdef.h
sed -f keywords.sed < /usr/include/X11/keysymdef.h | tr '\n' ' ' > keys.el
midizap-mode.el: midizap-mode.el.in keys.el
sed '/;; keysyms/r keys.el' < midizap-mode.el.in > midizap-mode.el
readconfig.o: midizap.h keys.h
midizap.o: midizap.h jackdriver.h
jackdriver.o: jackdriver.h

View File

@ -6,7 +6,7 @@ midizap -- control your multimedia applications with MIDI
# Synopsis
midizap [-hkn] [-d[rskmj]] [-j *name*] [-ost[*n*]] [-P[*prio*]] [-r *rcfile*]
midizap [-hkn] [-d[rskmj]] [-j *name*] [-ost[*n*]] [-P[*prio*]] [[-r] *rcfile*]
# Options
@ -31,8 +31,8 @@ midizap [-hkn] [-d[rskmj]] [-j *name*] [-ost[*n*]] [-P[*prio*]] [-r *rcfile*]
-P[*prio*]
: Run with the given real-time priority (default: 90). See Section *Jack-Related Options*.
-r *rcfile*
: Set the configuration file name. Default: taken from the MIDIZAP_CONFIG_FILE environment variable if it exists, or ~/.midizaprc if it exists, /etc/midizaprc otherwise. See Section *Configuration File*.
[-r] *rcfile*
: Set the configuration file name. The `-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 *Configuration File*.
-s[*n*]
: Pass through system messages from MIDI input to output; *n* 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 *Jack-Related Options*.
@ -42,13 +42,11 @@ midizap [-hkn] [-d[rskmj]] [-j *name*] [-ost[*n*]] [-P[*prio*]] [-r *rcfile*]
# Description
midizap lets you control your multimedia applications using [MIDI][], the Musical Instrument Digital Interface. Modern MIDI controllers are often USB class devices which can be connected to computers without any ado. midizap makes it possible to use this gear with just about any X11-based application. To these ends, it translates Jack MIDI input into X keyboard and mouse events, and optionally MIDI output. It does this by matching the `WM_CLASS` and `WM_NAME` properties of the window that has the keyboard focus against the regular expressions for each application section in its configuration (midizaprc) file. If a regex matches, the corresponding set of translations is used. If a matching section cannot be found, or if it doesn't define a suitable translation, the program falls back to a set of translations in a default section at the end of the file, if available.
midizap lets you control your multimedia applications using [MIDI][], the venerable "Musical Instrument Digital Interface" protocol which has been around since the 1980s. Modern MIDI controllers are usually USB class devices which don'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 X11-based application. To these ends, it translates Jack MIDI input into X keyboard and mouse events, and optionally MIDI output. 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 suitable translation, the program falls back to a set of default translations.
The midizaprc file is just an ordinary text file which you can edit to configure the program. The configuration language is fairly straightforward, basically the file is just a list of MIDI messages (denoted with familiar human-readable mnemonics, no hex numbers!) and their translations, which is divided into sections for different applications. An example.midizaprc file is included in the sources to get you started, and you can find some more examples of configuration files for various purposes in the examples directory.
The midizaprc file is just an ordinary text file which you can edit to configure the program. The configuration language is fairly straightforward, basically the file is just a list of MIDI messages (denoted with familiar human-readable mnemonics, no hex numbers!) and their translations. 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.
midizap provides you with a way to hook up just about any MIDI controller to your applications. Even if your target application already supports MIDI, midizap's MIDI output option will be useful if your controller can't work directly with the application because of protocol incompatibilities. In particular, you can use midizap to turn pretty much any MIDI controller with enough faders and buttons into a Mackie-compatible mixing console ready to be used with most DAW (digital audio workstation) programs. Another common use case is video editing software, which rarely offers built-in MIDI support. midizap allows you to map the faders, encoders and buttons of your MIDI controller to keyboard commands of your video editor for cutting, marking, playback, scrolling, zooming, etc.
In other words, as long as the target application can be controlled with simple keyboard shortcuts and/or MIDI commands, chances are that midizap can make it work (at least to some extent) with your controller.
Even if your target application already supports MIDI, midizap's MIDI output option will be useful if your controller can't work directly with the application because of protocol incompatibilities. In particular, you can use midizap to turn any MIDI controller with enough faders and buttons into a Mackie-compatible device ready to be used with most DAW (digital audio workstation) programs. Another common use case is photo and video editing software. This kind of software often lacks built-in MIDI support, and midizap can then be used to map the faders, encoders and buttons of your MIDI controller to keyboard commands for adjusting colors, cutting, marking, playback, scrolling, zooming, etc. In other words, as long as the target application can be controlled with simple keyboard shortcuts and/or MIDI commands, chances are that midizap can make it work (at least to some extent) with your controller.
# Installation
@ -58,6 +56,8 @@ 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. 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
After installation the system-wide default configuration file will be in /etc/midizaprc, where the program will be able to find it. We recommend copying this file to your home directory, renaming it to .midizaprc:
@ -66,19 +66,23 @@ After installation the system-wide default configuration file will be in /etc/mi
The ~/.midizaprc file, if it exists, takes priority over /etc/midizaprc, so it becomes your personal default midizap configuration. The midizaprc file included in the distribution is really just an example; you're expected to edit this file to adjust the bindings for the MIDI controllers and the applications that you use.
It is also possible to specify the configuration file to be used, by invoking midizap with the `-r` option followed by the name of the midizaprc file on the command line. This is often used with more specialized configurations dealing with specific applications or MIDI controllers. E.g., to try one of sample configurations in the sources: `midizap -r examples/MPKmini2.midizaprc`
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 line. This is often used with more specialized configurations dealing with specific applications or MIDI controllers. E.g., to try one of the sample configurations in the sources:
~~~
midizap examples/APCmini.midizaprc
~~~
The program automatically reloads the midizaprc file whenever it notices that the file has been changed. Thus you can edit the file while the program keeps running, and have the changes take effect immediately without having to restart the program. When working on new translations, you may want to run the program in a terminal, and employ some or all of the debugging options explained below to see exactly how your translations are being processed.
# Basic Usage
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 *Jack-Related Options* below) or from your desktop environment's startup files once you've set up everything to your liking.
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 *Jack-Related Options* 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 midizap-mode.el file included in the sources for details.
Try `midizap -h` for a brief summary of the available options with which the program can be invoked.
midizap uses [Jack][] for doing all its MIDI input and output, so you need to be able to run Jack and connect the Jack MIDI inputs and outputs of the program. We recommend using a Jack front-end and patchbay program like [QjackCtl][] for this purpose. In QjackCtl's setup, make sure that you have selected `seq` 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. As an alternative, you can also run [a2jmidid][] as a separate ALSA-Jack MIDI bridge. (The latter method will work with both Jack1 and Jack2, the former method is only recommended if you're using Jack1.)
midizap uses [Jack][] for doing all its MIDI input and output, so you need to be able to run Jack and connect the Jack MIDI inputs and outputs of the program. We recommend using a Jack front-end and patchbay program like [QjackCtl][] for this purpose. In QjackCtl's setup, make sure that you have selected `seq` 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. As an alternative, you can also run [a2jmidid][] 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 a2jmidid in that case. When in doubt, just use a2jmidid. You can have QJackCtl autostart a2jmidid by placing the command `a2jmidid -e &` into the "Execute script after Startup" field which can be found under "Options" in QJackctl's Setup dialog.
Having that set up, start Jack, make sure that your MIDI controller is connected, and try running `midizap` from the command line (without any arguments). In QjackCtl, open the Connections dialog and activate the second tab named "MIDI", which shows all available Jack MIDI inputs and outputs. On the right side of the MIDI tab, you should now see a client named `midizap` with one MIDI input port named `midi_in`. That's the one you need to connect to your MIDI controller, whose output port should be visible under the `alsa_midi` client on the left side of the dialog.
Having that set up, start Jack, make sure that your MIDI controller is connected, and try running `midizap` from the command line (without any arguments). In QjackCtl, open the Connections dialog and activate the second tab named "MIDI", which shows all available Jack MIDI inputs and outputs. On the right side of the MIDI tab, you should now see a client named `midizap` with one MIDI input port named `midi_in`. That's the one you need to connect to your MIDI controller, whose output port should be visible under the `alsa_midi` client on the left side of the dialog (or the `a2j` client, if you're using a2jmidid).
To test the waters, you can hook up just about any MIDI keyboard and give it a try with the default section in the distributed midizaprc file, which contains some basic translations for mouse and cursor key emulation. Here is the relevant excerpt from that section:
@ -143,7 +147,9 @@ Besides MIDI notes and control change (`CC`) messages, the midizap program also
# Jack-Related Options
There are some additional directives (and corresponding command line options) to set midizap's Jack client name and the number of input and output ports it uses. If both the command line options and directives in the midizaprc file are used, the former take priority, so that it's always possible to override the configuration settings from the command line.
There are some additional directives (and corresponding command line options) to configure midizap'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. 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.
## Jack Client Name and MIDI Port Setup
Firstly, there's the `-j` option and the `JACK_NAME` directive which change the Jack client name from the default (`midizap`) to whatever you want it to be. To use this option, simply invoke midizap as `midizap -j client-name`, or put the following directive into your midizaprc file:
@ -161,17 +167,54 @@ JACK_PORTS 1
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 `JACK_PORTS 1` if the configuration is primarily aimed at doing MIDI translations, so you'd like to have MIDI output enabled by default. `JACK_PORTS 2` or the `-o2` option indicates that *two* 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 *MIDI Feedback* section for details.
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 of translations will be silently ignored. Also note that midizap doesn't provide you with any options to actually connect the ports you created to other Jack MIDI clients. There already are plenty of excellent utilities specifically designed for this purpose, so there's no need to replicate that functionality in midizap. As already mentioned, we recommend using QjackCtl, which also offers a persistent MIDI patchbay, so that you can have the right connections automatically set up for you whenever you launch midizap. You then use the Jack client name option if you need to distinguish multiple midizap instances. (The examples folder in the sources contains a QjackCtl patchbay named midizap.xml which has been set up to work with any of the included examples. Use the "Load" button in QjackCtl's Patchbay dialog to load it, then hit the "Activate" button to have QjackCtl actually use it.)
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 of translations will be silently ignored.
## MIDI Connections
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.
As a remedy, midizap offers its own built-in patchbay functionality using the `JACK_IN` and `JACK_OUT` 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., `JACK_IN2` connects the second input port. If the port number is omitted then it defaults to 1, so both `JACK_OUT1` and just `JACK_OUT` 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. Please see the regex(7) manual page for a discussion of the syntax and meaning of regular expressions. Note that regular expressions come in two different flavors, "basic" and "extended"; midizap uses the latter kind.
A connection will be established automatically by midizap whenever a MIDI port belonging to another Jack client matches the regular expression, as well as the port type and I/O direction. This also works dynamically, as new devices get added and new applications are launched at runtime.
For instance, the following lines (from the XTouchONE.midizaprc example) connect midizap to an X-Touch One device on one side and Ardour's Mackie control port on the other:
~~~
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
~~~
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. This is a typical setup for bidirectional communication between controller and application as described in the *MIDI Feedback* 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 connections automatically.
Please note that in the present implementation, the built-in patchbay is only available through these directives, there are no corresponding command line options. 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:
~~~
JACK_OUT1 ardour:MIDI control in|Pure Data Midi-In 1
~~~
All matches are done against full port names including the *client-name*`:` 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., `MIDI control` will match *any* 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 `^` and `$` anchors as follows:
~~~
JACK_OUT1 ^ardour:MIDI control in$
~~~
## Pass-Through
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: `-t` which passes through any ordinary (non-system) message for which there are no translations (not even in the default section), and `-s` 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 messages; midizap cannot translate these, but it can pass them on unchanged when necessary. You can find examples for both use cases in the examples folder in the sources.
The corresponding directives are named `PASSTHROUGH` and `SYSTEM_PASSTHROUGH`, 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 `SYSTEM_PASSTHROUGH 2`, or use the `-s2` option on the command line; and to have unrecognized MIDI messages passed through in either direction, simply use `PASSTHROUGH`, or `-t`.
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.
## Jack Sessions
midizap also supports *Jack session management*, which makes it possible to record the options the program was invoked with, along with all the MIDI connections. QjackCtl has its own built-in Jack session manager which is available in its Session dialog. To use this, launch midizap and any other Jack applications you want to have in the session, use QjackCtl to set up all the connections as needed, and then hit the "Save" button in the Session dialog to have the session recorded. Now, at any later time you can rerun the recorded session with the "Load" button in the same dialog. Also, your most recent sessions are available in the "Recent" menu from where they can be launched quickly.
midizap also supports *Jack session management* which provides a convenient alternative way to launch your midizap instances. Once you'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.
Finally, midizap also offers an option to run the program with *real-time priorities*. Jack itself usually does that anyway where needed, but midizap's main thread won't unless you run it with the `-P` option (`midizap -P`, or `midizap -P80` if you also want to specify the priority). 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.)
Various Jack session managers are available for Linux, but if you'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. 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 "Save" button in the Session dialog to have the session recorded. Now, at any later time you can rerun the recorded session with the "Load" button in the same dialog. Also, your most recent sessions are available in the "Recent" menu from where they can be launched quickly.
## Realtime Priorities
Finally, midizap also offers an option to run the program with *real-time priorities*. Jack itself usually does that anyway where needed, but midizap's main thread won't unless you run it with the `-P` 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.)
# Translation Syntax
@ -189,7 +232,7 @@ PB output # pitch bend
The `#` 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.
Lines beginning with a `[`*name*`]` header are also special. Each such line introduces a translation class *name*, which may be followed by an extended regular expression *regex* (see the regex(7) manual page) to be matched against window class and title. A `CLASS` or `TITLE` token may precede *regex* to indicate that *only* the class or title is to be matched, respectively; otherwise both are matched. Note that the *regex* part is always taken verbatim, ignoring leading and trailing whitespace, but including embedded whitespace and `#` characters (so you can't place a comment on such lines).
Lines beginning with a `[`*name*`]` header are also special. Each such line introduces a translation class *name*, which may be followed by an extended regular expression *regex* to be matched against window class and title. A `CLASS` or `TITLE` token may precede *regex* to indicate that *only* the class or title is to be matched, respectively; otherwise both are matched. Note that the *regex* part is always taken verbatim, ignoring leading and trailing whitespace, but including embedded whitespace and `#` characters (so you can't place a comment on such lines).
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 `CLASS` nor `TITLE` is specified, then both are tried; in this case, midizap first tries to match the window class (the `WM_CLASS` property), then the window title (the `WM_NAME` property). The first section which matches determines the translations to be used for that window. An empty *regex* 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 `[MIDI]` and `[MIDI2]` which are used specifically for MIDI translations, please see the *MIDI Output* and *MIDI Feedback* 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 *name* is only used for debugging output and diagnostics, and needn't be unique.
@ -220,7 +263,7 @@ The header is followed by a list of translations which define what output should
Example:
~~~
[Terminal] CLASS ^.*-terminal.*|konsole|xterm$
[Terminal] CLASS ^(.*-terminal.*|konsole|xterm)$
F5 XK_Up
F#5 "pwd"
G5 XK_Down
@ -815,7 +858,7 @@ CC1[128] $CC0 # don't do this!
midizap *will* catch such mishaps after a few iterations, but it'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 calls, and there are no variables and no iteration constructs, so these facilities aren't really suitable for general-purpose programming.
But there'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 `CC7` in the example, and bit #*i* of the controller value becomes `CC`*i* in the output, where *i* 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 quotient.
But there'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 `CC7` in the example, and bit #*i* of the controller value becomes `CC`*i* in the output, where *i* 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 quotient. (You may want to run this example with debugging enabled to see what exactly is going on there.)
~~~
CC7[64]{0} $CC6 CC6'
@ -826,9 +869,7 @@ CC3[4]{0} $CC2 CC2'
CC2[2]{0} CC0 CC1'
~~~
You may want to run this example with debugging enabled to see what exactly is going on there.
The "naming" of macros is another issue worth discussing here. In principle, any message which can occur on the left-hand side of a mod translation (i.e., everything but `PC`) can also be used as a macro. Unfortunately, in general you can't be sure which messages might show up in *real* MIDI input. For instance, in the example above the macro translations for `CC2` to `CC6` 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 *macro event*, denoted `M0` to `M127`. These "synthetic" messages work exactly like `CC` messages, but they are guaranteed to never occur as real input, and they can *only* 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:
In principle, any message which can occur on the left-hand side of a mod translation (i.e., everything but `PC`) can also be used as a macro. Unfortunately, in general you can't be sure which messages might show up in *real* MIDI input. For instance, in the example above the macro translations for `CC2` to `CC6` 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 *macro event*, denoted `M0` to `M127`. These "synthetic" messages work exactly like `CC` messages, but they are guaranteed to never occur as real input, and they can *only* 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:
~~~
CC7[64]{0} $M6 CC6'
@ -878,6 +919,8 @@ 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 ]
midi-token ::= msg [ mod ] [ steps ] [ "-" number] [ flag ]
@ -924,7 +967,7 @@ midizap is free and open source software licensed under the GPLv3, please see th
Copyright 2013 Eric Messick (FixedImagePhoto.com/Contact)
Copyright 2018 Albert Graef (<aggraef@gmail.com>)
This is a version of Eric Messick's ShuttlePRO program which has been redesigned to work with Jack MIDI instead of the Contour Design Shuttle devices. ShuttlePRO was written in 2013 by Eric Messick, based on earlier code by Trammell Hudson and Arendt David. The MIDI support was added by Albert Gräf. 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.
midizap is a heavily modified version of the ShuttlePRO program which was written in 2013 by Eric Messick, based on earlier code by Trammell Hudson and Arendt David. 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.
[MIDI]: https://www.midi.org/
[OSC]: http://opensoundcontrol.org/

View File

@ -150,7 +150,7 @@
# WM_CLASS). These have very similar key bindings, see e.g.:
# https://www.shotcut.org/howtos/keyboard-shortcuts/
[Kdenlive/Shotcut] ^shotcut|kdenlive$
[Kdenlive/Shotcut] ^(shotcut|kdenlive)$
# Both Kdenlive and Shotcut use the J-K-L shortcuts, where each
# successive J or L key decrements or increments the playback speed. We

View File

@ -1,6 +1,12 @@
# Mackie emulation for the AKAI APCmini
# This turns the APCmini into a Mackie-compatible controller, so that it can
# be used with Linux DAW programs like Ardour. The emulation is complicated
# by the APCmini having no encoders, no motorized faders, and not nearly as
# many dedicated buttons as a Mackie device. But it offers enough controls to
# be usable as a basic DAW controller. Tested with Ardour.
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
# Copying and distribution of this file, with or without modification, are
@ -11,32 +17,29 @@
JACK_NAME "midizap-APCmini"
JACK_PORTS 2
# This turns the APCmini into a Mackie-compatible controller, so that it can
# be used with Linux DAW programs like Ardour. The emulation is complicated
# by the APCmini having no encoders, no motorized faders, and not nearly as
# many dedicated buttons as a Mackie device. But it offers enough controls to
# be usable as a basic DAW controller. I tested it with Ardour.
# SETUP: The following lines will take care of setting up all the connections
# automatically, but you still need to enable the Mackie control surface in
# Ardour, so that Ardour exposes the Mackie control ports.
# SETUP: In Ardour, enable the Mackie control surface, then connect Ardour's
# Mackie control ports to midizap's midi_out and midi_in2 ports, and the
# APCmini to midizap's midi_in and midi_out2 ports.
JACK_IN1 APC MINI MIDI 1
JACK_OUT1 ardour:mackie control in
JACK_IN2 ardour:mackie control out
JACK_OUT2 APC MINI MIDI 1
# PROTOCOL DOCUMENTATION: The Mackie protocol is fairly ubiquitous, but since
# manufacturers can't be bothered to properly *document* their stuff these
# days, we have to rely on volunteers who do their work using some reverse
# engineering. Here are the links that I found most useful:
# http://www.budgetfeatures.com/XctlDOC/Xctl Protocol for X-Touch V1.0.pdf
# (This chart really is a piece of art. It's actually about the Behringer
# X-Touch, but since that device is Mackie-compatible, there's a wealth of
# useful information in there; just ignore the bits which pertain to Xctl.)
# There's another fairly comprehensive one here (lacks the feedback messages,
# though):
# PROTOCOL DOCUMENTATION: The Mackie Control (MC) protocol is fairly
# ubiquitous, but since manufacturers can't be bothered to properly document
# their stuff these days, we have to rely on volunteers who do their work
# using some reverse engineering. Here are the links that I found most
# useful:
# This is fairly comprehensive, but lacks the feedback messages:
# http://www.jjlee.com/qlab/Mackie Control MIDI Map.pdf
# This chart really is a piece of art. It's actually about the Behringer
# X-Touch and its Xctl protocol, but there's useful information about MC in
# there as well:
# http://www.budgetfeatures.com/XctlDOC/Xctl Protocol for X-Touch V1.0.pdf
# Information about the APCmini can be found in the Akai forums here:
# http://community.akaipro.com/akai_professional/topics/midi-information-for-apc-mini
@ -206,8 +209,7 @@ CC69[] F7{0:49,1,0} E7{0:50,1,0} Eb7{0:51,1,0} D7{0:52,1,0}
# no feedback for faders (faders aren't motorized)
# NOTE: Feedback for rec/solo/mute/select also needs to be recognized in shift
# mode, so that the (shifted) bank/channel left/right keys work as expected.
# feedback for rec/solo/mute/select
# rec: color = red (vel. 3)
C0 C0[3]

59
examples/MP100.midizaprc Normal file
View File

@ -0,0 +1,59 @@
# Minimal Mackie emulation for the Harley Benton MP-100 a.k.a. MeloAudio MIDI
# Commander foot controller (https://meloaudio.com)
# This device is rather limited in what it can do as a Mackie controller (no
# feedback, just 4 switches, 4 toggles, and 2 continuous controllers), but it
# may still come in handy to guitarists for basic hands-free DAW control. Note
# that we can't make good use of the bank switches on the device (the two
# extra switches on the right), since these always emit a PC message, which
# interferes with our use of the PC messages for the transport controls. It
# may be possible to do something better by configuring a custom mode on the
# device, but here we stick to what's available in the factory settings.
# Copyright (c) 2019 Albert Graef <aggraef@gmail.com>
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any
# warranty.
JACK_NAME "midizap-MP100"
JACK_PORTS 1
# Auto-connect to the MP-100 on the input, and Ardour's Mackie control input
# on the output side.
JACK_IN TSMIDI.* MIDI 1
JACK_OUT ardour:mackie control in
# The following configuration assumes that the MP-100 is set to mode 1 (JAMP),
# which is the default. Note that the controller numbers for the top row and
# the expression pedal inputs are specific to JAMP mode, so you will have to
# adjust these if you run the device in a different host mode. As implemented
# below, the controls are laid out as follows:
# top row: [mute] [solo] [rec] [select] EXP1: volume (current channel)
# bottom row: [stop] [play] [chan<] [chan>] EXP2: volume (master)
[MIDI]
# Note that MCP expects a note-on/off pair for each activation of the
# mure/solo/rec/select switches, while the MP-100 top switches act as toggles,
# so we have to use suitable mod translations for the top row.
# top row (mute/solo/rec/select for current channel)
CC22[] E1{127} E1{0} # Mute
CC25[] G#0{127} G#0{0} # Solo
CC24[] C0{127} C0{0} # Rec
CC26[] C2{127} C2{0} # Select
# bottom row (basic transport and bank controls)
PC0 A7 # Stop
PC1 A#7 # Play
PC2 C4 # Channel Left
PC3 C#4 # Channel Right
# EXP-1 and EXP-2 (current channel and master volume)
CC4[] PB[129]-1 # Volume
CC7[] PB[129]-9 # Master

View File

@ -11,14 +11,17 @@
JACK_NAME "midizap-MPKmini2"
JACK_PORTS 1
# Auto-connect to the MPKMini2 on the input, and Ardour's Mackie control input
# on the output side.
JACK_IN MPKmini2 MIDI 1
JACK_OUT ardour:mackie control in
# This configuration assumes that the MPKmini2 is set to factory defaults.
# The device doesn't provide much feedback possibilities, so we don't even
# try. Connections: Controller goes into midizap midi_in, midi_out into the
# Mackie control input of your DAW.
# Controls: The joystick can be used as a shuttle control (push to the left
# for rewind, to the right for fast forward). The eight knobs are mapped to
# the channel volume controls. The drum pads are assigned as follows, with
# try. Controls: The joystick can be used as a shuttle control (push to the
# left for rewind, to the right for fast forward). The eight knobs are mapped
# to the channel volume controls. The drum pads are assigned as follows, with
# the transport section on bank A and the cursor and bank controls on bank B:
# Bank A: Pad 1-4: Stop Play Rec Cycle; Pad 5-8: Rew FFwd Click Marker

View File

@ -12,6 +12,12 @@ JACK_NAME "midizap-Maschine"
JACK_PORTS 2
SYSTEM_PASSTHROUGH # pass through MCP feedback
# automatic connections
JACK_IN1 Ctlra Maschine Mk3
JACK_OUT1 ardour:mackie control in
JACK_IN2 ardour:mackie control out
JACK_OUT2 Ctlra Maschine Mk3
# NOTE: At present, this controller isn't properly supported by ALSA, but it
# can be made to work in Linux with Harry van Haaren's Ctlra software.
# Specifically, you'll need the ctlra_daemonx program from the
@ -22,10 +28,11 @@ SYSTEM_PASSTHROUGH # pass through MCP feedback
# branch, you can run the following to install the libctlra library along with
# ctlra_daemonx: meson build && cd build && ninja && sudo ninja install
# Then run ctlra_daemonx -fnm alongside with midizap, and connect the ports as
# follows: Ctlra Maschine Mk3 -> midizap midi_in / midi_out -> Ardour mackie
# control in / mackie control out -> midizap midi_in2 / midi_out2 -> Ctlra
# Maschine Mk3.
# Then run ctlra_daemonx -fnm alongside with midizap, and check that the ports
# are connected as follows (the JACK_IN/OUT directives above should take care
# of this automagically): Ctlra Maschine Mk3 -> midizap midi_in / midi_out ->
# Ardour mackie control in / mackie control out -> midizap midi_in2 /
# midi_out2 -> Ctlra Maschine Mk3.
# Usage (executive summary):

View File

@ -11,16 +11,14 @@ This folder contains a couple of sample midizap configurations for different con
- [nanoKONTROL2.midizaprc](nanoKONTROL2.midizaprc): fix up the marker keys of the Korg nanoKONTROL2 in Cubase mode for use in Ardour
- [XTouchONE.midizaprc](XTouchONE.midizaprc): map the SCRUB key to the more important SHIFT key which the X-Touch ONE lacks
- [XTouchMini.midizaprc](XTouchMini.midizaprc): adds a bunch of Mackie control functions to make the device more useful in MC mode
- [XTouchONE2.midizaprc](XTouchONE2.midizaprc): an improved config for the X-Touch ONE which turns the SCRUB key into an internal shift key, and offers more advanced configuration options
- [XTouchONE.midizaprc](XTouchONE.midizaprc): adds a bunch of Mackie control functions to make the device more useful in MC mode
Other interesting items:
- [midizap.xml](midizap.xml): ready-to-use QjackCtl patchbay for all the sample configurations, auto-connects to Ardour
Installation: Open QjackCtl's Patchbay dialog, load the midizap.xml file and activate the patchbay. To connect with Ardour, you also need to enable the Mackie control surface in Ardour's preferences dialog.
- [x-touch-one.device](x-touch-one.device): X-Touch ONE device description for Ardour 5.12 (this is basically the X-Touch description with a bank size of 1, so that all tracks become accessible)
Installation: Copy the x-touch-one.device file to your ~/.config/ardour5/mcp/ directory and select "Behringer X-Touch ONE" as your Mackie control surface in Ardour's preferences dialog.
Note: You can also use my patched-up version of Ardour 5.12 instead, which fixes up the single-channel bank changes so that the X-Touch ONE will work nicely with Ardour *without* having to set the bank size to 1 (which will be problematic if you use the ONE in combination with other Mackie controllers which require a larger bank size). You can find the sources here: https://github.com/agraef/ardour/tree/5.12-ag-mcpfixes. Make sure to check out the 5.12-ag-mcpfixes branch. This also has a few other bugfixes in the MCP code which will become available with Ardour 6.0, but aren't in the upstream 5.12 tree.

View File

@ -0,0 +1,64 @@
# This is an addon to XTouchMini.midizaprc which adds some extra MIDI CC
# assignments for the encoders and the master fader to the ALT layer.
# NOTE: This is to be used along with XTouchMini.midizaprc (which see).
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any
# warranty.
JACK_NAME "midizap-XTouchMini+"
JACK_PORTS 2
JACK_IN1 X-TOUCH MINI MIDI 1
JACK_OUT1 ardour:MIDI control in
JACK_IN2 ardour:MIDI control out
JACK_OUT2 X-TOUCH MINI MIDI 1
[MIDI]
# ALT button (no feedback here, as this is already handled in the
# XTouchMini.midizaprc "mother" configuration)
E7 SHIFT2 RELEASE SHIFT2
# The encoders and the master fader are assigned to standard MIDI controls
# CC1..CC9 on the ALT layer, so you can assign them freely with Ardour's MIDI
# learn facility, and use the unit as an MC device at the same time.
# ALT encoders and fader = CC1..CC9, with direct feedback
2^CC16~ CC1 $M1
2^CC17~ CC2 $M2
2^CC18~ CC3 $M3
2^CC19~ CC4 $M4
2^CC20~ CC5 $M5
2^CC21~ CC6 $M6
2^CC22~ CC7 $M7
2^CC23~ CC8 $M8
2^PB[128]{0}-9 CC9'
# macros handling direct feedback for CC1..CC8
M1[12]{0} !CC48{33-43}'
M2[12]{0} !CC49{33-43}'
M3[12]{0} !CC50{33-43}'
M4[12]{0} !CC51{33-43}'
M5[12]{0} !CC52{33-43}'
M6[12]{0} !CC53{33-43}'
M7[12]{0} !CC54{33-43}'
M8[12]{0} !CC55{33-43}'
[MIDI2]
# feedback for the encoders on the ALT layer (CC1..CC8)
2^CC1[12]{0} CC48{33-43}'
2^CC2[12]{0} CC49{33-43}'
2^CC3[12]{0} CC50{33-43}'
2^CC4[12]{0} CC51{33-43}'
2^CC5[12]{0} CC52{33-43}'
2^CC6[12]{0} CC53{33-43}'
2^CC7[12]{0} CC54{33-43}'
2^CC8[12]{0} CC55{33-43}'

View File

@ -1,7 +1,15 @@
# Mapping for the X-Touch Mini in MC mode which takes care of the most glaring
# issues with this (rather nice) device: (1) no bank change keys, (2) no
# channel selection, and (3) no faders (except for the master fader).
# While the X-Touch Mini is very popular as a Lightroom controller, musicians
# often complain that its Mackie control mode is just too basic. But midizap
# makes it easy to add most of the essential MC functions that are missing, so
# that the unit becomes really usable as a control surface.
# NOTE: This configuration assumes that the X-Touch Mini is in MC mode, which
# is the case if the MC MODE LED on the right side is lit. If necessary, you
# can switch the device to MC mode by holding the MC key while powering it up.
# NOTE: There's an addon to this configuration with some MIDI CC bindings on
# the ALT layer, see XTouchMini+.midizaprc.
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
@ -13,50 +21,89 @@
JACK_NAME "midizap-XTouchMini"
JACK_PORTS 2
# Automatic connections for the device and Ardour.
JACK_IN1 X-TOUCH MINI MIDI 1
JACK_OUT1 ardour:mackie control in
JACK_IN2 ardour:mackie control out
JACK_OUT2 X-TOUCH MINI MIDI 1
# Pass everything through, except for the translations below.
PASSTHROUGH
SYSTEM_PASSTHROUGH
# The idea of this mapping is to leave the original bindings mostly untouched,
# and just add few things on top of it. Note that the device, besides the
# encoders and the master faders, has two rows of 8 buttons and 2 buttons on
# the right which are laid out in MC mode as follows:
# The idea of this mapping is to leave the original bindings mostly untouched.
# In order to accommodate the missing MC functions, we add two shifted layers.
# To access these layers, we reassign the first two keys in the bottom row as
# internal shift keys, denoted SHIFT and ALT in the following.
# [CLICK] [SOLO] [TRACK] [SEND] [PAN] [PLUGIN] [EQ] [INST] [MARKER]
# [DROP] [REPLACE] [REW] [FFWD] [LOOP] [STOP] [PLAY] [REC] [NUDGE]
# Note that the device, besides the encoders and the master fader, has two
# rows of 8 buttons and 2 buttons on the right which are laid out in MC mode
# as follows:
# We turn the MC/DROP key into an internal SHIFT key and remap the other keys
# as follows (with the shifted bindings given above and below in parentheses;
# these become active when holding down the MC/SHIFT key):
# [CLICK] [SOLO] [TRACK] [SEND] [PAN] [PLUGIN] [EQ] [INST] [MARKER/A]
# [DROP/MC] [REPLACE] [REW] [FFWD] [LOOP] [STOP] [PLAY] [REC] [NUDGE/B]
# (SELECT) ... (MARKER)
# [CLICK] [SOLO] [TRACK] [SEND] [PAN] [PLUGIN] [EQ] [INST] [BANK LEFT]
# [SHIFT] [REPLACE] [REW] [FFWD] [LOOP] [STOP] [PLAY] [REC] [BANK RIGHT]
# (DROP) (NUDGE)
# This midizap configuration remaps them as follows:
# That is, the shifted REPLACE key makes up for the remapped DROP key, and the
# MARKER and NUDGE keys must now be shifted to get these functions, while the
# unshifted keys are used to change banks. In addition, the eight buttons in
# the top row, when shifted, select the corresponding channel. And last but
# not least, the encoders, when operated while holding down the MC/SHIFT key,
# become the missing faders.
# [CLICK] [SOLO] [TRACK] [SEND] [PAN] [PLUGIN] [EQ] [INST] [BANK LEFT]
# [SHIFT] [ALT] [REW] [FFWD] [LOOP] [STOP] [PLAY] [REC] [BANK RIGHT]
# Note the two shift keys (SHIFT and ALT) in the lower button row, and the
# bank switch keys on the right. Other than that, the unshifted layer is
# unchanged. On the SHIFT layer, the bindings are as follows:
# [SELECT] ... [CHAN LEFT]
# [DROP] [REPLACE] [FLIP] [MARKER] [NUDGE] [CHAN RIGHT]
# Note that the remapped functions (DROP, REPLACE, MARKER, NUDGE) are now
# available as shifted keys in the bottom row. We also added the FLIP key
# there. The shifted keys in the top row are bound to the channel SELECT
# functions. Moreover, our translations for the SHIFT layer also assign the
# master fader to the first channel, like on the X-Touch ONE, and the encoders
# become the eight channel faders.
# Finally, the ALT layer. Since Ardour requires some of the keys to be
# combined with the MC SHIFT key to get at some functions (in particular,
# SHIFT + SELECT/MARKER/NUDGE), we provide those shifted bindings on this
# layer. We also throw in some more MC keys (cursor and zoom):
# [^SELECT] ... [UP]
# [LEFT] [RIGHT] [ZOOM] [^MARKER] [^NUDGE] [DOWN]
# Note that the way I've configured this layer is somewhat tailored to Ardour,
# so you may want to adjust it to your liking. The SHIFT layer, in contrast,
# should be pretty generic, and work fine as is with most DAWs.
[MIDI]
# MC = shift button, with direct feedback
# Note that, as explained in the midizap manual, you can change the SHIFT and
# ALT keys to CapsLock-style keys by removing the RELEASE part of the
# sequence. They will then work as toggles. With the RELEASE sequence, they
# work as momentary switches, i.e., you need to hold them down to invoke a
# shifted function.
# MC = SHIFT button, with direct feedback
D#7 SHIFT ^D#7 RELEASE SHIFT ^D#7
# ALT button
E7 SHIFT2 ^E7 RELEASE SHIFT2 ^E7
# A/B buttons on the right = bank left/right
C7 A#3 # bank left
C#7 B3 # bank right
# shifted A/B buttons = MARKER/NUDGE
^C7 C7
^C#7 C#7
# shifted A/B buttons = channel left/right
^C7 C4 # channel left
^C#7 C#4 # channel right
# shifted REPLACE button = DROP
^E7 D#7
# other shifted buttons
^G7 D#7 # REW = DROP
^G#7 E7 # FFWD = REPLACE
^D7 D4 # LOOP = FLIP
^A7 C7 # STOP = MARKER
^A#7 C#7 # PLAY = NUDGE
# ^B7 # REC, currently unassigned
# shifted top row = SELECT
^F7 C2
@ -78,22 +125,66 @@ C#7 B3 # bank right
^CC22~ PB[129]-7
^CC23~ PB[129]-8
# fader goes to first channel in bank when shifted
^PB[]-9 PB-1
# ALT layer. This uses the same trick (the explicit RELEASE sequence) as in
# XTouchONE.midizaprc to transmit the MC SHIFT key (A#5) in the right order.
# ALT top row = SHIFT+SELECT
2^F7 A#5 C2 RELEASE C2 A#5
2^F#7 A#5 C#2 RELEASE C#2 A#5
2^E3 A#5 D2 RELEASE D2 A#5
2^F3 A#5 D#2 RELEASE D#2 A#5
2^F#3 A#5 E2 RELEASE E2 A#5
2^G3 A#5 F2 RELEASE F2 A#5
2^G#3 A#5 F#2 RELEASE F#2 A#5
2^A3 A#5 G2 RELEASE G2 A#5
2^A7 A#5 C7 RELEASE C7 A#5 # ALT+STOP = SHIFT+MARKER
2^A#7 A#5 C#7 RELEASE C#7 A#5 # ALT+PLAY = SHIFT+NUDGE
2^G7 D8 # ALT+REW = LEFT
2^G#7 D#8 # ALT+FFWD = RIGHT
2^D7 E8 # ALT+LOOP = ZOOM
2^C7 C8 # ALT+A = UP
2^C#7 C#8 # ALT+B = DOWN
# Encoders and fader are disabled on the ALT layer, to accommodate the MIDI CC
# bindings in XTouchMini+.midizaprc.
2^CC16~ NOP
2^CC17~ NOP
2^CC18~ NOP
2^CC19~ NOP
2^CC20~ NOP
2^CC21~ NOP
2^CC22~ NOP
2^CC23~ NOP
2^PB[]-9 NOP
[MIDI2]
# feedback for the BANK LEFT/RIGHT buttons
A#3 C7
B3 C#7
# NOTE: We might also want to provide some actual feedback for the *shifted*
# faders here in the future, so that the current values are shown in the LED
# rings of the encoders while the faders are being operated.
# We also provide feedback for the *faders* here, so that the current values
# are shown on the LED rings of the encoders while the faders are being
# operated. Note that the fader values are shown in "fan" mode (arc from zero
# to the current value) so that they're distinguishable from pan values which
# will be shown in "pan" mode (single tick indicating left/right position).
# dummy feedback for the faders, to take advantage of automatic feedback
PB[]-1 NOP
PB[]-2 NOP
PB[]-3 NOP
PB[]-4 NOP
PB[]-5 NOP
PB[]-6 NOP
PB[]-7 NOP
PB[]-8 NOP
# NOTE: This is still experimental. Overloading the encoders in this manner is
# convenient and seems to work reasonably well in Ardour at least, but having
# some encoders display pan and others volume may be confusing at times.
PB[1536]{0}-1 CC48{33-43}'
PB[1536]{0}-2 CC49{33-43}'
PB[1536]{0}-3 CC50{33-43}'
PB[1536]{0}-4 CC51{33-43}'
PB[1536]{0}-5 CC52{33-43}'
PB[1536]{0}-6 CC53{33-43}'
PB[1536]{0}-7 CC54{33-43}'
PB[1536]{0}-8 CC55{33-43}'

View File

@ -1,104 +0,0 @@
# This is essentially the same as XTouchMini.midizaprc, but it assigns the
# shifted A/B keys to channel left/right, and also provides some other useful
# additional bindings on the SHIFT layer.
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any
# warranty.
JACK_NAME "midizap-XTouchMini"
JACK_PORTS 2
# Pass everything through, except for the translations below.
PASSTHROUGH
SYSTEM_PASSTHROUGH
# As with XTouchMini.midizaprc, [MC] is the shift key, holding it while
# pressing a button or operating the encoders or the fader provides additional
# MC functions. The other controls are assigned as usual in unshifted state,
# except that the A/B keys switch banks. When shifted, the master fader is
# assigned to the first channel, like on the X-Touch ONE, and the encoders
# become the eight channel faders. The bindings of the buttons are shown
# below, shifted bindings are indicated above and below in parentheses.
# (SELECT) (SELECT) ... (CHAN LEFT)
# [CLICK] [SOLO] [TRACK] [SEND] [PAN] [PLUGIN] [EQ] [INST] [BANK LEFT]
# [SHIFT] [REPLACE] [REW] [FFWD] [LOOP] [STOP] [PLAY] [REC] [BANK RIGHT]
# (DROP) (MARKER) (NUDGE) (FLIP) (CHAN RIGHT)
[MIDI]
# MC = shift button, with direct feedback
D#7 SHIFT ^D#7 RELEASE SHIFT ^D#7
# A/B buttons on the right = bank left/right
C7 A#3 # bank left
C#7 B3 # bank right
# shifted A/B buttons = channel left/right
^C7 C4 # channel left
^C#7 C#4 # channel right
# other shifted buttons
^E7 D#7 # REPLACE = DROP
^G7 C7 # REW = MARKER
^G#7 C#7 # FFWD = NUDGE
^D7 D4 # LOOP = FLIP
# SHIFT STOP/PLAY/REC are currently unassigned
# ^A7 # STOP
# ^A#7 # PLAY
# ^B7 # REC
# shifted top row = SELECT
^F7 C2
^F#7 C#2
^E3 D2
^F3 D#2
^F#3 E2
^G3 F2
^G#3 F#2
^A3 G2
# shifted encoders = channel faders
^CC16~ PB[129]-1
^CC17~ PB[129]-2
^CC18~ PB[129]-3
^CC19~ PB[129]-4
^CC20~ PB[129]-5
^CC21~ PB[129]-6
^CC22~ PB[129]-7
^CC23~ PB[129]-8
# fader goes to first channel in bank when shifted
^PB[]-9 PB-1
[MIDI2]
# feedback for the BANK LEFT/RIGHT buttons
A#3 C7
B3 C#7
# We also provide feedback for the *faders* here, so that the current values
# are shown on the LED rings of the encoders while the faders are being
# operated. Note that the fader values are shown in "fan" mode (arc from zero
# to the current value) so that they're distinguishable from pan values which
# will be shown in "pan" mode (single tick indicating left/right position).
# NOTE: This is still experimental. Overloading the encoders in this manner is
# convenient and seems to work reasonably well in Ardour at least, but having
# some encoders display pan and others volume may be confusing at times.
PB[1536]{0}-1 CC48{33-43}'
PB[1536]{0}-2 CC49{33-43}'
PB[1536]{0}-3 CC50{33-43}'
PB[1536]{0}-4 CC51{33-43}'
PB[1536]{0}-5 CC52{33-43}'
PB[1536]{0}-6 CC53{33-43}'
PB[1536]{0}-7 CC54{33-43}'
PB[1536]{0}-8 CC55{33-43}'

View File

@ -1,6 +1,12 @@
# The X-Touch ONE is quite capable as it is, it just lacks a SHIFT key.
# The sole purpose of this utterly trivial config is to provide one.
# The X-Touch ONE is a very capable Mackie device as it is, but it can still
# be improved a bit with some midizap magic. Most notably, the device lacks a
# SHIFT key, so we remap one of the lesser-used keys to provide an extra
# shifted layer which can be assigned freely to additional MC functions which
# aren't readily available on the device.
# NOTE: This config assumes that the X-Touch ONE is in its default Mackie
# mode. Otherwise you will have to adjust the mapping accordingly.
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
@ -12,17 +18,98 @@
JACK_NAME "midizap-XTouchONE"
JACK_PORTS 2
# Pass everything through, except for the one mapping below.
# Automatic connections for the device and Ardour.
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
# Pass everything through, except for the mappings below.
PASSTHROUGH
SYSTEM_PASSTHROUGH
# NOTE: This assumes that you use the default Mackie mode of the ONE.
# Otherwise you'll have to adjust the key mapping accordingly. I use the
# SCRUB key as a replacement (F8 in MC mode), because Ardour doesn't use
# it. If you do need that key, use another one that you can spare.
[MIDI]
F8 A#5
# I use the SCRUB key (F8 in MC mode) as the SHIFT key, because Ardour doesn't
# need it. YMMV, though, so if you need that key, you'll have to substitute
# another one that you can spare in the rule below.
F8 SHIFT ^F8 RELEASE SHIFT ^F8
# Remap the shifted F1 .. F4 keys to do something useful. I have them bound to
# the most important encoder assignment keys here, but of course you can
# change them to anything you want.
^F#4 E3 # Track (Trim in Ardour)
^G4 F#3 # Pan
^G#4 F3 # Send
^A4 G3 # Plugin (not supported by Ardour)
# Remap the shifted F5 and F6 keys to F7 and F8 which are missing on the ONE.
^A#4 C5
^B4 C#5
# If you're using the encoder assignment keys, then most likely you also want
# to have a FLIP button; we (rather arbitrarily) assign it to the shifted SOLO
# button in the TRANSPORT section.
^F#7 D4 # Flip
# Since the X-Touch ONE is a single-channel controller, I like to have the
# bank and channel keys linked up with channel SELECT, so that the current
# channel is also selected in the DAW when switching banks. Therefore I have
# bound these functions to the shifted bank and channel keys here, but of
# course you can change them to anything you want.
^A#3 A#3 C2 # BANK< SELECT
^B3 B3 C2 # BANK> SELECT
^C4 C4 C2 # CHAN< SELECT
^C#4 C#4 C2 # CHAN> SELECT
# With the translations below, the other shifted buttons are simply passed
# through along with the MC SHIFT key (A#5). You can either assign these
# combinations in the DAW (e.g., I have the shifted left/right keys bound to
# the previous/next marker functions in Ardour), or just directly edit the
# bindings below as you see fit.
# NOTE: We use an explicit RELEASE sequence here, to prevent the MC SHIFT key
# from being released too early. (Note that by default, midizap will release
# MIDI key events in the same order in which they are pressed, which may not
# work in some key combinations. At least I found that this confuses Ardour in
# some cases.)
^C8 A#5 C8 RELEASE C8 A#5 # Up
^C#8 A#5 C#8 RELEASE C#8 A#5 # Down
^D8 A#5 D8 RELEASE D8 A#5 # Left
^D#8 A#5 D#8 RELEASE D#8 A#5 # Right
^E8 A#5 E8 RELEASE E8 A#5 # Zoom
^C0 A#5 C0 RELEASE C0 A#5 # SHIFT REC
^G#0 A#5 G#0 RELEASE G#0 A#5 # SHIFT SOLO
^E1 A#5 E1 RELEASE E1 A#5 # SHIFT MUTE
^C2 A#5 C2 RELEASE C2 A#5 # SHIFT SELECT
^C7 A#5 C7 RELEASE C7 A#5 # SHIFT MARKER
^C#7 A#5 C#7 RELEASE C#7 A#5 # SHIFT NUDGE
^D7 A#5 D7 RELEASE D7 A#5 # SHIFT CYCLE
^D#7 A#5 D#7 RELEASE D#7 A#5 # SHIFT DROP
^E7 A#5 E7 RELEASE E7 A#5 # SHIFT REPLACE
^F7 A#5 F7 RELEASE F7 A#5 # SHIFT CLICK
^G7 A#5 G7 RELEASE G7 A#5 # SHIFT REW
^G#7 A#5 G#7 RELEASE G#7 A#5 # SHIFT FFWD
^A7 A#5 A7 RELEASE A7 A#5 # SHIFT STOP
^A#7 A#5 A#7 RELEASE A#7 A#5 # SHIFT PLAY
^B7 A#5 B7 RELEASE B7 A#5 # SHIFT REC
[MIDI2]
A#5 F8
# feedback for the (shifted) F1 .. F6 bindings and the remapped SOLO key
E3 F#4
F#3 G4
F3 G#4
A3 A4
C5 A#4
C#5 B4
D4 F#7 # FLIP -> SOLO

View File

@ -1,143 +0,0 @@
# This is an improved configuration for the X-Touch ONE which uses an internal
# SHIFT key instead. Setting up your own bindings in midizap offers a lot more
# possibilities than relying solely on your DAW's mapping abilities (you can
# still use those in conjunction with midizap, too).
# Copyright (c) 2018 Albert Graef <aggraef@gmail.com>
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any
# warranty.
JACK_NAME "midizap-XTouchONE"
JACK_PORTS 2
# Pass everything through, except for the mappings below.
PASSTHROUGH
SYSTEM_PASSTHROUGH
[MIDI]
# NOTE: This assumes that you use the default Mackie mode of the ONE.
# Otherwise you will have to adjust the mapping accordingly. I use the SCRUB
# key (F8 in MC mode) as a SHIFT key replacement, because I don't need that
# function (it's not available in Ardour yet). If you need that key, you'll
# have to use another one that you can spare.
F8 SHIFT ^F8 RELEASE SHIFT ^F8
# Remap the shifted F1 .. F4 keys to do something useful. I have them bound to
# the most important encoder assignment keys here, but of course you can
# change them to anything you want.
^F#4 E3 # Track (Trim)
^G4 F#3 # Pan
^G#4 F3 # Send
^A4 G3 # Plugin (not supported by Ardour)
# If you're using the bindings above, then most likely you also need the FLIP
# button which swaps fader and encoder; we (rather arbitrarily) assign it to
# the shifted SOLO button in the TRANSPORT section.
^F#7 D4 # Flip
# Here's an alternative binding to the utility keys which you may find useful.
# Uncomment these lines (and comment out the encoder assignment section above)
# to use these instead.
#^F#4 G#6 # Save
#^G4 A6 # Undo
#^G#4 A#6 # Cancel
#^A4 B6 # Enter
# Remap the shifted F5 and F6 keys to F7 and F8 which are missing on the ONE.
^A#4 C5
^B4 C#5
# Since the X-Touch ONE is a single-channel controller, I like to have the
# bank and channel keys linked up with channel SELECT, so that the current
# channel is also selected in the DAW when switching banks. Therefore I have
# bound these functions to the shifted bank and channel keys here, but of
# course you can change them to anything you want.
# NOTE: You might have to configure a bank size of 1 for the ONE, so that all
# tracks become accessible. A suitable device description for Ardour is
# included (see x-touch-one.device).
^A#3 A#3 C2 # BANK< SELECT
^B3 B3 C2 # BANK> SELECT
^C4 C4 C2 # CHAN< SELECT
^C#4 C#4 C2 # CHAN> SELECT
# Pass through the shifted cursor keys. This assumes that they're already
# mapped to something in the DAW; e.g., I have the shifted left/right keys
# bound to the previous/next marker functions in Ardour.
# NOTE: We use an explicit RELEASE sequence here, so that the SHIFT key (A#5)
# is released last. By default, midizap will release MIDI key events in the
# same order in which they are pressed, which may not work in some key
# combinations, since the SHIFT key gets released too early. (At least I found
# that this confuses Ardour in some cases, YMMV.)
^C8 A#5 C8 RELEASE C8 A#5 # Up
^C#8 A#5 C#8 RELEASE C#8 A#5 # Down
^D8 A#5 D8 RELEASE D8 A#5 # Left
^D#8 A#5 D#8 RELEASE D#8 A#5 # Right
# With the translations below, most other shifted keys in the CHANNEL and
# TRANSPORT sections are simply passed through along with the SHIFT key as
# well. You can either assign these combinations in the DAW, or edit the
# bindings below.
^C0 A#5 C0 RELEASE C0 A#5 # SHIFT REC
^G#0 A#5 G#0 RELEASE G#0 A#5 # SHIFT SOLO
^E1 A#5 E1 RELEASE E1 A#5 # SHIFT MUTE
^C2 A#5 C2 RELEASE C2 A#5 # SHIFT SELECT
^C7 A#5 C7 RELEASE C7 A#5 # SHIFT MARKER
^C#7 A#5 C#7 RELEASE C#7 A#5 # SHIFT NUDGE
^D7 A#5 D7 RELEASE D7 A#5 # SHIFT CYCLE
^D#7 A#5 D#7 RELEASE D#7 A#5 # SHIFT DROP
^E7 A#5 E7 RELEASE E7 A#5 # SHIFT REPLACE
^F7 A#5 F7 RELEASE F7 A#5 # SHIFT CLICK
^G7 A#5 G7 RELEASE G7 A#5 # SHIFT REW
^G#7 A#5 G#7 RELEASE G#7 A#5 # SHIFT FFWD
^A7 A#5 A7 RELEASE A7 A#5 # SHIFT STOP
^A#7 A#5 A#7 RELEASE A#7 A#5 # SHIFT PLAY
^B7 A#5 B7 RELEASE B7 A#5 # SHIFT REC
# Experiment with shifted controls. This remaps the shifted fader, encoder and
# jog wheel on the ONE to CC1..CC3. As these controls aren't used by MCP, they
# can be assigned freely, e.g., to some plugin parameters, using MIDI learn.
# (To make this work in Ardour, you have to connect midizap's midi_out port to
# Ardour's MIDI control in port, in addition to the Mackie control in port.)
# NOTE: Touching the fader also emits a note message (G#8), which will get in
# the way with MIDI learn, so we disable it here.
^G#8 NOP
^PB[128]{0} CC1'
^CC16~ CC2
^CC60~ CC3
[MIDI2]
# feedback for the (shifted) F1 .. F6 bindings
E3 F#4
F#3 G4
F3 G#4
A3 A4
D4 F#7 # FLIP -> SOLO
#G#6 F#4
#A6 G4
#A#6 G#4
#B6 A4
C5 A#4
C#5 B4

View File

@ -1,150 +0,0 @@
<!DOCTYPE patchbay>
<patchbay name="midizap" version="0.5.4">
<output-sockets>
<socket type="jack-midi" name="Ctlra Maschine" exclusive="off" client="a2j">
<plug>Ctlra Maschine Mk3.*</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine" exclusive="off" client="midizap-Maschine">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine 2" exclusive="off" client="midizap-Maschine">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="Ardour mackie out" exclusive="off" client="ardour">
<plug>mackie control out</plug>
</socket>
<socket type="jack-midi" name="nanoKONTROL2" exclusive="off" client="a2j">
<plug>nanoKONTROL2.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 1" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 2" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="X-Touch" exclusive="off" client="a2j">
<plug>.*X-Touch MIDI 1</plug>
</socket>
<socket type="jack-midi" name="X-Touch MINI" exclusive="off" client="a2j">
<plug>.*X-TOUCH MINI MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 1" exclusive="off" client="midizap-XTouchMini">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 2" exclusive="off" client="midizap-XTouchMini">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="X-Touch One" exclusive="off" client="a2j">
<plug>X-Touch One.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 1" exclusive="off" client="midizap-XTouchONE">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 2" exclusive="off" client="midizap-XTouchONE">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="APCmini" exclusive="off" client="a2j">
<plug>APC MINI.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 1" exclusive="off" client="midizap-APCmini">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 2" exclusive="off" client="midizap-APCmini">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="MPKmini2" exclusive="off" client="a2j">
<plug>MPKmini2.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-MPKmini 1" exclusive="off" client="midizap-MPKmini2">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="shuttlepro" exclusive="off" client="shuttlepro">
<plug>midi_out</plug>
</socket>
</output-sockets>
<input-sockets>
<socket type="jack-midi" name="midizap-Maschine" exclusive="off" client="midizap-Maschine">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine 2" exclusive="off" client="midizap-Maschine">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="Ctlra Maschine" exclusive="off" client="a2j">
<plug>Ctlra Maschine Mk3.*</plug>
</socket>
<socket type="jack-midi" name="Ardour mackie in" exclusive="off" client="ardour">
<plug>mackie control in</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 1" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 2" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="nanoKONTROL2" exclusive="off" client="a2j">
<plug>nanoKONTROL2.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="X-Touch" exclusive="off" client="a2j">
<plug>.*X-Touch MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 1" exclusive="off" client="midizap-XTouchMini">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 2" exclusive="off" client="midizap-XTouchMini">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="X-Touch MINI" exclusive="off" client="a2j">
<plug>.*X-TOUCH MINI MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 1" exclusive="off" client="midizap-XTouchONE">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 2" exclusive="off" client="midizap-XTouchONE">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="X-Touch One" exclusive="off" client="a2j">
<plug>X-Touch One.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 1" exclusive="off" client="midizap-APCmini">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 2" exclusive="off" client="midizap-APCmini">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="APCmini" exclusive="off" client="a2j">
<plug>APC MINI.* MIDI 1</plug>
</socket>
<socket type="jack-midi" name="midizap-MPKmini 1" exclusive="off" client="midizap-MPKmini2">
<plug>midi_in</plug>
</socket>
</input-sockets>
<slots/>
<cables>
<cable type="jack-midi" output="Ctlra Maschine" input="midizap-Maschine"/>
<cable type="jack-midi" output="midizap-Maschine" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-Maschine 2" input="Ctlra Maschine"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-Maschine 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="X-Touch"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-APCmini 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-XTouchONE 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-nanoKONTROL 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-XTouchMini 2"/>
<cable type="jack-midi" output="nanoKONTROL2" input="midizap-nanoKONTROL 1"/>
<cable type="jack-midi" output="midizap-nanoKONTROL 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-nanoKONTROL 2" input="nanoKONTROL2"/>
<cable type="jack-midi" output="X-Touch" input="Ardour mackie in"/>
<cable type="jack-midi" output="X-Touch One" input="midizap-XTouchONE 1"/>
<cable type="jack-midi" output="midizap-XTouchONE 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-XTouchONE 2" input="X-Touch One"/>
<cable type="jack-midi" output="APCmini" input="midizap-APCmini 1"/>
<cable type="jack-midi" output="midizap-APCmini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-APCmini 2" input="APCmini"/>
<cable type="jack-midi" output="MPKmini2" input="midizap-MPKmini 1"/>
<cable type="jack-midi" output="midizap-MPKmini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="shuttlepro" input="Ardour mackie in"/>
<cable type="jack-midi" output="X-Touch MINI" input="midizap-XTouchMini 1"/>
<cable type="jack-midi" output="midizap-XTouchMini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-XTouchMini 2" input="X-Touch MINI"/>
</cables>
</patchbay>

View File

@ -1,150 +0,0 @@
<!DOCTYPE patchbay>
<patchbay name="midizap" version="0.5.4">
<output-sockets>
<socket type="jack-midi" name="Ctlra Maschine" exclusive="off" client="alsa_midi">
<plug>Ctlra Maschine Mk3.*</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine" exclusive="off" client="midizap-Maschine">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine 2" exclusive="off" client="midizap-Maschine">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="Ardour mackie out" exclusive="off" client="ardour">
<plug>mackie control out</plug>
</socket>
<socket type="jack-midi" name="nanoKONTROL2" exclusive="off" client="alsa_midi">
<plug>nanoKONTROL2.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 1" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 2" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="X-Touch" exclusive="off" client="alsa_midi">
<plug>.*X-Touch MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="X-Touch MINI" exclusive="off" client="alsa_midi">
<plug>.*X-TOUCH MINI MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 1" exclusive="off" client="midizap-XTouchMini">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 2" exclusive="off" client="midizap-XTouchMini">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="X-Touch One" exclusive="off" client="alsa_midi">
<plug>X-Touch One.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 1" exclusive="off" client="midizap-XTouchONE">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 2" exclusive="off" client="midizap-XTouchONE">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="APCmini" exclusive="off" client="alsa_midi">
<plug>APC MINI.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 1" exclusive="off" client="midizap-APCmini">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 2" exclusive="off" client="midizap-APCmini">
<plug>midi_out2</plug>
</socket>
<socket type="jack-midi" name="MPKmini2" exclusive="off" client="alsa_midi">
<plug>MPKmini2.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-MPKmini 1" exclusive="off" client="midizap-MPKmini2">
<plug>midi_out</plug>
</socket>
<socket type="jack-midi" name="shuttlepro" exclusive="off" client="shuttlepro">
<plug>midi_out</plug>
</socket>
</output-sockets>
<input-sockets>
<socket type="jack-midi" name="midizap-Maschine" exclusive="off" client="midizap-Maschine">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-Maschine 2" exclusive="off" client="midizap-Maschine">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="Ctlra Maschine" exclusive="off" client="alsa_midi">
<plug>Ctlra Maschine Mk3.*</plug>
</socket>
<socket type="jack-midi" name="Ardour mackie in" exclusive="off" client="ardour">
<plug>mackie control in</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 1" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-nanoKONTROL 2" exclusive="off" client="midizap-nanoKONTROL2">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="nanoKONTROL2" exclusive="off" client="alsa_midi">
<plug>nanoKONTROL2.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="X-Touch" exclusive="off" client="alsa_midi">
<plug>.*X-Touch MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 1" exclusive="off" client="midizap-XTouchMini">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchMini 2" exclusive="off" client="midizap-XTouchMini">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="X-Touch MINI" exclusive="off" client="alsa_midi">
<plug>.*X-TOUCH MINI MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 1" exclusive="off" client="midizap-XTouchONE">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-XTouchONE 2" exclusive="off" client="midizap-XTouchONE">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="X-Touch One" exclusive="off" client="alsa_midi">
<plug>X-Touch One.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 1" exclusive="off" client="midizap-APCmini">
<plug>midi_in</plug>
</socket>
<socket type="jack-midi" name="midizap-APCmini 2" exclusive="off" client="midizap-APCmini">
<plug>midi_in2</plug>
</socket>
<socket type="jack-midi" name="APCmini" exclusive="off" client="alsa_midi">
<plug>APC MINI.* MIDI 1.*</plug>
</socket>
<socket type="jack-midi" name="midizap-MPKmini 1" exclusive="off" client="midizap-MPKmini2">
<plug>midi_in</plug>
</socket>
</input-sockets>
<slots/>
<cables>
<cable type="jack-midi" output="Ctlra Maschine" input="midizap-Maschine"/>
<cable type="jack-midi" output="midizap-Maschine" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-Maschine 2" input="Ctlra Maschine"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-Maschine 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="X-Touch"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-APCmini 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-XTouchONE 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-nanoKONTROL 2"/>
<cable type="jack-midi" output="Ardour mackie out" input="midizap-XTouchMini 2"/>
<cable type="jack-midi" output="nanoKONTROL2" input="midizap-nanoKONTROL 1"/>
<cable type="jack-midi" output="midizap-nanoKONTROL 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-nanoKONTROL 2" input="nanoKONTROL2"/>
<cable type="jack-midi" output="X-Touch" input="Ardour mackie in"/>
<cable type="jack-midi" output="X-Touch One" input="midizap-XTouchONE 1"/>
<cable type="jack-midi" output="midizap-XTouchONE 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-XTouchONE 2" input="X-Touch One"/>
<cable type="jack-midi" output="APCmini" input="midizap-APCmini 1"/>
<cable type="jack-midi" output="midizap-APCmini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-APCmini 2" input="APCmini"/>
<cable type="jack-midi" output="MPKmini2" input="midizap-MPKmini 1"/>
<cable type="jack-midi" output="midizap-MPKmini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="shuttlepro" input="Ardour mackie in"/>
<cable type="jack-midi" output="X-Touch MINI" input="midizap-XTouchMini 1"/>
<cable type="jack-midi" output="midizap-XTouchMini 1" input="Ardour mackie in"/>
<cable type="jack-midi" output="midizap-XTouchMini 2" input="X-Touch MINI"/>
</cables>
</patchbay>

View File

@ -13,6 +13,12 @@
JACK_NAME "midizap-nanoKONTROL2"
JACK_PORTS 2
# automatic connections
JACK_IN1 nanoKONTROL2 MIDI 1
JACK_OUT1 ardour:mackie control in
JACK_IN2 ardour:mackie control out
JACK_OUT2 nanoKONTROL2 MIDI 1
# Pass everything through (including feedback), except for the mappings below.
PASSTHROUGH

View File

@ -435,17 +435,111 @@ connect_callback(jack_port_id_t a, jack_port_id_t b, int yn, void *seqq)
const char *aname = jack_port_name(ap);
const char *bname = jack_port_name(bp);
size_t l = strlen(seq->client_name);
if (!strncmp(seq->client_name, aname, l))
if (jack_port_is_mine(seq->jack_client, ap))
printf("%-*s %s: %s\n", (int)l+10, aname,
(yn ? "connected to" : "disconnected from"), bname);
else if (!strncmp(seq->client_name, bname, l))
else if (jack_port_is_mine(seq->jack_client, bp))
printf("%-*s %s: %s\n", (int)l+10, bname,
(yn ? "connected to" : "disconnected from"), aname);
}
// queue for pending connections, to be processed in the main thread
#define CONN_SIZE 256
static int n_inconn, n_outconn;
static struct {
int portno;
char *name;
} inconn[CONN_SIZE], outconn[CONN_SIZE];
static void add_inconn(int portno, const char *name)
{
if (n_inconn < CONN_SIZE) {
inconn[n_inconn].portno = portno;
inconn[n_inconn].name = strdup(name);
n_inconn++;
}
}
static void add_outconn(int portno, const char *name)
{
if (n_outconn < CONN_SIZE) {
outconn[n_outconn].portno = portno;
outconn[n_outconn].name = strdup(name);
n_outconn++;
}
}
static void match_connections(JACK_SEQ* seq, jack_port_t *port)
{
if (jack_port_is_mine(seq->jack_client, port)) return;
int flags = jack_port_flags(port);
const char *name = jack_port_name(port);
if (flags & JackPortIsInput) {
// Try to match the port name to one of our out regexes.
for (int i = 0; i < 2 && i < seq->n_out; i++) {
if (seq->out[i] && regexec(&seq->outre[i], name, 0, 0, 0) == 0 &&
// check that port types are compatible
jack_port_type(seq->output_port[i]) == jack_port_type(port) &&
// check that we're not connected yet
!jack_port_connected_to(seq->output_port[i], name)) {
// we can't connect right here, that has to be done in the main
// thread, so we simply store the request for later
add_outconn(i, name);
}
}
} else if (flags & JackPortIsOutput) {
// Try to match the port name to one of our in regexes.
for (int i = 0; i < 2 && i < seq->n_in; i++) {
if (seq->in[i] && regexec(&seq->inre[i], name, 0, 0, 0) == 0 &&
// check that port types are compatible
jack_port_type(seq->input_port[i]) == jack_port_type(port) &&
// check that we're not connected yet
!jack_port_connected_to(seq->input_port[i], name)) {
add_inconn(i, name);
}
}
}
}
void
registration_callback(jack_port_id_t id, int reg, void *seqq)
{
if (!reg) return;
JACK_SEQ* seq = (JACK_SEQ*)seqq;
jack_port_t *port = jack_port_by_id(seq->jack_client, id);
match_connections(seq, port);
}
////////////////////////////////
//this is run in the main thread
////////////////////////////////
void process_connections(JACK_SEQ* seq)
{
int i;
for (i = 0; i < n_inconn; i++)
if (inconn[i].name) {
if (jack_connect(seq->jack_client,
inconn[i].name,
jack_port_name(seq->input_port[inconn[i].portno])))
fprintf(stderr, "error trying to connect in%d to %s\n",
inconn[i].portno, inconn[i].name);
free(inconn[i].name);
}
n_inconn = 0;
for (i = 0; i < n_outconn; i++)
if (outconn[i].name) {
if (jack_connect(seq->jack_client,
jack_port_name(seq->output_port[outconn[i].portno]),
outconn[i].name))
fprintf(stderr, "error trying to connect out%d to %s\n",
outconn[i].portno, outconn[i].name);
free(outconn[i].name);
}
n_outconn = 0;
}
int
init_jack(JACK_SEQ* seq, uint8_t verbose)
{
@ -454,6 +548,36 @@ init_jack(JACK_SEQ* seq, uint8_t verbose)
*client_name = seq->client_name?seq->client_name:"midizap";
jack_status_t status;
// compile the in/out connection regexes
for (int i = 0; i < 2; i++) {
if (seq->in[i] && *seq->in[i]) {
int err = regcomp(&seq->inre[i], seq->in[i], REG_EXTENDED|REG_NOSUB);
if (err) {
char buf[1024];
regerror(err, &seq->inre[i], buf, sizeof(buf));
fprintf(stderr, "error compiling in%d regex: %s\n%s\n",
i, seq->in[i], buf);
regfree(&seq->inre[i]);
seq->in[i] = 0;
}
} else {
seq->in[i] = 0;
}
if (seq->out[i] && *seq->out[i]) {
int err = regcomp(&seq->outre[i], seq->out[i], REG_EXTENDED|REG_NOSUB);
if (err) {
char buf[1024];
regerror(err, &seq->outre[i], buf, sizeof(buf));
fprintf(stderr, "error compiling out%d regex: %s\n%s\n",
i, seq->out[i], buf);
regfree(&seq->outre[i]);
seq->out[i] = 0;
}
} else {
seq->out[i] = 0;
}
}
if(verbose)printf("opening client...\n");
seq->jack_client = jack_client_open(client_name, JackNullOption, &status);
@ -473,6 +597,7 @@ init_jack(JACK_SEQ* seq, uint8_t verbose)
jack_on_shutdown(seq->jack_client, shutdown_callback, (void*)seq);
jack_set_session_callback(seq->jack_client, session_callback, (void*)seq);
jack_set_port_registration_callback(seq->jack_client, registration_callback, (void*)seq);
if (verbose) jack_set_port_connect_callback(seq->jack_client, connect_callback, (void*)seq);
//if(verbose)printf("assigning process callback...\n");
@ -571,6 +696,16 @@ init_jack(JACK_SEQ* seq, uint8_t verbose)
fprintf(stderr, "Cannot activate JACK client.\n");
return 0;
}
// All done, set up the initial connections.
const char **ports = jack_get_ports(seq->jack_client, 0, 0, 0);
for (const char **name = ports; *name; ++name) {
jack_port_t *port = jack_port_by_name(seq->jack_client, *name);
match_connections(seq, port);
}
free(ports);
process_connections(seq);
return 1;
}

View File

@ -1,7 +1,10 @@
#ifndef JACKDRIVER_H
#define JACKDRIVER_H
#include<jack/jack.h>
#include<jack/ringbuffer.h>
#include <jack/jack.h>
#include <jack/ringbuffer.h>
#include <regex.h>
typedef struct _jseq
{
@ -12,6 +15,8 @@ typedef struct _jseq
jack_port_t **output_port;
jack_port_t **input_port;
uint8_t n_in, n_out, passthrough[2];
char *in[2], *out[2];
regex_t inre[2], outre[2];
} JACK_SEQ;
extern int jack_quit;
@ -19,6 +24,7 @@ extern int jack_quit;
extern char *jack_command_line;
int init_jack(JACK_SEQ* seq, uint8_t verbose);
void process_connections(JACK_SEQ* seq);
void close_jack(JACK_SEQ* seq);
void queue_midi(void* seqq, uint8_t msg[], uint8_t port_no);
int pop_midi(void* seqq, uint8_t msg[], uint8_t *port_no);

3
keywords.sed Normal file
View File

@ -0,0 +1,3 @@
/^\#define/!d
s/^\#define //
s/^\([^[:space:]]*\).*$/"\1"/

112
midizap-mode.el.in Normal file
View File

@ -0,0 +1,112 @@
;;; midizap-mode.el --- midizap syntax highlighting for Emacs.
;;; Commentary:
;;; This is a simple mode for editing midizaprc files which provides basic
;;; syntax highlighting, and a command midizap-mode-run, bound to C-c C-c,
;;; which lets you quickly launch a midizap session (with options) on the
;;; edited midizaprc file in an Emacs buffer.
;;; Install this anywhere where Emacs finds it (e.g., in the Emacs site-lisp
;;; directory -- usually under /usr/share/emacs/site-lisp on Un*x systems, or
;;; in any directory on the Emacs load-path) and load it in your .emacs as
;;; follows:
;;; (require 'midizap-mode)
;;; The mode also supports auto-completion of midizaprc keywords, to make this
;;; work you'll need the auto-complete package available from MELPA, please
;;; check: https://github.com/auto-complete/auto-complete.
;;; In the midizap-mode subdirectory you'll find some snippets to be used with
;;; yasnippet (https://github.com/joaotavora/yasnippet); to use these, copy
;;; the entire folder to your ~/.emacs.d/snippets directory.
;;; Code:
(require 'comint)
(defconst midizap-keywords
(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
nil
midizap-keywords
'(("^[[:blank:]]*\\(#.*\\)" 1 'font-lock-comment-face t)
("[[:blank:]]+\\(#.*\\)" 1 'font-lock-comment-face t)
("^[[:blank:]]*\\[\\([^\n[]+\\)\\]\\(.*\\)"
1 'font-lock-variable-name-face)
("\\<\\(\\([Kk][Pp]:\\)?[A-Ga-g][#Bb]?-?[0-9]+\\|\\([Mm]\\|[Cc][Hh]\\|[Pp][Bb]\\|[Pp][Cc]\\|[Cc][Cc]\\|[Cc][Pp]\\)[0-9]*\\|XK_[A-Za-z_0-9]+\\(/[UDH]\\)?\\)\\>" 1 'default)
("\\<\\([0-9]+\\)\\>" 1 'font-lock-constant-face))
(list "\\.midizaprc\\'")
(list 'midizap-mode-setup-function)
"Generic mode for midizap configuration files.")
(defvar midizap-mode-keymap (make-sparse-keymap)
"Keymap for midizap-mode.")
(defvar midizap-command "midizap -drk ")
(defvar ac-sources)
(defvar midizap-mode-ac-source
'((candidates . midizap-keywords)))
(defun midizap-mode-run (command)
"Run the current midizaprc file with COMMAND in a comint buffer."
(interactive
(list
(let ((command (eval midizap-command)))
(read-string "Run midizap with: " command))))
(unless (equal command (eval midizap-command))
(setq midizap-command command))
(save-some-buffers)
(let* ((file (buffer-file-name))
(buf-name (concat "*" file "*")))
(with-current-buffer (get-buffer-create buf-name)
(erase-buffer)
(comint-mode)
(comint-exec
buf-name
file
shell-file-name
nil
(list "-c" (concat command " " file)))
(display-buffer buf-name))))
(define-key midizap-mode-keymap "\C-c\C-c" 'midizap-mode-run)
(defun midizap-mode-setup-function ()
"Custom setup function for midizap-mode."
(make-local-variable 'parse-sexp-ignore-comments)
(make-local-variable 'comment-start)
(make-local-variable 'comment-start-skip)
(make-local-variable 'comment-end)
(setq parse-sexp-ignore-comments t
comment-end ""
comment-start "# "
comment-start-skip "# *"
)
(if (boundp 'ac-sources)
(progn
(add-to-list 'ac-modes 'midizap-mode)
(add-to-list 'ac-sources 'midizap-mode-ac-source))
(message "You may want to install and use auto-complete"))
(use-local-map midizap-mode-keymap)
)
(provide 'midizap-mode)
;; End:
;;; midizap-mode.el ends here

27
midizap-mode/midizaprc Normal file
View File

@ -0,0 +1,27 @@
# -*- mode: snippet -*-
# name: midizaprc template
# key: #
# --
# midizap configuration template for Emacs (requires yasnippet)
# Jack client name and ports/connections
# NOTE: Remove the JACK_PORTS and JACK_OUT lines if you don't need MIDI
# output. For bidirectional setups, use JACK_PORTS 2 and add JACK_IN2,
# JACK_OUT2 and a [MIDI2] section for the feedback connection.
JACK_NAME "${1:client-name}"
JACK_PORTS 1
JACK_IN ${2:controller-regex}
JACK_OUT ${3:application-regex}
# common debugging options (uncomment as needed)
#DEBUG_REGEX
#DEBUG_KEYS
#DEBUG_MIDI
# translations go here
[MIDI]

5
midizap-mode/section Normal file
View File

@ -0,0 +1,5 @@
# -*- mode: snippet -*-
# name: section header
# key: [
# --
[${1:name}] ${2:regex}

2066
midizap.1

File diff suppressed because it is too large Load Diff

View File

@ -1428,10 +1428,10 @@ handle_event(uint8_t *msg, uint8_t portno, int depth, int recursive)
} else if (msg[2] > 64) {
int step = get_cc_step(tr, portno, chan, msg[1], -1);
if (step) {
int d = (msg[2]-64)/step;
uint8_t d = (msg[2]-128)/step;
while (d) {
send_strokes(tr, portno, status, chan, msg[1], 0, 0, -1, depth);
d--;
d++;
}
}
}
@ -1609,7 +1609,7 @@ handle_event(uint8_t *msg, uint8_t portno, int depth, int recursive)
void help(char *progname)
{
fprintf(stderr, "Usage: %s [-hkn] [-d[rskmj]] [-ost[n]] [-j name] [-P[prio]] [-r rcfile]\n", progname);
fprintf(stderr, "Usage: %s [-hkn] [-d[rskmj]] [-ost[n]] [-j name] [-P[prio]] [[-r] rcfile]\n", progname);
fprintf(stderr, "-h print this message\n");
fprintf(stderr, "-d debug (r = regex, s = strokes, k = keys, m = midi, j = jack; default: all)\n");
fprintf(stderr, "-j jack client name (default: midizap)\n");
@ -1842,11 +1842,16 @@ main(int argc, char **argv)
}
}
if (optind < argc) {
if (optind+1 < argc) {
help(argv[0]);
exit(1);
}
if (optind < argc) {
config_file_name = argv[optind];
add_command(absolute_path(argv[optind]), 1);
}
if (command_line) jack_command_line = command_line;
initdisplay();
@ -1863,6 +1868,10 @@ main(int argc, char **argv)
seq.n_out = jack_num_outputs>0?jack_num_outputs:0;
seq.passthrough[0] = jack_num_outputs>0?system_passthrough[0]>0:0;
seq.passthrough[1] = jack_num_outputs>1?system_passthrough[1]>0:0;
seq.in[0] = jack_in_regex[0];
seq.in[1] = jack_num_outputs>1?jack_in_regex[1]:0;
seq.out[0] = jack_num_outputs>0?jack_out_regex[0]:0;
seq.out[1] = jack_num_outputs>1?jack_out_regex[1]:0;
if (!init_jack(&seq, debug_jack)) {
exit(1);
}
@ -1892,6 +1901,7 @@ main(int argc, char **argv)
close_jack(&seq);
exit(0);
}
process_connections(&seq);
while (pop_midi(&seq, msg, &portno)) {
handle_event(msg, portno, 0, 0);
time_t t = time(0);

View File

@ -137,4 +137,4 @@ extern char *config_file_name;
extern int jack_num_outputs, auto_feedback;
extern int passthrough[2], system_passthrough[2];
extern int midi_octave, shift;
extern char *jack_client_name;
extern char *jack_client_name, *jack_in_regex[2], *jack_out_regex[2];

51
midizap.scm Normal file
View File

@ -0,0 +1,51 @@
(define-module (guixpkgs midizap)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix build-system gnu)
#:use-module (guix packages)
#:use-module (guix git-download)
#:use-module (gnu packages xorg)
#:use-module (gnu packages audio)
#:use-module (guix gexp))
(define-public midizap
(package
(name "midizap")
(version "0.8")
(source
(local-file "." "midizap" #:recursive? #t)
;; (origin
;; (method git-fetch)
;; (uri (git-reference
;; (url "https://github.com/agraef/midizap.git")
;; (commit version)))
;; (sha256
;; (base32
;; "0y31fnffl31n9lpkiw1dc3q4rnpfnras30n9y2h5j6586dkmgni4")))
)
(arguments
`(#:tests? #f ; no check target
#:make-flags
(list "CC=gcc"
(string-append "DESTDIR=" %output)
"prefix=")
#:phases
(modify-phases %standard-phases
(replace 'configure
(lambda* (#:key inputs outputs #:allow-other-keys)
(substitute* "Makefile"
(("/usr/include/X11/")
(string-append (assoc-ref inputs "xorgproto") "/include/X11/"))
(("-lXtst") "-lXtst -ljack"))
#t)))))
;; (native-inputs `(("pkg-config" ,pkg-config)))
(inputs `(("jack" ,jack-1)
("libx11" ,libx11)
("libxtst" ,libxtst)
("xorgproto" ,xorgproto)))
(build-system gnu-build-system)
(home-page "")
(synopsis "")
(description "")
(license license:gpl2+)))
midizap

View File

@ -60,7 +60,7 @@ int debug_midi = 0;
int midi_octave = 0;
char *jack_client_name = NULL;
char *jack_client_name, *jack_in_regex[2], *jack_out_regex[2];
char *
allocate(size_t len)
@ -1380,7 +1380,8 @@ static void dup_stroke_data(stroke_data **sd, uint16_t *n, uint16_t *a,
{
for (int i = 0; i < n1; i++) {
if (sd1[i].anyshift) {
for (int index = 0; index < 2; index++) {
int nindex = sd1[i].mod?1:2; // no release seq in mod translations
for (int index = 0; index < nindex; index++) {
stroke **t =
sd0 && check_stroke_data(sd0, sd1[i].chan, sd1[i].data, n0) ? 0 :
find_stroke_data(sd, sd1[i].chan, sd1[i].data, index,
@ -1953,6 +1954,53 @@ read_config_file(void)
}
continue;
}
if (!strncmp(tok, "JACK_", 5)) {
// JACK_IN/OUT. The port number follows (default: 1), then a regex
// (taken verbatim from the rest of the line).
char *s = tok+5, *regex;
int is_input = strncmp(s, "IN", 2) == 0;
if (is_input)
s += 2;
else if (strncmp(s, "OUT", 3) == 0)
s += 3;
else {
fprintf(stderr, "invalid token: %s, must be JACK_IN or JACK_OUT\n",
tok);
continue;
}
int portno = !*s||*s=='1'?0:*s=='2'?1:-1;
if (portno < 0) {
fprintf(stderr, "invalid port number: %s, must be 1 or 2\n", s);
continue;
}
if (*s && *++s) {
// trailing garbage
fprintf(stderr, "invalid token: %s, must be JACK_IN or JACK_OUT\n",
tok);
continue;
}
s = token_src;
while (*s && isspace(*s)) {
s++;
}
regex = s;
while (*s) {
s++;
}
s--;
while (s > regex && isspace(*s)) {
s--;
}
s[1] = '\0';
char **jack_regex = is_input?jack_in_regex:jack_out_regex;
if (jack_regex[portno]) {
if (strcmp(jack_regex[portno], regex))
fprintf(stderr, "error: attempt to redefine %s as '%s'\n(is already defined as '%s')\n", tok, regex, jack_regex[portno]);
} else {
jack_regex[portno] = strdup(regex);
}
continue;
}
if (!strcmp(tok, "PASSTHROUGH")) { // -t
char *a = token(NULL, &delim);
int k, n;