Unique identifiers for duplicate MIDI devices

Here’s my problem - I’m attempting to develop an application (currently on macOS but eventually Windows too) that needs to distinguish between two identical MIDI controllers. I can’t use the MidiInput device names as these will be the same, and I’ve found that I can’t use the MidiInput device index as the order of these won’t necessarily be the order that you connect the devices (e.g. if I’ve connected a device called ‘foo’ which has an index of 0, when connecting a second device called ‘foo’ it may be set to index 1, or it may be set to index 0 and push the 1st ‘foo’ to index 1). From what I can see, there is currently no way in the JUCE library to get any kind of unique identifier for each MidiInput/MidiOutput device.

From looking at juce_mac_CoreMidi.cpp and the CoreMIDI library I’ve found that the CoreMIDI MIDIGetSource() function will return a unique number, and so far using this appears to fix my problem.

Is there any reason why using MIDIGetSource() to get a unique identifier is a bad idea?

Are there any alternative options? I tried using the kMIDIPropertyUniqueID parameter but this always appears to return any empty string.

I haven’t yet tested this on Windows yet, but assuming I’ll run into the same problems is there an alternative to MIDIGetSource() in the Windows MIDI library?

Thanks.

1 Like

Making all the MIDI classes ID-based is something we were talking about adding last week - should be appearing soon.

1 Like

That’s great to hear!

Is it likely to be coming soon in a few days or a few weeks?

I’m also running into this issue - duplicate MIDI endpoint device get ‘confused’ when referencing by name. Looking forward for an update on this :slight_smile: In the meantime thanks for the tip on MIDIGetSource().

We’re still working on it. Still coming “soon”. Sorry I can’t be more specific.

We’ve added support for ID-based JUCE MIDI devices to the develop branch in commit 09ebd1d.

We’ve soft-deprecated the old index-based MIDI device methods getDevices(), getDefaultDeviceIndex() and openDevice (int) and replaced them with ID-based methods. The static getAvailableDevices() method will return an Array<MidiDeviceInfo> where MidiDeviceInfo is a struct containing the device name and a platform-specific device identifier which you can pass into openDevice() to open a MidiInput or MidiOutput device. This should allow you to differentiate between identical MIDI devices and fix issues with random duplicate device orders. The MidiDemo example has also been updated to show how to use this new API.

Please give it a try and post any feedback in this thread.

4 Likes

Thanks Ed, this is great news.
I should be able to give this a try next week, and will let you know how I get on.

I started to test this and in the process realized that it may not completely solve my specific issue.
I am trying to make sure that when identical Audio(with Midi) devices are found that the Audio device manager and Midi devices found can always be matched together so I am sending MIDI to the correct device. Osx Midi studio seems to be persistent and screw up which MIDI dev I talk to as multiple devices are added, removed and re-added.

Is there a straight forward way (that does not rely on names) to make sure a particular MIDI endpoint found belongs to the same physical Audio device ?

I’m not really sure what you mean here when you say “Audio(with Midi)” devices - audio devices and MIDI devices are treated separately at the software level and I can’t see how you’d tie the two together. Can you expand a bit on what you are trying to achieve? Perhaps posting some code would help to clarify.

I’ll try dilute to a specific example.

" audio devices and MIDI devices are treated separately at the software level and I can’t see how you’d tie the two together"
Yes that’s the issue I’d like to see how to work around…

For example: If I have two PreSonus Studio 2|4 devices available in a system for my JUCE app to discover how can I make sure that the Audio Device Manager and MIDI device selected within JUCE belong to the same physical device?

Having the same issue myself! It is also important that the same device connected via Bluetooth or USB can be distinguished.

Edit: The above fix on the develop branch works perfectly for me! I need to be able to support multiple instances of the same “Device” via USB or BLE (since the device can be run wired or wirelessly). Switched to using getAvailableDevices() and everything works like expected.

Finally poking at this. One thing that’s not clear looking at the code/docs (so far; sorry if I’ve missed this) – are the device identifiers constant across time, or e.g. only unique until the next power cycle on this machine?

What should I persist to file so a user can re-connect in/outs correctly?

1 Like

Unfortunately this isn’t mentioned in any of the platform docs either… From some quick testing with macOS it does seem that the IDs persist, but I’m not sure about other platforms.

Thanks for checking…

Shouldn’t the relevant methods in AudioDeviceManager also be updated to use device IDs instead of names? All of:

  • setMidiInputEnabled()
  • isMidiInputEnabled()
  • addMidiInputCallback()
  • removeMidiInputCallback()
  • setDefaultMidiOutput()

…are using device names, not IDs.

Yes you’re right, although it’s a little more tricky than just changing those methods to use IDs as that’ll silently break all the code that uses these methods. We’ll need to add new methods for ID-based MIDI devices and softly deprecate the old ones.

1 Like

Excellent – something to look at over the upcoming long weekend here in the US!