|
|
|
@@ -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;
|
|
|
|
|