use rodio::{decoder::DecoderError, Decoder, OutputStream, PlayError, Sink, StreamError}; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; use std::thread; use std::{error::Error, fmt::Display, fmt::Formatter, fmt::Result as FmtResult}; #[derive(Debug, Clone)] pub struct Alert { path: PathBuf, } impl Alert { pub fn new(path: PathBuf) -> Self { Self { path } } pub fn load(&mut self, path: PathBuf) { self.path = path; } // pub fn play(&self) -> Result<(), Box> { // let file = File::open(&self.path).unwrap(); // thread::Builder::new() // .name("Audio Thread".to_string()) // .spawn(|| -> Result<(), Error> { // let (_stream, handle) = OutputStream::try_default()?; // let source = Decoder::new(BufReader::new(file))?; // let sink = Sink::try_new(&handle)?; // sink.append(source); // loop { // if sink.len() == 0 { // break; // } // } // Ok(()) // })?; // Ok(()) // } pub fn play(&self) -> Result<(), Box> { let file = File::open(&self.path).unwrap(); thread::Builder::new() .name("Alert Playback Thread".to_string()) .spawn(move || -> Result<(), PlaybackError> { let (_stream, handle) = OutputStream::try_default()?; let source = Decoder::new(BufReader::new(file))?; let sink = Sink::try_new(&handle)?; sink.append(source); loop { if sink.len() == 0 { break; } } Ok(()) })?; Ok(()) } } #[derive(Debug)] enum PlaybackError { StreamError(StreamError), DecoderError(DecoderError), SinkError(PlayError), } impl From for PlaybackError { fn from(err: DecoderError) -> Self { Self::DecoderError(err) } } impl From for PlaybackError { fn from(err: StreamError) -> Self { Self::StreamError(err) } } impl From for PlaybackError { fn from(err: PlayError) -> Self { Self::SinkError(err) } } impl Error for PlaybackError { fn source(&self) -> Option<&(dyn Error + 'static)> { match &self { Self::StreamError(err) => Some(err), Self::DecoderError(err) => Some(err), Self::SinkError(err) => Some(err), } } } impl Display for PlaybackError { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match &self { Self::StreamError(err) => write!(f, "{}", err), Self::DecoderError(err) => write!(f, "{}", err), Self::SinkError(err) => write!(f, "{}", err), } } }