0001: //-----------------------------------------------------------------------------
0002: // File: DMUtil.cpp
0003: //
0004: // Desc: DirectMusic framework classes for playing DirectMusic segments and
0005: //       DirectMusic scripts. Feel free to use this class as a starting point 
0006: //       for adding extra functionality.
0007: //-----------------------------------------------------------------------------
0008: #define STRICT
0009: #include <dmusicc.h>
0010: #include <dmusici.h>
0011: #include <dsound.h>
0012: #include <dxerr9.h>
0013: #include "DMUtil.h"
0014: #include "DXUtil.h"
0015: 
0016: 
0017: 
0018: 
0019: //-----------------------------------------------------------------------------
0020: // Name: CMusicManager::CMusicManager()
0021: // Desc: Constructs the class
0022: //-----------------------------------------------------------------------------
0023: CMusicManager::CMusicManager()
0024: {
0025:     m_pLoader       = NULL;
0026:     m_pPerformance  = NULL;
0027:     m_pDSListener   = NULL;
0028:     
0029:     // Initialize COM
0030:     HRESULT hr = CoInitialize(NULL);
0031:     m_bCleanupCOM = SUCCEEDED(hr);
0032: }
0033: 
0034: 
0035: 
0036: 
0037: //-----------------------------------------------------------------------------
0038: // Name: CMusicManager::~CMusicManager()
0039: // Desc: Destroys the class
0040: //-----------------------------------------------------------------------------
0041: CMusicManager::~CMusicManager()
0042: {
0043:     SAFE_RELEASE( m_pLoader ); 
0044:     SAFE_RELEASE( m_pDSListener );
0045: 
0046:     if( m_pPerformance )
0047:     {
0048:         // If there is any music playing, stop it.
0049:         m_pPerformance->Stop( NULL, NULL, 0, 0 );
0050:         m_pPerformance->CloseDown();
0051: 
0052:         SAFE_RELEASE( m_pPerformance );
0053:     }
0054: 
0055:     if( m_bCleanupCOM )
0056:         CoUninitialize();
0057: }
0058: 
0059: 
0060: 
0061: 
0062: //-----------------------------------------------------------------------------
0063: // Name: CMusicManager::Initialize()
0064: // Desc: Inits DirectMusic using a standard audio path
0065: //-----------------------------------------------------------------------------
0066: HRESULT CMusicManager::Initialize( HWND hWnd, DWORD dwPChannels, DWORD dwDefaultPathType, LPDIRECTSOUND pDS )
0067: {
0068:     HRESULT hr;
0069:     IDirectSound** ppDirectSound;
0070: 
0071:     if( pDS )
0072:         ppDirectSound = &pDS;
0073:     else
0074:         ppDirectSound = NULL;
0075:  
0076:     // Create loader object
0077:     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, 
0078:                                        IID_IDirectMusicLoader8, (void**)&m_pLoader ) ) )
0079:         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
0080: 
0081:     // Create performance object
0082:     if( FAILED( hr = CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, 
0083:                                        IID_IDirectMusicPerformance8, (void**)&m_pPerformance ) ) )
0084:         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
0085: 
0086:     // Initialize the performance with the standard audio path.
0087:     // This initializes both DirectMusic and DirectSound and 
0088:     // sets up the synthesizer. Typcially its easist to use an 
0089:     // audio path for playing music and sound effects.
0090:     if( FAILED( hr = m_pPerformance->InitAudio( NULL, ppDirectSound, hWnd, dwDefaultPathType, 
0091:                                                 dwPChannels, DMUS_AUDIOF_ALL, NULL ) ) )
0092:     {
0093:         if( hr == DSERR_NODRIVER )
0094:         {
0095:             DXTRACE( TEXT("Warning: No sound card found\n") );
0096:             return hr;
0097:         }
0098: 
0099:         return DXTRACE_ERR_MSGBOX( TEXT("InitAudio"), hr );
0100:     }
0101: 
0102:     // Get the listener from the in the default audio path.
0103:     IDirectMusicAudioPath8* pAudioPath = GetDefaultAudioPath();
0104:     if( pAudioPath ) // might be NULL if dwDefaultPathType == 0
0105:     {
0106:         if( SUCCEEDED( hr = pAudioPath->GetObjectInPath( 0, DMUS_PATH_PRIMARY_BUFFER, 0,
0107:                                                         GUID_NULL, 0, IID_IDirectSound3DListener, 
0108:                                                         (LPVOID*) &m_pDSListener ) ) )
0109:         {
0110:             // Get listener parameters
0111:             m_dsListenerParams.dwSize = sizeof(DS3DLISTENER);
0112:             m_pDSListener->GetAllParameters( &m_dsListenerParams );
0113:         }
0114:     }
0115: 
0116:     return S_OK;
0117: }
0118: 
0119: 
0120: 
0121: 
0122: //-----------------------------------------------------------------------------
0123: // Name: CMusicManager::SetSearchDirectory()
0124: // Desc: Sets the search directory.  If not called, the current working
0125: //       directory is used to load content.
0126: //-----------------------------------------------------------------------------
0127: HRESULT CMusicManager::SetSearchDirectory( const TCHAR* strMediaPath )
0128: {
0129:     if( NULL == m_pLoader )
0130:         return E_UNEXPECTED;
0131:     if( NULL == strMediaPath )
0132:         return E_INVALIDARG;
0133: 
0134:     // DMusic only takes wide strings
0135:     WCHAR wstrMediaPath[MAX_PATH];
0136:     DXUtil_ConvertGenericStringToWideCb( wstrMediaPath, strMediaPath, sizeof(wstrMediaPath) );
0137: 
0138:     return m_pLoader->SetSearchDirectory( GUID_DirectMusicAllTypes, 
0139:                                           wstrMediaPath, FALSE );
0140: 
0141: }
0142: 
0143: 
0144: 
0145: 
0146: //-----------------------------------------------------------------------------
0147: // Name: CMusicManager::GetDefaultAudioPath()
0148: // Desc: 
0149: //-----------------------------------------------------------------------------
0150: IDirectMusicAudioPath8* CMusicManager::GetDefaultAudioPath()
0151: {
0152:     IDirectMusicAudioPath8* pAudioPath = NULL;
0153:     if( NULL == m_pPerformance )
0154:         return NULL;
0155: 
0156:     m_pPerformance->GetDefaultAudioPath( &pAudioPath );
0157:     return pAudioPath;
0158: }
0159: 
0160: 
0161: 
0162: 
0163: //-----------------------------------------------------------------------------
0164: // Name: CMusicManager::CollectGarbage()
0165: // Desc: Tells the loader to cleanup any garbage from previously 
0166: //       released objects.
0167: //-----------------------------------------------------------------------------
0168: VOID CMusicManager::CollectGarbage()
0169: {
0170:     if( m_pLoader )
0171:         m_pLoader->CollectGarbage();
0172: }
0173: 
0174: 
0175: 
0176: 
0177: //-----------------------------------------------------------------------------
0178: // Name: CMusicManager::StopAll()
0179: // Desc: Stops all segments.  Also simply calling Stop() on the segment won't 
0180: //       stop any MIDI sustain pedals, but calling StopAll() will.
0181: //-----------------------------------------------------------------------------
0182: VOID CMusicManager::StopAll()
0183: {
0184:     if( m_pPerformance )
0185:         m_pPerformance->Stop( NULL, NULL, 0, 0 );
0186: }
0187: 
0188: 
0189: 
0190: //-----------------------------------------------------------------------------
0191: // Name: CMusicManager::CreateSegmentFromFile()
0192: // Desc: 
0193: //-----------------------------------------------------------------------------
0194: HRESULT CMusicManager::CreateSegmentFromFile( CMusicSegment** ppSegment, 
0195:                                               TCHAR* strFileName, 
0196:                                               BOOL bDownloadNow,
0197:                                               BOOL bIsMidiFile )
0198: {
0199:     HRESULT               hr;
0200:     IDirectMusicSegment8* pSegment = NULL;
0201: 
0202:     // DMusic only takes wide strings
0203:     WCHAR wstrFileName[MAX_PATH];
0204:     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
0205: 
0206:     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
0207:                                                      IID_IDirectMusicSegment8,
0208:                                                      wstrFileName,
0209:                                                      (LPVOID*) &pSegment ) ) )
0210:     {
0211:         if( hr == DMUS_E_LOADER_FAILEDOPEN )
0212:             return hr;
0213:         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
0214:     }
0215: 
0216:     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
0217:     if (!*ppSegment)
0218:         return E_OUTOFMEMORY;
0219: 
0220:     if( bIsMidiFile )
0221:     {
0222:         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
0223:                                              0xFFFFFFFF, 0, 0, NULL ) ) )
0224:             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
0225:     }
0226: 
0227:     if( bDownloadNow )
0228:     {
0229:         if( FAILED( hr = (*ppSegment)->Download() ) )
0230:             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
0231:     }
0232: 
0233:     return S_OK;
0234: }
0235: 
0236: 
0237: 
0238: 
0239: //-----------------------------------------------------------------------------
0240: // Name: CMusicManager::CreateSegmentFromResource()
0241: // Desc: 
0242: //-----------------------------------------------------------------------------
0243: HRESULT CMusicManager::CreateSegmentFromResource( CMusicSegment** ppSegment, 
0244:                                                   TCHAR* strResource,
0245:                                                   TCHAR* strResourceType,
0246:                                                   BOOL bDownloadNow,
0247:                                                   BOOL bIsMidiFile )
0248: {
0249:     HRESULT               hr;
0250:     IDirectMusicSegment8* pSegment      = NULL;
0251:     HRSRC                 hres          = NULL;
0252:     void*                 pMem          = NULL;
0253:     DWORD                 dwSize        = 0;
0254:     DMUS_OBJECTDESC       objdesc;
0255: 
0256:     // Find the resource
0257:     hres = FindResource( NULL,strResource,strResourceType );
0258:     if( NULL == hres ) 
0259:         return E_FAIL;
0260: 
0261:     // Load the resource
0262:     pMem = (void*)LoadResource( NULL, hres );
0263:     if( NULL == pMem ) 
0264:         return E_FAIL;
0265: 
0266:     // Store the size of the resource
0267:     dwSize = SizeofResource( NULL, hres ); 
0268:     
0269:     // Set up our object description 
0270:     ZeroMemory(&objdesc,sizeof(DMUS_OBJECTDESC));
0271:     objdesc.dwSize = sizeof(DMUS_OBJECTDESC);
0272:     objdesc.dwValidData = DMUS_OBJ_MEMORY | DMUS_OBJ_CLASS;
0273:     objdesc.guidClass = CLSID_DirectMusicSegment;
0274:     objdesc.llMemLength =(LONGLONG)dwSize;
0275:     objdesc.pbMemData = (BYTE*)pMem;
0276:     
0277:     if (FAILED ( hr = m_pLoader->GetObject( &objdesc,
0278:                                             IID_IDirectMusicSegment8,
0279:                                             (void**)&pSegment ) ) )
0280:     {
0281:         if( hr == DMUS_E_LOADER_FAILEDOPEN )
0282:             return hr;
0283:         return DXTRACE_ERR_MSGBOX( TEXT("LoadObjectFromFile"), hr );
0284:     }
0285: 
0286:     *ppSegment = new CMusicSegment( m_pPerformance, m_pLoader, pSegment );
0287:     if( NULL == *ppSegment )
0288:         return E_OUTOFMEMORY;
0289: 
0290:     if( bIsMidiFile )
0291:     {
0292:         // Do this to make sure that the default General MIDI set 
0293:         // is connected appropriately to the MIDI file and 
0294:         // all instruments sound correct.                  
0295:         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
0296:                                              0xFFFFFFFF, 0, 0, NULL ) ) )
0297:             return DXTRACE_ERR_MSGBOX( TEXT("SetParam"), hr );
0298:     }
0299: 
0300:     if( bDownloadNow )
0301:     {
0302:         // The segment needs to be download first before playing.  
0303:         // However, some apps may want to wait before calling this 
0304:         // to because the download allocates memory for the 
0305:         // instruments. The more instruments currently downloaded, 
0306:         // the more memory is in use by the synthesizer.
0307:         if( FAILED( hr = (*ppSegment)->Download() ) )
0308:             return DXTRACE_ERR_MSGBOX( TEXT("Download"), hr );
0309:     }
0310: 
0311:     return S_OK;
0312: }
0313: 
0314: 
0315: 
0316: 
0317: //-----------------------------------------------------------------------------
0318: // Name: CMusicManager::Create3DSegmentFromFile()
0319: // Desc: 
0320: //-----------------------------------------------------------------------------
0321: HRESULT CMusicManager::Create3DSegmentFromFile( C3DMusicSegment** pp3DMusicSegment, 
0322:                                               TCHAR* strFileName, 
0323:                                               BOOL bDownloadNow,
0324:                                               BOOL bIsMidiFile,
0325:                                               IDirectMusicAudioPath8* p3DAudioPath )
0326: {
0327:     HRESULT               hr;
0328:     IDirectMusicSegment8* pSegment = NULL;
0329: 
0330:     // DMusic only takes wide strings
0331:     WCHAR wstrFileName[MAX_PATH];
0332:     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
0333: 
0334:     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment,
0335:                                                      IID_IDirectMusicSegment8,
0336:                                                      wstrFileName,
0337:                                                      (LPVOID*) &pSegment ) ) )
0338:     {
0339:         if( hr == DMUS_E_LOADER_FAILEDOPEN )
0340:             return hr;
0341:         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
0342:     }
0343: 
0344:     *pp3DMusicSegment = new C3DMusicSegment( m_pPerformance, m_pLoader, pSegment, p3DAudioPath );
0345:     if (!*pp3DMusicSegment)
0346:         return E_OUTOFMEMORY;
0347: 
0348:     if( FAILED( hr = (*pp3DMusicSegment)->Init() ) ) 
0349:         return DXTRACE_ERR( TEXT("SetParam"), hr );
0350: 
0351:     if( bIsMidiFile )
0352:     {
0353:         if( FAILED( hr = pSegment->SetParam( GUID_StandardMIDIFile, 
0354:                                              0xFFFFFFFF, 0, 0, NULL ) ) )
0355:             return DXTRACE_ERR( TEXT("SetParam"), hr );
0356:     }
0357: 
0358:     if( bDownloadNow )
0359:     {
0360:         if( FAILED( hr = (*pp3DMusicSegment)->Download() ) )
0361:             return DXTRACE_ERR( TEXT("Download"), hr );
0362:     }
0363: 
0364:     return S_OK;
0365: }
0366: 
0367: 
0368: 
0369: 
0370: //-----------------------------------------------------------------------------
0371: // Name: CMusicManager::CreateScriptFromFile()
0372: // Desc: 
0373: //-----------------------------------------------------------------------------
0374: HRESULT CMusicManager::CreateScriptFromFile( CMusicScript** ppScript, 
0375:                                              TCHAR* strFileName )
0376: {
0377:     HRESULT               hr;
0378:     IDirectMusicScript* pScript = NULL;
0379: 
0380:     // DMusic only takes wide strings
0381:     WCHAR wstrFileName[MAX_PATH];
0382:     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
0383:     
0384:     if ( FAILED( hr = m_pLoader->LoadObjectFromFile( CLSID_DirectMusicScript,
0385:                                                      IID_IDirectMusicScript8,
0386:                                                      wstrFileName,
0387:                                                      (LPVOID*) &pScript ) ) )
0388:         return DXTRACE_ERR( TEXT("LoadObjectFromFile"), hr );
0389: 
0390:     if ( FAILED( hr = pScript->Init( m_pPerformance, NULL ) ) )
0391:         return DXTRACE_ERR_MSGBOX( TEXT("Init"), hr );
0392: 
0393:     *ppScript = new CMusicScript( m_pPerformance, m_pLoader, pScript );
0394:     if (!*ppScript)
0395:         return E_OUTOFMEMORY;
0396: 
0397:     return hr;
0398: }
0399: 
0400: 
0401: 
0402: 
0403: //-----------------------------------------------------------------------------
0404: // Name: CMusicManager::CreateChordMapFromFile()
0405: // Desc: 
0406: //-----------------------------------------------------------------------------
0407: HRESULT CMusicManager::CreateChordMapFromFile( IDirectMusicChordMap8** ppChordMap, 
0408:                                                TCHAR* strFileName )
0409: {
0410:     // DMusic only takes wide strings
0411:     WCHAR wstrFileName[MAX_PATH];
0412:     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
0413: 
0414:     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicChordMap,
0415:                                           IID_IDirectMusicChordMap8,
0416:                                           wstrFileName, (LPVOID*) ppChordMap );
0417: }
0418: 
0419: 
0420: 
0421: 
0422: //-----------------------------------------------------------------------------
0423: // Name: CMusicManager::CreateChordMapFromFile()
0424: // Desc: 
0425: //-----------------------------------------------------------------------------
0426: HRESULT CMusicManager::CreateStyleFromFile( IDirectMusicStyle8** ppStyle, 
0427:                                             TCHAR* strFileName )
0428: {
0429:     // DMusic only takes wide strings
0430:     WCHAR wstrFileName[MAX_PATH];
0431:     DXUtil_ConvertGenericStringToWideCb( wstrFileName, strFileName, sizeof(wstrFileName) );
0432: 
0433:     return m_pLoader->LoadObjectFromFile( CLSID_DirectMusicStyle,
0434:                                           IID_IDirectMusicStyle8,
0435:                                           wstrFileName, (LPVOID*) ppStyle );
0436: }
0437: 
0438: 
0439: 
0440: 
0441: //-----------------------------------------------------------------------------
0442: // Name: CMusicManager::GetMotifFromStyle()
0443: // Desc: 
0444: //-----------------------------------------------------------------------------
0445: HRESULT CMusicManager::GetMotifFromStyle( IDirectMusicSegment8** ppMotif8, 
0446:                                           TCHAR* strStyle, TCHAR* strMotif )
0447: {       
0448:     UNREFERENCED_PARAMETER( strMotif );
0449:     
0450:     HRESULT              hr;
0451:     IDirectMusicStyle8*  pStyle = NULL;
0452:     IDirectMusicSegment* pMotif = NULL;
0453: 
0454:     if( FAILED( hr = CreateStyleFromFile( &pStyle, strStyle ) ) )
0455:         return DXTRACE_ERR_MSGBOX( TEXT("CreateStyleFromFile"), hr );
0456: 
0457:     if( pStyle )
0458:     {
0459:         // DMusic only takes wide strings
0460:         WCHAR wstrMotif[MAX_PATH];
0461:         DXUtil_ConvertGenericStringToWideCb( wstrMotif, strStyle, sizeof(wstrMotif) );
0462: 
0463:         hr = pStyle->GetMotif( wstrMotif, &pMotif );
0464:         SAFE_RELEASE( pStyle );
0465: 
0466:         if( FAILED( hr ) )
0467:             return DXTRACE_ERR_MSGBOX( TEXT("GetMotif"), hr );
0468: 
0469:         pMotif->QueryInterface( IID_IDirectMusicSegment8, (LPVOID*) ppMotif8 );
0470:     }
0471: 
0472:     return S_OK;
0473: }
0474: 
0475: 
0476: 
0477: 
0478: //-----------------------------------------------------------------------------
0479: // Name: Set3DParameters
0480: // Desc: 
0481: //-----------------------------------------------------------------------------
0482: VOID CMusicManager::Set3DParameters( FLOAT fDistanceFactor, FLOAT fDopplerFactor, FLOAT fRolloffFactor )
0483: {
0484:     m_dsListenerParams.flDistanceFactor = fDistanceFactor;
0485:     m_dsListenerParams.flDopplerFactor = fDopplerFactor;
0486:     m_dsListenerParams.flRolloffFactor = fRolloffFactor;
0487: 
0488:     if( m_pDSListener )
0489:         m_pDSListener->SetAllParameters( &m_dsListenerParams, DS3D_IMMEDIATE );
0490: }
0491: 
0492: 
0493: 
0494: 
0495: //-----------------------------------------------------------------------------
0496: // Name: CMusicSegment::CMusicSegment()
0497: // Desc: Constructs the class
0498: //-----------------------------------------------------------------------------
0499: CMusicSegment::CMusicSegment( IDirectMusicPerformance8* pPerformance, 
0500:                               IDirectMusicLoader8*      pLoader,
0501:                               IDirectMusicSegment8*     pSegment )
0502: {
0503:     m_pPerformance          = pPerformance;
0504:     m_pLoader               = pLoader;
0505:     m_pSegment              = pSegment;
0506:     m_pEmbeddedAudioPath    = NULL;
0507:     m_bDownloaded           = FALSE;
0508:     
0509:     // Try to pull out an audio path from the segment itself if there is one.
0510:     // This embedded audio path will be used instead of the default
0511:     // audio path if the app doesn't wish to use an overriding audio path.
0512:     IUnknown* pConfig = NULL;
0513:     if( SUCCEEDED( m_pSegment->GetAudioPathConfig( &pConfig ) ) )
0514:     {
0515:         m_pPerformance->CreateAudioPath( pConfig, TRUE, &m_pEmbeddedAudioPath );
0516:         SAFE_RELEASE( pConfig );
0517:     } 
0518: 
0519: }
0520: 
0521: 
0522: 
0523: 
0524: //-----------------------------------------------------------------------------
0525: // Name: CMusicSegment::~CMusicSegment()
0526: // Desc: Destroys the class
0527: //-----------------------------------------------------------------------------
0528: CMusicSegment::~CMusicSegment()
0529: {
0530:     if( m_pSegment )
0531:     {
0532:         // Tell the loader that this object should now be released
0533:         if( m_pLoader )
0534:             m_pLoader->ReleaseObjectByUnknown( m_pSegment );
0535: 
0536:         if( m_bDownloaded )
0537:         {
0538:             if( m_pEmbeddedAudioPath )
0539:                 m_pSegment->Unload( m_pEmbeddedAudioPath );
0540:             else
0541:                 m_pSegment->Unload( m_pPerformance );
0542:         }
0543: 
0544:         SAFE_RELEASE( m_pEmbeddedAudioPath ); 
0545:         SAFE_RELEASE( m_pSegment ); 
0546:     }
0547: 
0548:     m_pPerformance = NULL;
0549: }
0550: 
0551: 
0552: 
0553: 
0554: //-----------------------------------------------------------------------------
0555: // Name: CMusicSegment::Play()
0556: // Desc: Plays the sound using voice management flags.  Pass in DSBPLAY_LOOPING
0557: //       in the dwFlags to loop the sound
0558: //-----------------------------------------------------------------------------
0559: HRESULT CMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
0560: {
0561:     if( m_pSegment == NULL || m_pPerformance == NULL )
0562:         return CO_E_NOTINITIALIZED;
0563: 
0564:     if( !m_bDownloaded )
0565:         return E_FAIL;
0566: 
0567:     // If an audio path was passed in then use it, otherwise
0568:     // use the embedded audio path if there was one.
0569:     if( pAudioPath == NULL && m_pEmbeddedAudioPath != NULL )
0570:         pAudioPath = m_pEmbeddedAudioPath;
0571:         
0572:     // If pAudioPath is NULL then this plays on the default audio path.
0573:     return m_pPerformance->PlaySegmentEx( m_pSegment, 0, NULL, dwFlags, 
0574:                                           0, 0, NULL, pAudioPath );
0575: }
0576: 
0577: 
0578: 
0579: 
0580: 
0581: //-----------------------------------------------------------------------------
0582: // Name: CMusicSegment::Download()
0583: // Desc: 
0584: //-----------------------------------------------------------------------------
0585: HRESULT CMusicSegment::Download( IDirectMusicAudioPath8* pAudioPath )
0586: {
0587:     HRESULT hr;
0588:     
0589:     if( m_pSegment == NULL )
0590:         return CO_E_NOTINITIALIZED;
0591: 
0592:     // If no audio path was passed in, then download
0593:     // to the embedded audio path if it exists 
0594:     // else download to the performance
0595:     if( pAudioPath == NULL )
0596:     {
0597:         if( m_pEmbeddedAudioPath )
0598:             hr = m_pSegment->Download( m_pEmbeddedAudioPath );
0599:         else    
0600:             hr = m_pSegment->Download( m_pPerformance );
0601:     }
0602:     else
0603:     {
0604:         hr = m_pSegment->Download( pAudioPath );
0605:     }
0606:     
0607:     if ( SUCCEEDED( hr ) )
0608:         m_bDownloaded = TRUE;
0609:         
0610:     return hr;
0611: }
0612: 
0613: 
0614: 
0615: 
0616: //-----------------------------------------------------------------------------
0617: // Name: CMusicSegment::Unload()
0618: // Desc: 
0619: //-----------------------------------------------------------------------------
0620: HRESULT CMusicSegment::Unload( IDirectMusicAudioPath8* pAudioPath )
0621: {
0622:     HRESULT hr;
0623:     
0624:     if( m_pSegment == NULL )
0625:         return CO_E_NOTINITIALIZED;
0626: 
0627:     // If no audio path was passed in, then unload 
0628:     // from the embedded audio path if it exists 
0629:     // else unload from the performance
0630:     if( pAudioPath == NULL )
0631:     {
0632:         if( m_pEmbeddedAudioPath )
0633:             hr = m_pSegment->Unload( m_pEmbeddedAudioPath );
0634:         else    
0635:             hr = m_pSegment->Unload( m_pPerformance );
0636:     }
0637:     else
0638:     {
0639:         hr = m_pSegment->Unload( pAudioPath );
0640:     }
0641:         
0642:     if ( SUCCEEDED( hr ) )
0643:         m_bDownloaded = FALSE;
0644: 
0645:     return hr;
0646: }
0647: 
0648: 
0649: 
0650: 
0651: //-----------------------------------------------------------------------------
0652: // Name: CMusicSegment::IsPlaying()
0653: // Desc: 
0654: //-----------------------------------------------------------------------------
0655: BOOL CMusicSegment::IsPlaying()
0656: {
0657:     if( m_pSegment == NULL || m_pPerformance == NULL )
0658:         return FALSE;
0659: 
0660:     return ( m_pPerformance->IsPlaying( m_pSegment, NULL ) == S_OK );
0661: }
0662: 
0663: 
0664: 
0665: 
0666: //-----------------------------------------------------------------------------
0667: // Name: CMusicSegment::Stop()
0668: // Desc: Stops the sound from playing
0669: //-----------------------------------------------------------------------------
0670: HRESULT CMusicSegment::Stop( DWORD dwFlags )
0671: {
0672:     if( m_pSegment == NULL || m_pPerformance == NULL )
0673:         return CO_E_NOTINITIALIZED;
0674: 
0675:     return m_pPerformance->Stop( m_pSegment, NULL, 0, dwFlags );;
0676: }
0677: 
0678: 
0679: 
0680: 
0681: //-----------------------------------------------------------------------------
0682: // Name: CMusicSegment::SetRepeats()
0683: // Desc: 
0684: //-----------------------------------------------------------------------------
0685: HRESULT CMusicSegment::SetRepeats( DWORD dwRepeats )
0686: {
0687:     if( m_pSegment == NULL )
0688:         return CO_E_NOTINITIALIZED;
0689: 
0690:     return m_pSegment->SetRepeats( dwRepeats );
0691: }
0692: 
0693: 
0694: 
0695: 
0696: //-----------------------------------------------------------------------------
0697: // Name: CMusicSegment::GetStyle()
0698: // Desc: 
0699: //-----------------------------------------------------------------------------
0700: HRESULT CMusicSegment::GetStyle( IDirectMusicStyle8** ppStyle, DWORD dwStyleIndex )
0701: {
0702:     // Get the Style from the Segment by calling the Segment's GetData() with
0703:     // the data type GUID_StyleTrackStyle. 0xffffffff indicates to look at
0704:     // tracks in all TrackGroups in the segment. The first 0 indicates to
0705:     // retrieve the Style from the first Track  in the indicated TrackGroup.
0706:     // The second 0 indicates to retrieve the Style from the beginning of the
0707:     // segment, i.e. time 0 in Segment time. If this Segment was loaded from a
0708:     // section file, there is only one Style and it is at time 0.
0709:     return m_pSegment->GetParam( GUID_IDirectMusicStyle, 0xffffffff, dwStyleIndex, 
0710:                                  0, NULL, (VOID*)ppStyle );
0711: }
0712: 
0713: 
0714: 
0715: 
0716: 
0717: //-----------------------------------------------------------------------------
0718: // Name: C3DMusicSegment::C3DMusicSegment()
0719: // Desc: Constructs the class
0720: //-----------------------------------------------------------------------------
0721: C3DMusicSegment::C3DMusicSegment( IDirectMusicPerformance8* pPerformance, 
0722:                               IDirectMusicLoader8*      pLoader,
0723:                               IDirectMusicSegment8*     pSegment,
0724:                               IDirectMusicAudioPath8* pAudioPath ) :
0725:     CMusicSegment( pPerformance, pLoader, pSegment )
0726: {
0727:     m_p3DAudioPath      = pAudioPath;
0728:     m_pDS3DBuffer       = NULL;
0729:     m_bDeferSettings    = FALSE;
0730:     m_bCleanupAudioPath = FALSE;
0731: }
0732: 
0733: 
0734: 
0735: 
0736: //-----------------------------------------------------------------------------
0737: // Name: C3DMusicSegment::~C3DMusicSegment()
0738: // Desc: Destroys the class
0739: //-----------------------------------------------------------------------------
0740: C3DMusicSegment::~C3DMusicSegment()
0741: {
0742:     SAFE_RELEASE( m_pDS3DBuffer );
0743:     if( m_bCleanupAudioPath )
0744:         SAFE_RELEASE( m_p3DAudioPath );
0745: }
0746: 
0747: 
0748: 
0749: 
0750: //-----------------------------------------------------------------------------
0751: // Name: Init()
0752: // Desc: 
0753: //-----------------------------------------------------------------------------
0754: HRESULT C3DMusicSegment::Init()
0755: {
0756:     HRESULT hr;
0757: 
0758:     if( NULL == m_p3DAudioPath )
0759:     {
0760:         // Create a 3D audiopath with a 3d buffer.
0761:         // We can then play all segments into this buffer and directly control its
0762:         // 3D parameters.
0763:         if( FAILED( hr = m_pPerformance->CreateStandardAudioPath( DMUS_APATH_DYNAMIC_3D, 
0764:                                                                 64, TRUE, &m_p3DAudioPath ) ) )
0765:             return DXTRACE_ERR( TEXT("CreateStandardAudioPath"), hr );
0766:         m_bCleanupAudioPath = TRUE;
0767:     }
0768: 
0769:     // Get the 3D buffer in the audio path.
0770:     if( FAILED( hr = m_p3DAudioPath->GetObjectInPath( 0, DMUS_PATH_BUFFER, 0,
0771:                                                       GUID_NULL, 0, IID_IDirectSound3DBuffer, 
0772:                                                       (LPVOID*) &m_pDS3DBuffer ) ) )
0773:         return DXTRACE_ERR( TEXT("GetObjectInPath"), hr );
0774: 
0775:     // Get the 3D buffer parameters
0776:     m_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
0777:     m_pDS3DBuffer->GetAllParameters( &m_dsBufferParams );
0778: 
0779:     // Set new 3D buffer parameters
0780:     m_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
0781:     m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, DS3D_IMMEDIATE );
0782:    
0783:     return S_OK;
0784: }
0785: 
0786: 
0787: 
0788: 
0789: //-----------------------------------------------------------------------------
0790: // Name: Play
0791: // Desc: 
0792: //-----------------------------------------------------------------------------
0793: HRESULT C3DMusicSegment::Play( DWORD dwFlags, IDirectMusicAudioPath8* pAudioPath )
0794: {
0795:     if( pAudioPath ) 
0796:         return CMusicSegment::Play( dwFlags, pAudioPath );
0797:     else
0798:         return CMusicSegment::Play( dwFlags, m_p3DAudioPath );
0799: }
0800: 
0801: 
0802: 
0803: 
0804: //-----------------------------------------------------------------------------
0805: // Name: Set3DParameters
0806: // Desc: 
0807: //-----------------------------------------------------------------------------
0808: VOID C3DMusicSegment::Set3DParameters( FLOAT fMinDistance, FLOAT fMaxDistance )
0809: {
0810:     // Every change to 3-D sound buffer and listener settings causes 
0811:     // DirectSound to remix, at the expense of CPU cycles. 
0812:     // To minimize the performance impact of changing 3-D settings, 
0813:     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
0814:     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
0815:     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
0816:     // method to execute all of the deferred commands at once.
0817:     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
0818: 
0819:     m_dsBufferParams.flMinDistance = fMinDistance;
0820:     m_dsBufferParams.flMaxDistance = fMaxDistance;
0821: 
0822:     if( m_pDS3DBuffer )
0823:         m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, dwApplyFlag );
0824: }
0825: 
0826: 
0827: 
0828: 
0829: //-----------------------------------------------------------------------------
0830: // Name: SetObjectProperties
0831: // Desc: 
0832: //-----------------------------------------------------------------------------
0833: VOID C3DMusicSegment::SetObjectProperties( D3DVECTOR* pvPosition, D3DVECTOR* pvVelocity )
0834: {
0835:     DWORD dwApplyFlag = ( m_bDeferSettings ) ? DS3D_DEFERRED : DS3D_IMMEDIATE;
0836: 
0837:     // Every change to 3-D sound buffer and listener settings causes 
0838:     // DirectSound to remix, at the expense of CPU cycles. 
0839:     // To minimize the performance impact of changing 3-D settings, 
0840:     // use the DS3D_DEFERRED flag in the dwApply parameter of any of 
0841:     // the IDirectSound3DListener or IDirectSound3DBuffer methods that 
0842:     // change 3-D settings. Then call the IDirectSound3DListener::CommitDeferredSettings 
0843:     // method to execute all of the deferred commands at once.
0844:     memcpy( &m_dsBufferParams.vPosition, pvPosition, sizeof(D3DVECTOR) );
0845:     memcpy( &m_dsBufferParams.vVelocity, pvVelocity, sizeof(D3DVECTOR) );
0846: 
0847:     if( m_pDS3DBuffer )
0848:     {
0849:         m_pDS3DBuffer->SetPosition( m_dsBufferParams.vPosition.x,
0850:                                     m_dsBufferParams.vPosition.y,
0851:                                     m_dsBufferParams.vPosition.z, dwApplyFlag );
0852: 
0853:         m_pDS3DBuffer->SetVelocity( m_dsBufferParams.vVelocity.x,
0854:                                     m_dsBufferParams.vVelocity.y,
0855:                                     m_dsBufferParams.vVelocity.z, dwApplyFlag );
0856:     }
0857: }
0858: 
0859: 
0860: 
0861: //-----------------------------------------------------------------------------
0862: // Name: CMusicScript::CMusicScript()
0863: // Desc: Constructs the class
0864: //-----------------------------------------------------------------------------
0865: CMusicScript::CMusicScript( IDirectMusicPerformance8* pPerformance, 
0866:                             IDirectMusicLoader8* pLoader,                   
0867:                             IDirectMusicScript8* pScript )
0868: {
0869:     m_pPerformance = pPerformance;
0870:     m_pLoader      = pLoader;
0871:     m_pScript      = pScript;
0872: }
0873: 
0874: 
0875: 
0876: 
0877: //-----------------------------------------------------------------------------
0878: // Name: CMusicScript::~CMusicScript()
0879: // Desc: Destroys the class
0880: //-----------------------------------------------------------------------------
0881: CMusicScript::~CMusicScript()
0882: {
0883:     if( m_pLoader )
0884:     {
0885:         // Tell the loader that this object should now be released
0886:         m_pLoader->ReleaseObjectByUnknown( m_pScript );
0887:         m_pLoader = NULL;
0888:     }
0889: 
0890:     SAFE_RELEASE( m_pScript ); 
0891:     m_pPerformance = NULL;
0892: }
0893: 
0894: 
0895: 
0896: 
0897: //-----------------------------------------------------------------------------
0898: // Name: CMusicScript::Play()
0899: // Desc: Calls a routine in the script
0900: //-----------------------------------------------------------------------------
0901: HRESULT CMusicScript::CallRoutine( TCHAR* strRoutine )
0902: {
0903:     // DMusic only takes wide strings
0904:     WCHAR wstrRoutine[MAX_PATH];
0905:     DXUtil_ConvertGenericStringToWideCb( wstrRoutine, strRoutine, sizeof(wstrRoutine) );
0906: 
0907:     return m_pScript->CallRoutine( wstrRoutine, NULL );
0908: }
0909: 
0910: 
0911: 
0912: 
0913: //-----------------------------------------------------------------------------
0914: // Name: CMusicScript::SetVariableNumber()
0915: // Desc: Sets the value of a variable in the script
0916: //-----------------------------------------------------------------------------
0917: HRESULT CMusicScript::SetVariableNumber( TCHAR* strVariable, LONG lValue )
0918: {
0919:     // DMusic only takes wide strings
0920:     WCHAR wstrVariable[MAX_PATH];
0921:     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
0922: 
0923:     return m_pScript->SetVariableNumber( wstrVariable, lValue, NULL );
0924: }
0925: 
0926: 
0927: 
0928: 
0929: //-----------------------------------------------------------------------------
0930: // Name: CMusicScript::GetVariableNumber()
0931: // Desc: Gets the value of a variable in the script
0932: //-----------------------------------------------------------------------------
0933: HRESULT CMusicScript::GetVariableNumber( TCHAR* strVariable, LONG* plValue )
0934: {
0935:     // DMusic only takes wide strings
0936:     WCHAR wstrVariable[MAX_PATH];
0937:     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
0938: 
0939:     return m_pScript->GetVariableNumber( wstrVariable, plValue, NULL );
0940: }
0941: 
0942: 
0943: 
0944: //-----------------------------------------------------------------------------
0945: // Name: CMusicScript::SetVariableObject()
0946: // Desc: Sets an object in the script
0947: //-----------------------------------------------------------------------------
0948: HRESULT CMusicScript::SetVariableObject( TCHAR* strVariable, IUnknown *punkValue )
0949: {
0950:     // DMusic only takes wide strings
0951:     WCHAR wstrVariable[MAX_PATH];
0952:     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
0953: 
0954:     return m_pScript->SetVariableObject( wstrVariable, punkValue, NULL );
0955: }
0956: 
0957: 
0958: 
0959: 
0960: //-----------------------------------------------------------------------------
0961: // Name: CMusicScript::GetVariableObject()
0962: // Desc: Gets an object from the script
0963: //-----------------------------------------------------------------------------
0964: HRESULT CMusicScript::GetVariableObject( TCHAR* strVariable, REFIID riid, LPVOID FAR *ppv )
0965: {
0966:     // DMusic only takes wide strings
0967:     WCHAR wstrVariable[MAX_PATH];
0968:     DXUtil_ConvertGenericStringToWideCb( wstrVariable, strVariable, sizeof(wstrVariable) );
0969: 
0970:     return m_pScript->GetVariableObject( wstrVariable, riid, ppv, NULL );
0971: }
0972: 
0973: