dmutil.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:34k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: DMUtil.cpp
  3. //
  4. // Desc: DirectMusic framework classes for playing DirectMusic segments and
  5. //       DirectMusic scripts. Feel free to use this class as a starting point 
  6. //       for adding extra functionality.
  7. //
  8. // Copyright (c) Microsoft Corp. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #define STRICT
  11. #include <dmusicc.h>
  12. #include <dmusici.h>
  13. #include <dsound.h>
  14. #include <dxerr9.h>
  15. #include "DMUtil.h"
  16. #include "DXUtil.h"
  17. //-----------------------------------------------------------------------------
  18. // Name: CMusicManager::CMusicManager()
  19. // Desc: Constructs the class
  20. //-----------------------------------------------------------------------------
  21. CMusicManager::CMusicManager()
  22. {
  23.     m_pLoader       = NULL;
  24.     m_pPerformance  = NULL;
  25.     m_pDSListener   = NULL;
  26.     
  27.     // Initialize COM
  28.     HRESULT hr = CoInitialize(NULL);
  29.     m_bCleanupCOM = SUCCEEDED(hr);
  30. }
  31. //-----------------------------------------------------------------------------
  32. // Name: CMusicManager::~CMusicManager()
  33. // Desc: Destroys the class
  34. //-----------------------------------------------------------------------------
  35. CMusicManager::~CMusicManager()
  36. {
  37.     SAFE_RELEASE( m_pLoader ); 
  38.     SAFE_RELEASE( m_pDSListener );
  39.     if( m_pPerformance )
  40.     {
  41.         // If there is any music playing, stop it.
  42.         m_pPerformance->Stop( NULL, NULL, 0, 0 );
  43.         m_pPerformance->CloseDown();
  44.         SAFE_RELEASE( m_pPerformance );
  45.     }
  46.     if( m_bCleanupCOM )
  47.         CoUninitialize();
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Name: CMusicManager::Initialize()
  51. // Desc: Inits DirectMusic using a standard audio path
  52. //-----------------------------------------------------------------------------
  53. HRESULT CMusicManager::Initialize( HWND hWnd, DWORD dwPChannels, DWORD dwDefaultPathType, LPDIRECTSOUND pDS )
  54. {
  55.     HRESULT hr;
  56.     IDirectSound** ppDirectSound;
  57.     if( pDS )
  58.         ppDirectSound = &pDS;
  59.     else
  60.         ppDirectSound = NULL;
  61.  
  62.     // Create loader object
  63.     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, 
  64.                                        IID_IDirectMusicLoader8, (void**)&m_pLoader ) ) )
  65.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  66.     // Create performance object
  67.     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, 
  68.                                        IID_IDirectMusicPerformance8, (void**)&m_pPerformance ) ) )
  69.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  70.     // Initialize the performance with the standard audio path.
  71.     // This initializes both DirectMusic and DirectSound and 
  72.     // sets up the synthesizer. Typcially its easist to use an 
  73.     // audio path for playing music and sound effects.
  74.     if( FAILED( hr = m_pPerformance->InitAudio( NULL, ppDirectSound, hWnd, dwDefaultPathType, 
  75.                                                 dwPChannels, DMUS_AUDIOF_ALL, NULL ) ) )
  76.     {
  77.         if( hr == DSERR_NODRIVER )
  78.         {
  79.             DXTRACE( TEXT("Warning: No sound card foundn") );
  80.             return hr;
  81.         }
  82.         return DXTRACE_ERR_MSGBOX( TEXT("InitAudio"), hr );
  83.     }
  84.     // Get the listener from the in the default audio path.
  85.     IDirectMusicAudioPath8* pAudioPath = GetDefaultAudioPath();
  86.     if( pAudioPath ) // might be NULL if dwDefaultPathType == 0
  87.     {
  88.         if( SUCCEEDED( hr = pAudioPath->GetObjectInPath( 0, DMUS_PATH_PRIMARY_BUFFER, 0,
  89.                                                         GUID_NULL, 0, IID_IDirectSound3DListener, 
  90.                                                         (LPVOID*) &m_pDSListener ) ) )
  91.         {
  92.             // Get listener parameters
  93.             m_dsListenerParams.dwSize = sizeof(DS3DLISTENER);
  94.             m_pDSListener->GetAllParameters( &m_dsListenerParams );
  95.         }
  96.     }
  97.     return S_OK;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Name: CMusicManager::SetSearchDirectory()
  101. // Desc: Sets the search directory.  If not called, the current working
  102. //       directory is used to load content.
  103. //-----------------------------------------------------------------------------
  104. HRESULT CMusicManager::SetSearchDirectory( const TCHAR* strMediaPath )
  105. {
  106.     if( NULL == m_pLoader )
  107.         return E_UNEXPECTED;
  108.     if( NULL == strMediaPath )
  109.         return E_INVALIDARG;
  110.     // DMusic only takes wide strings
  111.     WCHAR wstrMediaPath[MAX_PATH];
  112.     DXUtil_ConvertGenericStringToWideCch( wstrMediaPath, strMediaPath, sizeof(wstrMediaPath)/sizeof(TCHAR) );
  113.     return m_pLoader->SetSearchDirectory( GUID_DirectMusicAllTypes, 
  114.                                           wstrMediaPath, FALSE );
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Name: CMusicManager::GetDefaultAudioPath()
  118. // Desc: 
  119. //-----------------------------------------------------------------------------
  120. IDirectMusicAudioPath8* CMusicManager::GetDefaultAudioPath()
  121. {
  122.     IDirectMusicAudioPath8* pAudioPath = NULL;
  123.     if( NULL == m_pPerformance )
  124.         return NULL;
  125.     m_pPerformance->GetDefaultAudioPath( &pAudioPath );
  126.     return pAudioPath;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Name: CMusicManager::CollectGarbage()
  130. // Desc: Tells the loader to cleanup any garbage from previously 
  131. //       released objects.
  132. //-----------------------------------------------------------------------------
  133. VOID CMusicManager::CollectGarbage()
  134. {
  135.     if( m_pLoader )
  136.         m_pLoader->CollectGarbage();
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Name: CMusicManager::StopAll()
  140. // Desc: Stops all segments.  Also simply calling Stop() on the segment won't 
  141. //       stop any MIDI sustain pedals, but calling StopAll() will.
  142. //-----------------------------------------------------------------------------
  143. VOID CMusicManager::StopAll()
  144. {
  145.     if( m_pPerformance )
  146.         m_pPerformance->Stop( NULL, NULL, 0, 0 );
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Name: CMusicManager::CreateSegmentFromFile()
  150. // Desc: 
  151. //-----------------------------------------------------------------------------
  152. HRESULT CMusicManager::CreateSegmentFromFile( CMusicSegment** ppSegment, 
  153.                                               LPCTSTR strFileName, 
  154.                                               BOOL bDownloadNow,
  155.                                               BOOL bIsMidiFile )
  156. {
  157.     HRESULT               hr;
  158.     IDirectMusicSegment8* pSegment = NULL;
  159.     // DMusic only takes wide strings
  160.     WCHAR wstrFileName[MAX_PATH];
  161.     DXUtil_ConvertGenericStringToWideCch( wstrFileName, strFileName, sizeof(wstrFileName)/sizeof(TCHAR) );
  162.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
  163.                                                      IID_IDirectMusicSegment8,
  164.                                                      wstrFileName,
  165.                                                      (LPVOID*) &pSegment ) ) )
  166.     {
  167.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  168.             return hr;
  169.         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
  170.     }
  171.     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
  172.     if (!*ppSegment)
  173.         return E_OUTOFMEMORY;
  174.     if( bIsMidiFile )
  175.     {
  176.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  177.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  178.             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
  179.     }
  180.     if( bDownloadNow )
  181.     {
  182.         if( FAILED( hr = (*ppSegment)->Download() ) )
  183.             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
  184.     }
  185.     return S_OK;
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Name: CMusicManager::CreateSegmentFromResource()
  189. // Desc: 
  190. //-----------------------------------------------------------------------------
  191. HRESULT CMusicManager::CreateSegmentFromResource( CMusicSegment** ppSegment, 
  192.                                                   LPCTSTR strResource,
  193.                                                   LPCTSTR strResourceType,
  194.                                                   BOOL bDownloadNow,
  195.                                                   BOOL bIsMidiFile )
  196. {
  197.     HRESULT               hr;
  198.     IDirectMusicSegment8* pSegment      = NULL;
  199.     HRSRC                 hres          = NULL;
  200.     void*                 pMem          = NULL;
  201.     DWORD                 dwSize        = 0;
  202.     DMUS_OBJECTDESC       objdesc;
  203.     // Find the resource
  204.     hres = FindResource( NULL,strResource,strResourceType );
  205.     if( NULL == hres ) 
  206.         return E_FAIL;
  207.     // Load the resource
  208.     pMem = (void*)LoadResource( NULL, hres );
  209.     if( NULL == pMem ) 
  210.         return E_FAIL;
  211.     // Store the size of the resource
  212.     dwSize = SizeofResource( NULL, hres ); 
  213.     
  214.     // Set up our object description 
  215.     ZeroMemory(&objdesc,sizeof(DMUS_OBJECTDESC));
  216.     objdesc.dwSize = sizeof(DMUS_OBJECTDESC);
  217.     objdesc.dwValidData = DMUS_OBJ_MEMORY | DMUS_OBJ_CLASS;
  218.     objdesc.guidClass = CLSID_DirectMusicSegment;
  219.     objdesc.llMemLength =(LONGLONG)dwSize;
  220.     objdesc.pbMemData = (BYTE*)pMem;
  221.     
  222.     if (FAILED ( hr = m_pLoader->GetObject( &objdesc,
  223.                                             IID_IDirectMusicSegment8,
  224.                                             (void**)&pSegment ) ) )
  225.     {
  226.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  227.             return hr;
  228.         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
  229.     }
  230.     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
  231.     if( NULL == *ppSegment )
  232.         return E_OUTOFMEMORY;
  233.     if( bIsMidiFile )
  234.     {
  235.         // Do this to make sure that the default General MIDI set 
  236.         // is connected appropriately to the MIDI file and 
  237.         // all instruments sound correct.                  
  238.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  239.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  240.             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
  241.     }
  242.     if( bDownloadNow )
  243.     {
  244.         // The segment needs to be download first before playing.  
  245.         // However, some apps may want to wait before calling this 
  246.         // to because the download allocates memory for the 
  247.         // instruments. The more instruments currently downloaded, 
  248.         // the more memory is in use by the synthesizer.
  249.         if( FAILED( hr = (*ppSegment)->Download() ) )
  250.             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
  251.     }
  252.     return S_OK;
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Name: CMusicManager::Create3DSegmentFromFile()
  256. // Desc: 
  257. //-----------------------------------------------------------------------------
  258. HRESULT CMusicManager::Create3DSegmentFromFile( C3DMusicSegment** pp3DMusicSegment, 
  259.                                               LPCTSTR strFileName, 
  260.                                               BOOL bDownloadNow,
  261.                                               BOOL bIsMidiFile,
  262.                                               IDirectMusicAudioPath8* p3DAudioPath )
  263. {
  264.     HRESULT               hr;
  265.     IDirectMusicSegment8* pSegment = NULL;
  266.     // DMusic only takes wide strings
  267.     WCHAR wstrFileName[MAX_PATH];
  268.     DXUtil_ConvertGenericStringToWideCch( wstrFileName, strFileName, sizeof(wstrFileName)/sizeof(TCHAR) );
  269.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
  270.                                                      IID_IDirectMusicSegment8,
  271.                                                      wstrFileName,
  272.                                                      (LPVOID*) &pSegment ) ) )
  273.     {
  274.         if( hr == DMUS_E_LOADER_FAILEDOPEN )
  275.             return hr;
  276.         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
  277.     }
  278.     *pp3DMusicSegment = new C3DMusicSegment( m_pPerformance, m_pLoader, pSegment, p3DAudioPath );
  279.     if (!*pp3DMusicSegment)
  280.         return E_OUTOFMEMORY;
  281.     if( FAILED( hr = (*pp3DMusicSegment)->Init() ) ) 
  282.         return DXTRACE_ERR( TEXT("SetParam"), hr );
  283.     if( bIsMidiFile )
  284.     {
  285.         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
  286.                                              0xFFFFFFFF, 0, 0, NULL ) ) )
  287.             return DXTRACE_ERR( TEXT("SetParam"), hr );
  288.     }
  289.     if( bDownloadNow )
  290.     {
  291.         if( FAILED( hr = (*pp3DMusicSegment)->Download() ) )
  292.             return DXTRACE_ERR( TEXT("Download"), hr );
  293.     }
  294.     return S_OK;
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Name: CMusicManager::CreateScriptFromFile()
  298. // Desc: 
  299. //-----------------------------------------------------------------------------
  300. HRESULT CMusicManager::CreateScriptFromFile( CMusicScript** ppScript, 
  301.                                              LPCTSTR strFileName )
  302. {
  303.     HRESULT               hr;
  304.     IDirectMusicScript* pScript = NULL;
  305.     // DMusic only takes wide strings
  306.     WCHAR wstrFileName[MAX_PATH];
  307.     DXUtil_ConvertGenericStringToWideCch( wstrFileName, strFileName, sizeof(wstrFileName)/sizeof(TCHAR) );
  308.     
  309.     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicScript,
  310.                                                      IID_IDirectMusicScript8,
  311.                                                      wstrFileName,
  312.                                                      (LPVOID*) &pScript ) ) )
  313.         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
  314.     if ( FAILED( hr = pScript->Init( m_pPerformance, NULL ) ) )
  315.         return DXTRACE_ERR_MSGBOX( TEXT("Init"), hr );
  316.     *ppScript = new CMusicScript( m_pPerformance, m_pLoader, pScript );
  317.     if (!*ppScript)
  318.         return E_OUTOFMEMORY;
  319.     return hr;
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Name: CMusicManager::CreateChordMapFromFile()
  323. // Desc: 
  324. //-----------------------------------------------------------------------------
  325. HRESULT CMusicManager::CreateChordMapFromFile( IDirectMusicChordMap8** ppChordMap, 
  326.                                                LPCTSTR strFileName )
  327. {
  328.     // DMusic only takes wide strings
  329.     WCHAR wstrFileName[MAX_PATH];
  330.     DXUtil_ConvertGenericStringToWideCch( wstrFileName, strFileName, sizeof(wstrFileName)/sizeof(TCHAR) );
  331.     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicChordMap,
  332.                                           IID_IDirectMusicChordMap8,
  333.                                           wstrFileName, (LPVOID*) ppChordMap );
  334. }
  335. //-----------------------------------------------------------------------------
  336. // Name: CMusicManager::CreateChordMapFromFile()
  337. // Desc: 
  338. //-----------------------------------------------------------------------------
  339. HRESULT CMusicManager::CreateStyleFromFile( IDirectMusicStyle8** ppStyle, 
  340.                                             LPCTSTR strFileName )
  341. {
  342.     // DMusic only takes wide strings
  343.     WCHAR wstrFileName[MAX_PATH];
  344.     DXUtil_ConvertGenericStringToWideCch( wstrFileName, strFileName, sizeof(wstrFileName)/sizeof(TCHAR) );
  345.     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicStyle,
  346.                                           IID_IDirectMusicStyle8,
  347.                                           wstrFileName, (LPVOID*) ppStyle );
  348. }
  349. //-----------------------------------------------------------------------------
  350. // Name: CMusicManager::GetMotifFromStyle()
  351. // Desc: 
  352. //-----------------------------------------------------------------------------
  353. HRESULT CMusicManager::GetMotifFromStyle( IDirectMusicSegment8** ppMotif8, 
  354.                                           LPCTSTR strStyle, LPCTSTR strMotif )
  355. {       
  356.     UNREFERENCED_PARAMETER( strMotif );
  357.     HRESULT              hr;
  358.     IDirectMusicStyle8*  pStyle = NULL;
  359.     IDirectMusicSegment* pMotif = NULL;
  360.     if( FAILED( hr = CreateStyleFromFile( &pStyle, strStyle ) ) )
  361.         return DXTRACE_ERR_MSGBOX( TEXT("CreateStyleFromFile"), hr );
  362.     if( pStyle )
  363.     {
  364.         // DMusic only takes wide strings
  365.         WCHAR wstrMotif[MAX_PATH];
  366.         DXUtil_ConvertGenericStringToWideCch( wstrMotif, strStyle, sizeof(wstrMotif)/sizeof(TCHAR) );
  367.         hr = pStyle->GetMotif( wstrMotif, &pMotif );
  368.         SAFE_RELEASE( pStyle );
  369.         if( FAILED( hr ) )
  370.             return DXTRACE_ERR_MSGBOX( TEXT("GetMotif"), hr );
  371.         pMotif->QueryInterface( IID_IDirectMusicSegment8, (LPVOID*) ppMotif8 );
  372.     }
  373.     return S_OK;
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Name: Set3DParameters
  377. // Desc: 
  378. //-----------------------------------------------------------------------------
  379. VOID CMusicManager::Set3DParameters( FLOAT fDistanceFactor, FLOAT fDopplerFactor, FLOAT fRolloffFactor )
  380. {
  381.     m_dsListenerParams.flDistanceFactor = fDistanceFactor;
  382.     m_dsListenerParams.flDopplerFactor = fDopplerFactor;
  383.     m_dsListenerParams.flRolloffFactor = fRolloffFactor;
  384.     if( m_pDSListener )
  385.         m_pDSListener->SetAllParameters( &m_dsListenerParams, DS3D_IMMEDIATE );
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Name: CMusicSegment::CMusicSegment()
  389. // Desc: Constructs the class
  390. //-----------------------------------------------------------------------------
  391. CMusicSegment::CMusicSegment( IDirectMusicPerformance8* pPerformance, 
  392.                               IDirectMusicLoader8*      pLoader,
  393.                               IDirectMusicSegment8*     pSegment )
  394. {
  395.     m_pPerformance          = pPerformance;
  396.     m_pLoader               = pLoader;
  397.     m_pSegment              = pSegment;
  398.     m_pEmbeddedAudioPath    = NULL;
  399.     m_bDownloaded           = FALSE;
  400.     
  401.     // Try to pull out an audio path from the segment itself if there is one.
  402.     // This embedded audio path will be used instead of the default
  403.     // audio path if the app doesn't wish to use an overriding audio path.
  404.     IUnknown* pConfig = NULL;
  405.     if( SUCCEEDED( m_pSegment->GetAudioPathConfig( &pConfig ) ) )
  406.     {
  407.         m_pPerformance->CreateAudioPath( pConfig, TRUE, &m_pEmbeddedAudioPath );
  408.         SAFE_RELEASE( pConfig );
  409.     } 
  410. }
  411. //-----------------------------------------------------------------------------
  412. // Name: CMusicSegment::~CMusicSegment()
  413. // Desc: Destroys the class
  414. //-----------------------------------------------------------------------------
  415. CMusicSegment::~CMusicSegment()
  416. {
  417.     if( m_pSegment )
  418.     {
  419.         // Tell the loader that this object should now be released
  420.         if( m_pLoader )
  421.             m_pLoader->ReleaseObjectByUnknown( m_pSegment );
  422.         if( m_bDownloaded )
  423.         {
  424.             if( m_pEmbeddedAudioPath )
  425.                 m_pSegment->Unload( m_pEmbeddedAudioPath );
  426.             else
  427.                 m_pSegment->Unload( m_pPerformance );
  428.         }
  429.         SAFE_RELEASE( m_pEmbeddedAudioPath ); 
  430.         SAFE_RELEASE( m_pSegment ); 
  431.     }
  432.     m_pPerformance = NULL;
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Name: CMusicSegment::Play()
  436. // Desc: Plays the sound using voice management flags.  Pass in DSBPLAY_LOOPING
  437. //       in the dwFlags to loop the sound
  438. //-----------------------------------------------------------------------------
  439. HRESULT CMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
  440. {
  441.     if( m_pSegment == NULL || m_pPerformance == NULL )
  442.         return CO_E_NOTINITIALIZED;
  443.     if( !m_bDownloaded )
  444.         return E_FAIL;
  445.     // If an audio path was passed in then use it, otherwise
  446.     // use the embedded audio path if there was one.
  447.     if( pAudioPath == NULL && m_pEmbeddedAudioPath != NULL )
  448.         pAudioPath = m_pEmbeddedAudioPath;
  449.         
  450.     // If pAudioPath is NULL then this plays on the default audio path.
  451.     return m_pPerformance->PlaySegmentEx( m_pSegment, 0, NULL, dwFlags, 
  452.                                           0, 0, NULL, pAudioPath );
  453. }
  454. //-----------------------------------------------------------------------------
  455. // Name: CMusicSegment::Download()
  456. // Desc: 
  457. //-----------------------------------------------------------------------------
  458. HRESULT CMusicSegment::Download( IDirectMusicAudioPath8* pAudioPath )
  459. {
  460.     HRESULT hr;
  461.     
  462.     if( m_pSegment == NULL )
  463.         return CO_E_NOTINITIALIZED;
  464.     // If no audio path was passed in, then download
  465.     // to the embedded audio path if it exists 
  466.     // else download to the performance
  467.     if( pAudioPath == NULL )
  468.     {
  469.         if( m_pEmbeddedAudioPath )
  470.             hr = m_pSegment->Download( m_pEmbeddedAudioPath );
  471.         else    
  472.             hr = m_pSegment->Download( m_pPerformance );
  473.     }
  474.     else
  475.     {
  476.         hr = m_pSegment->Download( pAudioPath );
  477.     }
  478.     
  479.     if ( SUCCEEDED( hr ) )
  480.         m_bDownloaded = TRUE;
  481.         
  482.     return hr;
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Name: CMusicSegment::Unload()
  486. // Desc: 
  487. //-----------------------------------------------------------------------------
  488. HRESULT CMusicSegment::Unload( IDirectMusicAudioPath8* pAudioPath )
  489. {
  490.     HRESULT hr;
  491.     
  492.     if( m_pSegment == NULL )
  493.         return CO_E_NOTINITIALIZED;
  494.     // If no audio path was passed in, then unload 
  495.     // from the embedded audio path if it exists 
  496.     // else unload from the performance
  497.     if( pAudioPath == NULL )
  498.     {
  499.         if( m_pEmbeddedAudioPath )
  500.             hr = m_pSegment->Unload( m_pEmbeddedAudioPath );
  501.         else    
  502.             hr = m_pSegment->Unload( m_pPerformance );
  503.     }
  504.     else
  505.     {
  506.         hr = m_pSegment->Unload( pAudioPath );
  507.     }
  508.         
  509.     if ( SUCCEEDED( hr ) )
  510.         m_bDownloaded = FALSE;
  511.     return hr;
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Name: CMusicSegment::IsPlaying()
  515. // Desc: 
  516. //-----------------------------------------------------------------------------
  517. BOOL CMusicSegment::IsPlaying()
  518. {
  519.     if( m_pSegment == NULL || m_pPerformance == NULL )
  520.         return FALSE;
  521.     return ( m_pPerformance->IsPlaying( m_pSegment, NULL ) == S_OK );
  522. }
  523. //-----------------------------------------------------------------------------
  524. // Name: CMusicSegment::Stop()
  525. // Desc: Stops the sound from playing
  526. //-----------------------------------------------------------------------------
  527. HRESULT CMusicSegment::Stop( DWORD dwFlags )
  528. {
  529.     if( m_pSegment == NULL || m_pPerformance == NULL )
  530.         return CO_E_NOTINITIALIZED;
  531.     return m_pPerformance->Stop( m_pSegment, NULL, 0, dwFlags );;
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Name: CMusicSegment::SetRepeats()
  535. // Desc: 
  536. //-----------------------------------------------------------------------------
  537. HRESULT CMusicSegment::SetRepeats( DWORD dwRepeats )
  538. {
  539.     if( m_pSegment == NULL )
  540.         return CO_E_NOTINITIALIZED;
  541.     return m_pSegment->SetRepeats( dwRepeats );
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Name: CMusicSegment::GetStyle()
  545. // Desc: 
  546. //-----------------------------------------------------------------------------
  547. HRESULT CMusicSegment::GetStyle( IDirectMusicStyle8** ppStyle, DWORD dwStyleIndex )
  548. {
  549.     // Get the Style from the Segment by calling the Segment's GetData() with
  550.     // the data type GUID_StyleTrackStyle. 0xffffffff indicates to look at
  551.     // tracks in all TrackGroups in the segment. The first 0 indicates to
  552.     // retrieve the Style from the first Track  in the indicated TrackGroup.
  553.     // The second 0 indicates to retrieve the Style from the beginning of the
  554.     // segment, i.e. time 0 in Segment time. If this Segment was loaded from a
  555.     // section file, there is only one Style and it is at time 0.
  556.     return m_pSegment->GetParam( GUID_IDirectMusicStyle, 0xffffffff, dwStyleIndex, 
  557.                                  0, NULL, (VOID*)ppStyle );
  558. }
  559. //-----------------------------------------------------------------------------
  560. // Name: C3DMusicSegment::C3DMusicSegment()
  561. // Desc: Constructs the class
  562. //-----------------------------------------------------------------------------
  563. C3DMusicSegment::C3DMusicSegment( IDirectMusicPerformance8* pPerformance, 
  564.                               IDirectMusicLoader8*      pLoader,
  565.                               IDirectMusicSegment8*     pSegment,
  566.                               IDirectMusicAudioPath8* pAudioPath ) :
  567.     CMusicSegment( pPerformance, pLoader, pSegment )
  568. {
  569.     m_p3DAudioPath      = pAudioPath;
  570.     m_pDS3DBuffer       = NULL;
  571.     m_bDeferSettings    = FALSE;
  572.     m_bCleanupAudioPath = FALSE;
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Name: C3DMusicSegment::~C3DMusicSegment()
  576. // Desc: Destroys the class
  577. //-----------------------------------------------------------------------------
  578. C3DMusicSegment::~C3DMusicSegment()
  579. {
  580.     SAFE_RELEASE( m_pDS3DBuffer );
  581.     if( m_bCleanupAudioPath )
  582.         SAFE_RELEASE( m_p3DAudioPath );
  583. }
  584. //-----------------------------------------------------------------------------
  585. // Name: Init()
  586. // Desc: 
  587. //-----------------------------------------------------------------------------
  588. HRESULT C3DMusicSegment::Init()
  589. {
  590.     HRESULT hr;
  591.     if( NULL == m_p3DAudioPath )
  592.     {
  593.         // Create a 3D audiopath with a 3d buffer.
  594.         // We can then play all segments into this buffer and directly control its
  595.         // 3D parameters.
  596.         if( FAILED( hr = m_pPerformance->CreateStandardAudioPath( DMUS_APATH_DYNAMIC_3D, 
  597.                                                                 64, TRUE, &m_p3DAudioPath ) ) )
  598.             return DXTRACE_ERR( TEXT("CreateStandardAudioPath"), hr );
  599.         m_bCleanupAudioPath = TRUE;
  600.     }
  601.     // Get the 3D buffer in the audio path.
  602.     if( FAILED( hr = m_p3DAudioPath->GetObjectInPath( 0, DMUS_PATH_BUFFER, 0,
  603.                                                       GUID_NULL, 0, IID_IDirectSound3DBuffer, 
  604.                                                       (LPVOID*) &m_pDS3DBuffer ) ) )
  605.         return DXTRACE_ERR( TEXT("GetObjectInPath"), hr );
  606.     // Get the 3D buffer parameters
  607.     m_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
  608.     m_pDS3DBuffer->GetAllParameters( &m_dsBufferParams );
  609.     // Set new 3D buffer parameters
  610.     m_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
  611.     m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, DS3D_IMMEDIATE );
  612.    
  613.     return S_OK;
  614. }
  615. //-----------------------------------------------------------------------------
  616. // Name: Play
  617. // Desc: 
  618. //-----------------------------------------------------------------------------
  619. HRESULT C3DMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
  620. {
  621.     if( pAudioPath ) 
  622.         return CMusicSegment::Play( dwFlags, pAudioPath );
  623.     else
  624.         return CMusicSegment::Play( dwFlags, m_p3DAudioPath );
  625. }
  626. //-----------------------------------------------------------------------------
  627. // Name: Set3DParameters
  628. // Desc: 
  629. //-----------------------------------------------------------------------------
  630. VOID C3DMusicSegment::Set3DParameters( FLOAT fMinDistance, FLOAT fMaxDistance )
  631. {
  632.     // Every change to 3-D sound buffer and listener settings causes 
  633.     // DirectSound to remix, at the expense of CPU cycles. 
  634.     // To minimize the performance impact of changing 3-D settings, 
  635.     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
  636.     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
  637.     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
  638.     // method to execute all of the deferred commands at once.
  639.     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
  640.     m_dsBufferParams.flMinDistance = fMinDistance;
  641.     m_dsBufferParams.flMaxDistance = fMaxDistance;
  642.     if( m_pDS3DBuffer )
  643.         m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, dwApplyFlag );
  644. }
  645. //-----------------------------------------------------------------------------
  646. // Name: SetObjectProperties
  647. // Desc: 
  648. //-----------------------------------------------------------------------------
  649. VOID C3DMusicSegment::SetObjectProperties( D3DVECTOR* pvPosition, D3DVECTOR* pvVelocity )
  650. {
  651.     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
  652.     // Every change to 3-D sound buffer and listener settings causes 
  653.     // DirectSound to remix, at the expense of CPU cycles. 
  654.     // To minimize the performance impact of changing 3-D settings, 
  655.     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
  656.     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
  657.     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
  658.     // method to execute all of the deferred commands at once.
  659.     memcpy( &m_dsBufferParams.vPosition, pvPosition, sizeof(D3DVECTOR) );
  660.     memcpy( &m_dsBufferParams.vVelocity, pvVelocity, sizeof(D3DVECTOR) );
  661.     if( m_pDS3DBuffer )
  662.     {
  663.         m_pDS3DBuffer->SetPosition( m_dsBufferParams.vPosition.x,
  664.                                     m_dsBufferParams.vPosition.y,
  665.                                     m_dsBufferParams.vPosition.z, dwApplyFlag );
  666.         m_pDS3DBuffer->SetVelocity( m_dsBufferParams.vVelocity.x,
  667.                                     m_dsBufferParams.vVelocity.y,
  668.                                     m_dsBufferParams.vVelocity.z, dwApplyFlag );
  669.     }
  670. }
  671. //-----------------------------------------------------------------------------
  672. // Name: CMusicScript::CMusicScript()
  673. // Desc: Constructs the class
  674. //-----------------------------------------------------------------------------
  675. CMusicScript::CMusicScript( IDirectMusicPerformance8* pPerformance, 
  676.                             IDirectMusicLoader8* pLoader,                   
  677.                             IDirectMusicScript8* pScript )
  678. {
  679.     m_pPerformance = pPerformance;
  680.     m_pLoader      = pLoader;
  681.     m_pScript      = pScript;
  682. }
  683. //-----------------------------------------------------------------------------
  684. // Name: CMusicScript::~CMusicScript()
  685. // Desc: Destroys the class
  686. //-----------------------------------------------------------------------------
  687. CMusicScript::~CMusicScript()
  688. {
  689.     if( m_pLoader )
  690.     {
  691.         // Tell the loader that this object should now be released
  692.         m_pLoader->ReleaseObjectByUnknown( m_pScript );
  693.         m_pLoader = NULL;
  694.     }
  695.     SAFE_RELEASE( m_pScript ); 
  696.     m_pPerformance = NULL;
  697. }
  698. //-----------------------------------------------------------------------------
  699. // Name: CMusicScript::Play()
  700. // Desc: Calls a routine in the script
  701. //-----------------------------------------------------------------------------
  702. HRESULT CMusicScript::CallRoutine( LPCTSTR strRoutine )
  703. {
  704.     // DMusic only takes wide strings
  705.     WCHAR wstrRoutine[MAX_PATH];
  706.     DXUtil_ConvertGenericStringToWideCch( wstrRoutine, strRoutine, sizeof(wstrRoutine)/sizeof(TCHAR) );
  707.     return m_pScript->CallRoutine( wstrRoutine, NULL );
  708. }
  709. //-----------------------------------------------------------------------------
  710. // Name: CMusicScript::SetVariableNumber()
  711. // Desc: Sets the value of a variable in the script
  712. //-----------------------------------------------------------------------------
  713. HRESULT CMusicScript::SetVariableNumber( LPCTSTR strVariable, LONG lValue )
  714. {
  715.     // DMusic only takes wide strings
  716.     WCHAR wstrVariable[MAX_PATH];
  717.     DXUtil_ConvertGenericStringToWideCch( wstrVariable, strVariable, sizeof(wstrVariable)/sizeof(TCHAR) );
  718.     return m_pScript->SetVariableNumber( wstrVariable, lValue, NULL );
  719. }
  720. //-----------------------------------------------------------------------------
  721. // Name: CMusicScript::GetVariableNumber()
  722. // Desc: Gets the value of a variable in the script
  723. //-----------------------------------------------------------------------------
  724. HRESULT CMusicScript::GetVariableNumber( LPCTSTR strVariable, LONG* plValue )
  725. {
  726.     // DMusic only takes wide strings
  727.     WCHAR wstrVariable[MAX_PATH];
  728.     DXUtil_ConvertGenericStringToWideCch( wstrVariable, strVariable, sizeof(wstrVariable)/sizeof(TCHAR) );
  729.     return m_pScript->GetVariableNumber( wstrVariable, plValue, NULL );
  730. }
  731. //-----------------------------------------------------------------------------
  732. // Name: CMusicScript::SetVariableObject()
  733. // Desc: Sets an object in the script
  734. //-----------------------------------------------------------------------------
  735. HRESULT CMusicScript::SetVariableObject( LPCTSTR strVariable, IUnknown *punkValue )
  736. {
  737.     // DMusic only takes wide strings
  738.     WCHAR wstrVariable[MAX_PATH];
  739.     DXUtil_ConvertGenericStringToWideCch( wstrVariable, strVariable, sizeof(wstrVariable)/sizeof(TCHAR) );
  740.     return m_pScript->SetVariableObject( wstrVariable, punkValue, NULL );
  741. }
  742. //-----------------------------------------------------------------------------
  743. // Name: CMusicScript::GetVariableObject()
  744. // Desc: Gets an object from the script
  745. //-----------------------------------------------------------------------------
  746. HRESULT CMusicScript::GetVariableObject( LPCTSTR strVariable, REFIID riid, LPVOID FAR *ppv )
  747. {
  748.     // DMusic only takes wide strings
  749.     WCHAR wstrVariable[MAX_PATH];
  750.     DXUtil_ConvertGenericStringToWideCch( wstrVariable, strVariable, sizeof(wstrVariable)/sizeof(TCHAR) );
  751.     return m_pScript->GetVariableObject( wstrVariable, riid, ppv, NULL );
  752. }