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