relpipe-data/examples-jack-ports.xml
author František Kučera <franta-hg@frantovo.cz>
Mon, 21 Feb 2022 00:43:11 +0100
branchv_0
changeset 329 5bc2bb8b7946
parent 317 fce3d6290c40
permissions -rw-r--r--
Release v0.18

<stránka
	xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
	xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
	
	<nadpis>Working with JACK ports</nadpis>
	<perex>list ports and connections, connect and disconnect ports, both MIDI and audio</perex>
	<m:pořadí-příkladu>04400</m:pořadí-příkladu>

	<text xmlns="http://www.w3.org/1999/xhtml">
		
		<p>
			A powerful audio system called <a href="https://jackaudio.org/">JACK</a> 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.
		</p>
		
		<p>
			In JACK, we have <em>clients</em> (applications) and they have <em>ports</em> (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).
		</p>
		
		<m:img src="img/jack-connections-2.png"/>
		
		<p>
			The JACK <em>daemon</em> is responsible for maintaining the graph and transmitting the messages.
			Clients connect to the <em>daemon</em>.
		</p>
		
		<p>
			Since <m:a href="release-v0.17">v0.17</m:a>, we can list the ports using the <code>relpipe-in-jack</code> command:
		</p>
		
		<m:pre jazyk="bash"><![CDATA[relpipe-in-jack --list-ports true --list-midi-messages false | relpipe-out-tabular]]></m:pre>

		<p>and see it as a relation:</p>
		
		<pre><![CDATA[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]]></pre>

		<p>
			Port names are prefixed with the names of clients.
			We see the port direction in the <code>input</code> and <code>output</code> attributes
			and can distinguish MIDI and audio ports by the value of the <code>midi</code> attribute.
		</p>
		
		<p>
			We can also list the connections using the <code>--list-connections true</code> option:
		</p>
		
		<pre><![CDATA[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]]></pre>

		<p>
			Instead of formatting as a table, we can direct this relation into a file and later recreate the saved connections:
		</p>
		
		<m:pre jazyk="bash"><![CDATA[relpipe-in-jack --list-connections true --list-midi-messages false > connections.rp
cat connections.rp | relpipe-out-jack --required-connections 0]]></m:pre>

		<p>
			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. <code>relpipe-out-csv</code> (or XML, or Recfile) stage before redirecting the stream to the file
			and add <code>relpipe-in-csv</code> etc. stage to the second pipeline.
		</p>
		
		<pre><![CDATA["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"]]></pre>

		
		<p>
			Or we can write the file by hand and just send it to the JACK output module:
		</p>
		
		<m:pre jazyk="bash"><![CDATA[cat connections.csv | relpipe-in-csv | relpipe-out-jack --required-connections 0]]></m:pre>

		<p>
			The primary purpose of the <code>relpipe-out-jack</code> 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 <code>--required-connections 0</code>.
		</p>
		
		<p>
			We can also connect or disconnect particular ports specified on the command line:
		</p>
		
		<m:pre jazyk="bash"><![CDATA[relpipe-in-jack --connect-ports "a2j_bridge:capture" "qmidiarp:in" --list-midi-messages false]]></m:pre>

		<p>
			The primary purpose of the <code>relpipe-in-jack</code> command is monitoring the MIDI commands.
			If we want just to connect or disconnect some ports, we can disable monitoring by setting <code>--list-midi-messages false</code>
			and the command will return immediately.
		</p>
		
		<p>
			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).
		</p>
		
		<p>
			Disconnecting works the same way – just use the <code>--disconnect-ports</code> option
			or specify the <code>disconnect</code> command in the <code>event</code> attribute.
		</p>

		<p>
			Note: there are sophisticated GUI tools focused on working with the JACK graph
			like <a href="https://qjackctl.sourceforge.io/">QjackCtl</a> or <a href="https://kx.studio/Applications:Claudia">KXStudio/Claudia</a>.
			But sometimes it is useful to have a simple CLI tool for this job.
		</p>

	</text>

</stránka>