devalang_core/core/audio/
player.rs1use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink, Source};
2use std::{fs::File, io::BufReader};
3
4pub struct AudioPlayer {
5 _stream: OutputStream,
6 handle: OutputStreamHandle,
7 sink: Sink,
8 last_path: Option<String>,
9}
10
11impl AudioPlayer {
12 pub fn new() -> Self {
13 let (stream, handle) = OutputStream::try_default().unwrap();
14 let sink = Sink::try_new(&handle).unwrap();
15
16 Self {
17 _stream: stream,
18 handle,
19 sink,
20 last_path: None,
21 }
22 }
23
24 fn load_source(&self, path: &str) -> Option<impl Source<Item = f32> + Send + 'static> {
25 if let Ok(file) = File::open(path) {
26 let reader = BufReader::new(file);
27 match Decoder::new(reader) {
28 Ok(decoder) => Some(decoder.convert_samples()),
29 Err(e) => {
30 eprintln!("❌ Failed to decode audio file '{}': {}", path, e);
31 None
32 }
33 }
34 } else {
35 eprintln!("❌ Could not open audio file: {}", path);
36 None
37 }
38 }
39
40 pub fn play_file_once(&mut self, path: &str) {
41 self.sink.stop();
42 self.sink = Sink::try_new(&self.handle).unwrap();
43 self.sink.set_volume(1.0);
44
45 if let Some(source) = self.load_source(path) {
46 self.sink.append(source);
47 self.last_path = Some(path.to_string());
48 } else {
49 eprintln!("⚠️ Skipping playback: failed to load '{}'", path);
50 }
51 }
52
53 pub fn replay_last(&mut self) {
54 if let Some(path) = self.last_path.clone() {
55 self.play_file_once(&path);
56 } else {
57 eprintln!("⚠️ No previous audio to replay.");
58 }
59 }
60
61 pub fn wait_until_end(&self) {
62 self.sink.sleep_until_end();
63 }
64}