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