Platform SDK: DirectX |
アプリケーションは、音楽イベントに応答しなければならない場合がある。たとえば、セグメントが終わったことを確認する必要がある場合や、グラフィックスと音楽の拍を同期させたい場合などである。特定のタイプのイベントが発生したときに、そのことを通知するよう DirectMusic に指示して、必要な情報を取得することができる。
通知を受けたい音楽イベントの種類を指定するには、イベントの種類ごとに一度だけ IDirectMusicPerformance::AddNotificationType メソッドを呼び出す。次のコード例では、DirectMusic にセグメントに関連するイベントを設定するように指示している。実際のイベントの種類 (セグメントの開始やセグメントの終了など) は、通知メッセージから得られる。
/* pPerformance は、有効な IDirectMusicPerformance ポインタであるとする。*/ GUID guid = GUID_NOTIFICATION_SEGMENT; // C の構文 pPerformance->AddNotificationType(&guid); // C++ の構文 pPerformance->AddNotificationType(guid);
IDirectMusicSegment::AddNotificationType メソッドを使って、特定のセグメントに対して通知タイプを追加することもできる。たとえば、特定のセグメントが演奏を停止したときに通知を受け取るような場合に、この設定を行うことができる。このメソッドを使って GUID_NOTIFICATION_PERFORMANCE 型を要求することはできない。これらの型は、パフォーマンス オブジェクトから取得しなければならない。
通知は、DMUS_NOTIFICATION_PMSG メッセージ構造体の形式で送られる。IDirectMusicPerformance::GetNotificationPMsg メソッドを呼び出して、Windows メッセージ ループ内で保留中の通知メッセージをポーリングすることができる。また、メッセージが保留中のときに、DirectMusic に別のスレッドでイベント オブジェクトを通知させることもできる。
Windows イベント オブジェクトを使って、保留中の DirectMusic 通知メッセージを知らせたい場合は、まず Win32 CreateEvent 関数を呼び出して、イベント ハンドルを取得しなければならない。通常は、次のような呼び出しを行って、自動リセット イベントを作成する。
HANDLE g_hNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
イベントの作成後、このハンドルを IDirectMusicPerformance::SetNotificationHandle メソッドに渡してパフォーマンスに割り当てる。イベントを取り出せなかった場合でも DirectMusic はイベントを待機するが、このメソッドの 2 番目のパラメータを使うとデフォルトの時間を変更できる。このパラメータに 0 を指定すると、デフォルトの時間の 2 秒が使用される。
次の例では、g_pPerf は IDirectMusicPerformance インターフェイスへの有効なポインタを表している。
g_pPerf->SetNotificationHandle(g_hNotify, 0);
次のコード例は、独自のスレッドで繰り返し実行され、通知されたイベントを確認して、通知メッセージを取り出している。
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)) { // 通知タイプを確認し、それに対応する処理を行う。 . . . g_pPerf->FreePMsg((DMUS_PMSG*)pPmsg); } } }
このスレッドは次のように実行される。
_beginthread(WaitForEvent, 0, NULL);
通知が必要なくなった場合は、次のコード例に示すように、スレッドをシャット ダウンし、パフォーマンスから通知ハンドルを削除し、イベント オブジェクトを破棄する。
_endthread(); g_pPerf->SetNotificationHandle(0, 0); CloseHandle(g_hNotify);
アプリケーションのメッセージ ループで、イベントを作成して通知メッセージを取り出す必要はない。IDirectMusicPerformance::AddNotificationType メソッドを呼び出して通知を要求している場合、メッセージはパフォーマンスによって送信され、IDirectMusicPerformance::GetNotificationPMsg の呼び出しで取り出すことができる。
イベントが通知される場合、またはメッセージ ループで GetNotificationPMsg を呼び出す場合は、複数のメッセージを待機することができる。すべての通知を確実に受け取るには、S_FALSE が返されるまで GetNotificationPMsg の呼び出しを繰り返す。
同じタイム スタンプを持つメッセージが複数ある場合、これらのメッセージはキューに格納されるときに特定の順序にはならない。
IDirectMusicPerformance::FreePMsg メソッドを呼び出して、取り出したイベントを解放するのは開発者の責任である。
通知を受けたい音楽イベントの種類を指定するには、イベントの種類ごとに一度だけ DirectMusicPerformance.AddNotificationType メソッドを呼び出す。次のコード例では、DirectMusic にセグメント イベントを要求している。perf は DirectMusicPerformance オブジェクトである。イベントの種類 (セグメントの開始やセグメントの終了など) は、通知メッセージから得られる。
Call perf.AddNotificationType(DMUS_NOTIFY_ON_SEGMENT)
通知は、DMUS_NOTIFICATION_PMSG メッセージ タイプの形式で送られる。Sub Main またはその他のループで DirectMusicPerformance.GetNotificationPMsg メソッドを呼び出して、保留中の通知メッセージをポーリングすることができる。また、メッセージが保留中のときに、DirectMusic に別のスレッドでイベント オブジェクトを通知させることもできる。
DirectMusic にイベントを通知させるには、DirectX7.CreateEvent を使ってイベント ハンドルを取得し、このハンドルをDirectMusicPerformance.SetNotificationHandle に渡す。CreateEvent に渡すモジュールは、DirectXEvent クラスを実装し、DirectXEvent.DXCallback メソッドの実装を提供しなければならない。これは、イベントが通知されるたびに DirectMusic によって呼び出される。
次のコード例は、frmMain というフォーム モジュールの通知を設定している。
' DX は DirectX7 オブジェクトを表し、perf は DirectMusicPerformance オブジェクトを表す。 Dim hEvent As Long hEvent = DX.CreateEvent(frmMain) Call perf.SetNotificationHandle(hEvent)
フォーム モジュールには、次に示すものと同様なコードが含まれる。このコードは、セグメントが演奏を終了したことを示すメッセージを検索する。
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 ' セグメントが演奏を終了している。 End If End If Loop Until Not GotMSG End Sub
アプリケーションのメイン ループで、イベントを作成して通知メッセージを取り出す必要はない。DirectMusicPerformance.AddNotificationType メソッドを呼び出して通知を要求している場合、メッセージはパフォーマンスによって送信され、DirectMusicPerformance.GetNotificationPMsg の呼び出しで取り出すことができる。
イベントが通知される場合、またはループで GetNotificationPMsg を呼び出す場合は、複数のメッセージを待機することができる。すべての通知を確実に受け取るには、False が返されるまで GetNotificationPMsg の呼び出しを繰り返す。
同じタイム スタンプを持つメッセージが複数ある場合、これらのメッセージはキューに格納されるときに特定の順序にはならない。