Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jack_midi_event_get behaviour does not match documentation when receiving SysEx messages #413

Closed
SpotlightKid opened this issue Jan 17, 2019 · 25 comments
Labels
backend Related to a specific backend discussion needs documentation Something that isn't obvious and should be documented

Comments

@SpotlightKid
Copy link

SpotlightKid commented Jan 17, 2019

The documentation for jack_midi_event_get says:

Jack MIDI is normalised, the MIDI event returned by this function is
guaranteed to be a complete MIDI event (the status byte will always be
present, and no realtime events will interspered with the event).

However, the behaviour I'm observing is, when a large MIDI message (e.g. a SysEx message with a synthesizer patch) is received, several events of up to 256 bytes in size are generated, and the second to last messages do not start with a status byte. and only the last message ends with status 0xF7 (end-of-sysex). So they are not complete MIDI events.

For example, here is the output of the jack_midi_dump client when I send the patch edit buffer from a Yamaha DX7II synthesizer, which consists of three SysEx messages of 510, 57, and 163 bytes length respectively.

  46: f0 43 00 7e 03 76 4c 4d 20 20 46 4b 53 59 45 20 30 30 30 30 30 30 30 30 30 32 30 34 30 38 30 3a 30 3c 31 30 31 32 31 34 31 38 31 3a 31 3c 32 30 32 32 32 34 32 38 32 3a 32 3c 33 30 33 32 33 34 33 38 33 3a 33 3c 34 30 34 32 34 34 34 38 34 3a 34 3c 35 30 35 32 35 34 35 34 35 34 35 34 35 34 35 34 30 30 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 30 30 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
  69: 32 32 32 32 32 32 30 30 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 30 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 38 31 3a 31 3a 31 3a 31 3c 31 3c 31 3e 31 3e 31 3e 32 30 32 30 32 30 32 32 32 32 32 34 32 34 32 34 32 36 32 36 32 36 32 38 32 38 32 3a 32 3a 32 3a 32 3c 32 3c 32 3c 30 30 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 30 38 3c f7
 181: f0 43 00 05 00 31 00 00 00 00 00 00 00 03 03 00 03 00 00 00 00 00 07 00 02 01 00 00 00 46 00 00 00 00 00 00 00 00 00 32 00 00 32 32 07 00 00 00 50 00 00 00 00 00 01 39 f7
 115: f0 43 00 00 01 1b 46 1b 10 1f 5a 63 5e 00 00 00 11 00 00 00 00 02 63 00 02 00 01 46 1b 10 28 5a 63 5f 00 00 00 00 00 00 00 03 01 41 00 00 00 0e 3c 1b 10 27 5a 63 5e 00 00 00 00 00 00 00 03 01 52 00 00 00 01 40 28 17 32 63 61 5e 00 00 00 00 00 00 00 00 00 5f 00 00 00 07 32 1a 09 24 5e 63 5e 00 18 00 05 00 00 00 03 01 57 00 00 00 0e 41 4f 45 32 63 63 63 00 00 00 00 00 00 00 00 00 5f 00 00 00 0d 63 63 63 63 32 32 32 32 08 06 01 1b 00 05 00 01 00 01 18 45 6e 73 65 6d 62 6c 65 20 20 59 f7

(Note: I had to increase the size of the buffer member of the midimsg struct on line 37 to >= 512 bytes, otherwise jack_midi_dump will terminate with a segfault on reception of the first message.)

Tested with jack2 with dbus from git (549ee2e) on Manjaro Linux (kernel 4.16.18-rt12-MANJARO) with ALSA backend (alsa-lib 1.1.7-2).

@7890
Copy link
Contributor

7890 commented Jan 20, 2019

Thanks for pointing this out. It would be good to have an example of long message that triggers the bug as an attachment in binary or eventually base64 encoded form feed to jack_midi_dump so we can see exactly the same behavior and talk about the expected.

@SpotlightKid
Copy link
Author

from random import randint

numbytes = 512 # anything > 256, really

with open('example.syx', 'wb') as syx:
    syx.write(b'\xF0')
    syx.write(bytes((randint(0, 127) for _ in range(numbytes - 2))))
    syx.write(b'\xF7')

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

I can confirm that throwing arbitrary bytes to jack_midi_dump causes a segfault. It could possibly be made more robust to nicely terminate or handle invalid situations. This needs to be addressed in a separate issue.

