Midi input fixes!


i’ve modified a bit the MidiInputThread, cause it was crashing everytime you try to attach other midi output device to the juce midi input device:

    void run()
        const int maxEventSize = 16 * 1024;
        snd_midi_event_t* midiParser;

        if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
            uint8* const buffer = (uint8*) juce_malloc (maxEventSize);

            const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
            struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));

            snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);

            while (! threadShouldExit())
                if (poll (pfd, numPfds, 100000) > 0)
                    snd_seq_event_t* inputEvent = 0;

                    snd_seq_nonblock (seqHandle, 1);

                        if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
                            // xxx what about SYSEXes that are too big for the buffer?
                            const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);

                            snd_midi_event_reset_decode (midiParser);

                            if (numBytes > 0)
                                const MidiMessage message ((const uint8*) buffer,
                                                           Time::getMillisecondCounter() * 0.001);

                                callback->handleIncomingMidiMessage (midiInput, message);

                            snd_seq_free_event (inputEvent);
                    while (snd_seq_event_input_pending (seqHandle, 0) > 0);

            snd_midi_event_free (midiParser);
            juce_free (buffer);

this way we put client in non blocking mode, so it will not be put sleeping if it fills the output memory pool with full events, also now we correctly check for remaining events in the buffer, and we check for numBytes > 0, cause on port connection/disconnection it will return -2 here.

now it works like a charm !

anyway i have to spend 2 words for the way on linux we see midi (and now audio thanks to jack): we don’t have the logic idea of hardware devices, so applications doesn’t connect to physical devices directly, instead they expose input/output port that the user will connect then to physical or to other software input/output ports. So the idea of opening a midi input device (MidiInput::openDevice … thinking this as attaching application to a “physical” device) is trivial, as we see more like a “my application will publish an input port… don’t know where the user will attach this to, physical or not… but please, create an input device for him so he can plug this application to whatever he wants!”

so the iterateDevice would not check for already existent devices to attach to, it will just publish a new sequencer client to the alsa_seq:
something like this:

static snd_seq_t* createDevicesForThisApplication (const bool forInput,
                                  StringArray& deviceNamesFound,
                                  const int /*deviceIndexToOpen*/)
    snd_seq_t* returnedHandle = 0;
    snd_seq_t* seqHandle;

    if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
                                                      : SND_SEQ_OPEN_OUTPUT, 0) == 0)
                deviceNamesFound.add ("JuceMidi");

                snd_seq_set_client_name (seqHandle,
                                         forInput ? "Juce Midi Input"
                                                  : "Juce Midi Output");
                 snd_seq_create_simple_port (seqHandle,
                                                    forInput ? "Juce Midi In Port"
                                                             : "Juce Midi Out Port",
                                                    forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
                                                             : (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
                                                    forInput ? SND_SEQ_PORT_TYPE_APPLICATION
                                                             : SND_SEQ_PORT_TYPE_MIDI_GENERIC);

                returnedHandle = seqHandle;

        if (returnedHandle == 0)
            snd_seq_close (seqHandle);

    return returnedHandle;


Cool. Cheers for the fix, kraken!