Microsoft DirectX 8.1 (C++)

Notification and Event Handling

From time to time, your application may need to respond to a performance event. For example, you might need to know when the end of a segment has been reached, or you might want to synchronize graphics with the beat of the music. You get the desired information by asking DirectMusic to notify you when a certain type of event has taken place.

Note   Performance notifications are not to be confused with DirectSound buffer notifications, which are used only by applications that are streaming wave data directly to or from buffers. See Play Buffer Notification and Capture Buffer Notification.

Specify what types of events you want to be notified of by calling the IDirectMusicPerformance8::AddNotificationType method once for each desired type of event. The following code example tells DirectMusic to set segment-related events. The actual type of event, such as a segment start or a segment end, will be derived later from the notification message.

// pPerformance is a valid IDirectMusicPerformance8 pointer.
 
GUID guid = GUID_NOTIFICATION_SEGMENT;
 
pPerformance->AddNotificationType(guid);

You can also add notification types for a particular segment by using the IDirectMusicSegment8::AddNotificationType method. You could do this, for example, to receive notification of when a particular segment stops playing. You cannot use this method to request GUID_NOTIFICATION_PERFORMANCE types, because these must come from the performance object.

Note   Most applications do not directly call the IDirectMusicTrack8::AddNotificationType method.

Information about notifications is sent in DMUS_NOTIFICATION_PMSG message structures. You can poll for any pending notification messages within the Windows message loop by calling the IDirectMusicPerformance8::GetNotificationPMsg method, or you can have DirectMusic signal an event object in a separate thread when a message is pending.

If you want to be alerted of pending DirectMusic notification messages by a Windows event object, you must first obtain an event handle by calling the Microsoft® Win32® CreateEvent function. Typically, you would create an autoreset event with a call such as the following:

HANDLE g_hNotify = CreateEvent(NULL, FALSE, FALSE, NULL);

After creating the event, assign the handle to the performance by passing it to the IDirectMusicPerformance8::SetNotificationHandle method. You can use the second parameter of this method to specify how long DirectMusic should hold onto the event if it is not retrieved. A value of 0 in this parameter indicates that the default time of 2 seconds is to be used.

In the following example, g_pPerf is a valid pointer to the IDirectMusicPerformance8 interface:

g_pPerf->SetNotificationHandle(g_hNotify, 0);

The following sample function executes repeatedly in its own thread, checking for signaled events and retrieving notification messages:

void WaitForEvent( LPVOID lpv)
{
  DWORD dwResult;
  DMUS_NOTIFICATION_PMSG* pPmsg;
  char szCount[4];
 
  while (TRUE)
  {
    dwResult = WaitForSingleObject(g_hNotify, 100);
    while (S_OK == g_pPerf->GetNotificationPMsg(&pPmsg))
    {
      // Check notification type and do something in response.
      .
      .
      .
      g_pPerf->FreePMsg((DMUS_PMSG*)pPmsg); 
    }
  }
}

This thread is executed as follows:

_beginthread(WaitForEvent, 0, NULL);

When notifications are no longer needed, the following code shuts down the thread, removes the notification handle from the performance, and destroys the event object:

_endthread();
g_pPerf->SetNotificationHandle(0, 0);
CloseHandle(g_hNotify);

It isn't necessary to create an event in order to retrieve notification messages in your application's message loop. As long as you have requested notifications by calling one of the AddNotificationType methods, the performance sends messages that can be retrieved by calling IDirectMusicPerformance8::GetNotificationPMsg.

More than one message might be waiting when an event is signaled or when you call GetNotificationPMsg in the message loop. To be sure of catching all notifications, call GetNotificationPMsg repeatedly until it returns S_FALSE.

Multiple messages with the same time stamp are not queued in any particular order.

It is the application's responsibility to free any messages it retrieves, by calling the IDirectMusicPerformance8::FreePMsg method.