From fd69d347b47889041176f9f75769fbe1fc4e9127 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 1 Mar 2023 17:12:12 +0000 Subject: [PATCH] CoreMidi: Never convert messages to MIDI 2.0 protocol --- .../midi/ump/juce_UMPConverters.h | 47 +++++++++---- .../native/juce_mac_CoreMidi.mm | 70 ++++++------------- 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/modules/juce_audio_basics/midi/ump/juce_UMPConverters.h b/modules/juce_audio_basics/midi/ump/juce_UMPConverters.h index 22ed3b563a..8f51f13af7 100644 --- a/modules/juce_audio_basics/midi/ump/juce_UMPConverters.h +++ b/modules/juce_audio_basics/midi/ump/juce_UMPConverters.h @@ -88,6 +88,15 @@ namespace universal_midi_packets */ class GenericUMPConverter { + template + static void visit (This& t, Args&&... args) + { + if (t.mode == PacketProtocol::MIDI_1_0) + convertImpl (std::get<0> (t.converters), std::forward (args)...); + else + convertImpl (std::get<1> (t.converters), std::forward (args)...); + } + public: explicit GenericUMPConverter (PacketProtocol m) : mode (m) {} @@ -97,33 +106,43 @@ namespace universal_midi_packets std::get<1> (converters).reset(); } + template + static void convertImpl (Converter& converter, const BytestreamMidiView& m, Fn&& fn) + { + converter.convert (m, std::forward (fn)); + } + + template + static void convertImpl (Converter& converter, const View& m, Fn&& fn) + { + converter.convert (m, std::forward (fn)); + } + + template + static void convertImpl (Converter& converter, Iterator b, Iterator e, Fn&& fn) + { + std::for_each (b, e, [&] (const auto& v) + { + convertImpl (converter, v, fn); + }); + } + template void convert (const BytestreamMidiView& m, Fn&& fn) { - switch (mode) - { - case PacketProtocol::MIDI_1_0: return std::get<0> (converters).convert (m, std::forward (fn)); - case PacketProtocol::MIDI_2_0: return std::get<1> (converters).convert (m, std::forward (fn)); - } + visit (*this, m, std::forward (fn)); } template void convert (const View& v, Fn&& fn) { - switch (mode) - { - case PacketProtocol::MIDI_1_0: return std::get<0> (converters).convert (v, std::forward (fn)); - case PacketProtocol::MIDI_2_0: return std::get<1> (converters).convert (v, std::forward (fn)); - } + visit (*this, v, std::forward (fn)); } template void convert (Iterator begin, Iterator end, Fn&& fn) { - std::for_each (begin, end, [&] (const View& v) - { - convert (v, fn); - }); + visit (*this, begin, end, std::forward (fn)); } PacketProtocol getProtocol() const noexcept { return mode; } diff --git a/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm b/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm index fc5ffa050d..490026719e 100644 --- a/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm +++ b/modules/juce_audio_devices/native/juce_mac_CoreMidi.mm @@ -73,8 +73,6 @@ namespace CoreMidiHelpers virtual void send (MIDIPortRef port, MIDIEndpointRef endpoint, const ump::BytestreamMidiView& m) = 0; virtual void send (MIDIPortRef port, MIDIEndpointRef endpoint, ump::Iterator b, ump::Iterator e) = 0; - - virtual ump::MidiProtocol getProtocol() const noexcept = 0; }; template @@ -84,10 +82,6 @@ namespace CoreMidiHelpers template <> struct API_AVAILABLE (macos (11.0), ios (14.0)) Sender : public SenderBase { - explicit Sender (MIDIEndpointRef ep) - : umpConverter (getProtocolForEndpoint (ep)) - {} - void send (MIDIPortRef port, MIDIEndpointRef endpoint, const ump::BytestreamMidiView& m) override { newSendImpl (port, endpoint, m); @@ -98,14 +92,8 @@ namespace CoreMidiHelpers newSendImpl (port, endpoint, b, e); } - ump::MidiProtocol getProtocol() const noexcept override - { - return umpConverter.getProtocol() == ump::PacketProtocol::MIDI_2_0 ? ump::MidiProtocol::UMP_MIDI_2_0 - : ump::MidiProtocol::UMP_MIDI_1_0; - } - private: - ump::GenericUMPConverter umpConverter; + ump::ToUMP1Converter umpConverter; static ump::PacketProtocol getProtocolForEndpoint (MIDIEndpointRef ep) noexcept { @@ -119,9 +107,6 @@ namespace CoreMidiHelpers template void newSendImpl (MIDIPortRef port, MIDIEndpointRef endpoint, Params&&... params) { - // The converter protocol got out-of-sync with the device protocol - jassert (getProtocolForEndpoint (endpoint) == umpConverter.getProtocol()); - #if JUCE_IOS const MIDITimeStamp timeStamp = mach_absolute_time(); #else @@ -133,9 +118,10 @@ namespace CoreMidiHelpers const auto init = [&] { - end = MIDIEventListInit (&stackList, - umpConverter.getProtocol() == ump::PacketProtocol::MIDI_2_0 ? kMIDIProtocol_2_0 - : kMIDIProtocol_1_0); + // At the moment, we can only send MIDI 1.0 protocol. If the device is using MIDI + // 2.0 protocol (as may be the case for the IAC driver), we trust in the system to + // translate it. + end = MIDIEventListInit (&stackList, kMIDIProtocol_1_0); }; const auto send = [&] @@ -159,16 +145,19 @@ namespace CoreMidiHelpers init(); - umpConverter.convert (params..., [&] (const ump::View& view) + ump::GenericUMPConverter::convertImpl (umpConverter, params..., [&] (const auto& v) { - add (view); + umpConverter.convert (v, [&] (const ump::View& view) + { + add (view); - if (end != nullptr) - return; + if (end != nullptr) + return; - send(); - init(); - add (view); + send(); + init(); + add (view); + }); }); send(); @@ -180,8 +169,6 @@ namespace CoreMidiHelpers template <> struct Sender : public SenderBase { - explicit Sender (MIDIEndpointRef) {} - void send (MIDIPortRef port, MIDIEndpointRef endpoint, const ump::BytestreamMidiView& m) override { oldSendImpl (port, endpoint, m); @@ -198,11 +185,6 @@ namespace CoreMidiHelpers }); } - ump::MidiProtocol getProtocol() const noexcept override - { - return ump::MidiProtocol::bytestream; - } - private: ump::ToBytestreamConverter bytestreamConverter { 2048 }; @@ -274,8 +256,8 @@ namespace CoreMidiHelpers template <> struct Sender { - explicit Sender (MIDIEndpointRef ep) - : sender (makeImpl (ep)) + Sender() + : sender (makeImpl()) {} void send (MIDIPortRef port, MIDIEndpointRef endpoint, const ump::BytestreamMidiView& m) @@ -288,18 +270,13 @@ namespace CoreMidiHelpers sender->send (port, endpoint, b, e); } - ump::MidiProtocol getProtocol() const noexcept - { - return sender->getProtocol(); - } - private: - static std::unique_ptr makeImpl (MIDIEndpointRef ep) + static std::unique_ptr makeImpl() { if (@available (macOS 11, iOS 14, *)) - return std::make_unique> (ep); + return std::make_unique>(); - return std::make_unique> (ep); + return std::make_unique>(); } std::unique_ptr sender; @@ -369,7 +346,7 @@ namespace CoreMidiHelpers { public: MidiPortAndEndpoint (ScopedPortRef p, ScopedEndpointRef ep) noexcept - : port (std::move (p)), endpoint (std::move (ep)), sender (*endpoint) + : port (std::move (p)), endpoint (std::move (ep)) {} ~MidiPortAndEndpoint() noexcept @@ -392,11 +369,6 @@ namespace CoreMidiHelpers bool canStop() const noexcept { return *port != 0; } void stop() const { CHECK_ERROR (MIDIPortDisconnectSource (*port, *endpoint)); } - ump::MidiProtocol getProtocol() const noexcept - { - return sender.getProtocol(); - } - private: ScopedPortRef port; ScopedEndpointRef endpoint;