# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

sound_bank.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdsound.h"
00027 
00028 #include "sound_bank.h"
00029 #include "simple_sound.h"
00030 #include "complex_sound.h"
00031 #include "context_sound.h"
00032 #include "background_sound.h"
00033 
00034 #include "nel/georges/u_form_loader.h"
00035 #include "nel/georges/u_form_elm.h"
00036 #include "nel/georges/u_form.h"
00037 #include "nel/misc/path.h"
00038 #include "driver/buffer.h"
00039 
00040 #include "nel/georges/load_form.h"
00041 
00042 using namespace std;
00043 using namespace NLMISC;
00044 using namespace NLGEORGES;
00045 
00046 
00047 namespace NLSOUND {
00048 
00049 CSoundBank              *CSoundBank::_Instance;
00050 
00051 
00052 
00053 CSoundBank      *CSoundBank::instance()
00054 {
00055         if (_Instance == 0)
00056                 _Instance = new CSoundBank();
00057         return _Instance;
00058 }
00059 
00060 void CSoundBank::release()
00061 {
00062         if (_Instance != 0)
00063                 delete _Instance;
00064         _Instance = 0;
00065 }
00066 
00067 
00068 void CSoundBank::bufferUnloaded(const std::string bufferName)
00069 {
00070         TBufferAssocContainer::iterator it(_BufferAssoc.find(bufferName));
00071 
00072         if (it != _BufferAssoc.end())
00073         {
00074                 // ok, found some sound associated with this buffer.
00075                 // update all sounds.
00076                 TSimpleSoundContainer::iterator first(it->second.begin()), last(it->second.end());
00077                 for (; first != last; ++first)
00078                 {
00079                         // remove the associated buffer.
00080                         CSimpleSound *ss = const_cast<CSimpleSound*>(*(first));
00081                         ss->setBuffer(NULL);
00082                 }
00083         }
00084 }
00085 
00086 void CSoundBank::bufferLoaded(const std::string bufferName, IBuffer *buffer)
00087 {
00088 //      std::map<std::string, std::vector<TBufferAssoc> >::iterator it(_BufferAssoc.find(buffer->getName()));
00089         TBufferAssocContainer::iterator it(_BufferAssoc.find(buffer->getName()));
00090 
00091         if (it != _BufferAssoc.end())
00092         {
00093                 // ok, found some sound associated with this buffer.
00094                 // update all sounds.
00095                 TSimpleSoundContainer::iterator first(it->second.begin()), last(it->second.end());
00096                 for (; first != last; ++first)
00097                 {
00098                         CSimpleSound *ss = const_cast<CSimpleSound*>(*(it->second.begin()));
00099                         // restore the associated buffer.
00100                         ss->setBuffer(buffer);
00101                 }
00102         }
00103 
00104 }
00105 
00106 void CSoundBank::registerBufferAssoc(CSimpleSound *sound, IBuffer *buffer) 
00107 {
00108         if (buffer != NULL)
00109         {
00110                 const std::string &bufferName = buffer->getName();
00111                 _BufferAssoc[bufferName].insert(sound);
00112         }
00113 }
00114 
00115 void CSoundBank::unregisterBufferAssoc(CSimpleSound *sound, IBuffer * buffer) 
00116 {
00117         if (buffer != NULL)
00118         {
00119                 const std::string &bufferName = buffer->getName();
00120                 TBufferAssocContainer::iterator it(_BufferAssoc.find(bufferName));
00121 
00122                 if (it != _BufferAssoc.end())
00123                 {
00124                         TSimpleSoundContainer::iterator it2(it->second.find(sound));
00125 
00126                         nlassert(it2 != it->second.end())
00127                         it->second.erase(it2);
00128 
00129                         if (it->second.empty())
00130                         {
00131                                 // last sound refenrecing this buffer
00132                                 _BufferAssoc.erase(it);
00133                         }
00134 
00135                 }
00136         }
00137 }
00138 
00139 
00140 /*
00141  * Destructor
00142  */
00143 CSoundBank::~CSoundBank()
00144 {
00145         unload();
00146 }
00147 
00148 void CSoundBank::addSound(CSound *sound)
00149 {
00150         _Sounds.insert(make_pair(sound->getName(), sound));
00151 }
00152 
00153 void CSoundBank::removeSound(const std::string &name)
00154 {
00155         _Sounds.erase(name);
00156 }
00157 
00158 
00165 class CSoundSerializer
00166 {
00167 public:
00169         CSound *_Sound;
00170 
00172         CSoundSerializer()
00173                 : _Sound(0)
00174         {}
00175 
00176         // load the values using the george sheet (called by GEORGE::loadForm)
00177         void readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const std::string &name)
00178         {
00179                 // just call the sound creation method with the xml form.
00180                 _Sound = CSound::createSound(name, form->getRootNode());
00181 
00182                 // success ?
00183                 if (_Sound != 0)
00184                         CSoundBank::instance()->addSound(_Sound);
00185         }
00186 
00187         // load/save the values using the serial system (called by GEORGE::loadForm)
00188         void serial (NLMISC::IStream &s)
00189         {
00190                 if (s.isReading())
00191                 {
00192                         // read the first item to find the type
00193                         CSound::TSOUND_TYPE type;
00194                         s.serialEnum(type);
00195                         // read the sound name
00196                         std::string name;
00197                         s.serial(name);
00198 
00199                         // Instantiate the corresponding sound.
00200                         switch(CSound::TSOUND_TYPE(type))
00201                         {
00202                         case CSound::SOUND_SIMPLE:
00203                                 _Sound = new CSimpleSound();
00204                                 break;
00205                         case CSound::SOUND_COMPLEX:
00206                                 _Sound = new CComplexSound();
00207                                 break;
00208                         case CSound::SOUND_CONTEXT:
00209                                 _Sound = new CContextSound();
00210                                 break;
00211                         case CSound::SOUND_BACKGROUND:
00212                                 _Sound = new CBackgroundSound();
00213                                 break;
00214                         default:
00215                                 _Sound = 0;
00216                         }
00217 
00218 //                      nlassert(_Sound != 0);
00219                         if (_Sound)
00220                         {
00221                                 // read the sound data
00222                                 _Sound->serial(s);
00223                                 CSoundBank::instance()->addSound(_Sound);
00224                         }
00225                 }
00226                 else
00227                 {
00228                         if (_Sound == 0)
00229                         {
00230                                 // the sound doesn't exist
00231                                 uint32 i = -1;
00232                                 s.serialEnum(i);
00233                                 s.serial(std::string("bad sound"));
00234                         }
00235                         else
00236                         {
00237                                 // write the sound type.
00238                                 CSound::TSOUND_TYPE type = _Sound->getSoundType();
00239                                 s.serialEnum(type);
00240                                 // write the sound name
00241                                 s.serial(const_cast<std::string&>(_Sound->getName()));
00242 
00243                                 // and write the sound data
00244                                 _Sound->serial(s);
00245                         }
00246                 }
00247         }
00248 
00252         void removed()
00253         {
00254                 if (_Sound != 0)
00255                 {
00256                         // we remove the sound from the bank and delete it.
00257                         CSoundBank::instance()->removeSound(_Sound->getName());
00258                         delete _Sound;
00259                 }
00260         }
00261 
00262         // return the version of this class, increments this value when the content of this class changed
00263         static uint getVersion () { return 1; }
00264 };
00265 
00266 // this structure is fill by the loadForm() function and will contain all you need
00267 std::map<std::string, CSoundSerializer> Container;
00268 
00273 void                            CSoundBank::load()
00274 {
00275         nlassert(!_Loaded);
00276         // Just call the GEORGE::loadFrom method to read all available sounds
00277         ::loadForm("sound", "sounds.packed_sheets", Container, true);
00278         _Loaded = true;
00279 }
00280 
00281 
00282 /*
00283  * Unload all the sound samples in this bank.
00284  */
00285 void                            CSoundBank::unload()
00286 {
00287         nlassert(_Loaded);
00288         vector<CSound*> vec;
00289         TSoundTable::iterator map_iter;
00290 
00291         for (map_iter = _Sounds.begin(); map_iter != _Sounds.end(); ++map_iter)
00292         {
00293                 // We can't delete directly second because the map is based on second->getName()
00294                 vec.push_back( (*map_iter).second );
00295         }
00296         
00297         _Sounds.clear();
00298 
00299         vector<CSound*>::iterator vec_iter;
00300 
00301         for (vec_iter = vec.begin(); vec_iter != vec.end(); ++vec_iter)
00302         {
00303                 CSound *sound = *vec_iter;
00304                 delete sound;
00305         }
00306 
00307         _Loaded = false;
00308 }
00309 
00310 /*
00311  * Returns true if the samples in this bank have been loaded.
00312  */
00313 bool                            CSoundBank::isLoaded()
00314 {
00315         return _Loaded;
00316 }
00317 
00318 /*
00319  * Return a sound sample corresponding to a name.
00320  */
00321 CSound*                 CSoundBank::getSound(const std::string &name)
00322 {
00323         // Find sound
00324         TSoundTable::iterator iter = _Sounds.find(name);
00325         if ( iter == _Sounds.end() )
00326         {
00327                 return 0;
00328         }
00329         else
00330         {
00331                 return (*iter).second;
00332         }
00333 }
00334 
00338 void                            CSoundBank::getNames( std::vector<std::string>& names )
00339 {
00340         TSoundTable::const_iterator iter;
00341         for (iter = _Sounds.begin(); iter != _Sounds.end(); ++iter)
00342         {
00343                 names.push_back((*iter).first);
00344                 //nlwarning("getting sound %s", (*iter).first);
00345         }
00346 }
00347 
00348 /*
00349  * Return the number of buffers in this bank.
00350  */
00351 uint                            CSoundBank::countSounds()
00352 {
00353         return _Sounds.size();
00354 }
00355 
00356 
00357 } // namespace NLSOUND
00358