lathoub / Arduino-AppleMIDI-Library

Send and receive MIDI messages over Ethernet (rtpMIDI or AppleMIDI)
Other
306 stars 66 forks source link

CK_MaxTimeout and MaxSessionNameLen #87

Closed ridgy-b closed 4 years ago

ridgy-b commented 4 years ago

Hi, working on a project (https://gitlab.com/ridgy/rtpmidibando) using your AppleMIDI-Library and the rtpmidid on linux (https://github.com/davidmoreno/rtpmidid), there were lots of problems trying to connect and staying connected. These problems did not occur using rtpmidi. I found the following differences:

There are two definitions in AppleMIDI_Settings.h I modified: MaxSessionNameLen from 24 to 48 (hope this will be enough), and CK_MaxTimeout from 45000 to 120000.

I could not find any hint in the original documentation of AppleMIDI about any limits on these values. Do you have more information on that? Or will this be an issue of rtpmidid?

Thank you for your precios work!

Richard

lathoub commented 4 years ago

Can do a trace using Wireshark and dump the messages here?

ridgy-b commented 4 years ago

Please save the attached files removing .txt at the end; these are binary pcap files.

Using Rtpmidi from McLaren Labs, the invitation only has a peer name of 'desk', which is the computer's name. And as you can see, there is Synchronization and Receiver Feedback every few seconds: Rtpmidi.pcap

Using rtpmidid by David Moreno, the invitation's peer name is 'desk/MIDI monitor-midi in', which is the name of the computer plus the name of the client plus the name of the port. And Synchronization is done every 60 seconds, and no Receiver Feedback: rtpmidid.pcap

Using the latter software needs to increase the MaxSessionNameLen to even more than 48, as there are even longer peer names (e.g. 'desk/FLUID Synth (qsynth)-Synth input port (qsynth:0)'), and increase CK_MaxTimeOut, otherwise your library throws "ERROR 5", which is a ListenerTimeOutException

There is one more problem: When all "Note On" messages had a corresponding "Note Off", i.e., no more buttons pressed, I send an "All Notes Off" just to be sure they are really off. As you can see in the dump files, this is sent in the same frame as the last "Note Off". Wireshark interprets this right, but not all of the MIDI programs, e.g.

richard@desk:~$ aseqdump 
Waiting for data at port 132:0. Press Ctrl+C to end.
Source  Event                  Ch  Data
  0:1   Port subscribed            128:1 -> 132:0
128:1   Control change          0, controller 7, value 0
128:1   Control change          0, controller 0, value 192
128:1   Control change          0, controller 123, value 0
128:1   Note on                 0, note 40, velocity 127
128:1   Note off                0, note 40, velocity 0
128:1   Note off                0, note 0, velocity 176
128:1   Note off                0, note 123, velocity 0
  0:1   Port unsubscribed          128:1 -> 132:0

Here, as is in GMIDImonitor, "All Notes Off" is interpreted as

NoteOff(0,0,176) 
NoteOff(0,123,0)

Is this an error of the respective programs? Does the protocol definition allow "Control change" in the same frame as "Note off"? Edit: qsynth/fluidsynth do this right, so maybe this is really a program error in aseqdump and GMIDImonitor..

Thank you in advance

Richard

lathoub commented 4 years ago

sessionName length

Don't worry about the sessionName length - you can leave it at 24 bytes, this lib will only read 24 and ignore all the rest. The protocol does not use the sessionName at all, it's only for displaying purposes. If you want to display the sessionName, you will have to override the default settings with your new value. The reason its at 24 bytes is not to use to much precious memory on Arduino like devices.

Receiver Feedback

Receiver Feedback must be send regularly, so the other side can flush the journaling records. Not sending Receiver feedback potentially can cause the other device to run into memory issues.

Timestamp Synchronization

Currently the CK_MaxTimeout is set to 45 seconds, assuming CK had to be sent at least twice a second according to the rtpMIDI wiki page - the Apple MIDI Network Driver Protocol page however says:

The initiator must initiate a new sync exchange at least once every 60 seconds

On both MacOs and Windows CK is sent multiple times a minute (on MacOS every 10 seconds) - as stated in the Wiki page; however Apple's own page indicates once a minute. So I better modify the CK_MaxTimeout to be greater than 60 seconds by default.

one more problem

yes, you can have multiple MIDI commands in the same rtpMIDI frame

https://github.com/lathoub/Arduino-AppleMIDI-Library/blob/145063ac18ea539ebb80f6e5d5f6ed203b386cdc/src/rtpMIDI_Parser_MidiCommandSection.hpp#L1-L9

ridgy-b commented 4 years ago

Thank you for your fast response. Some thoughts:

SessionName Lenght I'm not an experienced C++ programmer and not familiar to templates and things like deque, so I am not able to find out what is happening. Undefining KEEP_SESSION_NAME does not really help, the behaviour is about the same. Maybe filling of the structure AppleMIDI_Invitation (whose size depends on MaxSessionNameLen) at some place results in overwriting something? Anyway, increasing the size did help, so no need to respond immidiately.

Receiver Feedback: So I'ld have to discuss this issue with David Moreno.

Multiple MIDI commands in one frame: I think you are right. Maybe some programs get confused when mixing note and control commands. As long as programs like fluidsynth can deal with that there is no real problem.

ridgy-b commented 4 years ago

Except from the SessionNameLength, the problems are solved now. As you don't keep and send a journal, the "Receiver Feedback" message is not essential in this special case (and rtpmidid does ignore the sequence numbers and journal anyway). And there is an error in rtpmidid regarding the delta time byte between multiple MIDI commands. I will report this to David Moreno.

Thank you for your help.