From 40f50deae97c371a7313749e1aec6912dfeacd69 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 20 Jun 2022 15:51:33 +0200 Subject: [PATCH] alsa: remove NoteOn 0-velocity fixup Pass MIDI events as they are. JACK requires NoteOn 0-velocity midi events to be patched to NoteOff events for compatibility with LV2 plugins. Let's do this patchup in the JACK layer then and add an option to disable it. It's best to pass the midi messages unmodified and then patch them up wherever they need patching up. --- pipewire-jack/src/pipewire-jack.c | 31 +++++++++++++++++++++++++------ spa/plugins/alsa/alsa-seq.c | 6 ------ src/daemon/jack.conf.in | 3 ++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index c4ef10aaf..0616231a4 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -400,6 +400,7 @@ struct client { unsigned int default_as_system:1; int self_connect_mode; int rt_max; + unsigned int fix_midi_events:1; jack_position_t jack_position; jack_transport_state_t jack_state; @@ -985,10 +986,20 @@ static size_t convert_from_midi(void *midi, void *buffer, size_t size) return b.state.offset; } -static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi) +static inline void fix_midi_event(uint8_t *data, size_t size) +{ + /* fixup NoteOn with vel 0 */ + if (size > 2 && (data[0] & 0xF0) == 0x90 && data[2] == 0x00) { + data[0] = 0x80 + (data[0] & 0x0F); + data[2] = 0x40; + } +} + +static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix) { struct spa_pod_control *c[n_seq]; uint32_t i; + int res; for (i = 0; i < n_seq; i++) c[i] = spa_pod_control_first(&seq[i]->body); @@ -996,6 +1007,8 @@ static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void while (true) { struct spa_pod_control *next = NULL; uint32_t next_index = 0; + uint8_t *data; + size_t size; for (i = 0; i < n_seq; i++) { if (!spa_pod_control_is_inside(&seq[i]->body, @@ -1010,12 +1023,17 @@ static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void if (SPA_UNLIKELY(next == NULL)) break; + data = SPA_POD_BODY(&next->value); + size = SPA_POD_BODY_SIZE(&next->value); + switch(next->type) { case SPA_CONTROL_Midi: - jack_midi_event_write(midi, - next->offset, - SPA_POD_BODY(&next->value), - SPA_POD_BODY_SIZE(&next->value)); + if (fix) + fix_midi_event(data, size); + + if ((res = jack_midi_event_write(midi, next->offset, data, size)) < 0) + pw_log_warn("midi %p: can't write event: %s", midi, + spa_strerror(res)); break; } c[next_index] = spa_pod_control_next(c[next_index]); @@ -3383,6 +3401,7 @@ jack_client_t * jack_client_open (const char *client_name, client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false); client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true); client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false); + client->fix_midi_events = pw_properties_get_bool(client->props, "jack.fix-midi-events", true); client->self_connect_mode = SELF_CONNECT_ALLOW; if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) { @@ -4462,7 +4481,7 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames) if (n_seq == MAX_MIDI_MIX) break; } - convert_to_midi(seq, n_seq, ptr); + convert_to_midi(seq, n_seq, ptr, p->client->fix_midi_events); return ptr; } diff --git a/spa/plugins/alsa/alsa-seq.c b/spa/plugins/alsa/alsa-seq.c index 55f84b5ca..fe6b175b4 100644 --- a/spa/plugins/alsa/alsa-seq.c +++ b/spa/plugins/alsa/alsa-seq.c @@ -543,12 +543,6 @@ static int process_read(struct seq_state *state) continue; } - /* fixup NoteOn with vel 0 */ - if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) { - data[0] = 0x80 + (data[0] & 0x0F); - data[2] = 0x40; - } - /* queue_time is the estimated current time of the queue as calculated by * the DLL. Calculate the age of the event. */ ev_time = SPA_TIMESPEC_TO_NSEC(&ev->time.time); diff --git a/src/daemon/jack.conf.in b/src/daemon/jack.conf.in index 48b637c72..e3e2dc790 100644 --- a/src/daemon/jack.conf.in +++ b/src/daemon/jack.conf.in @@ -81,7 +81,8 @@ jack.properties = { # ignore-all: Ignore all self connect requests #jack.self-connect-mode = allow #jack.locked-process = true - #jack.default-as-system = false + #jack.default-as-system = false + #jack.fix-midi-events = true } # client specific properties