because the jack server connects to a single specific device when it is launched - in this case by systemd - and that is the device available to clients when they are created / connected. device discovery is totally separate (in fact i believe jack relies on the driver backend for this - viz., ALSA.)
you already found the correct invocation to pick your soundcard when starting jack. so, edit your norns-jack.service appropriately. presently, there is no convenient way to change this on the fly and still use systemd to manage norns process dependencies. if we wanted to extend this, i would use an environment variable for the device name, change the var, and restart the service.
but of course, in developing norns stack we were (/are) not generally worried about supporting dynamic audio device changes.
sure it does. the jack API function is jack_get_ports(). see the API docs. this returns a NULL-terminated lists of ports matching specified flags.
for example to get physical ADC ports, as we do in crone::Client::connectADCPorts():
const char **ports = jack_get_ports (client, nullptr, nullptr,
JackPortIsPhysical | JackPortIsOutput);
(potential point of confusion: JackPortIsOutput means the port is a source - viz, an ADC - and JackPortIsInput means it is a sink (DAC)).
and then loop over ports until you see a NULL. (we don’t check system port count at present in crone because we are only asking for stereo I/O.)
and if you want, here is a tiny standalone C program that reports ADC and DAC channel counts.
compile with -ljack
#include <jack/jack.h>
#include <stdio.h>
int count_ports(const char **ports) {
int count=0;
const char *port;
do {
port = ports[count];
if (port == NULL) { break; }
count++;
} while (1);
return count;
}
int main() {
jack_status_t status;
jack_client_t *client = jack_client_open("counter", JackNullOption, &status, NULL);
if (client == NULL) { return 1; }
const char **adc_ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical|JackPortIsOutput);
const char **dac_ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical|JackPortIsInput);
printf("ADC ports: %d\n", count_ports(adc_ports));
printf("DAC ports: %d\n", count_ports(dac_ports));
jack_client_close(client);
return 0;
}
or at least the scsynth Server and ServerOptions classes don’t have methods to access this
that is true on linux (oddly.) i guess the expectation is that linux users will manage things from the environment. there are SC_JACK_DEFAULT_INPUTS and SC_JACK_DEFAULT_OUTPUTS variables for example. we override these in Crone.sc with the hacky shell commands you found b/c we don’t want SC to connect to physical ports by default.
i guess linking to jack is an option, but in general we don’t want to set up a dependency like that. you can always use the quick and dirty method of capturing jack_lsb and searching for system:capture and system:playback patterns as you’ve already done.
but what i’d recommend as the cleanest method would be to extend crone process with an explicit hardware port count. matron and sclang and whatever can then query that via OSC.