NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
SoundModuleMessages.cpp
Go to the documentation of this file.
00001 
00011 #pragma once
00012 
00013 #include "SoundModule.h"
00014 
00015 // System Library Includes
00016 
00017 // Application Library Includes
00018 #include <EngineConfig.h>
00019 
00020 // Local Includes
00021 #include "../sharedbase/MessageRouter.h"
00022 #include "../sharedbase/Envelope.h"
00023 
00024 #include "Messages.h"
00025 
00026 // Helpers
00027 namespace Sound {
00028   // Taken from a comment on: http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/
00029   template <class T>
00030   inline std::string to_string (const T& t) {
00031     std::stringstream ss;
00032     ss << t;
00033     return ss.str();
00034   }
00035 
00036   template <class T>
00037   inline std::string to_hex (const T& t) {
00038     std::stringstream ss;
00039     ss << std::hex << t;
00040     return ss.str();
00041   }
00042 }
00043 
00044 // Classes
00045 namespace Sound {
00046   #define SUBSCRIBE_BASIC(msgid, handler)   {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Subscribe((msgid), handler_sptr);}
00047   #define UNSUBSCRIBE_BASIC(msgid, handler) {std::shared_ptr<Subscriber> handler_sptr(new Subscriber(boost::bind((&handler), this, _1))); this->msgrouter->Unsubscribe((msgid), handler_sptr);}
00048   #define SUBSCRIBE_DIRECTED(msgid, handler)   {std::shared_ptr<DirectedSubscriber> handler_sptr(new DirectedSubscriber(boost::bind((&handler), this, _1))); this->msgrouter->SubscribeDirected((msgid), handler_sptr);}
00049   #define UNSUBSCRIBE_DIRECTED(msgid, handler) {std::shared_ptr<DirectedSubscriber> handler_sptr(new DirectedSubscriber(boost::bind((&handler), this, _1))); this->msgrouter->UnsubscribeDirected((msgid), handler_sptr);}
00050   
00051   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00052   void SoundModule::RegisterMessageHandlers() {
00053     /* * * * * * * * * * * * * * * * * * * * * */
00054     // General Message Handlers
00055     /* * * * * * * * * * * * * * * * * * * * * */
00056     SUBSCRIBE_BASIC(MSG_MODULE_START, SoundModule::HandlerStartup);
00057     
00058     /* * * * * * * * * * * * * * * * * * * * * */
00059     // Operations Message Handlers
00060     /* * * * * * * * * * * * * * * * * * * * * */
00061     // *TODO: Break these up into seperate message handlers.
00062     SUBSCRIBE_BASIC(MSG_LOAD_XACT_SETTINGS_FILE, SoundModule::HandlerBasic);
00063     SUBSCRIBE_BASIC(MSG_LOAD_IN_MEMORY_WAVEBANK, SoundModule::HandlerBasic);
00064     SUBSCRIBE_BASIC(MSG_LOAD_STREAMING_WAVEBANK, SoundModule::HandlerBasic);
00065     SUBSCRIBE_BASIC(MSG_LOAD_SOUNDBANK, SoundModule::HandlerBasic);
00066     SUBSCRIBE_BASIC(MSG_PREPARE_CUE, SoundModule::HandlerBasic);
00067     SUBSCRIBE_BASIC(MSG_PLAY_CUE, SoundModule::HandlerBasic);
00068     //SUBSCRIBE_BASIC(MSG_PLAY_CUE_AT, SoundModule::HandlerBasic);
00069     //SUBSCRIBE_BASIC(MSG_PREPARE_3D_CUE, SoundModule::HandlerBasic);
00070     //SUBSCRIBE_BASIC(MSG_PLAY_3D_CUE, SoundModule::HandlerBasic);
00071     SUBSCRIBE_BASIC(MSG_STOP_CUE, SoundModule::HandlerBasic);
00072     
00073     SUBSCRIBE_DIRECTED(MSG_GET_CUE_KEY, SoundModule::HandlerDirectedGetCueIndex);
00074   }
00075   
00076   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00077   void SoundModule::HandlerStartup(EnvelopeSPTR envelope) {
00078     bool status = false;
00079     
00080     if (this->engine == NULL) {
00081       //Nothing to startup
00082       return;
00083     }
00084     
00085     {
00086       // Startup the XACT engine
00087       XACT_RUNTIME_PARAMETERS xrParams = {0};
00088       xrParams.fnNotificationCallback = XACTNotificationCallback;
00089       
00090       { //*HACK: This whole block doesn't belong here, but it can't go anywhere else.  Grrrr.  ~Ricky
00091         std::string file;
00092         HANDLE hFile;
00093         std::string errStr;
00094         
00095         try {
00096           file = NLS_ENGINE_DATA_PATH + boost::any_cast<std::string>(envelope->GetData(0));
00097         }
00098         catch (boost::bad_any_cast&) {
00099           errStr += "Audio Startup: Bad data type passed for the sound settings file path string!";
00100         }
00101         catch (std::out_of_range&) {
00102           errStr += "Audio Startup: Missing path string for the sound settings file!";
00103         }
00104         
00105         if (file.length() > 0) {
00106           LOG(LOG_PRIORITY::FLOW, "Loading setting file: " + file);
00107           
00108           unsigned int count;
00109           {
00110             Threading::ReadLock r_lock(this->waveBanksMutex);
00111             count = this->waveBanks.count(file);
00112           }
00113           
00114           if (count <= 0) {
00115             hFile = CreateFile( file.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
00116             
00117             if( hFile != INVALID_HANDLE_VALUE ) {
00118               DWORD dwFileSize = GetFileSize( hFile, NULL );
00119               HANDLE hMapFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL );
00120               VOID* pvGlobalSettingsData = MapViewOfFile( hMapFile, FILE_MAP_READ, 0, 0, 0 );
00121               
00122               if (pvGlobalSettingsData != NULL) {
00123                 xrParams.pGlobalSettingsBuffer = pvGlobalSettingsData;
00124                 xrParams.globalSettingsBufferSize = dwFileSize;
00125                 //xrParams.globalSettingsFlags = XACT_FLAG_GLOBAL_SETTINGS_MANAGEDATA;
00126               }
00127               else {
00128                 DWORD dw = GetLastError();
00129                 LPVOID lpMsgBuf;
00130                 
00131                 FormatMessage(
00132                   FORMAT_MESSAGE_ALLOCATE_BUFFER | 
00133                   FORMAT_MESSAGE_FROM_SYSTEM |
00134                   FORMAT_MESSAGE_IGNORE_INSERTS,
00135                   NULL,
00136                   dw,
00137                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00138                   (LPTSTR) &lpMsgBuf,
00139                   0, NULL
00140                 );
00141                 
00142                 errStr = "Unable to load the settings file into allocated memory!!"; //*TODO: better error message
00143                 errStr.append("\n\tError details: ").append((LPCTSTR)lpMsgBuf);
00144                 LOG(LOG_PRIORITY::ERR, errStr);
00145               }
00146             }
00147             else {
00148               errStr = "Couldn't find the settings file!!"; //*TODO: better error message
00149               LOG(LOG_PRIORITY::MISSRESS, errStr);
00150             }
00151           }
00152           else {
00153             errStr = "Settings file already loaded!!"; //*TODO: better error message
00154             LOG(LOG_PRIORITY::ERR, errStr);
00155           }
00156         }
00157         
00158         if (errStr.compare("") != 0) {
00159           // Notify failure to load
00160           EnvelopeSPTR confirmation(new Envelope);
00161           confirmation->msgid = ACK_LOAD_XACT_SETTINGS_FILE;
00162           confirmation->AddData(file);
00163           confirmation->AddData(false);
00164           this->msgrouter->SendSP(confirmation);
00165           return;
00166         }
00167       }
00168       
00169       xrParams.lookAheadTime = XACT_ENGINE_LOOKAHEAD_DEFAULT;
00170       HRESULT hr;
00171       {
00172         Threading::WriteLock w_lock(this->engineMutex);
00173         hr = this->engine->Initialize( &xrParams );
00174       }
00175       if (FAILED(hr)) {
00176         std::string errStr = "Unable to initialize the audio engine.  Do you have a sound device attached?  Error code 0x" + to_hex<HRESULT>(hr);
00177         LOG(LOG_PRIORITY::ERR, errStr);
00178         MessageBox(NULL, (LPCTSTR)errStr.c_str(), TEXT("Audio Error"), MB_OK);
00179         
00180         this->engine = NULL; // No engine.
00181         
00182         status = false;
00183       }
00184       else {
00185         // Register the need for wavebank loading completion notification
00186         this->RegisterNotification(XACTNOTIFICATIONTYPE_WAVEBANKPREPARED, XACT_FLAG_NOTIFICATION_PERSIST);
00187         
00188         // Register the need for wavebank destruction notification
00189         this->RegisterNotification(XACTNOTIFICATIONTYPE_WAVEBANKDESTROYED, XACT_FLAG_NOTIFICATION_PERSIST);
00190         
00191         
00192         // Register the need for soundbank loading completion notification
00193         //this->RegisterNotification(XACTNOTIFICATIONTYPE_SOUNDBANKPREPARED, XACT_FLAG_NOTIFICATION_PERSIST);
00194         // No such notification exists
00195         
00196         // Register the need for soundbank destruction notification
00197         this->RegisterNotification(XACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED, XACT_FLAG_NOTIFICATION_PERSIST);
00198         
00199         // Register for knowing when a cue has been prepared.
00200         this->RegisterNotification(XACTNOTIFICATIONTYPE_CUEPREPARED, XACT_FLAG_NOTIFICATION_PERSIST);
00201         
00202         // Register for knowing when a cue has stopped.
00203         this->RegisterNotification(XACTNOTIFICATIONTYPE_CUESTOP, XACT_FLAG_NOTIFICATION_PERSIST);
00204         
00205         
00206         // Reset the time accumulator
00207         this->deltaAccumulator = 0.0;
00208         
00209         status = true;
00210       }
00211     }
00212     
00213     // Un-register from the startup message, as there's no need to start again.
00214     UNSUBSCRIBE_BASIC(MSG_MODULE_START, SoundModule::HandlerStartup);
00215     
00216     // Send notification that the module is started.
00217     {
00218       EnvelopeSPTR e(new Envelope);
00219       e->msgid = ACK_MODULE_START;
00220       e->AddData(status);
00221       this->msgrouter->SendSP(e);
00222     }
00223     
00224     LOG(LOG_PRIORITY::FLOW, "SimpleSound started.");
00225     
00226     this->engineInitialized = true;
00227   }
00228   
00229   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00230   template <typename T>
00231   inline void HandleMessageSingleParam(boost::function<void (T)> setter, const int msgID, EnvelopeSPTR envelope) {
00232     T value;
00233     
00234     try {
00235       value = boost::any_cast<T>(envelope->GetData());
00236     }
00237     catch (boost::bad_any_cast&) {
00238       std::string errStr ("Bad data type passed for message id ");
00239       errStr.append(boost::lexical_cast<std::string>(msgID));
00240       LOG(LOG_PRIORITY::ERR, errStr);
00241     }
00242     
00243     setter(value);
00244   }
00245   
00246   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00247   void SoundModule::HandlerBasic(EnvelopeSPTR envelope) {
00248     if (this->engine == NULL) {
00249       //Nothing to do here
00250       return;
00251     }
00252     
00253     int msg = envelope->msgid;
00254     
00255     switch (msg) {
00256       case MSG_LOAD_XACT_SETTINGS_FILE: {
00257         HandleMessageSingleParam <std::string> (
00258           std::bind1st(std::mem_fun(&SoundModule::LoadXACTSettingsBuffer), this), // The setter method
00259           msg, envelope
00260         );
00261       }
00262       break;
00263       case MSG_LOAD_IN_MEMORY_WAVEBANK: {
00264         HandleMessageSingleParam <std::string> (
00265           std::bind1st(std::mem_fun(&SoundModule::LoadInMemoryWavebank), this), // The setter method
00266           msg, envelope
00267         );
00268       }
00269       break;
00270       case MSG_LOAD_STREAMING_WAVEBANK: {
00271         HandleMessageSingleParam <std::string> (
00272           std::bind1st(std::mem_fun(&SoundModule::LoadStreamingWavebank), this), // The setter method
00273           msg, envelope
00274         );
00275       }
00276       break;
00277       case MSG_LOAD_SOUNDBANK: {
00278         HandleMessageSingleParam <std::string> (
00279           std::bind1st(std::mem_fun(&SoundModule::LoadSoundbank), this), // The setter method
00280           msg, envelope
00281         );
00282       }
00283       break;
00284       case MSG_PREPARE_CUE: {
00285         std::string bankName ("");
00286         int cueIndex = -1;
00287         
00288         try {
00289           bankName = NLS_ENGINE_DATA_PATH + boost::any_cast<std::string>(envelope->GetData(0));
00290         }
00291         catch (boost::bad_any_cast&) {
00292           std::string errStr ("Prepare Cue: Bad data type passed for the sound bank id in message id ");
00293           errStr.append(boost::lexical_cast<std::string>(msg));
00294           LOG(LOG_PRIORITY::ERR, errStr);
00295         }
00296         
00297         try {
00298           cueIndex = boost::any_cast<int>(envelope->GetData(1));
00299         }
00300         catch (boost::bad_any_cast&) {
00301           std::string errStr ("Prepare Cue: Bad data type passed for the cue index in message id ");
00302           errStr.append(boost::lexical_cast<std::string>(msg));
00303           LOG(LOG_PRIORITY::ERR, errStr);
00304         }
00305         
00306         if (bankName.compare("") != 0 && cueIndex >= 0) {
00307           unsigned int count;
00308           {
00309             Threading::ReadLock r_lock(this->soundBanksMutex);
00310             count = this->soundBanks.count(bankName);
00311           }
00312           
00313           if (count) {
00314             std::pair<std::string, int> key (bankName, cueIndex);
00315             {
00316               Threading::ReadLock r_lock(this->preparedCuesMutex);
00317               count = this->preparedCues.count(key);
00318             }
00319             
00320             if (count == 0) {
00321               IXACT3SoundBank* soundBank;
00322               {
00323                 Threading::ReadLock r_lock(this->soundBanksMutex);
00324                 soundBank = this->soundBanks.at(bankName);
00325               }
00326               
00327               std::string logStr;
00328               logStr.assign("Preparing cue in ").append(bankName).append(" with index ").append(to_string<int>(cueIndex));
00329               LOG(LOG_PRIORITY::FLOW, logStr);
00330               
00331               IXACT3Cue* cue = nullptr;
00332               HRESULT hr = 0;
00333               
00334               XACTINDEX cue_count;
00335               {
00336                 Threading::ReadLock r_lock(this->engineMutex);
00337                 soundBank->GetNumCues(&cue_count);
00338               }
00339               
00340               if (cueIndex < cue_count) {
00341                 {
00342                   Threading::WriteLock w_lock(this->engineMutex);
00343                   hr = soundBank->Prepare(cueIndex, 0, 0, &cue);
00344                 }
00345                 
00346                 if (SUCCEEDED(hr)) {
00347                   Threading::WriteLock w_lock(this->preparedCuesMutex);
00348                   this->preparedCues[key] = cue;
00349                 }
00350                 else {
00351                   std::string logStr;
00352                   logStr.assign("Cue prepare failed with error code: 0x").append(to_hex<HRESULT>(hr));
00353                   LOG(LOG_PRIORITY::ERR, logStr);
00354                 }
00355               }
00356               else {
00357                 LOG(LOG_PRIORITY::CONFIG, "Attempted to prepare cue with out-of-bounds index!");
00358               }
00359             }
00360             else {
00361               std::string logStr;
00362               logStr.assign("Cue in ").append(bankName).append(" with index ").append(to_string<int>(cueIndex)).append(" already prepared!");
00363               LOG(LOG_PRIORITY::WARN, logStr);
00364             }
00365           }
00366           else {
00367             std::string logStr;
00368             logStr.assign("Prepare Cue: Named bank not found ").append(bankName).append(" for cue index ").append(to_string<int>(cueIndex));
00369             LOG(LOG_PRIORITY::ERR, logStr);
00370           }
00371         }
00372         else {
00373           std::string logStr;
00374           logStr.assign("Prepare Cue: Bank name or cue index missing! Bank name: '").append(bankName).append("'. Cue Index: ").append(to_string<int>(cueIndex));
00375           LOG(LOG_PRIORITY::ERR, logStr);
00376         }
00377       }
00378       break;
00379       case MSG_PLAY_CUE: {
00380         std::string bankName ("");
00381         XACTINDEX cueIndex = -1;
00382         int count = 1;
00383         float volume = 1.0f;
00384         
00385         try {
00386           bankName = NLS_ENGINE_DATA_PATH + boost::any_cast<std::string>(envelope->GetData(0));
00387         }
00388         catch (boost::bad_any_cast&) {
00389           std::string errStr ("Play Cue: Bad data type passed for the sound bank id in message id ");
00390           errStr.append(boost::lexical_cast<std::string>(msg));
00391           LOG(LOG_PRIORITY::ERR, errStr);
00392         }
00393         
00394         try {
00395           cueIndex = boost::any_cast<int>(envelope->GetData(1));
00396         }
00397         catch (boost::bad_any_cast&) {
00398           std::string errStr ("Play Cue: Bad data type passed for the cue index in message id ");
00399           errStr.append(boost::lexical_cast<std::string>(msg));
00400           LOG(LOG_PRIORITY::ERR, errStr);
00401         }
00402         
00403         try {
00404           count = boost::any_cast<int>(envelope->GetData(2));
00405         }
00406         catch (boost::bad_any_cast&) {
00407           std::string errStr ("Play Cue: Bad data type passed for the cue repeat count in message id ");
00408           errStr.append(boost::lexical_cast<std::string>(msg));
00409           LOG(LOG_PRIORITY::ERR, errStr);
00410         }
00411         catch (std::out_of_range&) {
00412           // Do nothing: parameter IS optional!
00413         }
00414         
00415         try {
00416           volume = boost::any_cast<float>(envelope->GetData(3));
00417         }
00418         catch (boost::bad_any_cast&) {
00419           std::string errStr ("Play Cue: Bad data type passed for the cue volume in message id ");
00420           errStr.append(boost::lexical_cast<std::string>(msg));
00421           LOG(LOG_PRIORITY::ERR, errStr);
00422         }
00423         catch (std::out_of_range&) {
00424           // Do nothing: parameter IS optional!
00425         }
00426         
00427         if (bankName.compare("") != 0 && cueIndex >= 0) {
00428           std::pair<std::string, int> key (bankName, cueIndex);
00429           HRESULT hr = 0;
00430           
00431           unsigned int prep_cues_count;
00432           unsigned int banks_count;
00433           
00434           {
00435             Threading::ReadLock r_lock(this->preparedCuesMutex);
00436             prep_cues_count = this->preparedCues.count(key);
00437           }
00438           
00439           {
00440             Threading::ReadLock r_lock(this->soundBanksMutex);
00441             banks_count = this->soundBanks.count(bankName);
00442           }
00443           
00444           if (prep_cues_count) {
00445             IXACT3Cue* cue;
00446             {
00447               Threading::ReadLock r_lock(this->preparedCuesMutex);
00448               cue = this->preparedCues[key];
00449             }
00450             //*TODO: adjust volume of cue based on parameter...
00451             //*TODO: figure out how to repeat the cue based on parameter... (note that -1 means infinite repeat)
00452             
00453             std::string logStr;
00454             logStr.assign("Playing pre-prepared cue in ").append(bankName).append(" with index ").append(to_string<int>(cueIndex));
00455             LOG(LOG_PRIORITY::FLOW, logStr);
00456             
00457             {
00458               Threading::ReadLock r_lock(this->engineMutex);
00459               hr = cue->Play();
00460             }
00461           }
00462           else if (banks_count) {
00463             IXACT3SoundBank* soundBank;
00464             {
00465               Threading::ReadLock r_lock(this->soundBanksMutex);
00466               soundBank = this->soundBanks.at(bankName);
00467             }
00468             
00469             //*TODO: adjust volume of cue based on parameter...
00470             //*TODO: figure out how to repeat the cue based on parameter... (note that -1 means infinite repeat)
00471             
00472             std::string logStr;
00473             logStr.assign("Playing unprepared cue in ").append(bankName).append(" with index ").append(to_string<int>(cueIndex));
00474             LOG(LOG_PRIORITY::FLOW, logStr);
00475             
00476             XACTINDEX cue_count;
00477             {
00478               Threading::ReadLock r_lock(this->engineMutex);
00479               soundBank->GetNumCues(&cue_count);
00480             }
00481             
00482             if (cueIndex < cue_count) {
00483               Threading::ReadLock r_lock(this->engineMutex);
00484               hr = soundBank->Play(cueIndex, 0, 0, nullptr);
00485             }
00486             else {
00487               LOG(LOG_PRIORITY::ERR, "Attempted to play an index that is out-of-bounds!");
00488             }
00489           }
00490           else {
00491             std::string logStr;
00492             logStr.assign("Play Cue: Named bank not found ").append(bankName).append(" for cue index ").append(to_string<int>(cueIndex));
00493             LOG(LOG_PRIORITY::ERR, logStr);
00494           }
00495           
00496           if (FAILED(hr)) {
00497             std::string logStr("Cue failed to play.");
00498             switch (hr) {
00499               case 0x8ac7000c: { //XACTENGINE_E_INVALIDCUEINDEX: {
00500                 logStr += " Invalid cue index of " + to_string<int>(cueIndex) + ".";
00501               }
00502               break;
00503               default: {
00504                 logStr += " Error code: 0x" + to_hex<HRESULT>(hr);
00505               }
00506             }
00507             LOG(LOG_PRIORITY::ERR, logStr);
00508           }
00509         }
00510         else {
00511           std::string logStr;
00512           logStr.assign("Play Cue: Bank name or cue index missing! Bank name: '").append(bankName).append("'. Cue Index: ").append(to_string<int>(cueIndex));
00513           LOG(LOG_PRIORITY::ERR, logStr);
00514         }
00515       }
00516       break;
00517       case MSG_STOP_CUE: {
00518         std::string bankName ("");
00519         int cueIndex = -1;
00520         
00521         try {
00522           bankName = NLS_ENGINE_DATA_PATH + boost::any_cast<std::string>(envelope->GetData(0));
00523         }
00524         catch (boost::bad_any_cast&) {
00525           std::string errStr ("Stop Cue: Bad data type passed for the sound bank id in message id ");
00526           errStr.append(boost::lexical_cast<std::string>(msg));
00527           LOG(LOG_PRIORITY::ERR, errStr);
00528         }
00529         
00530         try {
00531           cueIndex = boost::any_cast<int>(envelope->GetData(1));
00532         }
00533         catch (boost::bad_any_cast&) {
00534           std::string errStr ("Stop Cue: Bad data type passed for the cue index in message id ");
00535           errStr.append(boost::lexical_cast<std::string>(msg));
00536           LOG(LOG_PRIORITY::ERR, errStr);
00537         }
00538         
00539         if (bankName.compare("") != 0 && cueIndex >= 0) {
00540           unsigned int count;
00541           {
00542             Threading::ReadLock r_lock(this->soundBanksMutex);
00543             count = this->soundBanks.count(bankName);
00544           }
00545           
00546           if (count) {
00547             IXACT3SoundBank* soundBank;
00548             
00549             {
00550               Threading::ReadLock r_lock(this->soundBanksMutex);
00551               soundBank = this->soundBanks.at(bankName);
00552             }
00553             
00554             std::string logStr;
00555             logStr.assign("Stopping cue in ").append(bankName).append(" with index ").append(to_string<int>(cueIndex));
00556             LOG(LOG_PRIORITY::FLOW, logStr);
00557             
00558             HRESULT hr;
00559             {
00560               Threading::ReadLock r_lock(this->engineMutex);
00561               hr = soundBank->Stop(cueIndex, XACT_FLAG_SOUNDBANK_STOP_IMMEDIATE);
00562             }
00563             
00564             if (FAILED(hr)) {
00565               std::string logStr;
00566               logStr.assign("Cue failed to stop. Error code: 0x").append(to_hex<HRESULT>(hr));
00567               LOG(LOG_PRIORITY::ERR, logStr);
00568             }
00569           }
00570           else {
00571             std::string logStr;
00572             logStr.assign("Stop Cue: Named bank not found ").append(bankName).append(" for cue index ").append(to_string<int>(cueIndex));
00573             LOG(LOG_PRIORITY::ERR, logStr);
00574           }
00575         }
00576         else {
00577           std::string logStr;
00578           logStr.assign("Stop Cue: Bank name or cue index missing! Bank name: '").append(bankName).append("'. Cue Index: ").append(to_string<int>(cueIndex));
00579           LOG(LOG_PRIORITY::ERR, logStr);
00580         }
00581       }
00582       break;
00583       default: // Do nothing: the message wasn't meant for me.
00584       break;
00585     }
00586   }
00587   
00588   /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00589   EnvelopeSPTR SoundModule::HandlerDirectedGetCueIndex(EnvelopeSPTR envelope) {
00590     std::string bankName ("");
00591     std::string cueName ("");
00592     
00593     EnvelopeSPTR confirmation(new Envelope);
00594     confirmation->msgid = ACK_GET_CUE_KEY;
00595     
00596     try {
00597       bankName = NLS_ENGINE_DATA_PATH + boost::any_cast<std::string>(envelope->GetData(0));
00598     }
00599     catch (boost::bad_any_cast&) {
00600       LOG(LOG_PRIORITY::ERR, "Bad data type passed for the sound bank id!");
00601     }
00602     
00603     try {
00604       cueName = boost::any_cast<std::string>(envelope->GetData(1));
00605     }
00606     catch (boost::bad_any_cast&) {
00607       LOG(LOG_PRIORITY::ERR, "Bad data type passed for the cue name!");
00608     }
00609     
00610     if (bankName.compare("") != 0 && cueName.compare("") != 0) {
00611       unsigned int count;
00612       {
00613         Threading::ReadLock r_lock(this->soundBanksMutex);
00614         count = this->soundBanks.count(bankName);
00615       }
00616       
00617       if (count) {
00618         IXACT3SoundBank* soundBank;
00619         {
00620           Threading::ReadLock r_lock(this->soundBanksMutex);
00621           soundBank = this->soundBanks.at(bankName);
00622         }
00623         unsigned int cue_index;
00624         
00625         {
00626           Threading::ReadLock r_lock(this->engineMutex);
00627           cue_index = soundBank->GetCueIndex(cueName.c_str());
00628         }
00629         
00630         if (cue_index != XACTINDEX_INVALID) {
00631           confirmation->AddData(bankName);
00632           confirmation->AddData(cue_index);
00633           
00634           LOG(LOG_PRIORITY::FLOW, "Got cue in " + bankName + " with name " + cueName + " and resulting index " + boost::lexical_cast<std::string>(cue_index));
00635         }
00636         else {
00637           LOG(LOG_PRIORITY::ERR, "Cue not found in " + bankName + " with name " + cueName + "!");
00638         }
00639       }
00640       else {
00641         LOG(LOG_PRIORITY::ERR, "Named bank not found " + bankName + " for cue name " + cueName);
00642       }
00643     }
00644     else {
00645       LOG(LOG_PRIORITY::ERR, "Bank name or cue name missing! Bank name: '" + bankName + "'. Cue Name: " + cueName);
00646     }
00647     
00648     return confirmation;
00649   }
00650 }