Browse Source

CoreMidi: Never convert messages to MIDI 2.0 protocol

v7.0.9
reuk 2 years ago
parent
commit
fd69d347b4
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
2 changed files with 54 additions and 63 deletions
  1. +33
    -14
      modules/juce_audio_basics/midi/ump/juce_UMPConverters.h
  2. +21
    -49
      modules/juce_audio_devices/native/juce_mac_CoreMidi.mm

+ 33
- 14
modules/juce_audio_basics/midi/ump/juce_UMPConverters.h View File

@@ -88,6 +88,15 @@ namespace universal_midi_packets
*/
class GenericUMPConverter
{
template <typename This, typename... Args>
static void visit (This& t, Args&&... args)
{
if (t.mode == PacketProtocol::MIDI_1_0)
convertImpl (std::get<0> (t.converters), std::forward<Args> (args)...);
else
convertImpl (std::get<1> (t.converters), std::forward<Args> (args)...);
}
public:
explicit GenericUMPConverter (PacketProtocol m)
: mode (m) {}
@@ -97,33 +106,43 @@ namespace universal_midi_packets
std::get<1> (converters).reset();
}
template <typename Converter, typename Fn>
static void convertImpl (Converter& converter, const BytestreamMidiView& m, Fn&& fn)
{
converter.convert (m, std::forward<Fn> (fn));
}
template <typename Converter, typename Fn>
static void convertImpl (Converter& converter, const View& m, Fn&& fn)
{
converter.convert (m, std::forward<Fn> (fn));
}
template <typename Converter, typename Fn>
static void convertImpl (Converter& converter, Iterator b, Iterator e, Fn&& fn)
{
std::for_each (b, e, [&] (const auto& v)
{
convertImpl (converter, v, fn);
});
}
template <typename Fn>
void convert (const BytestreamMidiView& m, Fn&& fn)
{
switch (mode)
{
case PacketProtocol::MIDI_1_0: return std::get<0> (converters).convert (m, std::forward<Fn> (fn));
case PacketProtocol::MIDI_2_0: return std::get<1> (converters).convert (m, std::forward<Fn> (fn));
}
visit (*this, m, std::forward<Fn> (fn));
}
template <typename Fn>
void convert (const View& v, Fn&& fn)
{
switch (mode)
{
case PacketProtocol::MIDI_1_0: return std::get<0> (converters).convert (v, std::forward<Fn> (fn));
case PacketProtocol::MIDI_2_0: return std::get<1> (converters).convert (v, std::forward<Fn> (fn));
}
visit (*this, v, std::forward<Fn> (fn));
}
template <typename Fn>
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> (fn));
}
PacketProtocol getProtocol() const noexcept { return mode; }


+ 21
- 49
modules/juce_audio_devices/native/juce_mac_CoreMidi.mm View File

@@ -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 <ImplementationStrategy>
@@ -84,10 +82,6 @@ namespace CoreMidiHelpers
template <>
struct API_AVAILABLE (macos (11.0), ios (14.0)) Sender<ImplementationStrategy::onlyNew> : 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 <typename... Params>
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<ImplementationStrategy::onlyOld> : 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<ImplementationStrategy::both>
{
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<SenderBase> makeImpl (MIDIEndpointRef ep)
static std::unique_ptr<SenderBase> makeImpl()
{
if (@available (macOS 11, iOS 14, *))
return std::make_unique<Sender<ImplementationStrategy::onlyNew>> (ep);
return std::make_unique<Sender<ImplementationStrategy::onlyNew>>();
return std::make_unique<Sender<ImplementationStrategy::onlyOld>> (ep);
return std::make_unique<Sender<ImplementationStrategy::onlyOld>>();
}
std::unique_ptr<SenderBase> 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;


Loading…
Cancel
Save