Hello,
I’m not sure if this is even the right place to submit this. For a personal (a.k.a not for profit) project I am using multiple hardware MIDI input devices…a la Arturia KeyLab 49s, Samson Graphite 49, etc.
When two identical devices are plugged in the drivers are usually not smart enough to assign different device names. As such, current JUCE5 implementations of MidiInput::getDevices and MidiIniput::openDevice do not work for all active / enabled MIDI hardware controllers.
I know the code that follows is not “great” code and I do not currently have easy access to a Mac to check for any required changes in that code (let alone Linux etc) but the following two simple changes work very well to solve my problem.
Is it possible to add an option somewhere in the native JUCE codebase to do something simliar?..that is, optionally automatically add some type of device ID suffix such that identical devices are automatically handled?
I propose something similar to what is implemented in the following change:
//==============================================================================
//
// F:\MyWork\VS2017Work\juce\modules\juce_audio_devices\native\juce_win32_Midi.cpp
//
// Adds a numeric suffix to the list returned by getDevices() to deal with multiple
// instances of a device driver with the same name a la KeyLab 49 (!!!) now becomes
// KeyLab 49 - 1, KeyLab 49 - 2, etc.
//
//==============================================================================
static StringArray getDevices()
{
StringArray s;
const UINT num = midiInGetNumDevs();
for (UINT i = 0; i < num; ++i)
{
MIDIINCAPS mc = { 0 };
if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
// DEBUG START - JLD 2017-05-02
{
// OLD METHOD
//s.add (String (mc.szPname, sizeof (mc.szPname)));
// NEW METHOD
String str = mc.szPname;
str.append(" - ", 64);
String numSuffix(i);
str.append(numSuffix, 64);
s.add(str);
}
// DEBUG END --- JLD 2017-05-02
}
return s;
}
//==============================================================================
//
// in same file...the second half of the fix.
//
//==============================================================================
MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const callback)
{
if (callback == nullptr)
return nullptr;
ScopedPointer<MidiInput> in (new MidiInput (""));
ScopedPointer<MidiServiceType::InputWrapper> wrapper;
try
{
wrapper = MidiService::getInstance()->getService()->createInputWrapper (in, index, callback);
}
catch (std::runtime_error&)
{
return nullptr;
}
// DEBUG START - JLD 2017-05-02
// OLD METHOD
//in->setName (wrapper->getDeviceName());
// NEW METHOD
String newName = wrapper->getDeviceName();
newName.append(" - ", 64);
String numSuffix(index);
newName.append(numSuffix, 64);
in->setName(newName);
// DEBUG END --- JLD 2017-05-02
in->internal = wrapper.release();
return in.release();
}
//==============================================================================
Thank you for you consideration on this. I understand this change may not be a good general purpose fit therefore I believe something optional would cater to all.
i can’t believe more people with multiple / identical controllers haven’t already suggested this.
I’m not sure what I would need to subclass / override in order to use “my own” version. Every time a new build of JUCE comes out I need to make these changes. These simple changes work with AudioDeviceManager, MIDIInput, etc.