devalang_core/core/audio/
player.rs

1use 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}