Microsoft DirectX 9.0

Creating a Tool

A tool object can reside in a DLL or in the client application. The object implements the methods of IDirectMusicTool or IDirectMusicTool8. The purpose of each method is summarized in the following table.

Method Description
Init Performs any needed initialization of the object. This method is called when the application adds the tool to a graph by calling IDirectMusicGraph8::InsertTool. It should always return S_OK.
GetMsgDeliveryType Specifies when the performance should deliver messages to the tool by calling its ProcessPMsg method. Most tools can specify DMUS_PMSGF_TOOL_IMMEDIATE.
GetMediaTypes Returns an array of message types that the tool processes. This method is called by the DirectMusic performance to determine which messages to pass to the ProcessPMsg method.
GetMediaTypeArraySize Specifies the number of message types in the array.
ProcessPMsg Processes each message. This method is called by the performance each time a message that matches the requested types is available. After processing, the method either requeues or deletes the message.
Flush Specifies the behavior of the tool when it receives a message sent as a result of an invalidation. This can happen, for example, when a note or curve is in progress and the segment stops unexpectedly. Most tools can simply requeue the message.

When the performance engine is playing a segment, it enables each tool in the segment toolgraph, and then each tool in the performance toolgraph, to process each message. When a tool processes a message, it should obtain the IDirectMusicGraph8 pointer from the pGraph member of the DMUS_PMSG structure and then call the IDirectMusicGraph8::StampPMsg method to stamp the message with a pointer to the next tool, if any, that is to receive it.

The following sample code from the tool's implementation of IDirectMusicTool8::ProcessPMsg stamps the message (pPMsg) for the next tool, or frees the message if this is not possible.

if ((NULL == pPMsg->pGraph ) || (FAILED(pPMsg->pGraph->StampPMsg(pPMsg))))
{
    hr = DMUS_S_FREE;
}

It's important to stamp the message before reaching any code paths that might cause the method to return. If the message is not stamped for the next tool when it is handed back to the queue, it will be sent back to this tool, possibly resulting in an endless loop. On the other hand, be aware that StampPMsg can change the value in the dwPChannel member of the message structure. If your tool uses this value, save it before stamping the message.

Tools process messages in a high-priority thread. Do not call time-consuming functions, such as those involving graphics or file input/output, from within a tool's IDirectMusicTool8::ProcessPMsg method. If a tool needs to trigger an action, it should do so by signaling a different thread, perhaps the application's main thread.

When implementing the methods of IDirectMusicTool8, take care not to create circular references to parent objects. Circular references come about when one object creates another and the child keeps an additional reference to the parent. For example, suppose a tool creates a new reference to the toolgraph passed into its IDirectMusicTool8::Init method. If the tool fails to release this reference, there is a problem when the segment attempts to release the toolgraph. Because the tool still has a reference to the toolgraph, the toolgraph is not fully released; and because the toolgraph has a reference to the tool, the tool cannot be released either.

See Also