mpg123/
lib.rs

1mod error;
2
3pub use error::Error;
4use libc::{c_int, c_long};
5use mpg123_sys as mpg123;
6use std::error::Error as StdError;
7use std::ffi;
8use std::ops::Drop;
9use std::ptr;
10use std::sync::Once;
11
12static INIT: Once = Once::new();
13
14#[derive(Debug)]
15pub struct Format {
16    pub rate: i64,
17    pub channels: i32,
18    pub encoding: i32,
19}
20
21impl Default for Format {
22    fn default() -> Format {
23        Format {
24            rate: 0,
25            channels: 0,
26            encoding: 0,
27        }
28    }
29}
30
31pub struct Decoder {
32    mh: *mut mpg123::mpg123_handle,
33    format: Format,
34}
35
36impl Decoder {
37    pub fn new(filename: &str, params: Option<c_long>) -> Result<Decoder, Box<StdError>> {
38        unsafe {
39            init()?;
40
41            let mut res = 0;
42            let mh = mpg123::mpg123_new(ptr::null(), &mut res);
43            if res != mpg123::MPG123_OK as c_int || mh.is_null() {
44                return Err(Box::from("failed to instantiate mpg123"));
45            }
46
47            if let Some(flags) = params {
48                if mpg123::mpg123_param(mh, mpg123::MPG123_FLAGS, flags, 0.)
49                    != mpg123::MPG123_OK as c_int
50                {
51                    return Err(Box::from("failed to set parameters"));
52                }
53            }
54
55            let mut decoder = Decoder {
56                mh,
57                format: Format::default(),
58            };
59
60            decoder.open(filename)?;
61            decoder.get_format()?;
62
63            Ok(decoder)
64        }
65    }
66
67    fn open(&self, filename: &str) -> Result<(), Box<StdError>> {
68        let fname = ffi::CString::new(filename)?;
69
70        unsafe {
71            if mpg123::mpg123_open(self.mh, fname.as_ptr()) != mpg123::MPG123_OK as c_int {
72                return Err(Box::from(format!("failed to open `{}`", filename)));
73            }
74        }
75
76        Ok(())
77    }
78
79    fn get_format(&mut self) -> Result<(), Box<StdError>> {
80        unsafe {
81            if mpg123::mpg123_getformat(
82                self.mh,
83                &mut self.format.rate,
84                &mut self.format.channels,
85                &mut self.format.encoding,
86            ) != mpg123::MPG123_OK as c_int
87            {
88                return Err(Box::from("failed to get format"));
89            }
90        }
91
92        Ok(())
93    }
94
95    pub fn format(&self) -> &Format {
96        &self.format
97    }
98
99    pub fn read(&self, buf: &mut [u8]) -> Result<(), Error> {
100        unsafe {
101            let mut done = 0;
102            let res = mpg123::mpg123_read(self.mh, buf.as_mut_ptr(), buf.len(), &mut done);
103            if res != mpg123::MPG123_OK as c_int && res != mpg123::MPG123_DONE as c_int {
104                return Err(Error::BadInput);
105            }
106            if res == mpg123::MPG123_DONE as c_int {
107                return Err(Error::EOF);
108            }
109        }
110
111        Ok(())
112    }
113
114    fn close(&self) -> Result<(), Box<StdError>> {
115        unsafe {
116            if mpg123::mpg123_close(self.mh) != mpg123::MPG123_OK as c_int {
117                return Err(Box::from("failed to close"));
118            }
119        }
120
121        Ok(())
122    }
123
124    fn delete(&self) {
125        unsafe {
126            mpg123::mpg123_delete(self.mh);
127        }
128    }
129}
130
131impl Drop for Decoder {
132    fn drop(&mut self) {
133        if !self.mh.is_null() {
134            self.close().unwrap_or_else(|e| println!("{}", e));
135            self.delete();
136        }
137    }
138}
139
140fn init() -> Result<(), Box<StdError>> {
141    let mut result = Ok(());
142
143    INIT.call_once(|| unsafe {
144        if mpg123::mpg123_init() != mpg123::MPG123_OK as c_int {
145            result = Err(Box::from("Failed to initialize mpg123"));
146        }
147    });
148
149    result
150}