1use std::{
2 collections::HashMap,
3 fs,
4 io::{BufReader, Cursor},
5 path::{Path, PathBuf},
6 thread,
7};
8
9use anyhow::bail;
10use tokio::sync::mpsc::{self, Sender};
11
12#[derive(Debug, Clone)]
13pub struct Audio {
14 pub channel: Sender<AudioCommand>,
15 pub cached_audio: HashMap<String, Box<Cursor<Vec<u8>>>>,
16}
17
18#[derive(Debug, Clone)]
19pub enum AudioCommand {
20 Play(PathBuf),
21 Stop,
22}
23
24impl Audio {
25 pub fn new() -> Audio {
26 let (tx, mut rx) = mpsc::channel::<AudioCommand>(16);
27
28 tokio::spawn(async move {
29 println!("hey im the audio thread nya meow meow >:3");
30 let stream_handle = rodio::OutputStreamBuilder::open_default_stream()
31 .expect("audio: failed to initialize stream handle");
32 let mixer = stream_handle.mixer();
33 let mut current_sink: Option<rodio::Sink> = None;
34
35 while let Some(message) = rx.recv().await {
36 println!("{:?}", message);
37 if let AudioCommand::Play(pathbuf) = message {
38 if let Some(sink) = current_sink {
39 sink.stop();
40 }
41
42 let file = std::fs::File::open(pathbuf.to_string_lossy().to_string()).unwrap();
43 println!("{:?}", file.metadata());
44 let sink = rodio::play(mixer, BufReader::new(file)).unwrap();
45 sink.set_volume(1.0);
46 current_sink = Some(sink);
47 }
48 thread::sleep(std::time::Duration::from_millis(100));
49 }
50 });
51
52 Self {
53 channel: tx,
54 cached_audio: HashMap::new(),
55 }
56 }
57
58 pub fn load_asset(&mut self, path: &Path) -> anyhow::Result<()> {
59 if self
60 .cached_audio
61 .contains_key(&path.to_string_lossy().to_string())
62 {
63 bail!("resource already cached")
64 }
65
66 let data: Vec<u8> = fs::read(path)?;
67 self.cached_audio.insert(
68 path.to_string_lossy().to_string(),
69 Box::new(Cursor::new(data)),
70 );
71 Ok(())
72 }
73
74 pub async fn play_audio(
75 &mut self,
76 path: &Path,
77 _interrupt_current_playback: bool,
78 ) -> anyhow::Result<()> {
79 if !self
80 .cached_audio
81 .contains_key(&path.to_string_lossy().to_string())
82 {
83 println!("caching");
86 self.load_asset(path)?;
87 }
88 self.channel
89 .send(AudioCommand::Play(path.to_path_buf()))
90 .await?;
91 Ok(())
103 }
104}
105
106impl Default for Audio {
107 fn default() -> Self {
108 Self::new()
109 }
110}