mocha/
lib.rs

1use std::ffi::c_float;
2use std::os::raw::{c_uchar, c_void, c_int, c_uint};
3use std::fs;
4
5#[derive(Default, Debug, Copy, Clone)]
6pub enum AudioUsage {
7    Static,
8    #[default]
9    Stream
10}
11
12#[repr(C)]
13#[derive(Debug, Copy, Clone)]
14pub struct AudioParams {
15    pub volume: c_float,
16    pub pitch: c_float,
17    pub loop_: c_uchar,
18}
19
20impl Default for AudioParams {
21    fn default() -> Self {
22        AudioParams {
23            volume: 1.0,
24            pitch: 0.0,
25            loop_: 0,
26        }
27    }
28}
29
30#[repr(C)]
31#[derive(Debug, Clone, Copy)]
32struct AudioData {
33    usage: c_int,
34    size: c_uint,
35    data: *mut c_void
36}
37
38impl Default for AudioData {
39    fn default() -> Self {
40        AudioData {
41            usage: 0,
42            size: 0,
43            data: std::ptr::null_mut()
44        }
45    }
46}
47
48#[repr(C)]
49#[derive(Debug, Copy, Clone)]
50struct Decoder([c_uchar; 10312]);
51impl Default for Decoder {
52    fn default() -> Self {
53        Decoder([0; 10312])
54    }
55}
56
57#[repr(C)]
58#[derive(Debug, Copy, Clone)]
59pub struct AudioBuffer {
60    id: u32,
61    playing: i8,
62    loaded: i8,
63    offset: u32,
64    params: AudioParams,
65    data: AudioData,
66    decoder: Decoder
67}
68
69impl ToString for AudioBuffer {
70    fn to_string(&self) -> String {
71        format!("{} {} {} {}", self.id, self.playing, self.loaded, self.data.size)
72    }
73}
74
75impl Default for AudioBuffer {
76    fn default() -> Self {
77        AudioBuffer {
78            id: 0,
79            playing: 0,
80            loaded: 0,
81            offset: 0,
82            params: AudioParams::default(),
83            data: AudioData::default(),
84            decoder: Decoder::default()
85        }
86    }
87}
88
89extern "C" {
90    fn core_init() -> c_int;
91    fn core_quit();
92
93    // fn core_get_available_buffer() -> c_uint;
94    // fn core_release_buffer(id: c_uint);
95
96    fn core_new_data_from_memory(data: *mut c_void, size: c_uint, usage: c_int) -> c_int;
97    fn core_release_data(id: c_int);
98    fn core_setup_free_buffer(data_id: c_int, params: *const AudioParams) -> c_int;
99
100    fn core_get_buffer(id: c_int) -> *mut AudioBuffer;
101}
102
103#[derive(Default, Debug, Copy, Clone)]
104pub struct Audio {
105    id: u32,
106    params: AudioParams
107}
108
109impl Audio {
110    pub fn play(&self) -> AudioInstance {
111        let id = unsafe { core_setup_free_buffer(self.id as c_int, &self.params) } as u32;
112        let buffer = get_buffer(id);
113        buffer.playing = 1;
114        AudioInstance(id)
115    }
116
117    pub fn free(&self) {
118        unsafe { core_release_data(self.id as i32) };
119    }
120
121    pub fn id(&self) -> u32 { self.id }
122    
123    pub fn loop_(&self) -> bool {
124        self.params.loop_ == 1
125    }
126
127    pub fn set_loop(&mut self, val: bool) {
128        self.params.loop_ = val as u8;
129    }
130}
131
132#[derive(Default, Debug, Copy, Clone)]
133pub struct AudioInstance(u32);
134
135pub fn init() { unsafe { core_init(); } }
136pub fn quit() { unsafe { core_quit(); } }
137
138pub fn load(filename: &str, usage: AudioUsage) -> Result<Audio, String> {
139    let data = fs::read(filename)
140        .expect(filename);
141    let id = unsafe { core_new_data_from_memory(data.as_ptr() as *mut c_void, data.len() as u32, usage as i32) } as u32;
142
143    Ok(Audio {
144        id,
145        params: AudioParams::default()
146    })
147}
148
149fn get_buffer<'a>(id: u32) -> &'a mut AudioBuffer {
150    unsafe { core_get_buffer(id as c_int).as_mut().unwrap() }
151}
152
153impl AudioInstance {
154    fn get_buffer(&self) -> &mut AudioBuffer {
155        get_buffer(self.0)
156    }
157
158    pub fn resume(&self) {
159        let buffer = self.get_buffer();
160        buffer.playing = 1;
161    }
162
163    pub fn pause(&self) {
164        let buffer = self.get_buffer();
165        buffer.playing = 0;
166    }
167
168    pub fn stop(&self) {
169        let buffer = self.get_buffer();
170        buffer.playing = 0;
171        buffer.loaded = 0;
172    }
173
174    pub fn is_playing(&self) -> bool {
175        let buffer = self.get_buffer();
176        buffer.playing == 1
177    }
178
179    pub fn volume(&self) -> f32 { self.get_buffer().params.volume }
180    pub fn set_volume(&self, volume: f32) {
181        self.get_buffer().params.volume = volume;
182    }
183
184    pub fn looping(&self) -> bool { self.get_buffer().params.loop_ == 1 }
185    pub fn set_looping(&self, val: bool) {
186        self.get_buffer().params.loop_ = val as u8;
187    }
188}