home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioScript / MusicMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-25  |  11.3 KB  |  436 lines

  1. /***********************************************************\
  2. Copyright (C) James Boer, 2002. 
  3. All rights reserved worldwide.
  4.  
  5. This software is provided "as is" without express or implied
  6. warranties. You may freely copy and compile this source into
  7. applications you distribute provided that the copyright text
  8. below is included in the resulting source code, for example:
  9. "Portions Copyright (C) James Boer, 2002"
  10. \***********************************************************/
  11.  
  12. #include "MusicMgr.h"
  13. #include "Theme.h"
  14.  
  15. // Comment out this line if you don't want the sound manager to
  16. // require keywords to be case sensitive
  17. #define MUSMGR_CASE_SENSITIVE
  18.  
  19. #ifdef MUSMGR_CASE_SENSITIVE
  20. #define MUSMGR_STRCMP strcmp
  21. #else
  22. #define MUSMGR_STRCMP strcmpi
  23. #endif
  24.  
  25. using namespace std;
  26. using namespace Audio;
  27.  
  28. //------------------------------------------------------------------------//
  29. MusicManager::MusicManager()
  30. {
  31.     Clear();
  32. }
  33.  
  34.  
  35. //------------------------------------------------------------------------//
  36. MusicManager::~MusicManager()
  37. {
  38.     Term();
  39. }
  40.  
  41.  
  42. //------------------------------------------------------------------------//
  43. void MusicManager::Clear()
  44. {
  45.     // Script loader and parser
  46.     m_Loader.Clear();
  47.  
  48.     // music transition data
  49.     m_DLSMap.clear();
  50.     m_SegmentMap.clear();
  51.     m_ThemeMap.clear();
  52.     m_ThemeItr = m_ThemeMap.begin();
  53.  
  54.     // Current playback information
  55.     m_pPlayingTheme = 0;
  56.     m_pPlayingInterlude = 0;
  57.     m_pPreviousTheme = 0;
  58.  
  59.     m_bIsPlaying = false;
  60.  
  61.     m_pCurrentDLS = 0;
  62.  
  63.     m_bInitialized = false;
  64. }
  65.  
  66.  
  67. //------------------------------------------------------------------------//
  68. bool MusicManager::Init()
  69. {
  70.     if(!AudioMgr()->IsInitialized())
  71.         return Error::Handle("The audio manager has not been initialized");
  72.  
  73.     if(!m_Loader.Init())
  74.         return Error::Handle("Could not initialize script loader in SoundManager.");
  75.  
  76.     m_bInitialized = true;
  77.  
  78.     return true;
  79. }
  80.  
  81.  
  82. //------------------------------------------------------------------------//
  83. void MusicManager::Term()
  84. {
  85.     m_Loader.Term();
  86.     RemoveAll();
  87.     Clear();
  88. }
  89.  
  90.  
  91. //------------------------------------------------------------------------//
  92. bool MusicManager::LoadScript(string sFileName)
  93. {
  94.     if(!IsInitialized())
  95.         return Error::Handle("Music manager is not initialized");
  96.  
  97.     Script script;
  98.     if(!m_Loader.Load(sFileName, script))
  99.         return Error::Handle("Could not load script %s", sFileName.c_str());
  100.  
  101.     ScriptNode* pNode = script.GetRoot();
  102.     while(pNode)
  103.     {
  104.         // Look for named "DLS" nodes in the script
  105.         if(MUSMGR_STRCMP(pNode->GetName(), "DLS") == 0)
  106.         {
  107.             if(!LoadDLS(pNode))
  108.                 return false;
  109.         }
  110.         // Look for named "Segment" nodes in the script
  111.         else if(MUSMGR_STRCMP(pNode->GetName(), "Segment") == 0)
  112.         {
  113.             if(!LoadSegment(pNode))
  114.                 return false;
  115.         }
  116.         // Look for named "Theme" nodes in the script
  117.         else if(MUSMGR_STRCMP(pNode->GetName(), "Theme") == 0)
  118.         {
  119.             if(!LoadTheme(pNode))
  120.                 return false;
  121.         }
  122.         else
  123.         {
  124.             return Error::Handle("Unrecognized keyword in music script");
  125.         }
  126.  
  127.         // advance to the next sibling node if one exists
  128.         pNode = pNode->GetSibling();
  129.     };
  130.  
  131.     return true;
  132. }
  133.  
  134.  
  135. //------------------------------------------------------------------------//
  136. void MusicManager::ResetThemeItr()
  137. {
  138.     if(!IsInitialized())
  139.         Error::Handle("Music manager is not initialized");
  140.     m_ThemeItr = m_ThemeMap.begin();
  141. }
  142.  
  143. //------------------------------------------------------------------------//
  144. bool MusicManager::GetNextTheme(std::string& sThemeName)
  145. {
  146.     if(!IsInitialized())
  147.         return Error::Handle("Music manager is not initialized");
  148.     if(m_ThemeItr == m_ThemeMap.end())
  149.         return false;
  150.     sThemeName = (m_ThemeItr->first);
  151.     ++m_ThemeItr;
  152.     return true;
  153. }
  154.  
  155. //------------------------------------------------------------------------//
  156. bool MusicManager::RemoveTheme(std::string& sThemeName)
  157. {
  158.     if(!IsInitialized())
  159.         return Error::Handle("Music manager is not initialized");
  160.     ThemeMap::iterator itr = m_ThemeMap.find(sThemeName);
  161.     if(itr == m_ThemeMap.end())
  162.         return false;
  163.     m_ThemeMap.erase(itr);
  164.     return true;
  165. }
  166.  
  167. //------------------------------------------------------------------------//
  168. bool MusicManager::RemoveAll()
  169. {
  170.     if(!IsInitialized())
  171.         return Error::Handle("Music manager is not initialized");
  172.     ThemeMap::iterator itr1;
  173.     for(itr1 = m_ThemeMap.begin(); itr1 != m_ThemeMap.end(); ++itr1)
  174.         SAFE_DELETE(itr1->second);
  175.     m_ThemeMap.clear();
  176.  
  177.     ISegmentMap::iterator itr2;
  178.     for(itr2 = m_SegmentMap.begin(); itr2 != m_SegmentMap.end(); ++itr2)
  179.         itr2->second->Destroy();
  180.     m_SegmentMap.clear();
  181.  
  182.     IDLSMap::iterator itr3;
  183.     for(itr3 = m_DLSMap.begin(); itr3 != m_DLSMap.end(); ++itr3)
  184.         itr3->second->Destroy();
  185.     m_DLSMap.clear();
  186.     
  187.  
  188.     return true;
  189. }
  190.  
  191.  
  192. //------------------------------------------------------------------------//
  193. bool MusicManager::LoadDLS(ScriptNode* pNode)
  194. {
  195.     FN("MusicManager::LoadDLS()");
  196.     // We use string ids in this scripting system
  197.     if(pNode->GetDataType() != Script::STRING)
  198.         return Error::Handle("No id found for DLS identifier");
  199.  
  200.     // Make sure the segment ID doesn't already exist
  201.     IDLSMap::iterator itr = m_DLSMap.find(pNode->GetString());
  202.     if(itr != m_DLSMap.end())
  203.         return true;
  204.  
  205.     DLSInit init;
  206.     ScriptNode* pChildNode = pNode->GetChild();
  207.     while(pChildNode)
  208.     {
  209.         if(MUSMGR_STRCMP(pChildNode->GetName(), "FileName") == 0)
  210.             init.m_sFileName = pChildNode->GetString();
  211.         pChildNode = pChildNode->GetSibling();
  212.     }
  213.     
  214.     IDLS* pDLS;
  215.     if(!AudioMgr()->CreateDLS(pDLS))
  216.         return false;
  217.     if(!pDLS->Init(init))
  218.         return false;
  219.  
  220.     m_pCurrentDLS = pDLS;
  221.  
  222.     // Insert the segment into the map
  223.     m_DLSMap.insert(make_pair(pNode->GetString(), pDLS));
  224.  
  225.     return true;
  226. }
  227.  
  228.  
  229. //------------------------------------------------------------------------//
  230. bool MusicManager::LoadSegment(ScriptNode* pNode)
  231. {
  232.     FN("MusicManager::LoadSegment()");
  233.     // We use string ids in this scripting system
  234.     if(pNode->GetDataType() != Script::STRING)
  235.         return Error::Handle("No id found for sound identifier");
  236.  
  237.     // Make sure the segment ID doesn't already exist
  238.     ISegmentMap::iterator itr = m_SegmentMap.find(pNode->GetString());
  239.     if(itr != m_SegmentMap.end())
  240.         return true;
  241.  
  242.     SegmentInit init;
  243.     ScriptNode* pChildNode = pNode->GetChild();
  244.     init.m_pDLS = m_pCurrentDLS;
  245.     while(pChildNode)
  246.     {
  247.         if(MUSMGR_STRCMP(pChildNode->GetName(), "FileName") == 0)
  248.             init.m_sFileName = pChildNode->GetString();
  249.         else if(MUSMGR_STRCMP(pChildNode->GetName(), "Looping") == 0)
  250.             init.m_bLooping = pChildNode->GetBool();
  251.         else if(MUSMGR_STRCMP(pChildNode->GetName(), "Music") == 0)
  252.             init.m_bMusic = pChildNode->GetBool();
  253.         else if(MUSMGR_STRCMP(pChildNode->GetName(), "DLS") == 0)
  254.         {
  255.             IDLSMap::iterator itr = m_DLSMap.find(pChildNode->GetString());
  256.             if(itr != m_DLSMap.end())
  257.                 init.m_pDLS = itr->second;
  258.         }
  259.         pChildNode = pChildNode->GetSibling();
  260.     }
  261.  
  262.  
  263.     ISegment* pSegment;
  264.     if(!AudioMgr()->CreateSegment(pSegment))
  265.         return false;
  266.     if(!pSegment->Init(init))
  267.         return false;
  268.  
  269.     // Insert the segment into the map
  270.     m_SegmentMap.insert(make_pair(pNode->GetString(), pSegment));
  271.  
  272.     return true;
  273. }
  274.  
  275.  
  276. //------------------------------------------------------------------------//
  277. bool MusicManager::LoadTheme(ScriptNode* pNode)
  278. {
  279.     FN("MusicManager::LoadTheme()");
  280.     // We use string ids in this scripting system
  281.     if(pNode->GetDataType() != Script::STRING)
  282.         return Error::Handle("No id found for theme identifier");
  283.  
  284.     Theme* pTheme = 0;
  285.  
  286.     // Make sure the theme ID doesn't already exist
  287.     ThemeMap::iterator itr = m_ThemeMap.find(pNode->GetString());
  288.     if(itr != m_ThemeMap.end())
  289.         pTheme = itr->second;
  290.     else
  291.         pTheme = new Theme;
  292.  
  293.     if(!pTheme)
  294.         return false;
  295.  
  296.     ScriptNode* pChildNode = pNode->GetChild();
  297.     while(pChildNode)
  298.     {
  299.         if(MUSMGR_STRCMP(pChildNode->GetName(), "Src") == 0)
  300.         {
  301.             if(!LoadThemeNode(pChildNode, pTheme))
  302.                 return false;
  303.         }
  304.         else if(MUSMGR_STRCMP(pChildNode->GetName(), "Interlude") == 0)
  305.         {
  306.             pTheme->SetInterlude(pChildNode->GetBool());
  307.         }
  308.         else
  309.             return false;
  310.         pChildNode = pChildNode->GetSibling();
  311.     }
  312.     
  313.     // Insert the theme into the map
  314.     m_ThemeMap.insert(make_pair(pNode->GetString(), pTheme));
  315.  
  316.     return true;
  317. }
  318.  
  319.  
  320. //------------------------------------------------------------------------//
  321. bool MusicManager::LoadThemeNode(ScriptNode* pNode, Theme* pTheme)
  322. {
  323.     FN("MusicManager::LoadThemeNode()");
  324.  
  325.     if(pNode->GetDataType() != Script::STRING)
  326.         return Error::Handle("No id found for theme node");
  327.  
  328.     ISegment* pSegmentSource = 0;
  329.     Theme* pThemeSource = 0;
  330.     // First look for matching segments based on the id value
  331.     ISegmentMap::iterator itr = m_SegmentMap.find(pNode->GetString());
  332.     if(itr == m_SegmentMap.end())
  333.     {
  334.         // Next, look for matching themes
  335.         ThemeMap::iterator itor = m_ThemeMap.find(pNode->GetString());
  336.         if(itor == m_ThemeMap.end())
  337.             return Error::Handle("Unknown id %s in theme node", pNode->GetString());
  338.         pThemeSource = itor->second;
  339.         if(!pTheme->CreateNode(pThemeSource))
  340.             return Error::Handle("Could not create theme node");
  341.     }
  342.     else
  343.     {
  344.         pSegmentSource = itr->second;
  345.         if(!pTheme->CreateNode(pSegmentSource))
  346.             return Error::Handle("Could not create theme node");
  347.     }
  348.  
  349.     ScriptNode* pChildNode = pNode->GetChild();
  350.     while(pChildNode)
  351.     {
  352.         if(MUSMGR_STRCMP(pChildNode->GetName(), "Dest") == 0)
  353.         {
  354.             itr = m_SegmentMap.find(pChildNode->GetString());
  355.             if(itr == m_SegmentMap.end())
  356.                 return Error::Handle("Unknown id %s in theme node", pChildNode->GetString());
  357.             ISegment* pDest = itr->second;
  358.             if(pThemeSource)
  359.             {
  360.                 if(!pTheme->CreateTransition(pThemeSource, pDest))
  361.                     return Error::Handle("Error creating theme node transition");
  362.             }
  363.             else
  364.             {
  365.                 if(!pTheme->CreateTransition(pSegmentSource, pDest))
  366.                     return Error::Handle("Error creating theme node transition");
  367.             }
  368.         }
  369.         else
  370.         {
  371.             return Error::Handle("Unknown syntax or keyword in theme node");
  372.         }
  373.         pChildNode = pChildNode->GetSibling();
  374.     }
  375.  
  376.     return true;
  377. }
  378.  
  379.  
  380. //------------------------------------------------------------------------//
  381. bool MusicManager::PlayTheme(std::string sThemeName)
  382. {
  383.     if(!IsInitialized())
  384.         return Error::Handle("Music manager is not initialized");
  385.     ThemeMap::iterator itr = m_ThemeMap.find(sThemeName);
  386.     if(itr == m_ThemeMap.end())
  387.         return Error::Handle("Could not find theme %s", sThemeName.c_str());
  388.  
  389.     if(m_pPlayingInterlude)
  390.         m_pPreviousTheme = m_pPlayingInterlude;
  391.     else if(m_pPlayingTheme)
  392.         m_pPreviousTheme = m_pPlayingTheme;
  393.  
  394.     itr->second->StartTheme();
  395.  
  396.     if(itr->second->IsInterlude())
  397.         m_pPlayingInterlude = itr->second;
  398.     else
  399.         m_pPlayingTheme = itr->second;
  400.  
  401.     OnSegmentStart();
  402.     return true;
  403. }
  404.  
  405.  
  406. //------------------------------------------------------------------------//
  407. void MusicManager::OnSegmentStart()
  408. {
  409.     FN("MusicManager::OnSegmentStart()");
  410.  
  411.     ISegment* pCurrent;
  412.     ISegment* pNext;
  413.     AudioMgr()->GetCurrentSegment(pCurrent);
  414.     if(m_pPlayingInterlude)
  415.     {
  416.         if(!m_pPlayingInterlude->GetTransition(m_pPreviousTheme, pCurrent, pNext))
  417.         {
  418.             m_pPlayingInterlude = 0;
  419.             if(!m_pPlayingTheme)
  420.                 return;
  421.             m_pPlayingTheme->StartTheme();
  422.             if(!m_pPlayingTheme->GetTransition(m_pPreviousTheme, pCurrent, pNext))
  423.                 return;
  424.         }
  425.     }
  426.     else
  427.     {
  428.         if(!m_pPlayingTheme)
  429.             return;
  430.         if(!m_pPlayingTheme->GetTransition(m_pPreviousTheme, pCurrent, pNext))
  431.             return;
  432.     }
  433.     pNext->Play();
  434.  
  435. }
  436.