From 9a7e70ced3a68b9ac6041a0f1e74ab67042ff1f8 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 6 Mar 2025 18:09:54 +0000 Subject: [PATCH] MIDI: Get rid of InputHandler types that are no longer required --- .../juce_audio_devices/juce_audio_devices.cpp | 2 - .../ump/juce_UMPBytestreamInputHandler.h | 151 ---------------- .../midi_io/ump/juce_UMPU32InputHandler.h | 162 ------------------ .../native/juce_CoreMidi_mac.mm | 91 +++++----- 4 files changed, 50 insertions(+), 356 deletions(-) delete mode 100644 modules/juce_audio_devices/midi_io/ump/juce_UMPBytestreamInputHandler.h delete mode 100644 modules/juce_audio_devices/midi_io/ump/juce_UMPU32InputHandler.h diff --git a/modules/juce_audio_devices/juce_audio_devices.cpp b/modules/juce_audio_devices/juce_audio_devices.cpp index 433c48af8b..4252a8fdf5 100644 --- a/modules/juce_audio_devices/juce_audio_devices.cpp +++ b/modules/juce_audio_devices/juce_audio_devices.cpp @@ -66,8 +66,6 @@ #include #include #include - #include "midi_io/ump/juce_UMPBytestreamInputHandler.h" - #include "midi_io/ump/juce_UMPU32InputHandler.h" #endif #if JUCE_MAC diff --git a/modules/juce_audio_devices/midi_io/ump/juce_UMPBytestreamInputHandler.h b/modules/juce_audio_devices/midi_io/ump/juce_UMPBytestreamInputHandler.h deleted file mode 100644 index 97fa76f823..0000000000 --- a/modules/juce_audio_devices/midi_io/ump/juce_UMPBytestreamInputHandler.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE framework. - Copyright (c) Raw Material Software Limited - - JUCE is an open source framework subject to commercial or open source - licensing. - - By downloading, installing, or using the JUCE framework, or combining the - JUCE framework with any other source code, object code, content or any other - copyrightable work, you agree to the terms of the JUCE End User Licence - Agreement, and all incorporated terms including the JUCE Privacy Policy and - the JUCE Website Terms of Service, as applicable, which will bind you. If you - do not agree to the terms of these agreements, we will not license the JUCE - framework to you, and you must discontinue the installation or download - process and cease use of the JUCE framework. - - JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/ - JUCE Privacy Policy: https://juce.com/juce-privacy-policy - JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/ - - Or: - - You may also use this code under the terms of the AGPLv3: - https://www.gnu.org/licenses/agpl-3.0.en.html - - THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL - WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. - - ============================================================================== -*/ - -/** @cond */ -namespace juce::universal_midi_packets -{ - -/** - A base class for classes which convert bytestream midi to other formats. - - @tags{Audio} -*/ -struct BytestreamInputHandler -{ - virtual ~BytestreamInputHandler() noexcept = default; - - virtual void reset() = 0; - virtual void pushMidiData (const void* data, int bytes, double time) = 0; -}; - -/** - Parses a continuous bytestream and emits complete MidiMessages whenever a full - message is received. - - @tags{Audio} -*/ -struct BytestreamToBytestreamHandler : public BytestreamInputHandler -{ - BytestreamToBytestreamHandler (MidiInput& i, MidiInputCallback& c) - : input (i), callback (c), concatenator (2048) {} - - /** - Provides an `operator()` which can create an input handler for a given - MidiInput. - - All handler classes should have a similar Factory to facilitate - creation of handlers in generic contexts. - */ - class Factory - { - public: - explicit Factory (MidiInputCallback* c) - : callback (c) {} - - std::unique_ptr operator() (MidiInput& i) const - { - if (callback != nullptr) - return std::make_unique (i, *callback); - - jassertfalse; - return {}; - } - - private: - MidiInputCallback* callback = nullptr; - }; - - void reset() override { concatenator.reset(); } - - void pushMidiData (const void* data, int bytes, double time) override - { - concatenator.pushMidiData (data, bytes, time, &input, callback); - } - - MidiInput& input; - MidiInputCallback& callback; - MidiDataConcatenator concatenator; -}; - -/** - Parses a continuous MIDI 1.0 bytestream, and emits full messages in the requested - UMP format. - - @tags{Audio} -*/ -struct BytestreamToUMPHandler : public BytestreamInputHandler -{ - BytestreamToUMPHandler (PacketProtocol protocol, Receiver& c) - : recipient (c), dispatcher (0, protocol, 2048) {} - - /** - Provides an `operator()` which can create an input handler for a given - MidiInput. - - All handler classes should have a similar Factory to facilitate - creation of handlers in generic contexts. - */ - class Factory - { - public: - Factory (PacketProtocol p, Receiver& c) - : protocol (p), callback (c) {} - - std::unique_ptr operator() (MidiInput&) const - { - return std::make_unique (protocol, callback); - } - - private: - PacketProtocol protocol; - Receiver& callback; - }; - - void reset() override { dispatcher.reset(); } - - void pushMidiData (const void* data, int bytes, double time) override - { - const auto* ptr = static_cast (data); - dispatcher.dispatch (Span { ptr, (size_t) bytes }, time, [&] (const View& v, double t) - { - recipient.packetReceived (v, t); - }); - } - - Receiver& recipient; - BytestreamToUMPDispatcher dispatcher; -}; - -} // juce::universal_midi_packets -/** @endcond */ diff --git a/modules/juce_audio_devices/midi_io/ump/juce_UMPU32InputHandler.h b/modules/juce_audio_devices/midi_io/ump/juce_UMPU32InputHandler.h deleted file mode 100644 index a7b4b1cf60..0000000000 --- a/modules/juce_audio_devices/midi_io/ump/juce_UMPU32InputHandler.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE framework. - Copyright (c) Raw Material Software Limited - - JUCE is an open source framework subject to commercial or open source - licensing. - - By downloading, installing, or using the JUCE framework, or combining the - JUCE framework with any other source code, object code, content or any other - copyrightable work, you agree to the terms of the JUCE End User Licence - Agreement, and all incorporated terms including the JUCE Privacy Policy and - the JUCE Website Terms of Service, as applicable, which will bind you. If you - do not agree to the terms of these agreements, we will not license the JUCE - framework to you, and you must discontinue the installation or download - process and cease use of the JUCE framework. - - JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/ - JUCE Privacy Policy: https://juce.com/juce-privacy-policy - JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/ - - Or: - - You may also use this code under the terms of the AGPLv3: - https://www.gnu.org/licenses/agpl-3.0.en.html - - THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL - WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. - - ============================================================================== -*/ - -/** @cond */ -namespace juce::universal_midi_packets -{ - -/** - A base class for classes which convert Universal MIDI Packets to other - formats. - - @tags{Audio} -*/ -struct U32InputHandler -{ - virtual ~U32InputHandler() noexcept = default; - - virtual void reset() = 0; - virtual void pushMidiData (Span, double time) = 0; -}; - -/** - Parses a continuous stream of U32 words and emits complete MidiMessages whenever a full - message is received. - - @tags{Audio} -*/ -struct U32ToBytestreamHandler : public U32InputHandler -{ - U32ToBytestreamHandler (MidiInput& i, MidiInputCallback& c) - : input (i), callback (c), dispatcher (2048) {} - - /** - Provides an `operator()` which can create an input handler for a given - MidiInput. - - All handler classes should have a similar Factory to facilitate - creation of handlers in generic contexts. - */ - class Factory - { - public: - explicit Factory (MidiInputCallback* c) - : callback (c) {} - - std::unique_ptr operator() (MidiInput& i) const - { - if (callback != nullptr) - return std::make_unique (i, *callback); - - jassertfalse; - return {}; - } - - private: - MidiInputCallback* callback = nullptr; - }; - - void reset() override { dispatcher.reset(); } - - void pushMidiData (Span words, double time) override - { - dispatcher.dispatch (words, time, [&] (const BytesOnGroup& roundTripped, double t) - { - callback.handleIncomingMidiMessage (&input, MidiMessage { roundTripped.bytes.data(), (int) roundTripped.bytes.size(), t }); - }); - } - - MidiInput& input; - MidiInputCallback& callback; - ToBytestreamDispatcher dispatcher; -}; - -/** - Parses a continuous stream of U32 words and emits full messages in the requested - UMP format. - - @tags{Audio} -*/ -struct U32ToUMPHandler : public U32InputHandler -{ - U32ToUMPHandler (PacketProtocol protocol, Receiver& c) - : recipient (c), converter (protocol) {} - - /** - Provides an `operator()` which can create an input handler for a given - MidiInput. - - All handler classes should have a similar Factory to facilitate - creation of handlers in generic contexts. - */ - class Factory - { - public: - Factory (PacketProtocol p, Receiver& c) - : protocol (p), callback (c) {} - - std::unique_ptr operator() (MidiInput&) const - { - return std::make_unique (protocol, callback); - } - - private: - PacketProtocol protocol; - Receiver& callback; - }; - - void reset() override - { - dispatcher.reset(); - converter.reset(); - } - - void pushMidiData (Span words, double time) override - { - dispatcher.dispatch (words, time, [this] (const View& view, double thisTime) - { - converter.convert (view, [&] (const View& converted) - { - recipient.packetReceived (converted, thisTime); - }); - }); - } - - Receiver& recipient; - Dispatcher dispatcher; - GenericUMPConverter converter; -}; - -} // namespace juce::universal_midi_packets -/** @endcond */ diff --git a/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm b/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm index 57afb1d11c..6d6a441dc3 100644 --- a/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm +++ b/modules/juce_audio_devices/native/juce_CoreMidi_mac.mm @@ -41,6 +41,12 @@ namespace juce namespace CoreMidiHelpers { + struct Consumer + { + virtual ~Consumer() = default; + virtual void consume (ump::Iterator, ump::Iterator, double) = 0; + }; + static bool checkError (OSStatus err, [[maybe_unused]] int lineNum) { if (err == noErr) @@ -627,12 +633,8 @@ namespace CoreMidiHelpers template <> struct Receiver { - Receiver (ump::PacketProtocol protocol, ump::Receiver& receiver) - : u32InputHandler (std::make_unique (protocol, receiver)) - {} - - Receiver (MidiInput& input, MidiInputCallback& callback) - : u32InputHandler (std::make_unique (input, callback)) + explicit Receiver (Consumer& cb) + : callback (cb) {} void dispatch (const MIDIEventList* list, double time) const @@ -644,45 +646,49 @@ namespace CoreMidiHelpers static_assert (sizeof (uint32_t) == sizeof (UInt32) && alignof (uint32_t) == alignof (UInt32), "If this fails, the cast below will be broken too!"); - u32InputHandler->pushMidiData ({ reinterpret_cast (packet->words), - (size_t) packet->wordCount }, - time); + + callback.consume (ump::Iterator { packet->words, packet->wordCount }, + ump::Iterator { packet->words + packet->wordCount, 0 }, + time); packet = MIDIEventPacketNext (packet); } } private: - std::unique_ptr u32InputHandler; + Consumer& callback; }; #if JUCE_HAS_OLD_COREMIDI_API template <> struct Receiver { - Receiver (ump::PacketProtocol protocol, ump::Receiver& receiver) - : bytestreamInputHandler (std::make_unique (protocol, receiver)) - {} + explicit Receiver (Consumer& cb) + : dispatcher (0, ump::PacketProtocol::MIDI_1_0, 4096), callback (cb) {} - Receiver (MidiInput& input, MidiInputCallback& callback) - : bytestreamInputHandler (std::make_unique (input, callback)) - {} - - void dispatch (const MIDIPacketList* list, double time) const + void dispatch (const MIDIPacketList* list, double time) { auto* packet = list->packet; for (unsigned int i = 0; i < list->numPackets; ++i) { - auto len = readUnalignedlength)> (&(packet->length)); - bytestreamInputHandler->pushMidiData (packet->data, len, time); + const auto* bytes = unalignedPointerCast (packet->data); + const auto len = readUnalignedlength)> (&(packet->length)); + + dispatcher.dispatch (Span (bytes, len), time, [this] (const ump::View& v, double t) + { + ump::Iterator b { v.data(), v.size() }; + auto e = std::next (b); + callback.consume (b, e, t); + }); packet = MIDIPacketNext (packet); } } private: - std::unique_ptr bytestreamInputHandler; + ump::BytestreamToUMPDispatcher dispatcher; + Consumer& callback; }; #endif @@ -690,20 +696,16 @@ namespace CoreMidiHelpers template <> struct Receiver { - Receiver (ump::PacketProtocol protocol, ump::Receiver& receiver) - : newReceiver (protocol, receiver), oldReceiver (protocol, receiver) + explicit Receiver (Consumer& cb) + : newReceiver (cb), oldReceiver (cb) {} - Receiver (MidiInput& input, MidiInputCallback& callback) - : newReceiver (input, callback), oldReceiver (input, callback) - {} - - void dispatch (const MIDIEventList* list, double time) const + void dispatch (const MIDIEventList* list, double time) { newReceiver.dispatch (list, time); } - void dispatch (const MIDIPacketList* list, double time) const + void dispatch (const MIDIPacketList* list, double time) { oldReceiver.dispatch (list, time); } @@ -720,14 +722,14 @@ namespace CoreMidiHelpers CriticalSection callbackLock; Array activeCallbacks; - class MidiPortAndCallback + class MidiPortAndCallback : private Consumer { public: - MidiPortAndCallback (MidiInput& inputIn, ReceiverToUse receiverIn) - : input (&inputIn), receiver (std::move (receiverIn)) + MidiPortAndCallback (MidiInput& inputIn, MidiInputCallback& cb) + : input (&inputIn), callback (cb), receiver (*this) {} - ~MidiPortAndCallback() + ~MidiPortAndCallback() override { active = false; @@ -752,6 +754,7 @@ namespace CoreMidiHelpers } MidiInput* input = nullptr; + MidiInputCallback& callback; std::atomic active { false }; ReceiverToUse receiver; @@ -759,6 +762,19 @@ namespace CoreMidiHelpers std::unique_ptr portAndEndpoint; private: + void consume (ump::Iterator b, ump::Iterator e, double t) override + { + for (auto view : makeRange (b, e)) + { + bytestreamConverter.convert (view, t, [this] (ump::BytesOnGroup x, double time) + { + callback.handleIncomingMidiMessage (input, { x.bytes.data(), (int) x.bytes.size(), time }); + }); + } + } + + ump::ToBytestreamConverter bytestreamConverter { 2048 }; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiPortAndCallback) }; @@ -954,20 +970,13 @@ class MidiInput::Pimpl : public CoreMidiHelpers::MidiPortAndCallback public: using MidiPortAndCallback::MidiPortAndCallback; - static std::unique_ptr makePimpl (MidiInput& midiInput, - ump::PacketProtocol packetProtocol, - ump::Receiver& umpReceiver) - { - return std::make_unique (midiInput, CoreMidiHelpers::ReceiverToUse (packetProtocol, umpReceiver)); - } - static std::unique_ptr makePimpl (MidiInput& midiInput, MidiInputCallback* midiInputCallback) { if (midiInputCallback == nullptr) return {}; - return std::make_unique (midiInput, CoreMidiHelpers::ReceiverToUse (midiInput, *midiInputCallback)); + return std::make_unique (midiInput, *midiInputCallback); } template