snapcast_server/encoder/
mod.rs1#[cfg(feature = "f32lz4")]
4pub mod f32lz4;
5#[cfg(feature = "flac")]
6pub mod flac;
7#[cfg(feature = "opus")]
8pub mod opus;
9pub mod pcm;
10#[cfg(feature = "vorbis")]
11pub mod vorbis;
12
13use anyhow::Result;
14use snapcast_proto::SampleFormat;
15
16pub struct EncodedChunk {
18 pub data: Vec<u8>,
20 pub duration_ms: f64,
22}
23
24pub trait Encoder {
26 fn name(&self) -> &str;
28
29 fn header(&self) -> &[u8];
31
32 fn encode(&mut self, pcm: &[u8]) -> Result<EncodedChunk>;
34}
35
36#[derive(Debug, Clone)]
38pub struct EncoderConfig {
39 pub codec: String,
41 pub format: SampleFormat,
43 pub options: String,
45 #[cfg(feature = "encryption")]
47 pub encryption_psk: Option<String>,
48}
49
50impl EncoderConfig {
51 pub fn new(codec: &str, format: SampleFormat) -> Self {
53 Self {
54 codec: codec.into(),
55 format,
56 options: String::new(),
57 #[cfg(feature = "encryption")]
58 encryption_psk: None,
59 }
60 }
61}
62
63pub fn create(config: &EncoderConfig) -> Result<Box<dyn Encoder>> {
65 #[allow(unused_variables)]
66 let EncoderConfig {
67 codec,
68 format,
69 options,
70 ..
71 } = config;
72 let format = *format;
73 match codec.as_str() {
74 "pcm" => Ok(Box::new(pcm::PcmEncoder::new(format))),
75 #[cfg(feature = "flac")]
76 "flac" => Ok(Box::new(flac::FlacEncoder::new(format, options)?)),
77 #[cfg(feature = "opus")]
78 "opus" => Ok(Box::new(opus::OpusEncoder::new(format, options)?)),
79 #[cfg(feature = "vorbis")]
80 "ogg" => Ok(Box::new(vorbis::VorbisEncoder::new(format, options)?)),
81 #[cfg(feature = "f32lz4")]
82 "f32lz4" => {
83 let enc = f32lz4::F32Lz4Encoder::new(format);
84 #[cfg(feature = "encryption")]
85 let enc = if let Some(ref key) = config.encryption_psk {
86 enc.with_encryption(key)
87 } else {
88 enc
89 };
90 Ok(Box::new(enc))
91 }
92 other => anyhow::bail!("unsupported codec: {other} (check enabled features)"),
93 }
94}