1 // Description:
2 //   Audio subsysytem.
3 //
4 // Copyright (C) 2003 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation;  either version 2 of the License,  or (at your option) any  later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful,  but  WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include <Audio.hpp>
16 #include <Trace.hpp>
17 #include <Config.hpp>
18 #include <ResourceManager.hpp>
19 #include <zrwops.hpp>
20 #include <SampleManager.hpp>
21 #include <Timer.hpp>
22 
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 
26 #include "SDL.h"
27 #include "SDL_mixer.h"
28 
Audio()29 Audio::Audio():
30   _sampleManager(0),
31   _soundTrack(0),
32   _playDefaultSoundtrack( true),
33   _playMusic( true),
34   _isPlaying( false)
35 {
36     XTRACE();
37 
38     bool dummy;
39     //if config variables don't exist (upgrade, etc) update
40     if( ! ConfigS::instance()->getBoolean( "playMusic", dummy))
41     {
42 	Value *v = new Value( _playMusic);
43 	ConfigS::instance()->updateKeyword( "playMusic", v);
44     }
45     if( ! ConfigS::instance()->getBoolean(
46 	"playDefaultSoundtrack", dummy))
47     {
48 	Value *v = new Value( _playDefaultSoundtrack);
49 	ConfigS::instance()->updateKeyword( "playDefaultSoundtrack", v);
50     }
51 }
52 
~Audio()53 Audio::~Audio()
54 {
55     XTRACE();
56     LOG_INFO << "Audio shutdown..." << endl;
57 
58     turnMusicOff();
59 
60     Mix_CloseAudio();
61     delete _sampleManager;
62 
63     SDL_QuitSubSystem(SDL_INIT_AUDIO);
64 }
65 
loadMusic(const string & mod)66 void Audio::loadMusic( const string &mod)
67 {
68     XTRACE();
69     if( mod == "") return;
70 
71     LOG_INFO << "Loading soundtrack...[" << mod << "]" << endl;
72 
73 #if 0
74 //SDL_mixer doesn't have RWops support for MUS yet :(
75     if( !ResourceManagerS::instance()->selectResource( mod))
76     {
77 	LOG_ERROR << "Music file [" << mod << "] not found." << endl;
78 	return;
79     }
80 
81     ziStream &infile = ResourceManagerS::instance()->getInputStream();
82     SDL_RWops *src = RWops_from_ziStream( infile);
83 
84     _soundTrack = Mix_LoadMUS_RW(src);
85     SDL_RWclose( src);
86 #else
87     _soundTrack = Mix_LoadMUS( mod.c_str());
88 #endif
89 
90     if( !_soundTrack)
91     {
92 	LOG_ERROR << "Failed to load soundtrack: [" << mod << "]" << endl;
93 	LOG_ERROR << SDL_GetError() << endl;
94     }
95     else
96     {
97 	//loop soundtrack
98 	Mix_PlayMusic( _soundTrack, -1);
99 	_isPlaying = true;
100     }
101 }
102 
init(void)103 bool Audio::init( void)
104 {
105     XTRACE();
106     LOG_INFO << "Initializing Audio..." << endl;
107 
108     bool audio;
109     if( !ConfigS::instance()->getBoolean( "audio", audio))
110     {
111         audio = false;
112     }
113     if( audio)
114     {
115 	if( SDL_InitSubSystem( SDL_INIT_AUDIO) < 0 )
116 	{
117 	    LOG_ERROR << "Init Audio: failed # " << SDL_GetError() << endl;
118 	    return false;
119 	}
120 
121         if( Mix_OpenAudio(22050, AUDIO_S16, 1, 1024) < 0 )
122         {
123 	    LOG_ERROR << "Init Audio (Mixer): failed # "
124                       << SDL_GetError() << endl;
125 	    return false;
126         }
127 
128 	_sampleManager = new SampleManager();
129 
130 	ConfigS::instance()->getBoolean( "playMusic", _playMusic);
131 	ConfigS::instance()->getBoolean(
132 	    "playDefaultSoundtrack", _playDefaultSoundtrack);
133 	startMusic();
134 
135         LOG_INFO << "Audio ON." << endl;
136     }
137     else
138     {
139         LOG_INFO << "Audio OFF." << endl;
140     }
141 
142     return true;
143 }
144 
playSample(const string & sampleName)145 void Audio::playSample( const string &sampleName)
146 {
147     if( !_sampleManager) return;
148 
149     Mix_Chunk *sample = _sampleManager->getSample( sampleName);
150     if( sample)
151     {
152 	//any channel, no loop
153 	Mix_PlayChannel(-1, sample, 0);
154     }
155 }
156 
turnMusicOff(void)157 void Audio::turnMusicOff( void)
158 {
159     if( _isPlaying)
160     {
161 	Mix_HaltMusic();
162 	if( _soundTrack)
163 	{
164 	    Mix_FreeMusic( _soundTrack);
165 	    _soundTrack = 0;
166 	}
167 	_isPlaying = false;
168     }
169 }
170 
startMusic(void)171 void Audio::startMusic( void)
172 {
173     if( _playMusic)
174     {
175 	string soundtrack = "";
176 
177 	if( _playDefaultSoundtrack)
178 	{
179 	    //look in developer file tree first
180 	    soundtrack = string("../data/music/TODO.ogg");
181 
182 	    struct stat statInfo;
183 	    if( stat( soundtrack.c_str(), &statInfo) == -1)
184 	    {
185 		//try global
186 		soundtrack = DATA_DIR+string("TODO.ogg");
187 	    }
188 	}
189 	else
190 	{
191 	    ConfigS::instance()->getString( "soundtrack", soundtrack);
192 	}
193 
194         turnMusicOff();
195 	loadMusic( soundtrack);
196     }
197     else
198     {
199         turnMusicOff();
200     }
201 }
202 
updateSettings(void)203 void Audio::updateSettings( void)
204 {
205     bool oldPlayMusic = _playMusic;
206     bool oldPlayDefaultSoundtrack = _playDefaultSoundtrack;
207 
208     ConfigS::instance()->getBoolean( "playMusic", _playMusic);
209     ConfigS::instance()->getBoolean(
210 	"playDefaultSoundtrack", _playDefaultSoundtrack);
211 
212     if( (oldPlayMusic == _playMusic) &&
213 	(oldPlayDefaultSoundtrack == _playDefaultSoundtrack))
214     {
215 	//no changes...
216 	return;
217     }
218 
219     startMusic();
220 }
221 
update(void)222 bool Audio::update( void)
223 {
224     if( !_sampleManager) return true;
225 
226     static float nextTime = Timer::getTime()+0.5;
227     float thisTime = Timer::getTime();
228     if( thisTime > nextTime)
229     {
230 	updateSettings();
231 	nextTime = thisTime+0.5;
232     }
233 
234     return true;
235 }
236