DemoRunner > MidiDemo.h - only first 8 outputs work! <BUG>

So I’ve been checking out the MidiDemo.h example. I have enough devices connected to my Mac that I have 14 input and output ports.

I discovered that selecting any Output Port over #8 (0~7) does not work and will not send any MIDI notes to that destination.

So I launched a Projucer PIP of MidiDemo.h, and have compiled it and am running it under XCode. Indeed, selecting any output port over #8 results in a DBG message of:

MidiDemo::openDevice: open output device for index = 8 failed!
MidiDemo::openDevice: open output device for index = 9 failed! etc.

And then unselecting them after that causes a jassert at line 222 since ptr is null:

   void closeDevice (bool isInput, int index)
    {
        if (isInput)
        {
            jassert (midiInputs[index]->inDevice.get() != nullptr);
            midiInputs[index]->inDevice->stop();
            midiInputs[index]->inDevice.reset();
        }
        else
        {
// line 222           jassert (midiOutputs[index]->outDevice.get() != nullptr);
            midiOutputs[index]->outDevice.reset();
        }
    }

By adding and removing devices on my computer, I can alter the Output List and the order of ports. It is always Output ports greater than #8 (0~7) regardless of what device they are, so it is not related to a particular device or driver. No problem with Input Ports BTW.

Since I’m new to JUCE and specifically looking at making MIDI in and out apps/plugins, I have no idea where to begin on this, so I’m hoping for some ideas on how to fix this. And I wonder, can anyone else duplicate this? (You need a lot of output MIDI ports…)

Specs:
JUCE 5.4.4
Mac OSX Mojave 10.14.6
Xcode 10.3

Actually, I’ve been debugging this and I seem to have a found a bug in JUCE. Since I don’t know what I’m doing yet, it seemed unlikely, but take a look at this code from juce_mac_CoreMidi.cpp at line 375:

static Array<MIDIEndpointRef> getEndpoints (bool isInput)
{
    Array<MIDIEndpointRef> endpoints;
//bug here?:
    auto numDevices = (isInput ? MIDIGetNumberOfSources() : MIDIGetNumberOfDevices());

    for (ItemCount i = 0; i < numDevices; ++i)
        endpoints.add (isInput ? MIDIGetSource (i) : MIDIGetDestination (i));

    return endpoints;
}

This is called when attempting to select an Output Port in MidiDemo. In the 4th line, it seems that “MIDIGetNumberOfDevices()” should be “MIDIGetNumberOfDestinations().” You are either getting the sources or the destinations here.

On my system, MIDIGetNumberOfDevices() is returning ‘8’ which is why it fails on any port after that. Changing this to:

static Array<MIDIEndpointRef> getEndpoints (bool isInput)
{
    Array<MIDIEndpointRef> endpoints;
//change to:
    auto numDevices = (isInput ? MIDIGetNumberOfSources() : MIDIGetNumberOfDestinations());

    for (ItemCount i = 0; i < numDevices; ++i)
        endpoints.add (isInput ? MIDIGetSource (i) : MIDIGetDestination (i));

    return endpoints;
}

…and now it works correctly, all my Output Ports work.

2 Likes

Great catch, thanks! Will get that sorted out today!

1 Like

Thanks! - saw commit aa219c5a0 “Fixed a typo in CoreMIDI that caused it to recognise the wrong the wrong number of input devices” - It actually was the wrong number of Output ports (or devices if that’s what you call them…)

oh yes, silly me… well, the fix still works!