Some notes:
There is jack_midi_max_event_size(), for a small test it returns 32720 for jackd running with buffer size 1024.
One question is why the event is split up to several smaller chunks in the first place.
jack_midi_event_get() code and documentation need a closer look.
Note to self: also look in JackMidiRawInputWriteQueue.cpp

@SpotlightKid how exactly do you receive "several events of up to 256 bytes in size" ?

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

@SpotlightKid the jack_midi_dump example client does now support larger messages, please see recent commit.

For this process() function:

static int process(jack_nframes_t frames, void *arg)
{
        buffer_out=jack_port_get_buffer(port_out, frames);
        jack_midi_clear_buffer(buffer_out);

//      fprintf(stderr, "Max MIDI event size: %d\n", jack_midi_max_event_size(buffer_out));

        int msg_size=512;
        char *buffer;
        buffer=calloc(msg_size, 1);

        //create sysex message
        buffer[0]=0xf0;
        int i;
        for(i=1;i<msg_size/2;i++) //filling 1/2 of sysex event
        {
                buffer[i]=0x42; //data
        }
        buffer[msg_size-1]=0xf7;

        //write two midi sysex data messages to output buffer
        int pos=0; //sample pos in cycle
        jack_midi_event_write(buffer_out, pos, (void*)buffer, msg_size);
        jack_midi_event_write(buffer_out, pos, (void*)buffer, msg_size);

        free(buffer);

        return 0;
}

jack_midi_dump shows this:

   0: f0 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f7
   0: f0 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f7

It looks exactly as expected so far. Two midi events, each 512 bytes long, starting with f0, ending with f7. Is that what you would expect to see from the synth patch?

@SpotlightKid
Copy link
Author

SpotlightKid commented Jan 22, 2019

the jack_midi_dump example client does now support larger messages, please see recent commit.

That's what I basically did to test. RBSIZE is only the number of elements in the ringbuffer, isn't it? It should not affect the maximum size of single events the program is able to handle.

how exactly do you receive "several events of up to 256 bytes in size" ?

I'm not sure I understand the question. I just ran jack_midi_dump in a terminal, connected the system:midi_playback_1 port of my interface to its input port and then triggered the "Send patch edit buffer" function on my Yamaha DX7II, whose MIDI out is connected to the MIDI in of my interface.

You can see from the output of jack_midi_dump, that jack_midi_event_get is executed twice for the first SysEx message, which is 510 bytes long. I also confirmed this by adding a debugging print statement right after the jack_midi_event_get call in process:

        printf ("Received event of size = %ld\n", event.size);

and got this output:

Received event of size = 256
 227: f0 43 00 7e 03 76 4c 4d 20 20 46 4b 53 59 45 20 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c
Received event of size = 254
   0: 31 3c 31 3c 31 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 2d f7
[...]

I tried changing the JACK buffer period/size from 256 to 512 bytes, but that didn't change the outcome. My guess is that the 256 event size cap is imposed by the ALSA midi backend.

Two midi events, each 512 bytes long, starting with f0, ending with f7. Is that what you would expect to see from the synth patch?

Yes. And that also strengthens my belief, that this has to do with the ALSA backend, which is out of the picture in your test.

@SpotlightKid
Copy link
Author

BTW, I stumbled on this behaviour via RtMidi, which incorrectly assumes that jack_midi_event_get always produces complete MIDI events (see their JACK MIDI input process function here). I implemented a patch for this in my fork of RtMidi, but before I make a pull request upstream, I want to clarify whether this behaviour is intended and whether JACK's documentation or its code is "right".

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

As far as I understand, the jack_midi_event_get() will return whatever was written into the buffer by another process via jack_midi_event_write() beforehand. Your synth sends something (is it one message?), this gets into jack somehow and then is chunked up. Do you use a2jmidid to get it into jack?

@SpotlightKid
Copy link
Author

Do you use a2jmidid to get it into jack?

No, I use JACK2 with the seq MIDI backend.

@7890 7890 added the backend Related to a specific backend label Jan 22, 2019
@SpotlightKid
Copy link
Author

SpotlightKid commented Jan 22, 2019

Your synth sends something (is it one message?)

Yes.

Well, actually, as written in the issue description, it sends three messages per patch, and the first is 510 bytes long. I confirmed that with a MIDI monitor (midi-ox) on Windows.

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

