diff --git a/src/server/decoder.rs b/src/server/decoder.rs index d55bffe..e919d87 100644 --- a/src/server/decoder.rs +++ b/src/server/decoder.rs @@ -1,96 +1,72 @@ // Implement decoders missing from rodio. -// At the moment this means opus, mod and xm. +// At the moment this means: +// - Opus (Ogg, WebM) +// - Mod +// - XM use std::io::{Read, Seek}; -pub mod opus; +mod opus; -pub enum SourceImpl -where - R: Read + Seek, -{ - Rodio(rodio::Decoder), - // Custom(Decoder), -} +pub struct Decoder; -impl Iterator for SourceImpl -where - R: Read + Seek, -{ - type Item = i16; +impl Decoder { + pub fn new(mut data: R) -> Result>, ()> + where + R: Read + Seek + Send + Sync + 'static, + { + let start_position = data.stream_position().unwrap(); - #[inline] - fn next(&mut self) -> Option { - match self { - Self::Rodio(source) => source.next(), - } + match opus::OpusDecoder::new(&mut data) { + Ok(source) => return Ok(Box::new(source)), + Err(err) => { + eprintln!("Custom decode error: {err:?}"); + } + }; + + data.seek(std::io::SeekFrom::Start(start_position)).unwrap(); + + match rodio::Decoder::new(data) { + Ok(source) => return Ok(Box::new(source)), + Err(err) => { + eprintln!("Rodio decode error: {err:?}"); + } + }; + + Err(()) } } -impl rodio::Source for SourceImpl +pub trait DecoderImpl: rodio::Source + Send + Sync + 'static +where + R: Read + Seek, + ::Item: rodio::Sample, +{ +} + +impl rodio::Source for Box> where R: Read + Seek, { #[inline] fn current_frame_len(&self) -> Option { - match self { - Self::Rodio(source) => source.current_frame_len(), - } + self.as_ref().current_frame_len() } #[inline] fn channels(&self) -> u16 { - match self { - Self::Rodio(source) => source.channels(), - } + self.as_ref().channels() } #[inline] fn sample_rate(&self) -> u32 { - match self { - Self::Rodio(source) => source.sample_rate(), - } + self.as_ref().sample_rate() } #[inline] fn total_duration(&self) -> Option { - match self { - Self::Rodio(source) => source.total_duration(), - } + self.as_ref().total_duration() } } -pub enum Decoder -where - R: Read + Seek, -{ - Opus(opus::OpusDecoder), -} - -impl Decoder -where - R: Read + Seek, -{ - pub fn new(data: R) -> Result, ()> - where - R: Read + Seek + Send + Sync + 'static, - { - match rodio::Decoder::new(data) { - Ok(source) => return Ok(SourceImpl::Rodio(source)), - Err(err) => { - eprintln!( - "Rodio decode error:\n\terror: {err:?}\n\tcontinuing with custom decoder" - ); - } - }; - - // match Decoder::new(data) { - // Ok(source) => return Ok(SourceImpl::Custom(source)), - // Err(err) => { - // eprintln!("Custom decode error:\n\terror: {err:?}\n\tPlayback failed"); - // } - // } - - Err(()) - } -} +impl DecoderImpl for rodio::Decoder where R: Read + Seek + Send + Sync + 'static {} diff --git a/src/server/decoder/opus.rs b/src/server/decoder/opus.rs index ccd3f7d..d22041e 100644 --- a/src/server/decoder/opus.rs +++ b/src/server/decoder/opus.rs @@ -3,10 +3,56 @@ use std::{ marker::PhantomData, }; -/// Not implemented pub struct OpusDecoder where R: Read + Seek, { _data: PhantomData, } + +impl super::DecoderImpl for OpusDecoder where R: Read + Seek + Send + Sync + 'static {} + +impl OpusDecoder +where + R: Read + Seek + Send + Sync + 'static, +{ + pub fn new(data: &mut R) -> Result { + Err(()) + } +} + +impl Iterator for OpusDecoder +where + R: Read + Seek, +{ + type Item = i16; + + fn next(&mut self) -> Option { + None + } +} + +impl rodio::Source for OpusDecoder +where + R: Read + Seek, +{ + #[inline] + fn current_frame_len(&self) -> Option { + todo!() + } + + #[inline] + fn channels(&self) -> u16 { + todo!() + } + + #[inline] + fn sample_rate(&self) -> u32 { + todo!() + } + + #[inline] + fn total_duration(&self) -> Option { + todo!() + } +}