//! This file implements the interface to save waves into a file. use std::{ error::Error, fmt::{self, Display, Formatter}, io::{self, Write}, }; use super::*; #[derive(Debug)] pub enum OutputError { Io(std::io::Error), FFMpeg(String), EmptyWaves, } impl Display for OutputError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Io(e) => write!(f, "io: {e}"), Self::EmptyWaves => write!(f, "empty waves"), OutputError::FFMpeg(s) => write!(f, "FFMPEG error: {s}"), } } } impl Error for OutputError {} impl From for OutputError { fn from(io: io::Error) -> Self { Self::Io(io) } } /// A type that implements this trait implements a generic function /// for saving waves into files. pub trait Output { /// Save waves DATA with RATE samples per second into a file with /// NAME. fn save(&self, data: Wave, rate: Samples, name: &str) -> Result<(), OutputError>; } /// A dummy struct to hold a generic function for saving waves. #[derive(Default)] pub struct PlainOutput {} impl Output for PlainOutput { fn save(&self, data: Wave, _rate: Samples, name: &str) -> Result<(), OutputError> { if data.is_empty() { return Err(OutputError::EmptyWaves); } let bytes: Vec = data.iter().flat_map(|pulse| pulse.to_le_bytes()).collect(); let mut file = std::fs::OpenOptions::new() .create(true) .write(true) .open(name)?; file.write_all(&bytes)?; Ok(()) } } #[cfg(feature = "ffmpeg")] pub mod ffmpeg_output;