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