in alsa_seqmidi.c eventually:
MAX_EVENT_SIZE = 1024

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

Can you create a dummy output as you'd expect it for the messages in your first post? You'd expect it to collapse to 3 messages?

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

If you can record the midi bytestream that you think is correct, please attach it here. I'd like to send it to JACK in various ways.

@SpotlightKid
Copy link
Author

SpotlightKid commented Jan 22, 2019

I don't really care what jack_midi_dump outputs, I want clarification how jack_midi_event_get is supposed to behave. If breaking up large MIDI messages over several events is the way it works, that's ok for me (though not ideal, but other MIDI APIs do the same), but then the documentation should mention that.

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

jack_midi_dump should output pretty much what jack_midi_event_get is getting so if it works it's a good indicator of what's going on. You have to point out more clearly which output you'd expect. If you won't provide that or the data that would trigger it, it's hard to easily replicate and guess about whether it's a generic or another problem.

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

From http://jackaudio.org/api/group__MIDIAPI.html#ga838c794bd1451bfd47edde1c7cd1ff4f

Clients must write normalised MIDI data to the port - no running status and no (1-byte) realtime messages interspersed with other messages (realtime messages are fine when they occur on their own, like other messages).

If that rule is strictly followed, then

Jack MIDI is normalised, the MIDI event returned by this function is guaranteed to be a complete MIDI event (the status byte will always be present, and no realtime events will interspered with the event)."
will be true. It's unclear whether or not special checks are made to ensure the latter for non-conforming input via write.

It doesn't tell anything about splitting large messages.

@SpotlightKid
Copy link
Author

I would expect that jack_midi_event_get works as it is documented, i.e. each call returns a complete MIDI message. If that is not the case, it should be documented and the circumstances in which this isn't the case.

If jack_midi_event_get worked that way, I would expect jack_midi_dump to output something like the following (the event times before the colons may difffer), if I send the attached SysEx messages into it:

 110: f0 43 00 7e 03 76 4c 4d 20 20 46 4b 53 59 45 20 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 2d f7
 210: f0 43 00 05 00 31 00 00 00 00 00 00 00 01 01 00 01 00 00 01 00 00 02 00 00 00 00 00 00 00 00 63 00 00 00 00 00 00 00 32 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 33 f7
 147: f0 43 00 00 01 1b 63 63 63 63 63 63 63 00 27 00 00 00 00 00 00 00 00 00 01 00 07 63 63 63 63 63 63 63 00 27 00 00 00 00 00 01 00 00 00 00 00 0c 28 19 63 1e 63 00 00 00 27 00 00 00 00 00 01 00 55 00 00 00 0c 3c 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 00 00 0c 2c 14 63 1e 63 00 00 00 27 00 00 00 00 00 01 00 4d 00 01 00 02 3c 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 01 00 02 63 63 63 63 32 32 32 32 01 07 00 23 00 0a 00 01 00 03 18 52 69 63 68 20 50 61 64 4d 57 1c f7

patch.syx.zip

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

Note on how to reproduce:

jackd -dalsa -Xseq
sudo modprobe snd_virmidi
jack_midi_dump
jack_connect "system:midi_capture_2" "midi-monitor:input"
amidi -p "hw:1,0" -s patch.syx

Found this comment in midi_unpack.h:
// TODO: deal with big sysex'es (they are silently dropped for now)

https://github.com/jackaudio/jack2/blob/master/linux/alsa/alsa_seqmidi.c#L788
size and alsa_event->data.ext.len are already "short" at this place. 256, then 254.

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

This is the output when leaving jackd out of the test.

aseqdump -p"Virtual Raw MIDI 1-0:VirMIDI 1-0"
Waiting for data. Press Ctrl+C to end.
Source  Event                  Ch  Data
 20:0   System exclusive           F0 43 00 7E 03 76 4C 4D 20 20 46 4B 53 59 45 20 30 30 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 30 30 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 3F 30 30 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C 31 3C
 20:0   System exclusive           31 3C 31 3C 31 3C 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 32 3C 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 2D F7
 20:0   System exclusive           F0 43 00 05 00 31 00 00 00 00 00 00 00 01 01 00 01 00 00 01 00 00 02 00 00 00 00 00 00 00 00 63 00 00 00 00 00 00 00 32 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 33 F7
 20:0   System exclusive           F0 43 00 00 01 1B 63 63 63 63 63 63 63 00 27 00 00 00 00 00 00 00 00 00 01 00 07 63 63 63 63 63 63 63 00 27 00 00 00 00 00 01 00 00 00 00 00 0C 28 19 63 1E 63 00 00 00 27 00 00 00 00 00 01 00 55 00 00 00 0C 3C 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 00 00 0C 2C 14 63 1E 63 00 00 00 27 00 00 00 00 00 01 00 4D 00 01 00 02 3C 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 01 00 02 63 63 63 63 32 32 32 32 01 07 00 23 00 0A 00 01 00 03 18 52 69 63 68 20 50 61 64 4D 57 1C F7


