MIDISendMessages
Appearance
The MIDISendMessages function dispatches an array of standard, compound MIDI messages down the Real-Time MIDI (RTMIDI) pipeline. Messages can be scheduled for immediate execution or injected into a precision high-priority scheduling queue for playback at an absolute future timestamp.
Syntax
#include <mididll.h> PMESSAGE paMessage; /* Pointer to compound message array (Input) */ ULONG ulNumMessages; /* Number of array elements to process (Input) */ ULONG ulFlag; /* Reserved flag, must be 0 (Input) */ ULONG rc; /* Return code */ rc = MIDISendMessages(paMessage, ulNumMessages, ulFlag);
Parameters
- paMessage (PMESSAGE) - input
- A pointer to a caller-allocated array of MESSAGE structures. Each element represents an isolated, compound event packet configured with its own routing, sequencing track, and timestamp definitions.
- ulNumMessages (ULONG) - input
- The total count of consecutive MESSAGE elements populated within the `paMessage` target array block.
- ulFlag (ULONG) - input
- A reserved subsystem tracking modifier flag. This must be explicitly set to `0`.
Return Value
- rc (ULONG) - returns
- Returns `0` (or `MIDI_SUCCESS`) if the array of messages was safely parsed, executed, or accepted into the scheduler queue, or one of the following specific error codes:
- MIDIERR_INTERNAL_SYSTEM: An unrecoverable tracking anomaly occurred, or the high-resolution master subsystem timer has not been initiated.
- MIDIERR_INVALID_FLAG: The value passed into the context tracking modifier ulFlag was not configured to `0`.
- MIDIERR_INVALID_INSTANCE_NUMBER: An instance identification handle specified within the `ulSourceInstance` field of a parsed message node does not exist or has been dismantled.
- MIDIERR_INVALID_PARAMETER: The memory address pointer supplied for paMessage is null or maps to an inaccessible memory ring segment.
Remarks
- System Timer Dependency: The RTMIDI subsystem cannot route or schedule events without a valid master clock baseline. Developers **must** guarantee that the tracking infrastructure timer is live before calling this function. The timer state is explicitly managed by invoking MIDITimer.
- Polymorphic Node Routing: Because every compound event packet inside the target array specifies its own source node marker within its internal `ulSourceInstance` variable, an application can combine messages originating from distinct virtual output streams into a single vector call.
- Chronological Execution Rules:
- Immediate Processing: Messages stamped with an absolute timing value equal to or less than the current system time value are immediate-routed directly through the link matrix to hardware or filter links.
- Scheduled Processing: Messages stamped with a future absolute time value are transparently loaded into a high-priority, real-time multimedia queue.
- Timestamp Calculation: Timestamps are absolute measurements derived from the running system master clock. Relative delays must be computed using the current clock reference as a baseline:
$$\text{ulTime} = \text{Current Timer Value} + \text{Desired Delay (ms)}$$ - Thread Blocking Behaviors: The calling thread remains blocked until every element in the array has been evaluated and either executed or pushed to the queue. If the hardware-backed ring buffer or scheduling queue fills up completely due to dense data loads, the subsystem will stall the calling thread until there is sufficient room to handle the remaining payload. While blocked, the memory array referenced by paMessage **must not** be modified or freed by secondary concurrent application threads.
- Data Context Exclusions: MIDISendMessages is strictly optimized for performance-critical, short-form channel and system common messages (e.g., Note-On, Note-Off, Control Change, Pitch Bend). Long-form System Exclusive (SysEx) data blocks **cannot** use this routine and must be passed using specialized bulk streaming calls.
Example Code
The following code block demonstrates how to initialize and configure a single compound message packet to transmit a clear Note-On channel event scheduled exactly 10 milliseconds into the future:
MESSAGE message; /* Compound message container structure */
PULONG pulMIDITimer; /* Shared pointer mapped during initial MIDISetup() */
ULONG ulAppInstance; /* Application logical node instance handle */
ULONG rc; /* Operation return code */
/* Configure the origin context for routing */
message.ulSourceInstance = ulAppInstance;
message.ulTrack = 0;
/* Populate standard MIDI Channel Message structure elements */
message.msg.bytes.bStatus = 0x90; /* Note-On Command, MIDI Channel 0 */
message.msg.abData[0] = 0x40; /* Note Number (Middle E) */
message.msg.abData[1] = 0x7F; /* Attack Velocity (Maximum 127) */
/* Calculate absolute timestamp: 10 milliseconds ahead of the master timer */
message.ulTime = *pulMIDITimer + 10;
/* Dispatch the compound message payload array */
rc = MIDISendMessages(&message, 1, 0);
if (rc == MIDI_SUCCESS) {
/* Message successfully dispatched or securely queued for future playback */
}