midi_ci.h
MIDI Capability Inquiry.
#include <sonore/midi_ci.h>- 2types
- 15other declarations
- Guides: MIDI and MPE
On this page
Design notes
How a MIDI 2.0 device and a plugin introduce themselves: who are you, what can you do, and (the part that is actually useful) hand me your parameter list so I can map my knobs to it without the user doing it by hand.
This is the MESSAGE LAYER only, and deliberately so. Every CI message is a universal SysEx with a fixed prologue, and the bugs live there: the seven-bit packing (SysEx data bytes cannot have the top bit set, so anything wider has to be split), the MUID (a 28-bit identity carried as four seven-bit bytes), and the little-endian ordering of both. All of that is testable exhaustively with no hardware, exactly like the OSC codec.
What is NOT here is the negotiation state machine, for the same reason the ARA binding is a hook: it can only be proven against a CI-capable device or host, and shipping an unverifiable state machine is how the two macOS bugs in this SDK's history got written.
Types 2
A device's identity, as it appears in Discovery and its reply.
What a parsed message carries.
Functions 8
- fn
inline void writeHeader(std::vector<uint8_t>& out, MessageType type, uint32_t sourceMuid, uint32_t destinationMuid, uint8_t deviceId = 0x7f)The prologue every CI message shares, written intomidici::writeHeader · midi_ci.h:108out. - fn
inline std::vector<uint8_t> encodeDiscovery(const DeviceIdentity& identity)Encode a Discovery message: "who is out there, and what can you do?"midici::encodeDiscovery · midi_ci.h:121 - fn
inline std::vector<uint8_t> encodeDiscoveryReply(const DeviceIdentity& identity, uint32_t destinationMuid)Encode the reply, which carries the same identity plus a function block.midici::encodeDiscoveryReply · midi_ci.h:136 - fn
inline std::vector<uint8_t> encodePropertyCapabilities(uint32_t sourceMuid, uint32_t destinationMuid, uint8_t simultaneousRequests = 1)Encode a Property Exchange capabilities inquiry: the message that leads to a controller receiving a parameter list.midici::encodePropertyCapabilities · midi_ci.h:154 - fn
inline std::vector<uint8_t> encodeInvalidateMuid(uint32_t sourceMuid, uint32_t targetMuid)Tell everyone a MUID is no longer valid, which is what a plugin sends when it is being torn down.midici::encodeInvalidateMuid · midi_ci.h:168 - fn
inline bool decode(const uint8_t* data, size_t size, Message* out)Parse a CI message. Returns false for anything that is not one, rather than guessing: an ordinary SysEx from a synth must not be mistaken for a CI message and acted on.midici::decode · midi_ci.h:192 - fn
inline bool isCiMessage(const uint8_t* data, size_t size)Is this SysEx a CI message at all? Cheap enough to call on every incoming SysEx before doing anything more expensive.midici::isCiMessage · midi_ci.h:228 - fn
inline DeviceIdentity makeIdentity(uint32_t muid, const char* manufacturerId = "\x7D\x00\x00")Build the identity a Sonorie plugin presents. Property exchange is declared because that is the capability worth having: it is how a controller asks for the parameter list and maps its knobs itself.midici::makeIdentity · midi_ci.h:235
Enums 1
- enum
enum class MessageType : uint8_tThe message types this SDK models. The numbering is the specification's.midici::MessageType · midi_ci.h:31
Constants 6
- const
constexpr uint32_t kBroadcastMuid = 0x0FFFFFFFBroadcast destination: every device answers.midici::kBroadcastMuid · midi_ci.h:41 - const
constexpr uint8_t kCiVersion = 0x02The CI version this SDK speaks.midici::kCiVersion · midi_ci.h:44 - const
constexpr uint8_t kCategoryProtocolNegotiation = 0x02Discovery's category bits, as the specification numbers them. Bit 0 is reserved, and bit 1 is NOT property exchange: claiming it said "protocol negotiation" and nothing else, so a controller never asked for the parameter list it was meant to fetch.midici::kCategoryProtocolNegotiation · midi_ci.h:50 - const
constexpr uint8_t kCategoryProfiles = 0x04midici::kCategoryProfiles · midi_ci.h:51 - const
constexpr uint8_t kCategoryPropertyExchange = 0x08midici::kCategoryPropertyExchange · midi_ci.h:52 - const
constexpr uint8_t kCategoryProcessInquiry = 0x10midici::kCategoryProcessInquiry · midi_ci.h:53