1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* CMusicHandler.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../lib/CConfigHandler.h"
#include "../lib/CSoundBase.h"
class CSpell;
struct _Mix_Music;
struct SDL_RWops;
typedef struct _Mix_Music Mix_Music;
struct Mix_Chunk;
class CAudioBase {
protected:
boost::mutex mutex;
bool initialized;
int volume; // from 0 (mute) to 100
public:
CAudioBase(): initialized(false), volume(0) {};
virtual void init() = 0;
virtual void release() = 0;
virtual void setVolume(ui32 percent);
ui32 getVolume() const { return volume; };
};
class CSoundHandler: public CAudioBase
{
private:
//soundBase::soundID getSoundID(const std::string &fileName);
//update volume on configuration change
SettingsListener listener;
void onVolumeChange(const JsonNode &volumeNode);
using CachedChunk = std::pair<Mix_Chunk *, std::unique_ptr<ui8[]>>;
std::map<std::string, CachedChunk> soundChunks;
Mix_Chunk *GetSoundChunk(std::string &sound, bool cache);
//have entry for every currently active channel
//std::function will be nullptr if callback was not set
std::map<int, std::function<void()> > callbacks;
int ambientDistToVolume(int distance) const;
void ambientStopSound(std::string soundId);
const JsonNode ambientConfig;
bool allTilesSource;
std::map<std::string, int> ambientChannels;
public:
CSoundHandler();
void init() override;
void release() override;
void setVolume(ui32 percent) override;
void setChannelVolume(int channel, ui32 percent);
// Sounds
int playSound(soundBase::soundID soundID, int repeats=0);
int playSound(std::string sound, int repeats=0, bool cache=false);
int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
void stopSound(int handler);
void setCallback(int channel, std::function<void()> function);
void soundFinishedCallback(int channel);
int ambientGetRange() const;
bool ambientCheckVisitable() const;
void ambientUpdateChannels(std::map<std::string, int> currentSounds);
void ambientStopAllChannels();
// Sets
std::vector<soundBase::soundID> pickupSounds;
std::vector<soundBase::soundID> horseSounds;
std::vector<soundBase::soundID> battleIntroSounds;
};
// Helper //now it looks somewhat useless
#define battle_sound(creature,what_sound) creature->sounds.what_sound
class CMusicHandler;
//Class for handling one music file
class MusicEntry
{
CMusicHandler *owner;
Mix_Music *music;
int loop; // -1 = indefinite
//if not null - set from which music will be randomly selected
std::string setName;
std::string currentName;
void load(std::string musicURI);
public:
bool isSet(std::string setName);
bool isTrack(std::string trackName);
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
~MusicEntry();
bool play();
bool stop(int fade_ms=0);
};
class CMusicHandler: public CAudioBase
{
private:
//update volume on configuration change
SettingsListener listener;
void onVolumeChange(const JsonNode &volumeNode);
std::unique_ptr<MusicEntry> current;
std::unique_ptr<MusicEntry> next;
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
void queueNext(std::unique_ptr<MusicEntry> queued);
std::map<std::string, std::map<int, std::string> > musicsSet;
public:
CMusicHandler();
/// add entry with URI musicURI in set. Track will have ID musicID
void addEntryToSet(std::string set, int musicID, std::string musicURI);
void init() override;
void release() override;
void setVolume(ui32 percent) override;
/// play track by URI, if loop = true music will be looped
void playMusic(std::string musicURI, bool loop);
/// play random track from this set
void playMusicFromSet(std::string musicSet, bool loop);
/// play specific track from set
void playMusicFromSet(std::string musicSet, int entryID, bool loop);
void stopMusic(int fade_ms=1000);
void musicFinishedCallback();
friend class MusicEntry;
};
|