IDirectMusicPerformance8::SendPMsg

The SendPMsg method sends a performance message. This method is called by tracks when they are played. It can also be called by an application or tool to insert data into a performance.

Syntax

HRESULT SendPMsg(
  DMUS_PMSG* pPMSG
);

Parameters

pPMSG

Message allocated by IDirectMusicPerformance8::AllocPMsg.  This structure is of a type derived from DMUS_PMSG.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_NO_MASTER_CLOCK
DMUS_E_ALREADY_SENT
E_INVALIDARG
E_POINTER

Remarks

The dwFlags member (see DMUS_PMSG) must contain either DMUS_PMSGF_MUSICTIME or DMUS_PMSGF_REFTIME, depending on whether the time stamp is in rtTime or mtTime. The dwFlags member should also contain the appropriate delivery type—DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGF_TOOL_ATTIME, or DMUS_PMSGF_TOOL_IMMEDIATE—depending on the type of message. If none is selected, DMUS_PMSGF_TOOL_IMMEDIATE is used by default.

If the time of the message is set to 0 and the dwFlags member contains DMUS_PMSGF_REFTIME, it is assumed that this message is cued to go out immediately.

In most cases, the IDirectMusicGraph8::StampPMsg method should be called on the message before SendPMsg is called. If the message is not stamped, it is not delivered to any tools implemented by the application, and might not play on the correct performance channel. If you want the message to pass only through the performance toolgraph, obtain the IDirectMusicGraph8 interface by calling IDirectMusicPerformance8::QueryInterface. Otherwise, obtain it by calling IDirectMusicSegmentState8::QueryInterface. Do not attempt to obtain the interface by calling IDirectMusicPerformance8::GetGraph or IDirectMusicSegment8::GetGraph; these methods return a pointer to the graph object, rather than to the implementation of the IDirectMusicGraph8 interface on the performance or segment.

If you are using audiopaths, it is generally best not to send a message directly to the performance, because the performance channels may have been remapped, and messages sent to a particular channel may not be played. Instead, obtain the IDirectMusicGraph8 interface from IDirectMusicAudioPath8. The audiopath then manages the remapping of the performance channel.

Normally, the performance frees the message after it has been processed. For more information, see the Remarks for IDirectMusicPerformance8::FreePMsg.

The following example function shows how to allocate and send a system exclusive message to the performance graph.

HRESULT SendSysexMessage(IDirectMusicPerformance8* pPerformance, 
    MUSIC_TIME mtTime, DWORD pbSysExData[], DWORD dwSysExLength)
{ 
  IDirectMusicGraph* pGraph;
  HRESULT hr;
 
  if (SUCCEEDED(hr = pPerformance->QueryInterface(IID_IDirectMusicGraph,
                                                  (void**)&pGraph)))
  {
    DMUS_SYSEX_PMSG* pSysEx;
    if (SUCCEEDED(hr = pPerformance->AllocPMsg(
                    sizeof(DMUS_SYSEX_PMSG) + dwSysExLength,
                    (DMUS_PMSG**)&pSysEx)))
    {
      ZeroMemory(pSysEx, sizeof(DMUS_SYSEX_PMSG));
      pSysEx->dwLen = dwSysExLength;
      pSysEx->mtTime = mtTime;
      pSysEx->dwFlags = DMUS_PMSGF_MUSICTIME;
      pSysEx->dwType = DMUS_PMSGT_SYSEX;
      memcpy(pSysEx->abData, pbSysExData, dwSysExLength);
      pGraph->StampPMsg((DMUS_PMSG*)pSysEx);
      if (FAILED(hr = pPerformance->SendPMsg((DMUS_PMSG*)pSysEx)))
      {
        pPerformance->FreePMsg( (DMUS_PMSG*)pSysEx );
      }
    }
    pGraph->Release();
  }
  return hr;
}

The next example function sends a note message associated with the track identified by dwTrackID. The virtual track ID should be 0 if the message is not being generated from a DirectMusicTrack object.

