1 /*********************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011-2012 OmegaSDG **
5 *********************************/
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
27 #include <Gosu/Audio.hpp> // for Gosu::SampleInstance
28 #include <Gosu/Math.hpp>
30 #include "client-conf.h"
33 #include "readercache.h"
36 typedef boost::shared_ptr
<Gosu::Song
> SongRef
;
47 static SongRef musicInst
, introMusic
, loopMusic
;
49 static bool paused
= false;
51 static MUSIC_STATE state
= NOT_PLAYING
;
53 static std::string newIntro
;
54 static std::string newLoop
;
55 static std::string curIntro
;
56 static std::string curLoop
;
59 static SongRef
genSong(const std::string
& name
)
61 BufferPtr
buffer(Reader::readBuffer(name
));
64 return SongRef(new Gosu::Song(buffer
->frontReader()));
67 static ReaderCache
<SongRef
> songs(genSong
);
69 static SongRef
getSong(const std::string
& name
)
71 if (!conf
.audioEnabled
)
73 return songs
.lifetimeRequest(name
);
78 static const char* stateStr(MUSIC_STATE state)
84 return "PLAYING_INTRO";
86 return "PLAYING_LOOP";
88 return "CHANGED_INTRO";
90 return "CHANGED_LOOP";
97 static void setState(MUSIC_STATE state_
)
99 // printf("State changed from %s to %s.\n", stateStr(this->state), stateStr(state));
103 static void playIntro()
105 if (musicInst
&& musicInst
->playing())
108 introMusic
->play(false);
109 introMusic
->changeVolume(conf
.musicVolume
/ 100.0);
110 musicInst
= introMusic
;
111 setState(PLAYING_INTRO
);
114 static void playLoop()
116 if (musicInst
&& musicInst
->playing())
119 loopMusic
->play(true);
120 loopMusic
->changeVolume(conf
.musicVolume
/ 100.0);
121 musicInst
= loopMusic
;
122 setState(PLAYING_LOOP
);
133 if (musicInst && musicInst->playing())
138 std::string
Music::getIntro()
143 std::string
Music::getLoop()
148 void Music::setIntro(const std::string
& filename
)
150 if (newIntro
== filename
)
157 setState(CHANGED_INTRO
);
162 // Optimize XXX: Don't load until played.
163 introMusic
= filename
.size() ? getSong(filename
) : SongRef();
166 void Music::setLoop(const std::string
& filename
)
168 if (newLoop
== filename
)
175 setState(CHANGED_LOOP
);
180 // Optimize XXX: Don't load until played.
181 loopMusic
= filename
.size() ? getSong(filename
) : SongRef();
184 int Music::getVolume()
186 return conf
.musicVolume
;
189 void Music::setVolume(int level
)
191 if (0 < level
|| level
> 100) {
192 Log::info("Music", "volume can only be set between 0 and 100");
193 level
= Gosu::clamp(level
, 0, 100);
195 conf
.musicVolume
= level
;
197 musicInst
->changeVolume(level
);
200 bool Music::isPaused()
205 void Music::setPaused(bool p
)
233 if (musicInst
&& musicInst
->playing())
237 if (!musicInst
->playing()) {
238 if (newLoop
.size() && loopMusic
)
241 setState(NOT_PLAYING
);
247 if (newIntro
.size() && introMusic
)
249 else if (newLoop
.size() && newLoop
!= curLoop
)
250 setState(CHANGED_LOOP
);
251 else if (newLoop
.size())
252 setState(PLAYING_LOOP
);
254 setState(NOT_PLAYING
);
257 if (newIntro
.size() && loopMusic
)
259 else if (newLoop
.size() && loopMusic
)
262 setState(NOT_PLAYING
);
271 // FIXME: Broken with shift to singleton. No instantiated object to bind.
272 // Fix will require a stub object.
275 boost::python::class_
<Music
>("MusicManager", boost::python::no_init
)
276 .add_property("intro", &Music::getIntro
, &Music::setIntro
)
277 .add_property("loop", &Music::getLoop
, &Music::setLoop
)
278 .add_property("volume", &Music::getVolume
, &Music::setVolume
)
279 .add_property("paused", &Music::isPaused
, &Music::setPaused
)
280 .def("stop", &Music::stop
)
283 pythonSetGlobal("Music", this);