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