HRESULT CreateNotePMsg(IDirectMusicPerformance8* pPerformance,
    MUSIC_TIME mtTime, DWORD dwTrackID) 
{
  // Allocate a Note PMessage.
  DMUS_NOTE_PMSG* pNote = NULL;
  HRESULT hr = pPerformance->AllocPMsg( sizeof(DMUS_NOTE_PMSG),
      (DMUS_PMSG**) &pNote);
  if (FAILED(hr)) return hr;
 
  pNote->rtTime = 0;                      // Ignored.
  pNote->mtTime = mtTime;                 // When to play the note.
  pNote->dwFlags = DMUS_PMSGF_MUSICTIME;  // Use the mtTime field.
  pNote->dwPChannel = 5;                  // Play on PChannel 5.
  pNote->dwVirtualTrackID = dwTrackID;    // Track ID from parameter.
 
  // The following two fields should be set to NULL when a 
  // message is initially sent. They will be updated in
  // IDirectMusicGraph::StampPMsg.
  pNote->pTool = NULL; 
  pNote->pGraph = NULL;
  pNote->dwType = DMUS_PMSGT_NOTE; 
  pNote->dwVoiceID = 0;           // Always 0.
  pNote->dwGroupID = 0xFFFFFFFF;  // All track groups.
  pNote->punkUser = NULL;         // Always NULL.
 
  // Get the current time signature from the performance
  // to compute measure and beat information.
  DMUS_TIMESIGNATURE TimeSig;
  MUSIC_TIME mtNext;
  hr = pPerformance->GetParam(GUID_TimeSignature, 0xFFFFFFFF, 
    0, mtTime, &mtNext, &TimeSig);
  if (FAILED(hr)) return hr;
 
  // Recompute TimeSig.mtTime to have the value expected 
  // by pPerformance->TimeToRhythm.
  TimeSig.mtTime += mtTime;
 
  // Get the current chord from the performance 
  // to create a note value.
  DMUS_CHORD_KEY Chord;
  hr = pPerformance->GetParam(GUID_ChordParam, 0xFFFFFFFF, 0, 
      mtTime, &mtNext, &Chord);
  if (FAILED(hr)) return hr;
 
  // Create a note with octave 5, chord tone 2 (fifth), scale 
  // offset 1 (=> sixth), and no accidentals.
  WORD wMusicValue = 0x5210;
 
  // Use DMUS_PLAYMODE_PEDALPOINT as your play mode
  // in pPerformance->MusicToMIDI.
  BYTE bPlayModeFlags = DMUS_PLAYMODE_PEDALPOINT;
 
  // Fill in the fields specific to DMUS_NOTE_PMSG.
  pNote->wMusicValue = wMusicValue; 
  hr = pPerformance->MusicToMIDI(
      wMusicValue,
      &Chord,
      bPlayModeFlags,
      0,
      &(pNote->bMidiValue));
  if (FAILED(hr)) return hr;
 
  hr = pPerformance->TimeToRhythm(
      TimeSig.mtTime,
      &TimeSig,
      &(pNote->wMeasure),
      &(pNote->bBeat),
      &(pNote->bGrid),
      &(pNote->nOffset));
  if (FAILED(hr)) return hr;
 
  pNote->mtDuration = DMUS_PPQ;      // Quarter note duration.
  pNote->bVelocity = 120;            // MIDI velocity (0 to 127).
  pNote->bFlags = DMUS_NOTEF_NOTEON; // Always set to this value.
  pNote->bTimeRange = 250;           // Randomize start time a lot.
  pNote->bDurRange = 5;              // Randomize duration a little.
  pNote->bVelRange = 0;              // Don't randomize velocity.
  pNote->bPlayModeFlags = bPlayModeFlags; 
  pNote->bSubChordLevel = 0;         // Note uses subchord level 0.
  pNote->cTranspose = 0;             // No transposition.
 
  // Stamp the message with the performance graph.
  IDirectMusicGraph* pGraph;
  hr = pPerformance->QueryInterface(IID_IDirectMusicGraph,
      (void**)&pGraph);
  if (FAILED(hr)) return hr;
 
  pGraph->StampPMsg((DMUS_PMSG*)pNote);
  pGraph->Release();

  // Finally, send the message.
  hr = pPerformance->SendPMsg((DMUS_PMSG*)pNote);
  if (FAILED(hr))
  {
    pPerformance->FreePMsg((DMUS_PMSG*)pNote);
    return hr;
  }
  return S_OK;
}

Requirements

**  Header:** Dmusici.h
  Library: Dmime.dll, Dmimed.dll

See Also

© 2004 Microsoft Corporation. All rights reserved.