goud_engine/assets/audio_manager/
playback.rs1use crate::assets::loaders::AudioAsset;
4use crate::core::error::{GoudError, GoudResult};
5use rodio::{Player, Source};
6
7use super::AudioManager;
8
9impl AudioManager {
10 pub fn play(&mut self, asset: &AudioAsset) -> GoudResult<u64> {
27 if asset.is_empty() {
28 return Err(GoudError::ResourceLoadFailed(
29 "Cannot play empty audio asset".to_string(),
30 ));
31 }
32
33 let cursor = std::io::Cursor::new(asset.data().to_vec());
34 let source = rodio::Decoder::new(cursor)
35 .map_err(|e| GoudError::ResourceLoadFailed(format!("Failed to decode audio: {}", e)))?;
36
37 let player = Player::connect_new(self.device_sink.mixer());
38 player.set_volume(self.global_volume());
39 player.append(source);
40
41 let player_id = self.allocate_player_id();
42 self.players.lock().unwrap().insert(player_id, player);
43
44 Ok(player_id)
45 }
46
47 pub fn play_looped(&mut self, asset: &AudioAsset) -> GoudResult<u64> {
59 if asset.is_empty() {
60 return Err(GoudError::ResourceLoadFailed(
61 "Cannot play empty audio asset".to_string(),
62 ));
63 }
64
65 let cursor = std::io::Cursor::new(asset.data().to_vec());
66 let source = rodio::Decoder::new(cursor)
67 .map_err(|e| GoudError::ResourceLoadFailed(format!("Failed to decode audio: {}", e)))?;
68
69 let looped_source = source.repeat_infinite();
70 let player = Player::connect_new(self.device_sink.mixer());
71 player.set_volume(self.global_volume());
72 player.append(looped_source);
73
74 let player_id = self.allocate_player_id();
75 self.players.lock().unwrap().insert(player_id, player);
76
77 Ok(player_id)
78 }
79
80 pub fn play_with_settings(
93 &mut self,
94 asset: &AudioAsset,
95 volume: f32,
96 speed: f32,
97 looping: bool,
98 ) -> GoudResult<u64> {
99 if asset.is_empty() {
100 return Err(GoudError::ResourceLoadFailed(
101 "Cannot play empty audio asset".to_string(),
102 ));
103 }
104
105 let cursor = std::io::Cursor::new(asset.data().to_vec());
106 let source = rodio::Decoder::new(cursor)
107 .map_err(|e| GoudError::ResourceLoadFailed(format!("Failed to decode audio: {}", e)))?;
108
109 let clamped_speed = speed.clamp(0.1, 10.0);
110 let source_with_speed = source.speed(clamped_speed);
111
112 let player = Player::connect_new(self.device_sink.mixer());
113 let clamped_volume = volume.clamp(0.0, 1.0);
114 let final_volume = self.global_volume() * clamped_volume;
115 player.set_volume(final_volume);
116
117 if looping {
118 player.append(source_with_speed.repeat_infinite());
119 } else {
120 player.append(source_with_speed);
121 }
122
123 let player_id = self.allocate_player_id();
124 self.players.lock().unwrap().insert(player_id, player);
125
126 Ok(player_id)
127 }
128
129 pub fn pause(&self, sink_id: u64) -> bool {
139 let players = self.players.lock().unwrap();
140 if let Some(player) = players.get(&sink_id) {
141 player.pause();
142 true
143 } else {
144 false
145 }
146 }
147
148 pub fn resume(&self, sink_id: u64) -> bool {
158 let players = self.players.lock().unwrap();
159 if let Some(player) = players.get(&sink_id) {
160 player.play();
161 true
162 } else {
163 false
164 }
165 }
166
167 pub fn stop(&mut self, sink_id: u64) -> bool {
177 let mut players = self.players.lock().unwrap();
178 if let Some(player) = players.remove(&sink_id) {
179 player.stop();
180 true
181 } else {
182 false
183 }
184 }
185
186 pub fn is_playing(&self, sink_id: u64) -> bool {
196 let players = self.players.lock().unwrap();
197 if let Some(player) = players.get(&sink_id) {
198 !player.is_paused()
199 } else {
200 false
201 }
202 }
203
204 pub fn active_count(&self) -> usize {
206 self.players.lock().unwrap().len()
207 }
208
209 pub fn stop_all(&mut self) {
211 let mut players = self.players.lock().unwrap();
212 for player in players.values() {
213 player.stop();
214 }
215 players.clear();
216 }
217
218 pub fn cleanup_finished(&mut self) {
223 let mut players = self.players.lock().unwrap();
224 players.retain(|_, player| !player.empty());
225 }
226}