1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/modules/juce_midi_ci/detail/juce_CIMessageMeta.h

630 lines
20 KiB
C++

/*
==============================================================================
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.
==============================================================================
*/
/*
Namespace containing metadata about MIDI-CI message types, such as
replies corresponding to inquiries, and serialization functions.
@tags{Audio}
*/
namespace juce::midi_ci::detail::MessageMeta
{
//==============================================================================
/* The maximum CI version that can be parsed and generated by this implementation. */
static constexpr std::byte implementationVersion { 0x02 };
/* Wraps a pointer to a Span. Used to indicate to CI readers/writers that a particular field is
of variable length, starting with a 16-bit or 32-bit byte count.
*/
template <uint8_t NumBytes, typename T, bool isJson = false>
struct SpanWithSizeBytes
{
T& span;
};
/* Creates a SpanWithSizeBytes with an appropriate template argument. */
template <uint8_t NumBytes, typename T>
static constexpr auto makeSpanWithSizeBytes ( Span<T>& span) { return SpanWithSizeBytes<NumBytes, Span<T>> { span }; }
template <uint8_t NumBytes, typename T>
static constexpr auto makeSpanWithSizeBytes (const Span<T>& span) { return SpanWithSizeBytes<NumBytes, const Span<T>> { span }; }
template <uint8_t NumBytes, typename T>
static constexpr auto makeJsonWithSizeBytes ( Span<T>& span) { return SpanWithSizeBytes<NumBytes, Span<T>, true> { span }; }
template <uint8_t NumBytes, typename T>
static constexpr auto makeJsonWithSizeBytes (const Span<T>& span) { return SpanWithSizeBytes<NumBytes, const Span<T>, true> { span }; }
template <uint8_t SubID2, typename R = void>
struct Metadata
{
static constexpr std::byte subID2 { SubID2 };
using Reply = R;
};
template <typename T>
struct Meta;
template <>
struct Meta<Message::DiscoveryResponse> : Metadata<0x71> {};
template <>
struct Meta<Message::Discovery> : Metadata<0x70, Message::DiscoveryResponse> {};
template <>
struct Meta<Message::EndpointInquiryResponse> : Metadata<0x73> {};
template <>
struct Meta<Message::EndpointInquiry> : Metadata<0x72, Message::EndpointInquiryResponse> {};
template <>
struct Meta<Message::InvalidateMUID> : Metadata<0x7e> {};
template <>
struct Meta<Message::ACK> : Metadata<0x7d> {};
template <>
struct Meta<Message::NAK> : Metadata<0x7f> {};
template <>
struct Meta<Message::ProfileInquiryResponse> : Metadata<0x21> {};
template <>
struct Meta<Message::ProfileInquiry> : Metadata<0x20, Message::ProfileInquiryResponse> {};
template <>
struct Meta<Message::ProfileAdded> : Metadata<0x26> {};
template <>
struct Meta<Message::ProfileRemoved> : Metadata<0x27> {};
template <>
struct Meta<Message::ProfileDetailsResponse> : Metadata<0x29> {};
template <>
struct Meta<Message::ProfileDetails> : Metadata<0x28, Message::ProfileDetailsResponse> {};
template <>
struct Meta<Message::ProfileOn> : Metadata<0x22> {};
template <>
struct Meta<Message::ProfileOff> : Metadata<0x23> {};
template <>
struct Meta<Message::ProfileEnabledReport> : Metadata<0x24> {};
template <>
struct Meta<Message::ProfileDisabledReport> : Metadata<0x25> {};
template <>
struct Meta<Message::ProfileSpecificData> : Metadata<0x2f> {};
template <>
struct Meta<Message::PropertyExchangeCapabilitiesResponse> : Metadata<0x31> {};
template <>
struct Meta<Message::PropertyExchangeCapabilities> : Metadata<0x30, Message::PropertyExchangeCapabilitiesResponse> {};
template <>
struct Meta<Message::StaticSizePropertyExchange> {};
template <>
struct Meta<Message::DynamicSizePropertyExchange> {};
template <>
struct Meta<Message::PropertyGetDataResponse> : Meta<Message::DynamicSizePropertyExchange>, Metadata<0x35> {};
template <>
struct Meta<Message::PropertyGetData> : Meta<Message::StaticSizePropertyExchange>, Metadata<0x34, Message::PropertyGetDataResponse> {};
template <>
struct Meta<Message::PropertySetDataResponse> : Meta<Message::StaticSizePropertyExchange>, Metadata<0x37> {};
template <>
struct Meta<Message::PropertySetData> : Meta<Message::DynamicSizePropertyExchange>, Metadata<0x36, Message::PropertySetDataResponse> {};
template <>
struct Meta<Message::PropertySubscribeResponse> : Meta<Message::DynamicSizePropertyExchange>, Metadata<0x39> {};
template <>
struct Meta<Message::PropertySubscribe> : Meta<Message::DynamicSizePropertyExchange>, Metadata<0x38, Message::PropertySubscribeResponse> {};
template <>
struct Meta<Message::PropertyNotify> : Meta<Message::DynamicSizePropertyExchange>, Metadata<0x3f> {};
template <>
struct Meta<Message::ProcessInquiryResponse> : Metadata<0x41> {};
template <>
struct Meta<Message::ProcessInquiry> : Metadata<0x40, Message::ProcessInquiryResponse> {};
template <>
struct Meta<Message::ProcessMidiMessageReportResponse> : Metadata<0x43> {};
template <>
struct Meta<Message::ProcessMidiMessageReport> : Metadata<0x42, Message::ProcessMidiMessageReportResponse> {};
template <>
struct Meta<Message::ProcessEndMidiMessageReport> : Metadata<0x44> {};
} // namespace juce::midi_ci::detail::MessageMeta
/** @cond */
namespace juce
{
struct VersionBase
{
static constexpr auto marshallingVersion = (int) juce::midi_ci::detail::MessageMeta::implementationVersion;
};
template <uint8_t NumBytes, typename T, bool isJson>
struct SerialisationTraits<midi_ci::detail::MessageMeta::SpanWithSizeBytes<NumBytes, T, isJson>>
{
static constexpr auto marshallingVersion = std::nullopt;
template <typename This>
static auto getSize (This& t)
{
if constexpr (NumBytes == 1)
return (uint8_t) t.size();
else if constexpr (NumBytes == 2)
return (uint16_t) t.size();
else if constexpr (NumBytes == 4)
return (uint32_t) t.size();
else if constexpr (NumBytes == 8)
return (uint64_t) t.size();
else
static_assert (detail::delayStaticAssert<T>, "NumBytes is not a power of two");
}
template <typename Archive, typename This>
static auto load (Archive&, This&)
{
}
template <typename Archive, typename This>
static auto save (Archive& archive, const This& t)
{
auto size = getSize (t.span);
archive (serialisationSize (size));
for (const auto& element : t.span)
archive (element);
}
};
template <>
struct SerialisationTraits<ci::MUID> : VersionBase
{
template <typename Archive>
static auto load (Archive& archive, ci::MUID& t)
{
uint32_t muid{};
auto result = archive (muid);
t = ci::MUID::makeUnchecked (muid);
return result;
}
template <typename Archive>
static auto save (Archive& archive, const ci::MUID& t)
{
return archive (t.get());
}
};
template <>
struct SerialisationTraits<ci::Message::Header> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
const std::byte universalSystemExclusive { 0x7e }, subID { 0x0d };
return archive (universalSystemExclusive,
t.deviceID,
subID,
t.category,
t.version,
t.source,
t.destination);
}
};
template <>
struct SerialisationTraits<ci::Message::Generic> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
return archive (t.header, t.data);
}
};
template <>
struct SerialisationTraits<ci::Message::DiscoveryResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("device", t.device),
named ("capabilities", t.capabilities),
named ("maximumSysexSize", t.maximumSysexSize));
if (0x02 <= archive.getVersion())
archive (named ("outputPathID", t.outputPathID), named ("functionBlock", t.functionBlock));
}
};
template <>
struct SerialisationTraits<ci::Message::Discovery> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("device", t.device),
named ("capabilities", t.capabilities),
named ("maximumSysexSize", t.maximumSysexSize));
if (0x02 <= archive.getVersion())
archive (named ("outputPathID", t.outputPathID));
}
};
template <>
struct SerialisationTraits<ci::Message::EndpointInquiryResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("status", t.status),
named ("data", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.data)));
}
};
template <>
struct SerialisationTraits<ci::Message::EndpointInquiry> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("status", t.status));
}
};
template <>
struct SerialisationTraits<ci::Message::InvalidateMUID> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("target", t.target));
}
};
template <>
struct SerialisationTraits<ci::Message::ACK> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("originalCategory", t.originalCategory),
named ("statusCode", t.statusCode),
named ("statusData", t.statusData),
named ("details", t.details),
named ("messageText", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.messageText)));
}
};
template <>
struct SerialisationTraits<ci::Message::NAK> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
if (0x02 <= archive.getVersion())
{
archive (named ("originalCategory", t.originalCategory),
named ("statusCode", t.statusCode),
named ("statusData", t.statusData),
named ("details", t.details),
named ("messageText", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.messageText)));
}
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileInquiryResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("enabledProfiles", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.enabledProfiles)),
named ("disabledProfiles", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.disabledProfiles)));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileInquiry> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive&, This&)
{
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileAdded> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileRemoved> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileDetailsResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile),
named ("target", t.target),
named ("data", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.data)));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileDetails> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile),
named ("target", t.target));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileOn> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
if (0x02 <= archive.getVersion())
archive (named ("numChannels", t.numChannels));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileOff> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
if (0x02 <= archive.getVersion())
{
uint16_t reserved{};
archive (named ("reserved", reserved));
}
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileEnabledReport> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
if (0x02 <= archive.getVersion())
archive (named ("numChannels", t.numChannels));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileDisabledReport> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile));
if (0x02 <= archive.getVersion())
archive (named ("numChannels", t.numChannels));
}
};
template <>
struct SerialisationTraits<ci::Message::ProfileSpecificData> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("profile", t.profile), named ("data", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<4> (t.data)));
}
};
template <>
struct SerialisationTraits<ci::Message::PropertyExchangeCapabilitiesResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("numRequests", t.numSimultaneousRequestsSupported));
if (0x02 <= archive.getVersion())
archive (named ("major", t.majorVersion), named ("minor", t.minorVersion));
}
};
template <>
struct SerialisationTraits<ci::Message::PropertyExchangeCapabilities> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("numRequests", t.numSimultaneousRequestsSupported));
if (0x02 <= archive.getVersion())
archive (named ("major", t.majorVersion), named ("minor", t.minorVersion));
}
};
template <>
struct SerialisationTraits<ci::Message::StaticSizePropertyExchange> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
const uint16_t chunkNum = 1, dataLength = 0;
archive (named ("requestID", t.requestID),
named ("header", midi_ci::detail::MessageMeta::makeJsonWithSizeBytes<2> (t.header)),
named ("numChunks", chunkNum),
named ("thisChunk", chunkNum),
named ("length", dataLength));
}
};
template <>
struct SerialisationTraits<ci::Message::DynamicSizePropertyExchange> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (named ("requestID", t.requestID),
named ("header", midi_ci::detail::MessageMeta::makeJsonWithSizeBytes<2> (t.header)),
named ("numChunks", t.totalNumChunks),
named ("thisChunk", t.thisChunkNum),
named ("data", midi_ci::detail::MessageMeta::makeSpanWithSizeBytes<2> (t.data)));
}
};
template <>
struct SerialisationTraits<ci::Message::PropertyGetDataResponse> : SerialisationTraits<ci::Message::DynamicSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertyGetData> : SerialisationTraits<ci::Message::StaticSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertySetDataResponse> : SerialisationTraits<ci::Message::StaticSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertySetData> : SerialisationTraits<ci::Message::DynamicSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertySubscribeResponse> : SerialisationTraits<ci::Message::DynamicSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertySubscribe> : SerialisationTraits<ci::Message::DynamicSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::PropertyNotify> : SerialisationTraits<ci::Message::DynamicSizePropertyExchange> {};
template <>
struct SerialisationTraits<ci::Message::ProcessInquiryResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
archive (t.supportedFeatures);
}
};
template <>
struct SerialisationTraits<ci::Message::ProcessInquiry> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive&, This&)
{
}
};
template <>
struct SerialisationTraits<ci::Message::ProcessMidiMessageReportResponse> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
std::byte reserved{};
archive (named ("messageDataControl", t.messageDataControl),
named ("requestedMessages", t.requestedMessages),
named ("reserved", reserved),
named ("channelControllerMessages", t.channelControllerMessages),
named ("noteDataMessages", t.noteDataMessages));
}
};
template <>
struct SerialisationTraits<ci::Message::ProcessMidiMessageReport> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive& archive, This& t)
{
std::byte reserved{};
archive (named ("messageDataControl", t.messageDataControl),
named ("requestedMessages", t.requestedMessages),
named ("reserved", reserved),
named ("channelControllerMessages", t.channelControllerMessages),
named ("noteDataMessages", t.noteDataMessages));
}
};
template <>
struct SerialisationTraits<ci::Message::ProcessEndMidiMessageReport> : VersionBase
{
template <typename Archive, typename This>
static auto serialise (Archive&, This&)
{
}
};
} // namespace juce
/** @endcond */