AUv3 host unable to set MIDI output callback using kAudioUnitProperty_MIDIOutputCallback

I have a working AUv3 host implementation and I'm in the process of adding support for MIDI output from the plugin (introduced in iOS 11).


My host is written using the C AudioUnit API, but I know that the plugin (which supports MIDI output since iOS 11) is written using the AUAudioUnit API.


My host can successfully obtain a list of the MIDI outputs from the plugin with the following code:


UInt32 DataSize = 0;
Boolean IsWritable = false;
UInt32 NumMIDIOutputs = 0;

if ((AudioUnitGetPropertyInfo(mpAudioUnit, kAudioUnitProperty_MIDIOutputCallbackInfo, kAudioUnitScope_Global, 0, &DataSize, &IsWritable) == noErr) && (DataSize != 0))
{
     CFArrayRef MIDIArray;
     if (AudioUnitGetProperty (mpAudioUnit, kAudioUnitProperty_MIDIOutputCallbackInfo, kAudioUnitScope_Global, 0, &MIDIArray, &DataSize) == noErr)
     {
          NumMIDIOutputs = CFArrayGetCount(MIDIArray);
          CFRelease(MIDIArray);
     }
}


However, when the host attempts to set the MIDI output callback:


// Function prototype for the host's callback (shown for reference)
static OSStatus MIDIOutCallback(void* zpThis, const AudioTimeStamp* zpTimestamp, UInt32 zMIDIOutNum, const MIDIPacketList* zpPacketList)

// Does the plugin have at least one MIDI output?
if (NumMIDIOutputs > 0)
{
     // Set up the host's callback
     AUMIDIOutputCallbackStruct CallbackInfo;
     zerostruct(CallbackInfo);

     CallbackInfo.userData = this;
     CallbackInfo.midiOutputCallback = HostMIDIOutCallback;

     // Tell the plugin to use our callback for its MIDI output
     OSStatus ReturnCode = AudioUnitSetProperty(mpAudioUnit, kAudioUnitProperty_MIDIOutputCallback, kAudioUnitScope_Global, 0, &CallbackInfo, sizeof(CallbackInfo));
     if (ReturnCode != noErr)
     {
          // THIS FAILS WITH RETURN CODE -10879 (kAudioUnitErr_InvalidProperty) !!!
          InfoPrintf("Couldn't set MIDI output callback : return code = %d\n", ReturnCode);
     }
}


... it gets a return code of -10879 (kAudioUnitErr_InvalidProperty).


The plugin's developer informs me that MIDI output definitely works for hosts implemented using AUAudioUnit, but he hasn't tried it with hosts written using the C AudioUnit API.


- Is there anything I'm obviously doing wrong with my call to AudioUnitSetProperty(kAudioUnitProperty_MIDIOutputCallback)?


- Is there anything extra the plugin developer needs to do in order to make this work? (for example, the plugin implements AUAudioUnit's MIDIOutputNames property, but does not implement MIDIOutputBufferSizeHint)


- Is this a bug/lack of implentation in AUAudioUnit?

Replies

Sorry, I just noticed the initial part of the second code snippet should be:


// Function prototype for the host's callback (shown for reference)
static OSStatus HostMIDIOutCallback(void* zpThis, const AudioTimeStamp* zpTimestamp, UInt32 zMIDIOutNum, const MIDIPacketList* zpPacketList)


(ie. HostMIDIOutCallback, not MIDIOutCallback)

FTR: I'm running into this problem too.