Proper use of AudioDeviceManager::addMidiInputCallback


#1

Hi,
We got some problems making midi input works properly with AudioDeviceManager.
We are using Juce 1.51, not really warm about moving to tip (big app, potentially lot of changes to make). Key functions involved look the same anyway.

We are currently placing calls such as “devManager->addMidiInputCallback (String::empty, player);”, and everything works as advertised.
But we are limited to a single midi port at a time, something that’s not obvious within the dialog to select midi ports (made with AudioDeviceSelectorComponent).

In this component, the user can pick as many midi input ports he/she wishes, but a single one will be actually used (something like the last clicked onto)
This is because of the empty argument in the call to addMidiInputCallback that translates into using the “default midi input port”.

This is inconsistent for the user, we had to either prevents our user to select multiple inputs, either to make multiple inputs work.
We attempted the later, and didn’t sort things out.

When not using an empty argument, we had to add as many callbacks as there are midi input ports installed. This is not only inconvenient, but this didn’t work.
Callbacks were never called at best, and some exceptions occurred at worst.
The only things that helped has been patching Juce as below:

void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source,
                                                       const MidiMessage& message)
{
    if (! message.isActiveSense())
    {
        // Plain Juce version: const bool isDefaultSource = (source == 0 || source == enabledMidiInputs.getFirst());
        const bool isDefaultSource = true;
        ...

With this patch, all midi inputs are now considered default, and this is really what we want.

But what would be the “official” way?
Are we missing something?

Thx


#2

So, why are you giving an empty argument then ? :slight_smile:

It’s been a while I didn’t do MIDI stuff, but I’m pretty sure something like that should work :

int i; const juce::StringArray& devices = juce::MidiInput::getDevices(); for(i=0;i<devices.size(); i++) { _deviceManager.addMidiInputCallback(devices[i],player); }
HTH


#3

Thanks dinaiz.

I’ve tried something like that and wasn’t able to make it work properly.

The problem seems located here (excerpt from AudioDeviceManager::handleIncomingMidiMessageInt()):

        for (int i = midiCallbackDevices.size(); --i >= 0;)
        {
            MidiInput* const md = midiCallbackDevices.getUnchecked(i);

            if (md == source || (md == 0 && isDefaultSource)) <------------
                midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message);
        }

For some reasons midiCallbackDevices seems to contain data unrelated to current settings, so the part “md == source” never triggers.

Robert


#4

Ah, it must be because the midi device has been closed and a new one re-opened since you added the callback. I guess I should use the device names instead of their actual pointers in that midiCallbackDevices array…