1+ /*
2+ ** EPITECH PROJECT, 2024
3+ ** GameEngine
4+ ** File description:
5+ ** AudioManager.cpp
6+ */
7+
8+ #include " GEngine/libdev/systems/driver/output/AudioManager.hpp"
9+
10+ namespace gengine ::system::driver::output {
11+
12+ AudioManager::AudioManager (const std::string &soundFolder, const std::string &musicFolder)
13+ : m_soundFolder(soundFolder)
14+ , m_musicFolder(musicFolder) {
15+ }
16+
17+ void AudioManager::onStartEngine (gengine::system::event::StartEngine &e) {
18+ SetTraceLogLevel (LOG_WARNING);
19+ InitAudioDevice ();
20+ for (const auto &entry : std::filesystem::recursive_directory_iterator (m_soundFolder)) {
21+ if (entry.is_regular_file ()) {
22+ std::string filePath = entry.path ().string ();
23+
24+ Sound sound = LoadSound (filePath.c_str ());
25+ std::string path = std::filesystem::relative (entry.path (), m_soundFolder).string ();
26+ m_soundTable.insert ({path, {m_soundBaseId++, sound}});
27+ }
28+ }
29+ for (const auto &entry : std::filesystem::recursive_directory_iterator (m_musicFolder)) {
30+ if (entry.is_regular_file ()) {
31+ std::string filePath = entry.path ().string ();
32+
33+ Music music = LoadMusicStream (filePath.c_str ());
34+ std::string path = std::filesystem::relative (entry.path (), m_musicFolder).string ();
35+ m_musicTable.insert ({path, {m_musicBaseId++, music}});
36+ }
37+ }
38+ }
39+
40+ Music AudioManager::getMusicById (std::uint64_t id) {
41+ for (auto &[_, pair] : m_musicTable)
42+ if (pair.first == id)
43+ return pair.second ;
44+ THROW_WARNING (" Music component not initilized" );
45+ }
46+
47+ void AudioManager::onStopEngine (gengine::system::event::StopEngine &e) {
48+ for (auto &[path, sound] : m_soundTable)
49+ UnloadSound (sound.second );
50+ }
51+
52+ const Sound &AudioManager::get (const std::string &path) {
53+ const auto &sound = m_soundTable.find (path);
54+ if (sound == m_soundTable.cend ())
55+ THROW_ERROR (" Out of range: This sound does not exist. PATH: " + path);
56+
57+ return sound->second .second ;
58+ }
59+
60+ void AudioManager::onMainLoop (geg::event::MainLoop &e) {
61+ auto &sounds = getComponents<gengine::component::driver::output::Sound>();
62+ auto &musics = getComponents<gengine::component::driver::output::Music>();
63+
64+ if (musics.size ()) {
65+ auto &music = getMusicComponent ();
66+ if (music.musicId != m_currentMusicId) {
67+ if (m_currentMusicId)
68+ StopMusicStream (getMusicById (m_currentMusicId));
69+ m_currentMusicId = music.musicId ;
70+ PlayMusicStream (getMusicById (m_currentMusicId));
71+ }
72+ }
73+
74+ if (m_currentMusicId)
75+ UpdateMusicStream (getMusicById (m_currentMusicId));
76+
77+ static std::set<gengine::Entity> m_soundsPlayed;
78+
79+ for (auto &[e, sound] : sounds) {
80+ if (m_soundsPlayed.find (e) == m_soundsPlayed.end ()) {
81+ m_soundsPlayed.insert (e);
82+ playSoundById (sound.soundId );
83+ }
84+ publishEvent (gengine::system::event::driver::output::SoundPlayed (sound.soundId ));
85+ }
86+ for (auto it = m_soundsPlayed.begin (); it != m_soundsPlayed.end ();)
87+ if (!sounds.contains (*it))
88+ it = m_soundsPlayed.erase (it);
89+ else
90+ ++it;
91+ }
92+
93+ gengine::component::driver::output::Music &AudioManager::getMusicComponent (void ) {
94+ auto &musics = getComponents<gengine::component::driver::output::Music>();
95+
96+ if (!musics.size ())
97+ THROW_WARNING (" Music component not initilazed" );
98+ for (auto &[_, m] : musics)
99+ return m;
100+ }
101+
102+ void AudioManager::onSoundPlayed (
103+ gengine::interface::event::SharedEvent<gengine::system::event::driver::output::SoundPlayed> &e) {
104+ static std::unordered_map<std::uint64_t , std::set<uuids::uuid>> m_soundsAck;
105+ auto &remoteLocals = getComponents<gengine::interface::component::RemoteLocal>();
106+ auto &sounds = getComponents<gengine::component::driver::output::Sound>();
107+
108+ if (m_soundsAck.find (e->soundId ) == m_soundsAck.end ())
109+ m_soundsAck.insert ({e->soundId , std::set<uuids::uuid>()});
110+ m_soundsAck[e->soundId ].insert (e.remoteUUID );
111+
112+ for (auto &[entity, s] : sounds) {
113+ if (s.soundId == e->soundId && m_soundsAck[e->soundId ].size () == remoteLocals.size ())
114+ killEntity (entity);
115+ m_soundsAck.erase (e->soundId );
116+ }
117+ }
118+
119+ std::uint64_t AudioManager::getIdByPath (const std::string &path) const {
120+ auto it = m_soundTable.find (path);
121+
122+ if (it == m_soundTable.end ())
123+ THROW_WARNING (" Sound not found" );
124+
125+ return it->second .first ;
126+ }
127+
128+ void AudioManager::playSoundById (std::uint64_t id) {
129+ for (auto &[_, pair] : m_soundTable) {
130+ if (pair.first == id) {
131+ PlaySound (pair.second );
132+ return ;
133+ }
134+ }
135+ }
136+
137+ AudioManagerLocal::AudioManagerLocal (const std::string &soundFolder, const std::string &musicFolder)
138+ : AudioManager(soundFolder, musicFolder) {
139+ }
140+
141+ void AudioManagerLocal::init (void ) {
142+ subscribeToEvent<gengine::system::event::StartEngine>(&AudioManager::onStartEngine);
143+ subscribeToEvent<gengine::system::event::StopEngine>(&AudioManager::onStopEngine);
144+ subscribeToEvent<geg::event::MainLoop>(&AudioManager::onMainLoop);
145+ }
146+
147+ AudioManagerRemote::AudioManagerRemote (const std::string &soundFolder, const std::string &musicFolder)
148+ : AudioManager(soundFolder, musicFolder) {
149+ }
150+
151+ void AudioManagerRemote::init (void ) {
152+ subscribeToEvent<gengine::system::event::StartEngine>(&AudioManager::onStartEngine);
153+ subscribeToEvent<gengine::system::event::StopEngine>(&AudioManager::onStopEngine);
154+ subscribeToEvent<gengine::system::event::driver::output::Sound>(&AudioManager::onSound);
155+ subscribeToEvent<gengine::interface::event::SharedEvent<gengine::system::event::driver::output::SoundPlayed>>(
156+ &AudioManager::onSoundPlayed);
157+ subscribeToEvent<gengine::system::event::driver::output::Music>(&AudioManager::onMusic);
158+ }
159+ } // namespace gengine::system::driver::output
0 commit comments