From fee9063a5dc3e53d6dfe96dba0330f7786b70822 Mon Sep 17 00:00:00 2001
From: Qfactor <xxx@xxx.com>
Date: Wed, 9 Aug 2023 18:03:23 +0200
Subject: [PATCH] Make sendMessageNow(const MidiMessage&) return false if it
 can't send the message

---
 .../midi_io/juce_MidiDevices.h                |  2 +-
 .../native/juce_android_Midi.cpp              |  4 ++-
 .../native/juce_linux_Bela.cpp                |  2 +-
 .../native/juce_linux_Midi.cpp                |  6 ++--
 .../native/juce_mac_CoreMidi.mm               | 19 +++++-----
 .../native/juce_win32_Midi.cpp                | 35 ++++++++++++-------
 6 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/modules/juce_audio_devices/midi_io/juce_MidiDevices.h b/modules/juce_audio_devices/midi_io/juce_MidiDevices.h
index 5dab3f925..d07dd5142 100644
--- a/modules/juce_audio_devices/midi_io/juce_MidiDevices.h
+++ b/modules/juce_audio_devices/midi_io/juce_MidiDevices.h
@@ -301,7 +301,7 @@ public:
 
     //==============================================================================
     /** Sends out a MIDI message immediately. */
-    void sendMessageNow (const MidiMessage& message);
+    bool sendMessageNow (const MidiMessage& message);
 
     /** Sends out a sequence of MIDI messages immediately. */
     void sendBlockOfMessagesNow (const MidiBuffer& buffer);
diff --git a/modules/juce_audio_devices/native/juce_android_Midi.cpp b/modules/juce_audio_devices/native/juce_android_Midi.cpp
index 08825325c..437a5daac 100644
--- a/modules/juce_audio_devices/native/juce_android_Midi.cpp
+++ b/modules/juce_audio_devices/native/juce_android_Midi.cpp
@@ -680,7 +680,7 @@ MidiOutput::~MidiOutput()
     stopBackgroundThread();
 }
 
-void MidiOutput::sendMessageNow (const MidiMessage& message)
+bool MidiOutput::sendMessageNow (const MidiMessage& message)
 {
     if (auto* androidMidi = internal.get())
     {
@@ -695,7 +695,9 @@ void MidiOutput::sendMessageNow (const MidiMessage& message)
         env->ReleaseByteArrayElements (content, rawBytes, 0);
 
         androidMidi->send (content, (jint) 0, (jint) messageSize);
+        return true;
     }
+    return false;
 }
 
 } // namespace juce
diff --git a/modules/juce_audio_devices/native/juce_linux_Bela.cpp b/modules/juce_audio_devices/native/juce_linux_Bela.cpp
index bf1ff16f3..e00dde7d2 100644
--- a/modules/juce_audio_devices/native/juce_linux_Bela.cpp
+++ b/modules/juce_audio_devices/native/juce_linux_Bela.cpp
@@ -588,7 +588,7 @@ std::unique_ptr<MidiInput> MidiInput::openDevice (int index, MidiInputCallback*
 // TODO: Add Bela MidiOutput support
 class MidiOutput::Pimpl {};
 MidiOutput::~MidiOutput() = default;
-void MidiOutput::sendMessageNow (const MidiMessage&)                     {}
+bool MidiOutput::sendMessageNow (const MidiMessage&)                     {}
 Array<MidiDeviceInfo> MidiOutput::getAvailableDevices()                  { return {}; }
 MidiDeviceInfo MidiOutput::getDefaultDevice()                            { return {}; }
 std::unique_ptr<MidiOutput> MidiOutput::openDevice (const String&)       { return {}; }
diff --git a/modules/juce_audio_devices/native/juce_linux_Midi.cpp b/modules/juce_audio_devices/native/juce_linux_Midi.cpp
index 3f87c27d0..65ddf6f50 100644
--- a/modules/juce_audio_devices/native/juce_linux_Midi.cpp
+++ b/modules/juce_audio_devices/native/juce_linux_Midi.cpp
@@ -654,9 +654,9 @@ MidiOutput::~MidiOutput()
     stopBackgroundThread();
 }
 
-void MidiOutput::sendMessageNow (const MidiMessage& message)
+bool MidiOutput::sendMessageNow (const MidiMessage& message)
 {
-    internal->ptr->sendMessageNow (message);
+    return internal->ptr->sendMessageNow (message);
 }
 
 //==============================================================================
@@ -684,7 +684,7 @@ std::unique_ptr<MidiInput> MidiInput::openDevice (int, MidiInputCallback*)
 class MidiOutput::Pimpl {};
 
 MidiOutput::~MidiOutput()                                                                 {}
-void MidiOutput::sendMessageNow (const MidiMessage&)                                      {}
+bool MidiOutput::sendMessageNow (const MidiMessage&)                                      {}
 Array<MidiDeviceInfo> MidiOutput::getAvailableDevices()                                   { return {}; }
 MidiDeviceInfo MidiOutput::getDefaultDevice()                                             { return {}; }
 std::unique_ptr<MidiOutput> MidiOutput::openDevice (const String&)                        { return {}; }
diff --git a/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm b/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm
index fd61986e7..d3a70615b 100644
--- a/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm
+++ b/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm
@@ -71,8 +71,8 @@ namespace CoreMidiHelpers
     {
         virtual ~SenderBase() noexcept = default;
 
-        virtual void send (MIDIPortRef port, MIDIEndpointRef endpoint, const MidiMessage& m) = 0;
-        virtual void send (MIDIPortRef port, MIDIEndpointRef endpoint, ump::Iterator b, ump::Iterator e) = 0;
+        virtual bool send (MIDIPortRef port, MIDIEndpointRef endpoint, const MidiMessage& m) = 0;
+        virtual bool send (MIDIPortRef port, MIDIEndpointRef endpoint, ump::Iterator b, ump::Iterator e) = 0;
 
         virtual ump::MidiProtocol getProtocol() const noexcept = 0;
     };
