Jack MIDI portnames (fixes #944) (#945)

* Rework the seqmidi aliases.

- The 1st alias is now the Jack1 MIDI port name with alsa_midi prefix.

- This 2nd alias is basically the same as the 1st alias with the
  alsa_midi prefix stripped, so that devices are listed under the ALSA
  names.

Also fixed the "capture" and "playback" port type names which were the
wrong way round.

* Rework the rawmidi alias.

Like in alsa_seqmidi.c, the 1st alias is now the Jack1 MIDI port name
with alsa_midi prefix.

* Rework pretty-name metadata.

The rawmidi and seqmidi pretty-name metadata now uses the same Jack1
port name as the 1st alias, without the alsa_midi: prefix.
This commit is contained in:
Albert Graef 2023-08-29 16:07:54 +02:00 committed by GitHub
parent f4da9d25ca
commit b83d2340a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 25 deletions

View File

@ -91,6 +91,7 @@ struct midi_port_t {
char dev[16];
char name[64];
char device_name[64];
char subdev_name[64];
jack_port_t *jack;
snd_rawmidi_t *rawmidi;
@ -415,6 +416,7 @@ void midi_port_init(const alsa_rawmidi_t *midi, midi_port_t *port, snd_rawmidi_i
name = snd_rawmidi_info_get_subdevice_name(info);
if (!strlen(name))
name = port->device_name;
strncpy(port->subdev_name, name, sizeof(port->subdev_name));
snprintf(port->name, sizeof(port->name), "%s %s %s", port->id.id[2] ? "out":"in", port->dev, name);
// replace all offending characters with '-'
@ -438,9 +440,43 @@ inline int midi_port_open_jack(alsa_rawmidi_t *midi, midi_port_t *port, int type
port->jack = jack_port_register(midi->client, name, JACK_DEFAULT_MIDI_TYPE,
type | JackPortIsPhysical | JackPortIsTerminal, 0);
// Like in alsa_seqmidi.c, use the Jack1 port name as alias. -ag
const char *prefix = "alsa_midi:";
const char* device_name = port->device_name;
const char* port_name = port->subdev_name;
const char *type_name = (type & JackPortIsOutput) ? "out" : "in";
if (strstr (port_name, device_name) == port_name) {
/* entire client name is part of the port name so don't replicate it */
snprintf (name,
sizeof(name),
"%s%s (%s)",
prefix,
port_name,
type_name);
} else {
snprintf (name,
sizeof(name),
"%s%s %s (%s)",
prefix,
device_name,
port_name,
type_name);
}
// replace all offending characters with ' '
char *c;
for (c = name; *c; ++c) {
if (!isalnum(*c) && *c != ' ' && *c != '/' && *c != '_' && *c != ':' && *c != ',' && *c != '(' && *c != ')') {
*c = ' ';
}
}
if (port->jack) {
jack_port_set_alias(port->jack, alias);
jack_port_set_default_metadata(port->jack, port->device_name);
// we just ignore the given alias argument, and use the Jack1
// port name from above instead -ag
jack_port_set_alias(port->jack, name);
// Pretty-name metadata is the same as alias without the prefix.
jack_port_set_default_metadata (port->jack, name+strlen(prefix));
}
return port->jack == NULL;

View File

@ -147,13 +147,13 @@ static port_type_t port_type[2] = {
{
SND_SEQ_PORT_CAP_SUBS_READ,
JackPortIsOutput,
"playback",
"capture",
do_jack_input
},
{
SND_SEQ_PORT_CAP_SUBS_WRITE,
JackPortIsInput,
"capture",
"playback",
do_jack_output
}
};
@ -493,15 +493,6 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s
snd_seq_client_info_alloca (&client_info);
snd_seq_get_any_client_info (self->seq, addr.client, client_info);
const char *device_name = snd_seq_client_info_get_name(client_info);
snprintf(port->name, sizeof(port->name), "alsa_pcm:%s/midi_%s_%d",
device_name, port_type[type].name, addr.port+1);
// replace all offending characters by -
for (c = port->name; *c; ++c)
if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')')
*c = '-';
jack_caps = port_type[type].jack_caps;
/* mark anything that looks like a hardware port as physical&terminal */
@ -520,21 +511,61 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s
if (!port->jack_port)
goto failed;
jack_port_set_alias (port->jack_port, port->name);
jack_port_set_default_metadata (port->jack_port, device_name);
// First alias: Jack1-compatible port name. -ag
const char *prefix = "alsa_midi:";
const char *device_name = snd_seq_client_info_get_name(client_info);
const char* port_name = snd_seq_port_info_get_name (info);
const char* type_name = jack_caps & JackPortIsOutput ? "out" : "in";
// This code is pilfered from Jack1. -ag
if (strstr (port_name, device_name) == port_name) {
/* entire client name is part of the port name so don't replicate it */
snprintf (port->name,
sizeof(port->name),
"%s%s (%s)",
prefix,
port_name,
type_name);
} else {
snprintf (port->name,
sizeof(port->name),
"%s%s %s (%s)",
prefix,
device_name,
port_name,
type_name);
}
/* generate an alias */
snprintf(port->name, sizeof(port->name), "%s:midi/%s_%d",
snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port+1);
// replace all offending characters by -
for (c = port->name; *c; ++c)
if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')')
*c = '-';
// replace all offending characters with ' '
for (c = port->name; *c; ++c) {
if (!isalnum(*c) && *c != ' ' && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') {
*c = ' ';
}
}
jack_port_set_alias (port->jack_port, port->name);
// Pretty-name metadata is the same as first alias without the prefix.
jack_port_set_default_metadata (port->jack_port, port->name+strlen(prefix));
// Second alias: Strip the alsa_midi prefix, so that devices appear
// under their ALSA names. Use the ALSA port names (without device
// prefix) for the individual ports. -ag
if (strstr (port_name, device_name) == port_name) {
// remove the device name prefix from the port name if present
port_name += strlen(device_name);
while (*port_name == ' ' || *port_name == '\t')
port_name++;
}
snprintf(port->name, sizeof(port->name), "%s:%s (%s)",
device_name, port_name, port_type[type].name);
// replace all offending characters with ' '
for (c = port->name; *c; ++c) {
if (!isalnum(*c) && *c != ' ' && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') {
*c = ' ';
}
}
jack_port_set_alias (port->jack_port, port->name);
jack_port_set_default_metadata (port->jack_port, device_name);
if (type == PORT_INPUT)
err = alsa_connect_from(self, port->remote.client, port->remote.port);