Capturing Music

Capturing MIDI messages from a device such as a keyboard is very easy in DirectMusic.

Typically you would create a port for the capture device and use its IDirectMusicPort::SetReadNotificationHandle method to cause an event to be signaled whenever messages are available to be read. In response to the event, call IDirectMusicPort::Read method repeatedly to place pending events into a buffer, until S_FALSE is returned. Each time Read is called, as many events are put into the buffer as are available, or as will fit into the buffer. If at least one event was put into the buffer, S_OK is returned.

To retrieve events from the buffer, you call the IDirectMusicBuffer::GetNextEvent method. Each call retrieves a single event, until no more are available, at which point S_FALSE is returned.

The following code fragment illustrates this process:

/* Assume that hEvent was created with CreateEvent and
   given to the capture port pPort by a call to 
   SetReadNotificationHandle. Assume also that pBuffer was
   initialized by IDirectMusic::CreateMusicBuffer. */
 
REFERENCE_TIME rt;
DWORD          dwGroup;
DWORD          cb;
BYTE          *pb;
 
DWORD dw = WaitForMultipleObjects(1, hEvent, FALSE, INFINITE);
for (;;)
{
    hr = pPort->Read(pBuffer);
    if (hr == S_FALSE)
      {
          break;  // No more messages to read into buffer
      }
    pBuffer->ResetReadPtr();
    for (;;)
    {
        hr = pBuffer->GetNextEvent(&rt, &dwGroup, &cb, &pb);
        if (hr == S_OK)
        {
            // pb points to the data structure for the message and
            // you can do with it what you want.
        }
        else if (hr == S_FALSE)
        {
            break;  // No more messages in buffer
        }
    }  // Done with buffer
}  // Done reading pending events
 

If you do not wish to intercept messages but simply want to send them from one port to another, you can use the IDirectMusicThru interface.