use std::{
io::BufReader,
path::{Path, PathBuf},
};
use tokio::sync::mpsc::{self, Sender};
#[derive(Debug, Clone)]
pub struct Audio {
pub channel: Sender<AudioCommand>,
}
#[derive(Debug, Clone)]
pub enum AudioCommand {
Play(PathBuf),
Stop,
}
impl Audio {
pub fn new() -> Audio {
let (tx, mut rx) = mpsc::channel::<AudioCommand>(16);
tokio::spawn(async move {
println!("hey im the audio thread nya meow meow >:3");
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()
.expect("audio: failed to initialize stream handle");
let mixer = stream_handle.mixer();
let mut current_sink: Option<rodio::Sink> = None;
while let Some(message) = rx.recv().await {
match message {
AudioCommand::Play(pathbuf) => {
if let Some(sink) = current_sink.take() {
sink.stop();
}
let file =
std::fs::File::open(&pathbuf).expect("audio: failed to open file");
let sink = rodio::play(mixer, BufReader::new(file))
.expect("audio: failed to start playback");
sink.set_volume(1.0);
current_sink = Some(sink);
}
AudioCommand::Stop => {
if let Some(sink) = current_sink.take() {
sink.stop();
}
}
}
}
});
Self { channel: tx }
}
pub async fn play_audio(
&mut self,
path: &Path,
_interrupt_current_playback: bool,
) -> anyhow::Result<()> {
self.channel
.send(AudioCommand::Play(path.to_path_buf()))
.await?;
Ok(())
}
}
impl Default for Audio {
fn default() -> Self {
Self::new()
}
}