How do I receive Sysex Messages - do I have to go around the parser ?

It would be nice with a Sysex callback 🙂

That works fine 🙂

If it was up to me, the callback would have a std::vector<midi_byte_t> sysexMessage with the relevant bytes between the start byte 240 and endbyte 247 as argument. The callback would then only fire when the endbyte is received and the message is complete... Just a suggestion...

Thanks for being so fast with solutions always !

That was my first thought, but there are a number of implications. One problem is that there is no guarantee as to what thread this callback would run on: depending on the rest of the code, it could run in the audio thread or in another thread. In case it runs in the audio thread, resizing a std::vector would not be RT-safe. Additionally, sysex blocks could be very large but you may process the data in smaller chunks. For instance, if you are receiving a large parameter dump where the information is organised in 4 bytes per parameter, you wouldn't need to store all the content of the dump and only process it all at once, but you could process every block of 4 bytes at at time. In another case, you can also samples via sysex, what would be the point of caching in memory several megabytes of samples to then process them and write them to disk one at a time? Some applications (e.g.: libpd) require to pass one byte at a time, so this is the most generic solution.

Ultimately, if you want to achieve the behaviour you mentioned, you can with this API, with just a couple of extra lines of code E.g.:


void sysexCallback(midi_byte_t byte, void*arg)
{
  auto sysexIn =  (std::vector<midi_byte_t>*)arg;
  if(0xF0 == byte) {
    /// end of message
    // do something with its content  ...
   /// ... then empty it
   sysexIn->resize(0); 
  }
  else
    sysexIn->push_back(byte);
}

// this must be in a valid state at all times while the callback is called. For instance, make it global.
std::vector<midi_byte_t> gSysexIn;

bool setup(...) {
  ... 
 // I pass it as an argument here because it's good practice and it helps when you are using the same callback to 
// act on different objects, but if you only have one object, you could just access the global variable from the callback
  midi.setSysexCallback(sysexCallback, (void*)&gSysexIn);
  ...
}