@@ -88,14 +88,14 @@ namespace CoreMidiHelpers
             : umpConverter (getProtocolForEndpoint (ep))
         {}
 
-        void send (MIDIPortRef port, MIDIEndpointRef endpoint, const MidiMessage& m) override
+        bool send (MIDIPortRef port, MIDIEndpointRef endpoint, const MidiMessage& m) override
         {
-            newSendImpl (port, endpoint, m);
+            return newSendImpl (port, endpoint, m);
         }
 
-        void send (MIDIPortRef port, MIDIEndpointRef endpoint, ump::Iterator b, ump::Iterator e) override
+        bool send (MIDIPortRef port, MIDIEndpointRef endpoint, ump::Iterator b, ump::Iterator e) override
         {
-            newSendImpl (port, endpoint, b, e);
+            return newSendImpl (port, endpoint, b, e);
         }
 
         ump::MidiProtocol getProtocol() const noexcept override
@@ -117,7 +117,7 @@ namespace CoreMidiHelpers
         }
 
         template <typename... Params>
-        void newSendImpl (MIDIPortRef port, MIDIEndpointRef endpoint, Params&&... params)
+        bool newSendImpl (MIDIPortRef port, MIDIEndpointRef endpoint, Params&&... params)
         {
             // The converter protocol got out-of-sync with the device protocol
             jassert (getProtocolForEndpoint (endpoint) == umpConverter.getProtocol());
@@ -172,6 +172,7 @@ namespace CoreMidiHelpers
             });
 
             send();
+            return true;
         }
     };
    #endif
@@ -1295,9 +1296,9 @@ MidiOutput::~MidiOutput()
     stopBackgroundThread();
 }
 
-void MidiOutput::sendMessageNow (const MidiMessage& message)
+bool MidiOutput::sendMessageNow (const MidiMessage& message)
 {
-    internal->send (message);
+    return internal->send (message);
 }
 
 #undef CHECK_ERROR
diff --git a/modules/juce_audio_devices/native/juce_win32_Midi.cpp b/modules/juce_audio_devices/native/juce_win32_Midi.cpp
index c2b13f709..706f3e2ab 100644
--- a/modules/juce_audio_devices/native/juce_win32_Midi.cpp
+++ b/modules/juce_audio_devices/native/juce_win32_Midi.cpp
@@ -82,7 +82,7 @@ public:
     virtual String getDeviceIdentifier() = 0;
     virtual String getDeviceName() = 0;
 
-    virtual void sendMessageNow (const MidiMessage&) = 0;
+    virtual bool sendMessageNow (const MidiMessage&) = 0;
 };
 
 struct MidiServiceType
@@ -605,7 +605,7 @@ private:
             throw std::runtime_error ("Failed to create Windows output device wrapper");
         }
 
-        void sendMessageNow (const MidiMessage& message) override
+        bool sendMessageNow (const MidiMessage& message) override
         {
             if (message.getRawDataSize() > 3 || message.isSysEx())
             {
@@ -632,7 +632,7 @@ private:
                             if (res == MIDIERR_STILLPLAYING)
                                 Sleep (2);
                             else
-                                break;
+                                return true;
                         }
                     }
                 }
@@ -641,12 +641,19 @@ private:
             {
                 for (int i = 0; i < 50; ++i)
                 {
-                    if (midiOutShortMsg (han->handle, *unalignedPointerCast<const unsigned int*> (message.getRawData())) != MIDIERR_NOTREADY)
-                        break;
-
-                    Sleep (1);
+                    MMRESULT res = midiOutShortMsg (han->handle, *unalignedPointerCast<const unsigned int*> (message.getRawData()));
+                    if ( res == MMSYSERR_NOERROR )
+                        return true;
+                    else if (res == MIDIERR_NOTREADY) {
+                        Sleep(1);
+                    }
+                    else {
+                        return false;
+                    }
                 }
             }
+
+            return false;
         }
 
         static DWORD sendMidiMessage (UINT_PTR deviceID, UINT msg, DWORD_PTR arg1, DWORD_PTR arg2)
@@ -1787,10 +1794,10 @@ private:
         }
 
         //==============================================================================
-        void sendMessageNow (const MidiMessage& message) override
+        bool sendMessageNow (const MidiMessage& message) override
         {
             if (midiPort == nullptr)
-                return;
+                return false;
 
             auto numBytes = message.getRawDataSize();
             auto hr = buffer->put_Length (numBytes);
@@ -1798,11 +1805,13 @@ private:
             if (FAILED (hr))
             {
                 jassertfalse;
-                return;
+                return false;
             }
 
             memcpy_s (bufferData, numBytes, message.getRawData(), numBytes);
-            midiPort->SendBuffer (buffer);
+            HRESULT res = midiPort->SendBuffer (buffer);
+
+            return SUCCEED(res));
         }
 
         String getDeviceIdentifier() override    { return deviceInfo.containerID; }
@@ -2008,9 +2017,9 @@ MidiOutput::~MidiOutput()
     stopBackgroundThread();
 }
 
-void MidiOutput::sendMessageNow (const MidiMessage& message)
+bool MidiOutput::sendMessageNow (const MidiMessage& message)
 {
-    internal->sendMessageNow (message);
+    return internal->sendMessageNow (message);
 }
 
 } // namespace juce
-- 
2.42.0.windows.2

