00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "jukebox.h"
00023 #include <iostream>
00024
00025 #include "../game/config.h"
00026 #include "../tool/debug.h"
00027 #include "../tool/i18n.h"
00028 #include "../tool/random.h"
00029 #include "../tool/file_tools.h"
00030
00031 JukeBox jukebox;
00032
00033 JukeBox::JukeBox()
00034 {
00035 m_init = false;
00036
00037 m_config.music = true;
00038 m_config.effects = true;
00039 m_config.frequency = 44100;
00040 m_config.channels = 2;
00041 }
00042
00043 void JukeBox::Pause()
00044 {
00045 Mix_Pause(-1);
00046 Mix_PauseMusic();
00047 }
00048
00049 void JukeBox::Resume()
00050 {
00051 Mix_Resume(-1);
00052 Mix_ResumeMusic();
00053 }
00054
00055 void JukeBox::Init()
00056 {
00057 if (!m_config.music && !m_config.effects) {
00058 End();
00059 return;
00060 }
00061
00062 if (m_init) return;
00063
00064 Uint16 audio_format = MIX_DEFAULT_FORMAT;
00065
00066
00067 if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
00068 std::cerr << "* Couldn't initialize SDL: "<< SDL_GetError() << std::endl;
00069 return;
00070 }
00071
00072 int audio_buffer = 1024;
00073
00074
00075 if (Mix_OpenAudio(m_config.frequency, audio_format, m_config.channels, audio_buffer) < 0) {
00076 std::cerr << "* Couldn't open audio: " << SDL_GetError() << std::endl;
00077 return;
00078 } else {
00079 Mix_QuerySpec(&m_config.frequency, &audio_format, &m_config.channels);
00080 std::cout << "o Opened audio at " << m_config.frequency <<" Hz "<< (audio_format&0xFF)
00081 <<" bit " << std::endl;
00082 }
00083 Mix_ChannelFinished(JukeBox::EndChunk);
00084
00085 m_init = true;
00086
00087 LoadXML("share");
00088 }
00089
00090 void JukeBox::End()
00091 {
00092 if (!m_init) return;
00093 m_init = false;
00094
00095 StopAll();
00096
00097 m_soundsamples.clear();
00098 m_profiles_loaded.clear();
00099
00100 Mix_CloseAudio();
00101 }
00102
00103 void JukeBox::SetFrequency (int frequency)
00104 {
00105 if ((frequency != 11025)
00106 && (frequency != 22050)
00107 && (frequency != 44100)) frequency = 44100;
00108
00109 if (m_config.frequency == frequency) return;
00110
00111 m_config.frequency = frequency;
00112
00113
00114 End();
00115 Init();
00116 }
00117
00118
00119 #if 0
00120 void JukeBox::SetNumbersOfChannel(int channels)
00121 {
00122 if (m_config.channels == channels) return;
00123
00124 m_config.channels = channels;
00125
00126
00127 End();
00128 Init();
00129 }
00130 #endif
00131
00132 void JukeBox::LoadXML(const std::string& profile)
00133 {
00134
00135 if (!UseEffects()) return;
00136
00137
00138 std::set<std::string>::iterator it_profile = m_profiles_loaded.find(profile) ;
00139 if (it_profile != m_profiles_loaded.end()) {
00140 MSG_DEBUG("jukebox", "Profile %s is already loaded !", profile.c_str());
00141 return;
00142 }
00143 std::cout << "o Loading sound profile " << profile << std::endl;
00144
00145 XmlReader doc;
00146
00147
00148 std::string folder = Config::GetInstance()->GetDataDir() + PATH_SEPARATOR + "sound"+ PATH_SEPARATOR + profile + PATH_SEPARATOR;
00149 std::string xml_filename = folder + "profile.xml";
00150 if( !IsFileExist(xml_filename) ){
00151 std::cerr << "[Sound] Error : file " << xml_filename << " not found" << std::endl;
00152 return;
00153 }
00154 if(!doc.Load(xml_filename))
00155 return;
00156
00157 xmlpp::Node::NodeList nodes = doc.GetRoot()->get_children("sound");
00158 xmlpp::Node::NodeList::iterator
00159 it=nodes.begin(),
00160 fin=nodes.end();
00161
00162 for (; it != fin; ++it)
00163 {
00164
00165 xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it);
00166 std::string sample="no_sample";
00167 std::string file="no_file";
00168 XmlReader::ReadStringAttr(elem, "sample", sample);
00169 XmlReader::ReadStringAttr(elem, "file", file);
00170
00171 MSG_DEBUG("jukebox", "Load sound sample %s/%s: %s", profile.c_str(), sample.c_str(), file.c_str());
00172
00173
00174 std::string sample_filename = folder + file;
00175 if( !IsFileExist(sample_filename) ){
00176 std::cerr << "Sound error: File " << sample_filename.c_str()
00177 << " does not exist !" << std::endl;
00178 continue;
00179 }
00180
00181
00182 m_soundsamples.insert(sound_sample(profile+"/"+sample, sample_filename));
00183 }
00184
00185
00186 m_profiles_loaded.insert(profile);
00187 }
00188
00189 int JukeBox::Play (const std::string& category, const std::string& sample,
00190 const int loop)
00191 {
00192 if (!UseEffects()) return -1;
00193
00194 uint nb_sons= m_soundsamples.count(category+"/"+sample);
00195 if (nb_sons)
00196 {
00197 std::pair<sample_iterator, sample_iterator> p = m_soundsamples.equal_range(category+"/"+sample);
00198 sample_iterator it = p.first;
00199
00200
00201 if (nb_sons > 1)
00202 {
00203 uint selection = uint(randomObj.GetLong(0, nb_sons));
00204 if (selection == nb_sons) --selection ;
00205
00206 it = p.first ;
00207
00208 for ( uint i=0 ; i<selection && it!=p.second ; ++i ) it++ ;
00209 }
00210
00211
00212 Mix_Chunk * sampleChunk = Mix_LoadWAV(it->second.c_str());
00213 MSG_DEBUG("jukebox.play", "Playing sample %s/%s", category.c_str(), sample.c_str());
00214 return PlaySample(sampleChunk, loop);
00215 }
00216 else if (category != "default") {
00217 return Play("default", sample, loop) ;
00218 }
00219
00220 MSG_DEBUG("jukebox", "Error: No sound found for sample %s/%s", category.c_str(), sample.c_str());
00221 return -1;
00222 }
00223
00224 int JukeBox::Stop (int channel)
00225 {
00226 if(!m_config.music && !m_config.effects) return 0;
00227 if (channel == -1) return 0;
00228 return Mix_HaltChannel(channel);
00229 }
00230
00231 int JukeBox::StopAll()
00232 {
00233 if (!m_config.music && !m_config.effects) return 0;
00234
00235
00236 return Mix_HaltChannel(-1);
00237 }
00238
00239 int JukeBox::PlaySample (Mix_Chunk * sample, int loop)
00240 {
00241 if (loop != -1) loop--;
00242
00243 int channel = Mix_PlayChannel(-1, sample, loop);
00244
00245 if (channel == -1) {
00246 MSG_DEBUG("jukebox", "Error: Jukebox::PlaySample: %s", Mix_GetError());
00247 Mix_FreeChunk(sample);
00248 }
00249 else
00250 chunks[channel] = sample;
00251 return channel;
00252 }
00253
00254 void JukeBox::EndChunk(int channel)
00255 {
00256 Mix_Chunk* chk = jukebox.chunks[channel];
00257
00258 if(!chk) return;
00259
00260 Mix_FreeChunk(chk);
00261 jukebox.chunks[channel] = 0;
00262 }