Search code examples
ioscmidicoremidi

Sending MIDI using MIDISendEventList() in C/C++


I've been working to migrate an older Core MIDI sending implementation to send MIDI 1.0 messages using Apple's newer UMP-aware MIDI Event List API methods.

I've figured out code that runs and should output MIDI clock messages, but when I send it with MIDISendEventList(...) I see nothing being output from my MIDI interface; there's also no error returned from that method to indicate what the problem is.

Here is the code I'm using:

const ByteCount clockMessageSize = 1;
const UInt32 clockMessage[clockMessageSize] = { (UInt32)0xF8 };    // MIDI clock tick 
const MIDITimeStamp timeStamp = mach_absolute_time();
MIDIEventList clockMessageEventList = {};
MIDIEventPacket* clockMessageEventListEndPacket = nullptr;

clockMessageEventListEndPacket = MIDIEventListInit(&clockMessageEventList, kMIDIProtocol_1_0);
clockMessageEventListEndPacket = MIDIEventListAdd(&clockMessageEventList, sizeof(MIDIEventList::packet), clockMessageEventListEndPacket, timeStamp, clockMessageSize, clockMessage);
                
for (NSUInteger endpointRefIndex = 0; endpointRefIndex < endPointRefsCount; ++endpointRefIndex) {
    MIDIObjectRef destinationEndpoint = endPointRefs[endpointRefIndex];
    OSStatus midiSendError = MIDISendEventList(outputPortRef, destinationEndpoint, &clockMessageEventList);
                    
    if (midiSendError != noErr) {
        printf("MIDISendEventList error: %i", (int)midiSendError);
    }
 }

Inspecting clockMessageEventList.packet after it has been configured but before it is sent shows:

(248, 0, 0, [... all zeros to index 63]) 

Does anyone know where I'm going wrong?


Solution

  • With a bit of additional direction provided by https://stackoverflow.com/a/74248460/8653957 I managed to crack this.

    For some reason, the word created for the MIDI clock message needs to be formatted slightly differently, with the first byte being 0x10, and the second byte being the MIDI clock message:

    const ByteCount clockMessageSize = 1;
    const UInt32 clockMessage[clockMessageSize] = { 0x10000000 | ((UInt32)message << 16) };
    const MIDITimeStamp timeStamp = mach_absolute_time();
    MIDIEventList clockMessageEventList = {};
    MIDIEventPacket* clockMessageEventListEndPacket = nullptr;
    
    clockMessageEventListEndPacket = MIDIEventListInit(&clockMessageEventList, kMIDIProtocol_1_0);
    clockMessageEventListEndPacket = MIDIEventListAdd(&clockMessageEventList, sizeof(MIDIEventList::packet), clockMessageEventListEndPacket, timeStamp, clockMessageSize, clockMessage);
    

    If anyone know why this is, please post it! But here you go, MIDI clock via MIDIEventList.