A powerful audio system called JACK allows us to build pipelines consisting of audio interfaces, players, recorders, filters and effects… and route sound streams (both PCM and MIDI) through them. MIDI messages can come from keyboards or other hardware MIDI controllers or from MIDI players and other software.
In JACK, we have clients (applications) and they have ports (input and output channels). The JACK graph consists of connections between input and output ports. There might be multiple connections from or to a single port – singals are then replicated or combined. Obviously, we can connect MIDI ports only to other MIDI ports and PCM/audio ports only to other ports of the same kind. However there can be applications with both kinds of ports that e.g. translate MIDI signal to audio signal (synthesizers).
The JACK daemon is responsible for maintaining the graph and transmitting the messages. Clients connect to the daemon.
Since v0.17, we can list the ports using the relpipe-in-jack
command:
relpipe-in-jack --list-ports true --list-midi-messages false | relpipe-out-tabular
and see it as a relation:
port: ╭───────────────────────────────────┬───────────────┬─────────────────┬──────────────────┬────────────────────┬────────────────────┬────────────────┬────────────────┬─────────────────────────╮ │ name (string) │ uuid (string) │ input (boolean) │ output (boolean) │ physical (boolean) │ terminal (boolean) │ mine (boolean) │ midi (boolean) │ type (string) │ ├───────────────────────────────────┼───────────────┼─────────────────┼──────────────────┼────────────────────┼────────────────────┼────────────────┼────────────────┼─────────────────────────┤ │ system:capture_1 │ │ false │ true │ true │ true │ false │ false │ 32 bit float mono audio │ │ system:capture_2 │ │ false │ true │ true │ true │ false │ false │ 32 bit float mono audio │ │ system:playback_1 │ │ true │ false │ true │ true │ false │ false │ 32 bit float mono audio │ │ system:playback_2 │ │ true │ false │ true │ true │ false │ false │ 32 bit float mono audio │ │ j2a_bridge:playback │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ relpipe-in-jack_processed:midi-in │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ relpipe-out-jack:midi-out │ │ false │ true │ false │ false │ false │ true │ 8 bit raw midi │ │ a2j_bridge:capture │ │ false │ true │ false │ false │ false │ true │ 8 bit raw midi │ │ yoshimi:left │ │ false │ true │ false │ false │ false │ false │ 32 bit float mono audio │ │ yoshimi:right │ │ false │ true │ false │ false │ false │ false │ 32 bit float mono audio │ │ yoshimi:midi in │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ Qtractor:Master/in_1 │ │ true │ false │ false │ false │ false │ false │ 32 bit float mono audio │ │ Qtractor:Master/in_2 │ │ true │ false │ false │ false │ false │ false │ 32 bit float mono audio │ │ Qtractor:Master/out_1 │ │ false │ true │ false │ false │ false │ false │ 32 bit float mono audio │ │ Qtractor:Master/out_2 │ │ false │ true │ false │ false │ false │ false │ 32 bit float mono audio │ │ qmidiarp:in │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ qmidiarp:out 1 │ │ false │ true │ false │ false │ false │ true │ 8 bit raw midi │ │ qmidiarp:out 2 │ │ false │ true │ false │ false │ false │ true │ 8 bit raw midi │ │ jack-keyboard:midi_out │ │ false │ true │ false │ false │ false │ true │ 8 bit raw midi │ │ jack-keyboard:midi_in │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ relpipe-in-jack_original:midi-in │ │ true │ false │ false │ false │ false │ true │ 8 bit raw midi │ │ relpipe-in-jack:midi-in │ │ true │ false │ false │ false │ true │ true │ 8 bit raw midi │ ╰───────────────────────────────────┴───────────────┴─────────────────┴──────────────────┴────────────────────┴────────────────────┴────────────────┴────────────────┴─────────────────────────╯ Record count: 22
Port names are prefixed with the names of clients.
We see the port direction in the input
and output
attributes
and can distinguish MIDI and audio ports by the value of the midi
attribute.
We can also list the connections using the --list-connections true
option:
connection: ╭────────────────┬───────────────────────────┬───────────────────────────────────╮ │ event (string) │ source_port (string) │ destination_port (string) │ ├────────────────┼───────────────────────────┼───────────────────────────────────┤ │ connect │ system:capture_1 │ Qtractor:Master/in_1 │ │ connect │ system:capture_2 │ Qtractor:Master/in_2 │ │ connect │ relpipe-out-jack:midi-out │ qmidiarp:in │ │ connect │ relpipe-out-jack:midi-out │ relpipe-in-jack_original:midi-in │ │ connect │ yoshimi:left │ system:playback_1 │ │ connect │ yoshimi:right │ system:playback_2 │ │ connect │ Qtractor:Master/out_1 │ system:playback_1 │ │ connect │ Qtractor:Master/out_2 │ system:playback_2 │ │ connect │ qmidiarp:out 1 │ yoshimi:midi in │ │ connect │ qmidiarp:out 1 │ relpipe-in-jack_processed:midi-in │ │ connect │ jack-keyboard:midi_out │ qmidiarp:in │ │ connect │ jack-keyboard:midi_out │ relpipe-in-jack_original:midi-in │ ╰────────────────┴───────────────────────────┴───────────────────────────────────╯ Record count: 12
Instead of formatting as a table, we can direct this relation into a file and later recreate the saved connections:
relpipe-in-jack --list-connections true --list-midi-messages false > connections.rp
cat connections.rp | relpipe-out-jack --required-connections 0
If we want to store the connections in a human readable format in order to be able to edit them,
we should add e.g. relpipe-out-csv
(or XML, or Recfile) stage before redirecting the stream to the file
and add relpipe-in-csv
etc. stage to the second pipeline.
"event","source_port","destination_port" "connect","system:capture_1","Qtractor:Master/in_1" "connect","system:capture_2","Qtractor:Master/in_2" "connect","relpipe-out-jack:midi-out","qmidiarp:in" "connect","relpipe-out-jack:midi-out","relpipe-in-jack_original:midi-in" "connect","yoshimi:left","system:playback_1" "connect","yoshimi:right","system:playback_2" "connect","Qtractor:Master/out_1","system:playback_1" "connect","Qtractor:Master/out_2","system:playback_2" "connect","qmidiarp:out 1","yoshimi:midi in" "connect","qmidiarp:out 1","relpipe-in-jack_processed:midi-in" "connect","jack-keyboard:midi_out","qmidiarp:in" "connect","jack-keyboard:midi_out","relpipe-in-jack_original:midi-in"
Or we can write the file by hand and just send it to the JACK output module:
cat connections.csv | relpipe-in-csv | relpipe-out-jack --required-connections 0
The primary purpose of the relpipe-out-jack
is sending MIDI messages.
And because it does not make much sense to send them nowhere, it waits for at least one connection.
But if we are not sending any messages and are using this tool just to connect or disconnect the ports,
we should set --required-connections 0
.
We can also connect or disconnect particular ports specified on the command line:
relpipe-in-jack --connect-ports "a2j_bridge:capture" "qmidiarp:in" --list-midi-messages false
The primary purpose of the relpipe-in-jack
command is monitoring the MIDI commands.
If we want just to connect or disconnect some ports, we can disable monitoring by setting --list-midi-messages false
and the command will return immediately.
The port names are suggested by the Bash-completion, so we do not have to memorize them. Because these names contain the colon, we should use quotes (otherwise the Bash-completion may be confused).
Disconnecting works the same way – just use the --disconnect-ports
option
or specify the disconnect
command in the event
attribute.
Note: there are sophisticated GUI tools focused on working with the JACK graph like QjackCtl or KXStudio/Claudia. But sometimes it is useful to have a simple CLI tool for this job.
Relational pipes, open standard and free software © 2018-2022 GlobalCode