Fix INT_MAX definition on some newer systems.
[Tsunagari.git] / src / music.cpp
blobc0945bf02792a731ae2d724565e2de620f42d8fd
1 /***************************************
2 ** Tsunagari Tile Engine **
3 ** music.cpp **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <Gosu/Math.hpp>
29 #include "client-conf.h"
30 #include "music.h"
31 #include "reader.h"
32 #include "python.h"
33 #include "python-bindings-template.cpp"
35 static Music::SongRef genSong(const std::string& name)
37 std::unique_ptr<Gosu::Buffer> buffer(Reader::readBuffer(name));
38 if (!buffer)
39 return Music::SongRef();
40 return Music::SongRef(new Gosu::Song(buffer->frontReader()));
45 Music::SongRef Music::getSong(const std::string& name)
47 if (!conf.audioEnabled)
48 return SongRef();
49 return songs.lifetimeRequest(name);
54 static const char* stateStr(MUSIC_STATE state)
56 switch (state) {
57 case NOT_PLAYING:
58 return "NOT_PLAYING";
59 case PLAYING_INTRO:
60 return "PLAYING_INTRO";
61 case PLAYING_LOOP:
62 return "PLAYING_LOOP";
63 case CHANGED_INTRO:
64 return "CHANGED_INTRO";
65 case CHANGED_LOOP:
66 return "CHANGED_LOOP";
67 default:
68 return "";
73 void Music::setState(MUSIC_STATE state_)
75 // printf("State changed from %s to %s.\n", stateStr(this->state), stateStr(state));
76 state = state_;
79 void Music::playIntro()
81 if (musicInst && musicInst->playing())
82 musicInst->stop();
83 curIntro = newIntro;
84 introMusic->play(false);
85 introMusic->changeVolume(conf.musicVolume / 100.0);
86 musicInst = introMusic;
87 setState(PLAYING_INTRO);
90 void Music::playLoop()
92 if (musicInst && musicInst->playing())
93 musicInst->stop();
94 curLoop = newLoop;
95 loopMusic->play(true);
96 loopMusic->changeVolume(conf.musicVolume / 100.0);
97 musicInst = loopMusic;
98 setState(PLAYING_LOOP);
103 Music::Music() : songs(genSong), paused(false), state(NOT_PLAYING)
107 Music::~Music()
109 if (musicInst && musicInst->playing())
110 musicInst->stop();
113 std::string Music::getIntro()
115 return newIntro;
118 std::string Music::getLoop()
120 return newLoop;
123 void Music::setIntro(const std::string& filename)
125 if (newIntro == filename)
126 return;
128 switch (state) {
129 case NOT_PLAYING:
130 case PLAYING_INTRO:
131 case PLAYING_LOOP:
132 setState(CHANGED_INTRO);
133 default: break;
136 newIntro = filename;
137 // Optimize XXX: Don't load until played.
138 introMusic = filename.size() ? getSong(filename) : SongRef();
141 void Music::setLoop(const std::string& filename)
143 if (newLoop == filename)
144 return;
146 switch (state) {
147 case NOT_PLAYING:
148 case PLAYING_INTRO:
149 case PLAYING_LOOP:
150 setState(CHANGED_LOOP);
151 default: break;
154 newLoop = filename;
155 // Optimize XXX: Don't load until played.
156 loopMusic = filename.size() ? getSong(filename) : SongRef();
159 int Music::getVolume()
161 return conf.musicVolume;
164 void Music::setVolume(int level)
166 if (0 < level || level > 100) {
167 Log::info("Music", "volume can only be set between 0 and 100");
168 level = Gosu::clamp(level, 0, 100);
170 conf.musicVolume = level;
171 if (musicInst)
172 musicInst->changeVolume(level);
175 bool Music::isPaused()
177 return paused;
180 void Music::setPaused(bool p)
182 if (paused == p)
183 return;
184 paused = p;
185 if (musicInst) {
186 if (p)
187 musicInst->pause();
188 else
189 musicInst->play();
193 void Music::stop()
195 paused = false;
196 if (musicInst)
197 musicInst->stop();
198 state = NOT_PLAYING;
201 void Music::tick()
203 if (paused)
204 return;
206 switch (state) {
207 case NOT_PLAYING:
208 if (musicInst && musicInst->playing())
209 musicInst->stop();
210 break;
211 case PLAYING_INTRO:
212 if (!musicInst->playing()) {
213 if (newLoop.size() && loopMusic)
214 playLoop();
215 else
216 setState(NOT_PLAYING);
218 break;
219 case PLAYING_LOOP:
220 break;
221 case CHANGED_INTRO:
222 if (newIntro.size() && introMusic)
223 playIntro();
224 else if (newLoop.size() && newLoop != curLoop)
225 setState(CHANGED_LOOP);
226 else if (newLoop.size())
227 setState(PLAYING_LOOP);
228 else
229 setState(NOT_PLAYING);
230 break;
231 case CHANGED_LOOP:
232 if (newIntro.size() && loopMusic)
233 playIntro();
234 else if (newLoop.size() && loopMusic)
235 playLoop();
236 else
237 setState(NOT_PLAYING);
238 break;
243 void exportMusic()
245 using namespace boost::python;
247 class_<Music>("MusicManager", no_init)
248 .add_property("intro", &Music::getIntro, &Music::setIntro)
249 .add_property("loop", &Music::getLoop, &Music::setLoop)
250 .add_property("volume", &Music::getVolume, &Music::setVolume)
251 .add_property("paused", &Music::isPaused, &Music::setPaused)
252 .def("stop", &Music::stop)