Browse and listen to thousands of radio stations across the globe right from your terminal 🌎 📻 🎵✨
radio rust tokio web-radio command-line-tool tui
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

at c489121edecc4fe25a8b075eecc9368b3c9e94cd 99 lines 2.1 kB view raw
1use std::time::Duration; 2use std::{io::Read, sync::mpsc::Sender}; 3 4use minimp3::{Decoder, Frame}; 5use rodio::Source; 6 7pub struct Mp3Decoder<R> 8where 9 R: Read, 10{ 11 decoder: Decoder<R>, 12 current_frame: Frame, 13 current_frame_offset: usize, 14 tx: Sender<Frame>, 15} 16 17impl<R> Mp3Decoder<R> 18where 19 R: Read, 20{ 21 pub fn new(mut data: R, tx: Sender<Frame>) -> Result<Self, R> { 22 if !is_mp3(data.by_ref()) { 23 return Err(data); 24 } 25 let mut decoder = Decoder::new(data); 26 let current_frame = decoder.next_frame().unwrap(); 27 28 Ok(Mp3Decoder { 29 decoder, 30 current_frame, 31 current_frame_offset: 0, 32 tx, 33 }) 34 } 35} 36 37impl<R> Source for Mp3Decoder<R> 38where 39 R: Read, 40{ 41 #[inline] 42 fn current_frame_len(&self) -> Option<usize> { 43 Some(self.current_frame.data.len()) 44 } 45 46 #[inline] 47 fn channels(&self) -> u16 { 48 self.current_frame.channels as _ 49 } 50 51 #[inline] 52 fn sample_rate(&self) -> u32 { 53 self.current_frame.sample_rate as _ 54 } 55 56 #[inline] 57 fn total_duration(&self) -> Option<Duration> { 58 None 59 } 60} 61 62impl<R> Iterator for Mp3Decoder<R> 63where 64 R: Read, 65{ 66 type Item = i16; 67 68 #[inline] 69 fn next(&mut self) -> Option<i16> { 70 if self.current_frame_offset == self.current_frame.data.len() { 71 match self.decoder.next_frame() { 72 Ok(frame) => { 73 match self.tx.send(frame.clone()) { 74 Ok(_) => {} 75 Err(_) => return None, 76 } 77 self.current_frame = frame 78 } 79 _ => return None, 80 } 81 self.current_frame_offset = 0; 82 } 83 84 let v = self.current_frame.data[self.current_frame_offset]; 85 self.current_frame_offset += 1; 86 87 Some(v) 88 } 89} 90 91/// Returns true if the stream contains mp3 data, then resets it to where it was. 92fn is_mp3<R>(mut data: R) -> bool 93where 94 R: Read, 95{ 96 let mut decoder = Decoder::new(data.by_ref()); 97 let ok = decoder.next_frame().is_ok(); 98 ok 99}