Fix WinMME midi driver shutdown with sysex enabled
authorTim Mayberry <mojofunk@gmail.com>
Tue, 6 Oct 2015 03:24:53 +0000 (13:24 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Tue, 6 Oct 2015 03:29:57 +0000 (13:29 +1000)
midiInReset triggers the sysex callback to tell the application that it has
finished with the buffer. Calling midiInAddBuffer results in an infinite loop
so just return during shutdown.

libs/backends/portaudio/winmmemidi_input_device.cc
libs/backends/portaudio/winmmemidi_input_device.h

index 9fcee83efb4aa9dec47926bd1068f693f47f1b31..ed8f23b45ed89687fa3b9bf0944d0539f5a10d9b 100644 (file)
@@ -37,6 +37,7 @@ namespace ARDOUR {
 WinMMEMidiInputDevice::WinMMEMidiInputDevice (int index)
        : m_handle(0)
        , m_started(false)
+       , m_in_reset(false)
        , m_midi_buffer(new RingBuffer<uint8_t>(MIDI_BUFFER_SIZE))
        , m_sysex_buffer(new uint8_t[SYSEX_BUFFER_SIZE])
 {
@@ -92,12 +93,14 @@ WinMMEMidiInputDevice::close (std::string& error_msg)
        // return error message for first error encountered?
        bool success = true;
 
+       m_in_reset = true;
        MMRESULT result = midiInReset (m_handle);
        if (result != MMSYSERR_NOERROR) {
                error_msg = get_error_string (result);
                DEBUG_MIDI (error_msg);
                success = false;
        }
+       m_in_reset = false;
        result = midiInUnprepareHeader (m_handle, &m_sysex_header, sizeof(MIDIHDR));
        if (result != MMSYSERR_NOERROR) {
                error_msg = get_error_string (result);
@@ -258,12 +261,19 @@ WinMMEMidiInputDevice::handle_sysex_msg (MIDIHDR* const midi_header,
 
        uint8_t* data = (uint8_t*)header->lpData;
 
-       if ((data[0] != 0xf0) || (data[byte_count - 1] != 0xf7)) {
-               DEBUG_MIDI (string_compose ("Discarding %1 byte sysex chunk\n", byte_count));
+       DEBUG_MIDI(string_compose("WinMME sysex flags: %1\n", header->dwFlags));
+
+       if (m_in_reset) {
+               DEBUG_MIDI(string_compose("Midi device %1 being reset ignoring sysex msg\n",
+                                         name()));
+               return;
+       } else if ((data[0] != 0xf0) || (data[byte_count - 1] != 0xf7)) {
+               DEBUG_MIDI(string_compose("Discarding %1 byte sysex chunk\n", byte_count));
        } else {
                enqueue_midi_msg (data, byte_count, timestamp);
        }
 
+
        MMRESULT result = midiInAddBuffer (m_handle, &m_sysex_header, sizeof(MIDIHDR));
        if (result != MMSYSERR_NOERROR) {
                DEBUG_MIDI (get_error_string (result));
index b1a7fb6b88e894b3dc28896787d247f4f4bf0f10..06b8202f43c25e76ccbbe234d1fc8809ae43b5fc 100644 (file)
@@ -91,6 +91,7 @@ private: // data
        MIDIHDR m_sysex_header;
 
        bool m_started;
+       bool m_in_reset;
 
        std::string m_name;