#[cfg(feature = "f32lz4")]
pub mod f32lz4;
#[cfg(feature = "flac")]
pub mod flac;
#[cfg(feature = "opus")]
pub mod opus;
pub mod pcm;
#[cfg(feature = "vorbis")]
pub mod vorbis;
use anyhow::Result;
use snapcast_proto::SampleFormat;
pub struct EncodedChunk {
pub data: Vec<u8>,
pub duration_ms: f64,
}
pub trait Encoder {
fn name(&self) -> &str;
fn header(&self) -> &[u8];
fn encode(&mut self, pcm: &[u8]) -> Result<EncodedChunk>;
}
#[derive(Debug, Clone)]
pub struct EncoderConfig {
pub codec: String,
pub format: SampleFormat,
pub options: String,
#[cfg(feature = "encryption")]
pub encryption_psk: Option<String>,
}
impl EncoderConfig {
pub fn new(codec: &str, format: SampleFormat) -> Self {
Self {
codec: codec.into(),
format,
options: String::new(),
#[cfg(feature = "encryption")]
encryption_psk: None,
}
}
}
pub fn create(config: &EncoderConfig) -> Result<Box<dyn Encoder>> {
#[allow(unused_variables)]
let EncoderConfig {
codec,
format,
options,
..
} = config;
let format = *format;
match codec.as_str() {
"pcm" => Ok(Box::new(pcm::PcmEncoder::new(format))),
#[cfg(feature = "flac")]
"flac" => Ok(Box::new(flac::FlacEncoder::new(format, options)?)),
#[cfg(feature = "opus")]
"opus" => Ok(Box::new(opus::OpusEncoder::new(format, options)?)),
#[cfg(feature = "vorbis")]
"ogg" => Ok(Box::new(vorbis::VorbisEncoder::new(format, options)?)),
#[cfg(feature = "f32lz4")]
"f32lz4" => {
let enc = f32lz4::F32Lz4Encoder::new(format);
#[cfg(feature = "encryption")]
let enc = if let Some(ref key) = config.encryption_psk {
enc.with_encryption(key)
} else {
enc
};
Ok(Box::new(enc))
}
other => anyhow::bail!("unsupported codec: {other} (check enabled features)"),
}
}