MIDI messages sent to VirtualMidiInput ends up nowhere


I have a situation where I try to send MIDI notes to a track via a VirtualMidiInput. The notes never arrives at the synth living in the track (I can verify that by logging in the synth).

track->injectLiveMidiMessage(midiMessage, 0);  // This works
virtualMidiInput->handleIncomingMidiMessage(midiMessage); // This doesn't

I can verify that the track is indeed a target track for virtualMidiInput by listing the target tracks:

auto vmii = listener->getCurrentInstanceForInputDevice(virtualMidiInput);
for (auto target : vmii->getTargetTracks()) {
  juce::Logger::writeToLog("  target track " + target->getName() + "  " + (target == track ? "same" : "different"));

So… any tips for where to look further?


1 Like

Check the options for the input, make sure end to end is enabled and the midi filter isn’t blocking any channels.

Yes, I checked now, end-to-end is enabled and the channels are allowed.
Is there anything else I should look for?

Sorry, this is a bit tricky to guess at without a working example.
Can you step through it a bit and see where it’s getting dropped?

It should to to MidiInputDevice::sendMessageToInstances and then eventually MidiInputDeviceNode::handleIncomingMidiMessage

Debugging reveals that the if statement on line 138 of MidiInputDeviceNode::processSection is triggered and thereby discarding the note:

    // if it's been a long time since the last block, clear the buffer because
    // it means we were muted or glitching
    if (timeNow > lastReadTime + maxExpectedMsPerBuffer)
        numMessages = 0;

We experience the problem in a test where we first run TransportControl::ensureContextAllocated and soon after virtualMidiInput->handleIncomingMidiMessage(midiMessage).
If we add juce::Thread::sleep(100) before the handleIncomingMidiMessage it works as expected, so there seems to be a race condition!?

Is ensureContextAllocated synchronous or asynchronous?
If asynchronous, is there way to know when things are set up and handleIncomingMidiMessage can be sent?

1 Like

Might be related to Hanging notes when hosting AUv3 plugins on iOS · Issue #143 · Tracktion/tracktion_engine · GitHub

@eggnog, I don’t think its related to that.

@svenemtell ensureContextAllocated is synchronous.
If lastReadTime is initialised to juce::Time::getApproximateMillisecondCounter() rather than = 0, does your test case work? That’s probably what it should be.

1 Like

Yes! Initialising lastReadTime = juce::Time::getApproximateMillisecondCounter() in tracktion_MidiInputDeviceNode.h solves the problem! :slightly_smiling_face:

1 Like
1 Like