librespot_tremor/
lib.rs

1mod tremor_sys;
2extern crate libc;
3extern crate ogg_sys;
4
5use std::io::{self, Read, Seek};
6use std::mem::MaybeUninit;
7
8/// Allows you to decode a sound file stream into packets.
9pub struct Decoder<R>
10where
11    R: Read + Seek,
12{
13    // further informations are boxed so that a pointer can be passed to callbacks
14    data: Box<DecoderData<R>>,
15}
16
17///
18pub struct PacketsIter<'a, R: 'a + Read + Seek>(&'a mut Decoder<R>);
19
20///
21pub struct PacketsIntoIter<R: Read + Seek>(Decoder<R>);
22
23/// Errors that can happen while decoding
24#[derive(Debug)]
25pub enum VorbisError {
26    ReadError(io::Error),
27    NotVorbis,
28    VersionMismatch,
29    BadHeader,
30    InitialFileHeadersCorrupt,
31    Hole,
32}
33
34impl std::error::Error for VorbisError {
35    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
36        match self {
37            VorbisError::ReadError(ref err) => Some(err),
38            _ => None,
39        }
40    }
41}
42
43impl std::fmt::Display for VorbisError {
44    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
45        let description = match self {
46            VorbisError::ReadError(_) => "A read from media returned an error",
47            VorbisError::NotVorbis => "Bitstream does not contain any Vorbis data",
48            VorbisError::VersionMismatch => "Vorbis version mismatch",
49            VorbisError::BadHeader => "Invalid Vorbis bitstream header",
50            VorbisError::InitialFileHeadersCorrupt => "Initial file headers are corrupt",
51            VorbisError::Hole => "Interruption of data",
52        };
53
54        fmt.write_str(description)
55    }
56}
57
58impl From<io::Error> for VorbisError {
59    fn from(err: io::Error) -> VorbisError {
60        VorbisError::ReadError(err)
61    }
62}
63
64#[repr(C)]
65struct DecoderData<R>
66where
67    R: Read + Seek,
68{
69    vorbis: tremor_sys::OggVorbis_File,
70    reader: R,
71    current_logical_bitstream: libc::c_int,
72    read_error: Option<io::Error>,
73}
74
75#[repr(C)]
76struct DecoderDataUninit<R>
77where
78    R: Read + Seek,
79{
80    vorbis: MaybeUninit<tremor_sys::OggVorbis_File>,
81    reader: R,
82    current_logical_bitstream: libc::c_int,
83    read_error: Option<io::Error>,
84}
85
86unsafe impl<R: Read + Seek + Send> Send for DecoderData<R> {}
87
88/// Packet of data.
89///
90/// Each sample is an `i16` ranging from I16_MIN to I16_MAX.
91///
92/// The channels are interleaved in the data. For example if you have two channels, you will
93/// get a sample from channel 1, then a sample from channel 2, than a sample from channel 1, etc.
94#[derive(Clone, Debug)]
95pub struct Packet {
96    pub data: Vec<i16>,
97    pub channels: u16,
98    pub rate: u64,
99    pub bitrate_upper: u64,
100    pub bitrate_nominal: u64,
101    pub bitrate_lower: u64,
102    pub bitrate_window: u64,
103}
104
105impl<R> Decoder<R>
106where
107    R: Read + Seek,
108{
109    pub fn new(input: R) -> Result<Decoder<R>, VorbisError> {
110        extern "C" fn read_func<R>(
111            ptr: *mut libc::c_void,
112            size: libc::size_t,
113            nmemb: libc::size_t,
114            datasource: *mut libc::c_void,
115        ) -> libc::size_t
116        where
117            R: Read + Seek,
118        {
119            use std::slice;
120
121            /*
122             * In practice libvorbisfile always sets size to 1.
123             * This assumption makes things much simpler
124             */
125            assert_eq!(size, 1);
126
127            let ptr = ptr as *mut u8;
128
129            let data: &mut DecoderData<R> = unsafe { &mut *(datasource as *mut _) };
130
131            let buffer = unsafe { slice::from_raw_parts_mut(ptr as *mut u8, nmemb as usize) };
132
133            loop {
134                match data.reader.read(buffer) {
135                    Ok(nb) => return nb as libc::size_t,
136                    Err(ref e) if e.kind() == io::ErrorKind::Interrupted => (),
137                    Err(e) => {
138                        data.read_error = Some(e);
139                        return 0;
140                    }
141                }
142            }
143        }
144
145        extern "C" fn seek_func<R>(
146            datasource: *mut libc::c_void,
147            offset: tremor_sys::ogg_int64_t,
148            whence: libc::c_int,
149        ) -> libc::c_int
150        where
151            R: Read + Seek,
152        {
153            let data: &mut DecoderData<R> = unsafe { &mut *(datasource as *mut _) };
154
155            let result = match whence {
156                libc::SEEK_SET => data.reader.seek(io::SeekFrom::Start(offset as u64)),
157                libc::SEEK_CUR => data.reader.seek(io::SeekFrom::Current(offset)),
158                libc::SEEK_END => data.reader.seek(io::SeekFrom::End(offset)),
159                _ => unreachable!(),
160            };
161
162            match result {
163                Ok(_) => 0,
164                Err(_) => -1,
165            }
166        }
167
168        extern "C" fn tell_func<R>(datasource: *mut libc::c_void) -> libc::c_long
169        where
170            R: Read + Seek,
171        {
172            let data: &mut DecoderData<R> = unsafe { &mut *(datasource as *mut DecoderData<R>) };
173            data.reader
174                .seek(io::SeekFrom::Current(0))
175                .map(|v| v as libc::c_long)
176                .unwrap_or(-1)
177        }
178
179        extern "C" fn close_func<R>(_datasource: *mut libc::c_void) -> libc::c_int
180        where
181            R: Read + Seek,
182        {
183            0
184        }
185
186        let callbacks = tremor_sys::ov_callbacks {
187            read_func: read_func::<R>,
188            seek_func: seek_func::<R>,
189            tell_func: tell_func::<R>,
190            close_func: close_func::<R>,
191        };
192
193        let mut data = Box::new(DecoderDataUninit {
194            vorbis: MaybeUninit::uninit(),
195            reader: input,
196            current_logical_bitstream: 0,
197            read_error: None,
198        });
199
200        // initializing
201        unsafe {
202            let data_ptr = data.vorbis.as_mut_ptr();
203            check_errors(tremor_sys::ov_open_callbacks(
204                data_ptr as *mut libc::c_void,
205                data_ptr,
206                std::ptr::null(),
207                0,
208                callbacks,
209            ))?;
210        }
211
212        let data: Box<DecoderData<R>> = unsafe { std::mem::transmute(data) };
213
214        Ok(Decoder { data })
215    }
216
217    pub fn time_seek(&mut self, s: i64) -> Result<(), VorbisError> {
218        unsafe { check_errors(tremor_sys::ov_time_seek(&mut self.data.vorbis, s)) }
219    }
220
221    pub fn time_tell(&mut self) -> Result<i64, VorbisError> {
222        unsafe { Ok(tremor_sys::ov_time_tell(&mut self.data.vorbis)) }
223    }
224
225    pub fn packets(&mut self) -> PacketsIter<R> {
226        PacketsIter(self)
227    }
228
229    pub fn into_packets(self) -> PacketsIntoIter<R> {
230        PacketsIntoIter(self)
231    }
232
233    fn next_packet(&mut self) -> Option<Result<Packet, VorbisError>> {
234        let mut buffer = std::iter::repeat(0i16).take(2048).collect::<Vec<_>>();
235        let buffer_len = buffer.len() * 2;
236
237        match unsafe {
238            tremor_sys::ov_read(
239                &mut self.data.vorbis,
240                buffer.as_mut_ptr() as *mut libc::c_char,
241                buffer_len as libc::c_int,
242                0,
243                2,
244                1,
245                &mut self.data.current_logical_bitstream,
246            )
247        } {
248            0 => match self.data.read_error.take() {
249                Some(err) => Some(Err(VorbisError::ReadError(err))),
250                None => None,
251            },
252
253            err if err < 0 => match check_errors(err as libc::c_int) {
254                Err(e) => Some(Err(e)),
255                Ok(_) => unreachable!(),
256            },
257
258            len => {
259                buffer.truncate(len as usize / 2);
260
261                let infos = unsafe {
262                    tremor_sys::ov_info(&mut self.data.vorbis, self.data.current_logical_bitstream)
263                };
264
265                let infos: &tremor_sys::vorbis_info = unsafe { &*infos };
266
267                Some(Ok(Packet {
268                    data: buffer,
269                    channels: infos.channels as u16,
270                    rate: infos.rate as u64,
271                    bitrate_upper: infos.bitrate_upper as u64,
272                    bitrate_nominal: infos.bitrate_nominal as u64,
273                    bitrate_lower: infos.bitrate_lower as u64,
274                    bitrate_window: infos.bitrate_window as u64,
275                }))
276            }
277        }
278    }
279}
280
281impl<'a, R> Iterator for PacketsIter<'a, R>
282where
283    R: 'a + Read + Seek,
284{
285    type Item = Result<Packet, VorbisError>;
286
287    fn next(&mut self) -> Option<Result<Packet, VorbisError>> {
288        self.0.next_packet()
289    }
290}
291
292impl<R> Iterator for PacketsIntoIter<R>
293where
294    R: Read + Seek,
295{
296    type Item = Result<Packet, VorbisError>;
297
298    fn next(&mut self) -> Option<Result<Packet, VorbisError>> {
299        self.0.next_packet()
300    }
301}
302
303impl<R> Drop for Decoder<R>
304where
305    R: Read + Seek,
306{
307    fn drop(&mut self) {
308        unsafe {
309            tremor_sys::ov_clear(&mut self.data.vorbis);
310        }
311    }
312}
313
314fn check_errors(code: libc::c_int) -> Result<(), VorbisError> {
315    match code {
316        0 => Ok(()),
317
318        tremor_sys::OV_ENOTVORBIS => Err(VorbisError::NotVorbis),
319        tremor_sys::OV_EVERSION => Err(VorbisError::VersionMismatch),
320        tremor_sys::OV_EBADHEADER => Err(VorbisError::BadHeader),
321        tremor_sys::OV_EINVAL => Err(VorbisError::InitialFileHeadersCorrupt),
322        tremor_sys::OV_HOLE => Err(VorbisError::Hole),
323
324        tremor_sys::OV_EREAD => unimplemented!(),
325
326        // indicates a bug or heap/stack corruption
327        tremor_sys::OV_EFAULT => panic!("Internal libvorbis error"),
328        _ => panic!("Unknown vorbis error {}", code),
329    }
330}