MIDI device naming issues

I am trying to configure my application to use two midi devices, one input, and one output. I also want them to attempt to autoconnect to a named midi device - initially hardcoded to my USB Midi cable, known as “USB Midi”.

The problem I am experiencing is trying to get the two devices to have a custom name, AND to autoconnect to a remote device.

I am doing my development on a current version of Juce, using 64 bit Linux.

Listed here is my whole init code…

    // Try to locate a remote device to attach to OUTPUT device first
    int default_dev = MidiOutput::getDefaultDeviceIndex();

    StringArray all_devs = MidiOutput::getDevices();
    for(int i = 0; i < all_devs.size(); i++)
        {
        std::cout << "Device [" << i << "] = " << all_devs[i] << "\n";
        if(all_devs[i] == "USB Midi")
            default_dev = i;
        }
    midiOutput = MidiOutput::createNewDevice("KurzPanel");
    midiOutput->openDevice(default_dev);

    // Now try to process the INPUT device
    default_dev = MidiInput::getDefaultDeviceIndex();

    all_devs = MidiInput::getDevices();
    for (int i = 0; i < all_devs.size(); i++)
	{
	std::cout << "Device [" << i << "] = " << all_devs[i] << "\n";
	if (all_devs[i] == "USB Midi")
	    default_dev = i;
	}
    // Should be doing it this way...
    midiInput = MidiInput::createNewDevice("KurzPanel", this);
    midiInput->openDevice(default_dev, this);

    //midiInput = MidiInput::openDevice(default_dev, this);
    //midiInput->setName("KurzPanel");

The real work is happenning here:

    midiOutput = MidiOutput::createNewDevice("KurzPanel");
    midiOutput->openDevice(default_dev);

and here for the input:

    // Should be doing it this way...
    midiInput = MidiInput::createNewDevice("KurzPanel", this);
    midiInput->openDevice(default_dev, this);

    //midiInput = MidiInput::openDevice(default_dev, this);
    //midiInput->setName("KurzPanel");

The code above results in two Output ports, “KurzPanel” and “Juce Midi Output”. “Juce Midi Output” is connected to my “USB Midi” device, but my program is actually sending to the “KurzPanel” port (which I have to manually connect to make it work). The Input behaviour is identical.

Firstly, if I just call openDevice as a static method instead of createNewDevice then I get a single MIDI port configured, and connected, unfortunately it has the system default name of “Juce Midi Output”.

The same behaviour is true for the Input device, and the call to setName has no effect at all.

So what does work:

Option 1: I can just use createNewDevice to set up my MIDI Input and Output and they are correctly named, but there is no way I can see to get them connected to another MIDI port from within Juce.

Option 2: I can just use openDevice, and get incorrectly named MIDI devices that are correctly connected to the external MIDI device.

In my understanding, I feel that openDevice should not be a static member, and should not create a new device - it should just open the specified port, and associate it with the object its called from. This would be a lot more intuitive.
1: Create a local device with createNewDevice
2: Connect it to a remote device with openDevice
3: Repeat Step 2 (and optionally step 1 if we want multiple internal devices) for any other devices we want to send/receive from.

Regards, Euan.

Ha Ha, I seem to make a habit of answering my own posts.

The two Juce devices can be renamed by overriding two #define variables in the [quote]modules/juce_audio_devices/native/juce_linux_Midi.cpp[/quote] file.

To do this, configure the new values as a preprocessor variable using Introjucer (or edit your Makefile manually)

In Introjucer, add the following line:

Euan.

And Finally…

The above doesn’t quite fix everything. The Devices now get renamed, but the Ports within the device still retain the “Juce…” moniker.

This requires a deeper dig, these values are actually hardcoded in [quote]modules/juce_audio_devices/native/juce_linux_Midi.cpp[/quote]

const int portId = snd_seq_create_simple_port (seqHandle, "Juce Midi In Port",

To get around this, it is necessary to change the code itself.

Jules I’d like to suggest this as a candidate for a patch fix.

I’ve changed my code to add an additional two defines to the top of the file:

#ifndef JUCE_ALSA_MIDI_INPUT_PORT
 #define JUCE_ALSA_MIDI_INPUT_PORT  "Juce Midi In Port"
#endif

#ifndef JUCE_ALSA_MIDI_OUTPUT_PORT
 #define JUCE_ALSA_MIDI_OUTPUT_PORT "Juce Midi Out Port"
#endif

And have then changed the “snd_seq_create_simple_port” calls to use this #define var rather than the hard coded values.

const int portId = snd_seq_create_simple_port (seqHandle, JUCE_ALSA_MIDI_INPUT_PORT,

The Introjucer section now requires that we define overrides for all four values:

And voila:

I’ve attached a copy of the new juce_linux_Midi.cpp as a .zip as .cpp or .txt are not allowed ;-( for comparison.

Euan.

I think the juce alsa code would deserve an even larger update, where it would present one single client name that would handle all input and output ports. Right now it creates one client for each input and output midi connection

Thanks, I’ve added some code like you suggest to make those names customisable, but like jpo said, it probably does all need a bit of a spring-cleaning!

Thanks Jules.

I agree with jpo above, and I also think this should be a bit more dynamic - a modifiable string rather than a compile time definition, but for now at least this does work. Maybe a little hint in the Documentation advising people that they should be looking at the #define code would also be a help…

Euan.