1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2012-2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/sound/sound_bank.h"
24 #include "nel/sound/simple_sound.h"
25 #include "nel/sound/complex_sound.h"
26 #include "nel/sound/context_sound.h"
27 #include "nel/sound/background_sound.h"
28 #include "nel/sound/music_sound.h"
29 #include "nel/sound/stream_sound.h"
30 #include "nel/sound/stream_file_sound.h"
32 #include "nel/georges/u_form_loader.h"
33 #include "nel/georges/u_form_elm.h"
34 #include "nel/georges/u_form.h"
35 #include "nel/misc/path.h"
36 #include "nel/sound/driver/buffer.h"
38 #include "nel/georges/load_form.h"
45 using namespace NLMISC
;
46 using namespace NLGEORGES
;
51 void CSoundBank::bufferUnloaded(const NLMISC::TStringId
&bufferName
)
53 TBufferAssocContainer::iterator
it(_BufferAssoc
.find(bufferName
));
55 if (it
!= _BufferAssoc
.end())
57 // ok, found some sound associated with this buffer.
59 TSimpleSoundContainer::iterator
first(it
->second
.begin()), last(it
->second
.end());
60 for (; first
!= last
; ++first
)
62 // remove the associated buffer.
63 CSimpleSound
*ss
= const_cast<CSimpleSound
*>(*(first
));
69 //void CSoundBank::bufferLoaded(const std::string bufferName, IBuffer *buffer)
70 void CSoundBank::bufferLoaded(const NLMISC::TStringId
&/* bufferName */, IBuffer
*buffer
)
72 // std::map<std::string, std::vector<TBufferAssoc> >::iterator it(_BufferAssoc.find(buffer->getName()));
73 TBufferAssocContainer::iterator
it(_BufferAssoc
.find(buffer
->getName()));
75 if (it
!= _BufferAssoc
.end())
77 // ok, found some sound associated with this buffer.
79 TSimpleSoundContainer::iterator
first(it
->second
.begin()), last(it
->second
.end());
80 for (; first
!= last
; ++first
)
82 CSimpleSound
*ss
= const_cast<CSimpleSound
*>(*(it
->second
.begin()));
83 // restore the associated buffer.
84 ss
->setBuffer(buffer
);
90 void CSoundBank::registerBufferAssoc(CSimpleSound
*sound
, IBuffer
*buffer
)
94 const NLMISC::TStringId
&bufferName
= buffer
->getName();
95 _BufferAssoc
[bufferName
].insert(sound
);
99 void CSoundBank::unregisterBufferAssoc(CSimpleSound
*sound
, IBuffer
* buffer
)
103 const TStringId
&bufferName
= buffer
->getName();
104 TBufferAssocContainer::iterator
it(_BufferAssoc
.find(bufferName
));
106 if (it
!= _BufferAssoc
.end())
108 TSimpleSoundContainer::iterator
it2(it
->second
.find(sound
));
110 nlassert(it2
!= it
->second
.end());
111 it
->second
.erase(it2
);
113 if (it
->second
.empty())
115 // last sound refenrecing this buffer
116 _BufferAssoc
.erase(it
);
127 CSoundBank::~CSoundBank()
132 void CSoundBank::addSound(CSound
*sound
)
134 std::pair
<TSoundTable::iterator
, bool> ret
;
135 ret
= _Sounds
.insert(make_pair(sound
->getName(), sound
));
136 nlassert(ret
.second
);
139 void CSoundBank::removeSound(const NLMISC::TStringId
&name
)
145 /** Pseudo serializer for packed sheet loading/saving.
146 * This class act as a wrapper to create sound from
147 * xml document being read, call the serialisation method
148 * to read/write packed sheet and to delete sounds that are
151 class CSoundSerializer
154 /// The sound beeing managed by this serializer.
157 /// Default constructor.
162 // load the values using the george sheet (called by GEORGE::loadForm)
163 void readGeorges (const NLMISC::CSmartPtr
<NLGEORGES::UForm
> &form
, const std::string
&name
)
165 // just call the sound creation method with the xml form.
166 Sound
= CSound::createSound(name
, form
->getRootNode());
170 // CSoundBank::instance()->addSound(_Sound);
173 // load/save the values using the serial system (called by GEORGE::loadForm)
174 void serial (NLMISC::IStream
&s
)
178 // read the first item to find the type
179 CSound::TSOUND_TYPE type
= CSound::SOUND_SIMPLE
;
181 // read the sound name
185 // Instantiate the corresponding sound.
186 switch(CSound::TSOUND_TYPE(type
))
188 case CSound::SOUND_SIMPLE
:
189 Sound
= new CSimpleSound();
191 case CSound::SOUND_COMPLEX
:
192 Sound
= new CComplexSound();
194 case CSound::SOUND_CONTEXT
:
195 Sound
= new CContextSound();
197 case CSound::SOUND_BACKGROUND
:
198 Sound
= new CBackgroundSound();
200 case CSound::SOUND_MUSIC
:
201 Sound
= new CMusicSound();
203 case CSound::SOUND_STREAM
:
204 Sound
= new CStreamSound();
206 case CSound::SOUND_STREAM_FILE
:
207 Sound
= new CStreamFileSound();
213 // nlassert(_Sound != 0);
216 // read the sound data
218 // CSoundBank::instance()->addSound(_Sound);
225 // the sound doesn't exist
226 uint32 i
= std::numeric_limits
<uint32
>::max();
228 // s.serial(std::string("bad sound"));
232 // write the sound type.
233 CSound::TSOUND_TYPE type
= Sound
->getSoundType();
235 // write the sound name
236 // s.serial(const_cast<std::string&>(_Sound->getName()));
238 // and write the sound data
244 /** called by GEORGE::loadForm when a sheet read from the packed sheet is no more in
251 // we remove the sound from the bank and delete it.
252 // CSoundBank::instance()->removeSound(_Sound->getName());
257 // return the version of this class, increments this value when the content of this class changed
258 static uint
getVersion () { return 3; }
262 /** Load all the sound samples.
264 * Can throw EPathNotFound or ESoundFileNotFound (check Exception)
266 void CSoundBank::load(const std::string
&packedSheetDir
, bool packedSheetUpdate
)
268 // this structure is fill by the loadForm() function and will contain all you need
269 std::map
<std::string
, CSoundSerializer
> Container
;
271 // Just call the GEORGE::loadFrom method to read all available sounds
272 ::loadForm("sound", packedSheetDir
+ "sounds.packed_sheets", Container
, packedSheetUpdate
, false);
275 // add all the loaded sound in the sound banks
276 std::map
<std::string
, CSoundSerializer
>::iterator
first(Container
.begin()), last(Container
.end());
277 for (; first
!= last
; ++first
)
279 if (first
->second
.Sound
!= 0)
280 addSound(first
->second
.Sound
);
288 * Unload all the sound samples in this bank.
290 void CSoundBank::unload()
294 TSoundTable::iterator
first(_Sounds
.begin()), last(_Sounds
.end());
295 for (; first
!= last
; ++first
)
297 delete first
->second
;
303 /* vector<CSound*> vec;
306 TSoundTable::iterator map_iter;
308 for (map_iter = _Sounds.begin(); map_iter != _Sounds.end(); ++map_iter)
310 // We can't delete directly second because the map is based on second->getName()
311 vec.push_back( (*map_iter).second );
316 vector<CSound*>::iterator vec_iter;
318 for (vec_iter = vec.begin(); vec_iter != vec.end(); ++vec_iter)
320 CSound *sound = *vec_iter;
329 * Returns true if the samples in this bank have been loaded.
331 bool CSoundBank::isLoaded()
337 * Return a sound sample corresponding to a name.
339 CSound
* CSoundBank::getSound(const NLMISC::TStringId
&name
)
342 TSoundTable::iterator iter
= _Sounds
.find(name
);
343 if ( iter
== _Sounds
.end() )
349 return (*iter
).second
;
354 * Return the names of the sounds
356 void CSoundBank::getNames( std::vector
<NLMISC::TStringId
> &names
)
358 TSoundTable::const_iterator iter
;
359 for (iter
= _Sounds
.begin(); iter
!= _Sounds
.end(); ++iter
)
361 names
.push_back((*iter
).first
);
362 //nlwarning("getting sound %s", (*iter).first);
367 * Return the number of buffers in this bank.
369 uint
CSoundBank::countSounds()
371 return (uint
)_Sounds
.size();
375 } // namespace NLSOUND