[ Home | Alpha index | Topic index | Tutorials | Download | Feedback ]

The OS/2 API Project

MIDIRetrieveMessages

[ Syntax | Params | Returns | Include | Usage | Structs | Gotchas | Code | Also ]

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
0NO_ERROROperation was successful.
7003MIDIERR_INTERNAL_SYSTEMError, Either the RTMIDI timer is not running, or the RTMIDI subsystem has become corrupt, and the application should terminate immediately, cleaning up as much as possible. In latter case, rebooting will most likely be necessary to restore RTMIDI to a functional state.
7007MIDIERR_INVALID_FLAGError, The ulFlag value is not set to 0.
7009MIDIERR_INVALID_INSTANCE_NUMBERError, The instance number is invalid.
7005MIDIERR_INVALID_CLASS_NUMBERError, The instance number refers to an instance that is not of the Application class.
7010MIDIERR_INVALID_PARAMETERError, Either of the pBuffer or pulBufferLength pointers is invalid.
7014MIDIERR_NOT_ALLOWEDError, The function is not implemented on this version of RTMIDI.

Include Info

#include <mididll.h>

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

#include <mididll.h> 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. */ }

See Also

MIDISendMessages.html, SendSysexMessage,

Author

Timur Tabi - http://www.shirenet.com/~crusader/Timur/
mailto:timur@vnet.ibm.com

Additions

Last Modified November 7/1996
Please send all errors, comments, and suggestions to: timur@vnet.ibm.com

The OS/2 API Project

MIDIRetrieveMessages