1 /* Copyright (C) 2013-2014 Michal Brzozowski (rusolis@poczta.fm)
2
3 This file is part of KeeperRL.
4
5 KeeperRL is free software; you can redistribute it and/or modify it under the terms of the
6 GNU General Public License as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with this program.
14 If not, see http://www.gnu.org/licenses/ . */
15
16 #include "stdafx.h"
17 #include "music.h"
18 #include "options.h"
19 #include "audio_device.h"
20
Jukebox(Options * options,AudioDevice & audio,vector<pair<MusicType,FilePath>> tracks,float maxVol,map<MusicType,float> maxV)21 Jukebox::Jukebox(Options* options, AudioDevice& audio, vector<pair<MusicType, FilePath> > tracks,
22 float maxVol, map<MusicType, float> maxV)
23 : numTracks(tracks.size()), maxVolume(maxVol), maxVolumes(maxV), audioDevice(audio) {
24 for (int i : All(tracks)) {
25 music.emplace_back(tracks[i].second);
26 byType[tracks[i].first].push_back(i);
27 }
28 options->addTrigger(OptionId::MUSIC, [this](bool turnOn) { toggle(turnOn); });
29 refreshLoop.emplace([this] {
30 refresh();
31 sleep_for(milliseconds(200));
32 });
33 }
34
getMaxVolume(int track)35 float Jukebox::getMaxVolume(int track) {
36 auto type = getCurrentType();
37 if (maxVolumes.count(type))
38 return maxVolumes.at(type);
39 else
40 return maxVolume;
41 }
42
toggle(bool state)43 void Jukebox::toggle(bool state) {
44 MusicLock lock(musicMutex);
45 if (state == on)
46 return;
47 if (!numTracks)
48 return;
49 on = state;
50 if (on) {
51 current = Random.choose(byType[getCurrentType()]);
52 currentPlaying = current;
53 play(current);
54 } else
55 stream.reset();
56 }
57
setCurrent(MusicType c)58 void Jukebox::setCurrent(MusicType c) {
59 current = Random.choose(byType[c]);
60 }
61
continueCurrent()62 void Jukebox::continueCurrent() {
63 if (byType[getCurrentType()].size() >= 2)
64 while (current == currentPlaying)
65 setCurrent(getCurrentType());
66 }
67
getCurrentType()68 MusicType Jukebox::getCurrentType() {
69 for (auto& elem : byType)
70 if (elem.second.contains(current))
71 return elem.first;
72 FATAL << "Track type not found " << current;
73 return MusicType::PEACEFUL;
74 }
75
76 const float volumeDec = 0.1f;
77
setType(MusicType c,bool now)78 void Jukebox::setType(MusicType c, bool now) {
79 MusicLock lock(musicMutex);
80 if (!now)
81 nextType = c;
82 else {
83 nextType.reset();
84 if (byType[c].empty())
85 return;
86 if (getCurrentType() != c)
87 current = Random.choose(byType[c]);
88 }
89 }
90
play(int index)91 void Jukebox::play(int index) {
92 stream.reset();
93 stream.reset(new SoundStream(music[current], getMaxVolume(current)));
94 }
95
refresh()96 void Jukebox::refresh() {
97 MusicLock lock(musicMutex);
98 if (!on || !numTracks)
99 return;
100 if (current != currentPlaying) {
101 if (!stream || !stream->isPlaying() || stream->getVolume() == 0) {
102 currentPlaying = current;
103 play(current);
104 } else
105 stream->setVolume(max(0.0, stream->getVolume() - volumeDec));
106 } else
107 if (!stream || !stream->isPlaying()) {
108 if (nextType) {
109 setCurrent(*nextType);
110 nextType.reset();
111 } else
112 continueCurrent();
113 currentPlaying = current;
114 if (getCurrentType() != MusicType::INTRO)
115 play(current);
116 }
117 }
118