1 /* Copyright (C) 2017 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_SOUNDMANAGER_H
19 #define INCLUDED_SOUNDMANAGER_H
20 
21 #include "lib/config2.h"
22 
23 #if CONFIG2_AUDIO
24 
25 #include "ISoundManager.h"
26 #include "data/SoundData.h"
27 #include "items/ISoundItem.h"
28 #include "scripting/SoundGroup.h"
29 
30 #include "lib/external_libraries/openal.h"
31 #include "lib/file/vfs/vfs_path.h"
32 #include "ps/Profiler2.h"
33 #include "simulation2/system/Entity.h"
34 
35 #include <vector>
36 #include <map>
37 
38 #define AL_CHECK CSoundManager::al_check(__func__, __LINE__)
39 
40 struct ALSourceHolder
41 {
42 	/// Title of the column
43 	ALuint 		ALSource;
44 	ISoundItem*	SourceItem;
45 };
46 
47 typedef std::vector<VfsPath> PlayList;
48 typedef std::vector<ISoundItem*> ItemsList;
49 typedef std::map<entity_id_t, ISoundItem*> ItemsMap;
50 typedef	std::map<std::wstring, CSoundGroup*> SoundGroupMap;
51 
52 class CSoundManagerWorker;
53 
54 
55 class CSoundManager : public ISoundManager
56 {
57 	NONCOPYABLE(CSoundManager);
58 
59 protected:
60 
61 	ALCcontext* m_Context;
62 	ALCdevice* m_Device;
63 	ALSourceHolder* m_ALSourceBuffer;
64 	ISoundItem* m_CurrentTune;
65 	ISoundItem* m_CurrentEnvirons;
66 	CSoundManagerWorker* m_Worker;
67 	CMutex m_DistressMutex;
68 	PlayList* m_PlayListItems;
69 	SoundGroupMap m_SoundGroups;
70 
71 	float m_Gain;
72 	float m_MusicGain;
73 	float m_AmbientGain;
74 	float m_ActionGain;
75 	float m_UIGain;
76 	bool m_Enabled;
77 	long m_BufferSize;
78 	int m_BufferCount;
79 	bool m_SoundEnabled;
80 	bool m_MusicEnabled;
81 
82 	bool m_MusicPaused;
83 	bool m_AmbientPaused;
84 	bool m_ActionPaused;
85 	bool m_RunningPlaylist;
86 	bool m_PlayingPlaylist;
87 	bool m_LoopingPlaylist;
88 
89 	long m_PlaylistGap;
90 	long m_DistressErrCount;
91 	long m_DistressTime;
92 
93 
94 public:
95 	CSoundManager();
96 	virtual ~CSoundManager();
97 
98 	void StartWorker();
99 
100 	ISoundItem* LoadItem(const VfsPath& itemPath);
101 	ISoundItem* ItemForData(CSoundData* itemData);
102 	ISoundItem* ItemForEntity(entity_id_t source, CSoundData* sndData);
103 
104 	Status ReloadChangedFiles(const VfsPath& path);
105 
106 	void ClearPlayListItems();
107 	void StartPlayList(bool doLoop);
108 	void AddPlayListItem(const VfsPath& itemPath);
109 
110 	static void CreateSoundManager();
111 	static void SetEnabled(bool doEnable);
112 	static Status ReloadChangedFileCB(void* param, const VfsPath& path);
113 
114 	static void CloseGame();
115 
116 	static void al_ReportError(ALenum err, const char* caller, int line);
117 	static void al_check(const char* caller, int line);
118 
119 	void SetMusicEnabled(bool isEnabled);
120 	void SetSoundEnabled(bool enabled);
121 
122 	ALuint GetALSource(ISoundItem* anItem);
123 	void ReleaseALSource(ALuint theSource);
124 	ISoundItem* ItemFromData(CSoundData* itemData);
125 
126 	ISoundItem* ItemFromWAV(VfsPath& fname);
127 	ISoundItem* ItemFromOgg(VfsPath& fname);
128 
129 	ISoundItem* GetSoundItem(unsigned long itemRow);
130 	unsigned long Count();
131 	void IdleTask();
132 
133 	void SetMemoryUsage(long bufferSize, int bufferCount);
134 	long GetBufferCount();
135 	long GetBufferSize();
136 
137 	void PlayAsMusic(const VfsPath& itemPath, bool looping);
138 	void PlayAsAmbient(const VfsPath& itemPath, bool looping);
139 	void PlayAsUI(const VfsPath& itemPath, bool looping);
140 	void PlayAsGroup(const VfsPath& groupPath, const CVector3D& sourcePos, entity_id_t source, bool ownedSound);
141 
142 	void PlayGroupItem(ISoundItem* anItem, ALfloat groupGain);
143 
144 	bool InDistress();
145 	void SetDistressThroughShortage();
146 	void SetDistressThroughError();
147 
148 	void Pause(bool pauseIt);
149 	void PauseMusic(bool pauseIt);
150 	void PauseAmbient(bool pauseIt);
151 	void PauseAction(bool pauseIt);
152 	void SetAmbientItem(ISoundItem* anItem);
153 
154 	void SetMasterGain(float gain);
155 	void SetMusicGain(float gain);
156 	void SetAmbientGain(float gain);
157 	void SetActionGain(float gain);
158 	void SetUIGain(float gain);
159 
160 protected:
161 	void InitListener();
162 	Status AlcInit();
163 	void SetMusicItem(ISoundItem* anItem);
164 
165 private:
CSoundManager(CSoundManager * UNUSED (other))166 	CSoundManager(CSoundManager* UNUSED(other)){};
167 };
168 
169 #else // !CONFIG2_AUDIO
170 
171 #define AL_CHECK
172 
173 #endif // !CONFIG2_AUDIO
174 
175 #endif // INCLUDED_SOUNDMANAGER_H
176 
177