MIDIRetrieveMessages

Syntax
rc = MIDIRetrieveMessages( minstance, pBuffer,                           pulBufferLength, ulFlag );

Parameters

 * MINSTANCE minstance (input)
 * The source instance number.


 * PVOID pBuffer (output)
 * Pointer to the buffer to be filled with the compound messages.


 * PULONG pulBufferLength (input/output)
 * Length of buffer in input (must be at least "sizeof(MESSAGE)" bytes long), number of bytes written on output.


 * ULONG ulFlag (input)
 * This parameter is not currently used and must be set to 0.

Returns

 * ULONG rc: The following values can be returned:

Include Info

 * 1) include 

Usage Explanation
MIDIRetrieveMessages is used to receive the MIDI data that is sent to the Application node specified by minstance. Compound messages sent to the Application node are stored in a queue. When MIDIRetrieveMessages is called, and the queue is not empty, the contents of the queue are copied to the pBuffer and the call returns immediately. If the queue is empty, the thread blocks until the queue becomes non-empty.

Since it is possible (and even likely) that the thread calling MIDIRetrieveMessages will be blocked, it is strongly suggested that a thread be allocated specifically for this function.

On return, pBuffer will be filled with an array of compound messages. Since the call blocks until a message arrives, pBuffer will always have at least one compound message. The number of bytes copied will never exceed pulBufferLength, even if the queue holds more, and only whole compound messages will be copied. Therefore, it is suggested that pulBufferLength be equal to a multiple of sizeof(MESSAGE).

Relevant Structures
typedef struct { // inst # of the instance which generated the msg ULONG ulSourceInstance; // time the message is to be (or was) sent ULONG ulTime; ULONG ulTrack; union { ULONG ulMessage; struct { // The 1st byte of the message BYTE bStatus; // the rest of the message BYTE abData[3]; } bytes; BYTE abData[4]; } msg; } MESSAGE, *PMESSAGE;

Gotchas
Currently, MIDIRetrieveMessages does not support receiving of SysEx messages. Any SysEx messages which are sent to an Application node are immediately discarded. This limitation will be removed in a future release of RTMIDI.

The Warp 4 GA version of RTMIDI has a bug where if a thread is blocked in MIDIRetrieveMessages, there is no way to unblock the thread prematurely. The work-around is to create a second Application node, use MIDIAddLink.html to create a link from it to the first Application node, and then use MIDISendMessages.html to send a message to the second Application node. The message will travel along the link to the first Application node, causing this node to unblock the MIDIRetrieveMessages call. The thread can then terminate itself.

This also means that if an Application node is deleted while a thread is block in a MIDIRetrieveMessages call to it, the thread will be permanently hung and there will be no way to terminate it.

Sample Code
MINSTANCE miHardwareNode; MINSTANCE miApplicationNode; ULONG ulApplicationClass; volatile int fRecordMIDI = TRUE; MESSAGE msg; ULONG ulBufferSize; /* Assume that miHardwareNode has been set to the Hardware node  */ /* from which we want to record MIDI data. Also assume that     */ /* ulApplicationClass has been set to the class number of the    */ /* Application class. */  /* First, we create an Application node. Then we link the       */ /* Hardware node to it. Then we enable the Hardware node for    */ /* "send". This will cause the hardware to start sending        */ /* incoming MIDI data to the Application node. Then we enter a  */ /* loop of MIDIRetrieveMessages calls. The loop terminates when */ /* some thread sets fRecordMIDI to false. */  /* Our pBuffer is actually variable msg, so it can only hold a    */ /* single compound message. This means that we'll only be       */ /* receiving one MIDI message at a time. This is okay for low   */ /* throughput, but for higher rates we'll need to be able to     */ /* receive more than one at a time. */       rc = MIDICreateInstance(ulApplicationClass,                                "My Applictaion Node",                                &miApplicationNode, 0); if (rc != 0) {          /* Either not enough memory to create another node,       */ /* or there already is an node called                    */ /* "My Application Node". */       }        rc = MIDIAddLink(miHardwareNode, miApplicationNode, 0, 0); if (rc != 0) {          /* We got an error to take care of. */       }        rc = MIDIEnableInstance(miHardwareNode, MIDI_ENABLE_SEND); if (rc != 0) {          /* We got an error to take care of. */       }        while (fRecordMIDI) {          ulBufferSize = sizeof(msg); rc = MIDIRetrieveMessages(miApplicationNode,                                    (PVOID) &msg,                                     &ulBufferSize, 0); if (rc != 0) {             /* We got an error to take care of. */          }           /* 'msg' now contains a new message. Process it here, or  */ /* dispatch it to another thread. The longer this section */ /* takes execute, the lower your maximum throughput will   */ /* be. */       }
 * 1) include 