amidi -p "hw:1,0" -s patch.syx

It seems to do exactly the same thing as jack_midi_dump regarding the chunk sizes of the first message.

@7890
Copy link
Contributor

7890 commented Jan 22, 2019

@SpotlightKid please try this preliminary patch:
alsa_seqmidi.c.diff.txt
This is the output I get with jack_midi_dump:

385: f0 43 00 7e 03 76 4c 4d 20 20 46 4b 53 59 45 20 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 30 30 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 31 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 32 3c 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 2d f7
 385: f0 43 00 05 00 31 00 00 00 00 00 00 00 01 01 00 01 00 00 01 00 00 02 00 00 00 00 00 00 00 00 63 00 00 00 00 00 00 00 32 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 33 f7
 386: f0 43 00 00 01 1b 63 63 63 63 63 63 63 00 27 00 00 00 00 00 00 00 00 00 01 00 07 63 63 63 63 63 63 63 00 27 00 00 00 00 00 01 00 00 00 00 00 0c 28 19 63 1e 63 00 00 00 27 00 00 00 00 00 01 00 55 00 00 00 0c 3c 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 00 00 0c 2c 14 63 1e 63 00 00 00 27 00 00 00 00 00 01 00 4d 00 01 00 02 3c 63 63 28 63 63 63 00 27 00 00 00 00 00 00 00 63 00 01 00 02 63 63 63 63 32 32 32 32 01 07 00 23 00 0a 00 01 00 03 18 52 69 63 68 20 50 61 64 4d 57 1c f7

@SpotlightKid
Copy link
Author

Yes, I can confirm that jack_midi_dump generates only three events from this input with this patch applied to JACK.

@7890
Copy link
Contributor

7890 commented Jan 23, 2019

The bonus question is what would we consider as a too large message. The current limit of 256 bytes is a bit low. If somebody sends a 2 MB message, it could be necessary to either drop it or do the same, chunk it up at the ALSA level. In that case, the documentation would need to say that it could be necessary to concatenate the messages at client side. The problem is not yet fully solved.
Side note: in foreseeable future, zita a2j j2a will supersede the other ALSA backends.

@SpotlightKid
Copy link
Author

Dropping messages is always a bad idea, IMHO. At least this should be signalled by the return value of jack_midi_event_get and the size limit should be configurable at runtime. Another possibility would be to drop all sysex messages unless explicitly enabled (as RtMidi does).

@7890
Copy link
Contributor

7890 commented Jan 24, 2019

Yes, interesting ideas. It needs to be possible to receive large sysex without compromising real time performance. This means to create chunks at some point. It could be a user setting, a filter (OFF), or plain what ALSA has to offer. The last case means to only update documentation on the 256 bytes limit (this might vary between backends) plus a hint that if checking for sysex messages, caller can not expect a "normalized" single event.

@7890 7890 added discussion needs documentation Something that isn't obvious and should be documented labels Jan 24, 2019
@SpotlightKid
Copy link
Author

The last case means to only update documentation on the 256 bytes limit (this might vary between backends) plus a hint that if checking for sysex messages, caller can not expect a "normalized" single event.

Would be fine by me. Like I mentioned above, I already implemented code in RtMidi to handle this situation and the same logic needs to be applied in its ALSA and CoreMIDI backends anyway.

@7890
Copy link
Contributor

7890 commented Jan 30, 2019

Note added for jack_midi_event_get() here:
b744332
Thanks for your valuable input! - Now we have jack_midi_dump "fixed" for larger buffers plus a more accurate documentation.

@7890 7890 closed this as completed Jan 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Related to a specific backend discussion needs documentation Something that isn't obvious and should be documented
Projects
None yet
Development

No branches or pull requests

2 participants