Win32 MIDI Input Device - Humble change request / addition


#1

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.


#2

I doubt most of the JUCE developers on here have multiple midi controllers from the same manufacturer. I’m a full-time musician and I personally don’t know anyone who owns 2 of the same midi controller in their studio.


#3

That’s not a bad idea… (TBH we already do that for linux midi devices and some audio device formats)

FYI we already have this utility:
https://www.juce.com/doc/classStringArray#a9a2b916e858c3f5d941c751220216387
:slight_smile:


#4

With all due respect. Until very recently I have never previously owned duplicates of anything except a Roland D50 “back in the day”. However with the introduction of decent lower cost controllers (the Samson Graphite 49 comes to mind, $179 retail US semi-weighted keys with aftertouch) if you have $600 and some basic wood-working skills you quickly assemble a three manual “organ” type controller. Nothing like that currently on the retail market let alone at that price point. I personally would prefer to have all identical keybeds rather than “an assortment”. I see a trend in the making here. When people realize they can plug two, three, or even four of these into a MAC mini and run many virtual instruments reliably live then more people will get on the “live host” band wagon. I’ve just started down that path now the my Receptor is officially dead. I’ve taken my first steps towards writing a custom VST host meant for live use. I have years to go but I’ve seen my path forward. When I started this I was thinking B3 or Prophet 10, now I’m thinking more like a Wurlitzer 216.


#5

So much to learn! Thank you Jules! Love your work!


#6

Thanks! Will push a fix for this later today.


#7

by custom VST host, do you mean MainStage v3?


#8

It would certainly by similar…I intend to use multiple set lists, patch pre-loading, etc. My idea was to have more of a Keyboard-centric touch-screen interface and fixed routing for simplicity’s sake. Once I get that far I will figure out my mistakes and start v2! Multiplatform of course which is one of many reasons JUCE is just incredible to me.

I’ve also toyed with the idea of virtual organ console a la Hauptwerk, Miditzer, etc.

I’m just learning JUCE so I have too many ideas, too many questions, and not enough free time.


#9

+1 we actually have quite some customers that have multiple Identical Midi Controllers. We also implemented similar tricks to distinguish between different devices . So if this would be fixed in JUCE itself that would be wonderful.
What would be even nicer that you can identify the device by it’s unique id. Not sure if that’s possible on all platforms but using a device id would be make it even more foolproof.


#10

I added code to make sure all the devices have unique suffixes, but when we tested on Windows 10 we actually found that the OS or MIDI driver was already doing the same thing and our fix wasn’t needed. But at least it might help on some older systems.


#11

Thank you so much! I’m off to learn and practice GUI messaging between different components, classes, etc.