Figured it out. There’s basically this:
JuceAU (AudioUnit component)
: MusicDeviceBase (component,
(UInt32) AudioUnitHelpers::getBusCountForWrapper (*juceFilter, true),
(UInt32) AudioUnitHelpers::getBusCountForWrapper (*juceFilter, false))
{
// ...
}
Which calls this:
static int getBusCountForWrapper (const AudioProcessor& juceFilter, bool isInput)
{
#if JucePlugin_IsMidiEffect
const auto numRequiredBuses = isInput ? 0 : 1;
#else
const auto numRequiredBuses = 0;
#endif
return jmax (numRequiredBuses, getBusCount (juceFilter, isInput));
}
So we have numRequiredBuses = 1
for the output for MIDI effects. I’m not sure why; maybe AU MIDI processors require this or something. But then later we call this
static Array<AUChannelInfo> getAUChannelInfo (const AudioProcessor& processor)
{
Array<AUChannelInfo> channelInfo;
auto hasMainInputBus = (AudioUnitHelpers::getBusCountForWrapper (processor, true) > 0);
auto hasMainOutputBus = (AudioUnitHelpers::getBusCountForWrapper (processor, false) > 0);
if ((! hasMainInputBus) && (! hasMainOutputBus))
{
// midi effect plug-in: no audio
AUChannelInfo info;
info.inChannels = 0;
info.outChannels = 0;
return { &info, 1 };
}
// ... all kinds of stuff ...
}
And it turns out that hasMainOutputBus
is always set to 1, even if it is a MIDI effect plugin. So, the if
statement which seems intended to run for MIDI effects doesn’t actually run.
Because of a fairly elaborate sequence of things thereafter, JuceAU::channelInfo
is then set incorrectly unless {something, 2}
is manually specified in Plugin Channel Configurations. Just having isBusesLayoutSupported()
always return true;
which is what’s happening currently for MIDI effects, doesn’t work.
I would guess that what’s happened is initially it wasn’t required to have an output bus for MIDI effects, and then for some reason that requirement was added - but certain parts of the rest of the library still assume that MIDI effects have no output bus.