Platform SDK: DirectX

Notification and Event Handling

From time to time, your application might need to respond to a music 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. Get the desired information by asking DirectMusic to notify you when a certain type of event has taken place.

[C++]

Specify what types of music events you want to be notified of by calling the IDirectMusicPerformance::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.

/* It is assumed that pPerformance is a valid 
   IDirectMusicPerformance pointer. */
 
GUID guid = GUID_NOTIFICATION_SEGMENT;
// C syntax:
pPerformance->AddNotificationType(&guid);
// C++ syntax:
pPerformance->AddNotificationType(guid);

You can also add notification types for a particular segment by using the IDirectMusicSegment::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.

Notifications are sent in the form of DMUS_NOTIFICATION_PMSG message structures. You can poll for any pending notification messages within the Windows message loop by calling the IDirectMusicPerformance::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 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 IDirectMusicPerformance::SetNotificationHandle method. You can use the second parameter of this method to change the default time that DirectMusic holds 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 IDirectMusicPerformance interface:

g_pPerf->SetNotificationHandle(g_hNotify, 0);

The following code example runs 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 run as follows:

_beginthread(WaitForEvent, 0, NULL);

When notifications are no longer needed, the following code example 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 is not necessary to create an event to retrieve notification messages in your application's message loop. As long as you have requested notifications by calling the IDirectMusicPerformance::AddNotificationType method, the performance sends messages that can be retrieved by calling IDirectMusicPerformance::GetNotificationPMsg.

More than one message can 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.

You must free any message that you retrieve, by calling the IDirectMusicPerformance::FreePMsg method.

[Visual Basic]

Specify what types of music events you want to be notified of by calling the DirectMusicPerformance.AddNotificationType method once for each desired type of event. The following code example, in which perf is a DirectMusicPerformance object, requests notifications for segment events. The type of event (such as a segment start or a segment end) will be derived later from the notification message.

Call perf.AddNotificationType(DMUS_NOTIFY_ON_SEGMENT)

Notifications are sent in the form of a DMUS_NOTIFICATION_PMSG message type. You can poll for any pending notification messages by calling the DirectMusicPerformance.GetNotificationPMsg method in Sub Main or another loop, or you can have DirectMusic signal an event when a message is pending.

To have DirectMusic signal events, use DirectX7.CreateEvent to obtain an event handle, and then pass this handle to DirectMusicPerformance.SetNotificationHandle. The module that you pass to CreateEvent must implement the DirectXEvent class and must also provide an implementation of the DirectXEvent.DXCallback method, which is called by DirectMusic whenever an event is signaled.

The following code example sets up notification for a form module called frmMain:

' DX is a DirectX7 object; perf is a DirectMusicPerformance object.
Dim hEvent As Long
hEvent = DX.CreateEvent(frmMain)
Call perf.SetNotificationHandle(hEvent)

The form module contains code similar to the following, which looks for a message indicating that the segment has finished playing:

Implements DirectXEvent
 
Private Sub DirectXEvent_DXCallback(ByVal eventid As Long)
 
  Dim GotMSG As Boolean
  Dim PMsg As DMUS_NOTIFICATION_PMSG
 
  Do
    GotMSG = gobjDMPerformance.GetNotificationPMSG(PMsg)
    If GotMSG Then
      If PMsg.lNotificationOption = DMUS_NOTIFICATION_SEGEND Then
        ' Segment has finished playing.
      End If
    End If
  Loop Until Not GotMSG
 
End Sub

It is not necessary to create an event to retrieve notification messages in your application's main loop. As long as you have requested notifications by calling the DirectMusicPerformance.AddNotificationType method, the performance sends messages that can be retrieved by calling DirectMusicPerformance.GetNotificationPMsg.

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

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