rfmod/
fmod_sys.rs

1/*
2* Rust-FMOD - Copyright (c) 2014 Gomez Guillaume.
3*
4* The Original software, FmodEx library, is provided by FIRELIGHT TECHNOLOGIES.
5*
6* This software is provided 'as-is', without any express or implied warranty.
7* In no event will the authors be held liable for any damages arising from
8* the use of this software.
9*
10* Permission is granted to anyone to use this software for any purpose,
11* including commercial applications, and to alter it and redistribute it
12* freely, subject to the following restrictions:
13*
14* 1. The origin of this software must not be misrepresented; you must not claim
15*    that you wrote the original software. If you use this software in a product,
16*    an acknowledgment in the product documentation would be appreciated but is
17*    not required.
18*
19* 2. Altered source versions must be plainly marked as such, and must not be
20*    misrepresented as being the original software.
21*
22* 3. This notice may not be removed or altered from any source distribution.
23*/
24
25use libc::{c_void, c_uint, c_int, c_char, c_short};
26use ffi;
27use types::*;
28use sound;
29use sound::Sound;
30use sound_group;
31use std::mem;
32use channel_group;
33use channel;
34use dsp;
35use dsp::Dsp;
36use vector;
37use reverb_properties;
38use geometry;
39use reverb;
40use dsp_connection;
41use std::default::Default;
42use callbacks::*;
43use std;
44use file;
45use libc::FILE;
46use c_vec::CVec;
47use std::ffi::CString;
48
49fn get_saved_sys_callback<'r>() -> &'r mut SysCallback {
50    static mut CALLBACK : SysCallback = SysCallback {
51            file_open: None,
52            file_close: None,
53            file_read: None,
54            file_seek: None
55        };
56
57    unsafe { &mut CALLBACK }
58}
59
60struct SysCallback {
61    file_open: FileOpenCallback,
62    file_close: FileCloseCallback,
63    file_read: FileReadCallback,
64    file_seek: FileSeekCallback
65}
66
67impl SysCallback {
68    fn new() -> SysCallback {
69        SysCallback {
70            file_open: None,
71            file_close: None,
72            file_read: None,
73            file_seek: None
74        }
75    }
76}
77
78extern "C" fn file_open_callback(name: *mut c_char, unicode: c_int, file_size: *mut c_uint,
79                                 handle: *mut *mut c_void,
80                                 user_data: *mut *mut c_void) -> ::Status {
81    let tmp = get_saved_sys_callback();
82
83    match tmp.file_open {
84        Some(s) => {
85            let t_name = if name.is_null() {
86                String::new()
87            } else {
88                let l = ffi::strlen(name);
89
90                unsafe { String::from_raw_parts(name as *mut u8, l, l) }
91            };
92            match s(t_name.as_ref(), unicode) {
93                Some((f, s)) => {
94                    unsafe {
95                        *file_size = f.get_file_size() as u32;
96                        *handle = file::get_ffi(&f) as *mut c_void;
97                        *user_data = match s {
98                            Some(mut d) => std::mem::transmute(&mut d),
99                            None => ::std::ptr::null_mut()
100                        };
101                    }
102                   ::Status::Ok
103                }
104                None => {
105                    unsafe {
106                        *file_size = 0u32;
107                        *handle = std::ptr::null_mut();
108                        *user_data = std::ptr::null_mut();
109                    }
110                    ::Status::FileNotFound
111                }
112            }
113        },
114        None => {
115            unsafe {
116                *file_size = 0u32;
117                *handle = std::ptr::null_mut();
118                *user_data = std::ptr::null_mut();
119            }
120            ::Status::Ok
121        }
122    }
123}
124
125extern "C" fn file_close_callback(handle: *mut c_void, user_data: *mut c_void) -> ::Status {
126    let tmp = get_saved_sys_callback();
127
128    match tmp.file_close {
129        Some(s) => {
130            unsafe {
131                s(&mut file::from_ffi(handle as *mut FILE), if user_data.is_null() {
132                    None
133                } else {
134                    Some(std::mem::transmute(user_data))
135                });
136            }
137            ::Status::Ok
138        }
139        None => ::Status::Ok
140    }
141}
142
143extern "C" fn file_read_callback(handle: *mut c_void, buffer: *mut c_void, size_bytes: c_uint,
144                                 bytes_read: *mut c_uint, user_data: *mut c_void) -> ::Status {
145    let tmp = get_saved_sys_callback();
146
147    match tmp.file_read {
148        Some(s) => {
149            unsafe {
150                let mut data_vec : CVec<u8> = CVec::new(buffer as *mut u8, size_bytes as usize);
151
152                let read_bytes = s(&mut file::from_ffi(handle as *mut FILE), data_vec.as_mut(),
153                                   size_bytes, if user_data.is_null() {
154                    None
155                } else {
156                    Some(std::mem::transmute(user_data))
157                });
158                *bytes_read = read_bytes as u32;
159                if read_bytes < size_bytes as usize {
160                    ::Status::FileEOF
161                } else {
162                   ::Status::Ok
163                }
164            }
165        }
166        None => ::Status::Ok
167    }
168}
169
170extern "C" fn file_seek_callback(handle: *mut c_void, pos: c_uint,
171                                 user_data: *mut c_void) -> ::Status {
172    let tmp = get_saved_sys_callback();
173
174    match tmp.file_seek {
175        Some(s) => {
176            unsafe {
177                s(&mut file::from_ffi(handle as *mut FILE), pos, if user_data.is_null() {
178                    None
179                } else {
180                    Some(std::mem::transmute(user_data))
181                });
182            }
183            ::Status::Ok
184        }
185        None => ::Status::Ok
186    }
187}
188
189extern "C" fn pcm_read_callback(sound: *mut ffi::FMOD_SOUND, data: *mut c_void,
190                                data_len: c_uint) -> ::Status {
191    unsafe {
192        if !sound.is_null() {
193            let mut tmp = ::std::ptr::null_mut();
194
195            ffi::FMOD_Sound_GetUserData(sound, &mut tmp);
196            if !tmp.is_null() {
197                let callbacks : &mut ffi::SoundData = std::mem::transmute(tmp);
198
199                match callbacks.pcm_read {
200                    Some(p) => {
201                        let max = data_len as isize >> 2;
202                        let mut data_vec = CVec::new(data as *mut c_short, max as usize * 2);
203
204                        let ret = p(&ffi::FFI::wrap(sound), data_vec.as_mut());
205                        ret
206                    },
207                    None => ::Status::Ok
208                }
209            } else {
210               ::Status::Ok
211            }
212        } else {
213            ::Status::Ok
214        }
215    }
216}
217
218extern "C" fn non_block_callback(sound: *mut ffi::FMOD_SOUND, result: ::Status) -> ::Status {
219    unsafe {
220        if !sound.is_null() {
221            let mut tmp = ::std::ptr::null_mut();
222
223            ffi::FMOD_Sound_GetUserData(sound, &mut tmp);
224            if !tmp.is_null() {
225                let callbacks : &mut ffi::SoundData = ::std::mem::transmute(tmp);
226
227                match callbacks.non_block {
228                    Some(p) => p(&ffi::FFI::wrap(sound), result),
229                    None => ::Status::Ok
230                }
231            } else {
232               ::Status::Ok
233            }
234        } else {
235            ::Status::Ok
236        }
237    }
238}
239
240extern "C" fn pcm_set_pos_callback(sound: *mut ffi::FMOD_SOUND, sub_sound: c_int, position: c_uint,
241                                   postype: ffi::FMOD_TIMEUNIT) -> ::Status {
242    unsafe {
243        if !sound.is_null() {
244            let mut tmp = ::std::ptr::null_mut();
245
246            ffi::FMOD_Sound_GetUserData(sound, &mut tmp);
247            if !tmp.is_null() {
248                let callbacks : &mut ffi::SoundData = ::std::mem::transmute(tmp);
249
250                match callbacks.pcm_set_pos {
251                    Some(p) => p(&ffi::FFI::wrap(sound), sub_sound, position, TimeUnit(postype)),
252                    None => ::Status::Ok
253                }
254            } else {
255               ::Status::Ok
256            }
257        } else {
258            ::Status::Ok
259        }
260    }
261}
262
263/// Structure describing a globally unique identifier.
264pub struct Guid
265{
266    /// Specifies the first 8 hexadecimal digits of the GUID
267    pub data1: u32,
268    /// Specifies the first group of 4 hexadecimal digits.
269    pub data2: u16,
270    /// Specifies the second group of 4 hexadecimal digits.
271    pub data3: u16,
272    /// Array of 8 bytes. The first 2 bytes contain the third group of 4 hexadecimal digits. The
273    /// remaining 6 bytes contain the final 12 hexadecimal digits.
274    pub data4: [u8; 8]
275}
276
277impl Default for Guid {
278    fn default() -> Guid {
279        Guid {
280            data1: 0u32,
281            data2: 0u16,
282            data3: 0u16,
283            data4: [0u8; 8]
284        }
285    }
286}
287
288/// Structure used to store user data for file callback
289pub struct UserData {
290    user_data: *mut c_void
291}
292
293impl UserData {
294    pub fn set_user_data<'r, T>(&'r mut self, user_data: &'r mut T) {
295        unsafe { self.user_data = std::mem::transmute(user_data) }
296    }
297
298    pub fn get_user_data<'r, T>(&self) -> Option<&'r mut T> {
299        if self.user_data.is_null() {
300            None
301        } else {
302            Some(unsafe { std::mem::transmute(self.user_data) })
303        }
304    }
305}
306
307impl Default for UserData {
308    fn default() -> UserData {
309        UserData {
310            user_data: ::std::ptr::null_mut()
311        }
312    }
313}
314
315/// Wrapper for arguments of
316/// [`Sys::set_software_format`](struct.Sys.html#method.set_software_format) and
317/// [`Sys::get_software_format`](struct.Sys.html#method.get_software_format).
318pub struct SoftwareFormat
319{
320    pub sample_rate        : i32,
321    pub format             : ::SoundFormat,
322    pub num_output_channels: i32,
323    pub max_input_channels : i32,
324    pub resample_method    : ::DspResampler,
325    pub bits               : i32
326}
327
328impl Default for SoftwareFormat {
329    fn default() -> SoftwareFormat {
330        SoftwareFormat {
331            sample_rate: 0i32,
332            format: ::SoundFormat::None,
333            num_output_channels: 0i32,
334            max_input_channels: 0i32,
335            resample_method: ::DspResampler::NoInterp,
336            bits: 0i32
337        }
338    }
339}
340
341/// Settings for advanced features like configuring memory and cpu usage for the
342/// FMOD_CREATECOMPRESSEDSAMPLE feature.
343pub struct AdvancedSettings {
344    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. Mpeg
345    /// codecs consume 21,684 bytes per instance and this number will determine how many mpeg
346    /// channels can be played simultaneously. Default = 32.
347    pub max_MPEG_codecs               : i32,
348    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. ADPCM
349    /// codecs consume 2,136 bytes per instance and this number will determine how many ADPCM
350    /// channels can be played simultaneously. Default = 32.
351    pub max_ADPCM_codecs              : i32,
352    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. XMA
353    /// codecs consume 14,836 bytes per instance and this number will determine how many XMA
354    /// channels can be played simultaneously. Default = 32.
355    pub max_XMA_codecs                : i32,
356    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. CELT
357    /// codecs consume 11,500 bytes per instance and this number will determine how many CELT
358    /// channels can be played simultaneously. Default = 32.
359    pub max_CELT_codecs               : i32,
360    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. Vorbis
361    /// codecs consume 12,000 bytes per instance and this number will determine how many Vorbis
362    /// channels can be played simultaneously. Default = 32.
363    pub max_VORBIS_codecs             : i32,
364    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_CREATECOMPRESSEDSAMPLE only. AT9
365    /// codecs consume 8,720 bytes per instance and this number will determine how many AT9
366    /// channels can be played simultaneously. Default = 32.
367    pub max_AT9_codecs                : i32,
368    /// [r/w] Optional. Specify 0 to ignore. For use with PS3 only. PCM codecs consume 12,672 bytes
369    /// per instance and this number will determine how many streams and PCM voices can be played
370    /// simultaneously. Default = 16.
371    pub max_PCM_codecs                : i32,
372    /// [r/w] Optional. Specify 0 to ignore. Number of channels available on the ASIO device.
373    pub ASIO_num_channels             : i32,
374    /// [r/w] Optional. Specify 0 to ignore. Pointer to an array of strings (number of entries
375    /// defined by ASIONumChannels) with ASIO channel names.
376    pub ASIO_channel_list             : Vec<String>,
377    /// [r/w] Optional. Specify 0 to ignore. Pointer to a list of speakers that the ASIO channels
378    /// map to. This can be called after [`Sys::init`](doc/rfmod/struct.Sys.html#method.init) to
379    /// remap ASIO output.
380    pub ASIO_speaker_list             : Vec<::Speaker>,
381    /// [r/w] Optional. Specify 0 to ignore. The max number of 3d reverb DSP's in the system. (NOTE:
382    /// CURRENTLY DISABLED / UNUSED)
383    pub max_3D_reverb_DSPs            : i32,
384    /// [r/w] Optional. For use with FMOD_INIT_HRTF_LOWPASS. The angle range (0-360) of a 3D sound
385    /// in relation to the listener, at which the HRTF function begins to have an effect. 0 = in
386    /// front of the listener. 180 = from 90 degrees to the left of the listener to 90 degrees to
387    /// the right. 360 = behind the listener. Default = 180.0.
388    pub HRTF_min_angle                : f32,
389    /// [r/w] Optional. For use with FMOD_INIT_HRTF_LOWPASS. The angle range (0-360) of a 3D sound
390    /// in relation to the listener, at which the HRTF function has maximum effect. 0 = front of the
391    /// listener. 180 = from 90 degrees to the left of the listener to 90 degrees to the right. 360
392    /// = behind the listener. Default = 360.0.
393    pub HRTF_max_angle                : f32,
394    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_HRTF_LOWPASS. The cutoff
395    /// frequency of the HRTF's lowpass filter function when at maximum effect. (i.e. at
396    /// HRTFMaxAngle). Default = 4000.0.
397    pub HRTF_freq                     : f32,
398    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_VOL0_BECOMES_VIRTUAL. If this
399    /// flag is used, and the volume is 0.0, then the sound will become virtual. Use this value to
400    /// raise the threshold to a different point where a sound goes virtual.
401    pub vol0_virtual_vol              : f32,
402    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD Event system only. Specifies the
403    /// number of slots available for simultaneous non blocking loads, across all threads. Default =
404    /// 32.
405    pub event_queue_size              : i32,
406    /// [r/w] Optional. Specify 0 to ignore. For streams. This determines the default size of the
407    /// double buffer (in milliseconds) that a stream uses. Default = 400ms
408    pub default_decode_buffer_size    : u32,
409    /// [r/w] Optional. Specify 0 to ignore. Gives fmod's logging system a path/filename. Normally
410    /// the log is placed in the same directory as the executable and called fmod.log. When using
411    /// [`Sys::get_advanced_settings`](doc/rfmod/struct.Sys.html#method.get_advanced_settings),
412    /// provide at least 256 bytes of memory to copy into.
413    pub debug_log_filename            : String,
414    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_ENABLE_PROFILE. Specify the port
415    /// to listen on for connections by the
416    /// profiler application.
417    pub profile_port                  : u16,
418    /// [r/w] Optional. Specify 0 to ignore. The maximum time in miliseconds it takes for a channel
419    /// to fade to the new level when its
420    /// occlusion changes.
421    pub geometry_max_fade_time        : u32,
422    /// [r/w] Optional. Specify 0 to ignore. Tells
423    /// [`Sys::init`](doc/rfmod/struct.Sys.html#method.init) to allocate a pool of wavedata/spectrum
424    /// buffers to prevent memory fragmentation, any additional buffers will be allocated normally.
425    pub max_spectrum_wave_data_buffers: u32,
426    /// [r/w] Optional. Specify 0 to ignore. The delay the music system should allow for loading a
427    /// sample from disk (in milliseconds). Default = 400 ms.
428    pub music_system_cache_delay      : u32,
429    /// [r/w] Optional. Specify 0 to ignore. For use with FMOD_INIT_DISTANCE_FILTERING. The default
430    /// center frequency in Hz for the distance filtering effect. Default = 1500.0.
431    pub distance_filter_center_freq   : f32,
432    /// [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD Stream thread in
433    /// bytes. Useful for custom codecs that use excess stack. Default 49,152 (48kb)
434    pub stack_size_stream             : u32,
435    /// [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD_NONBLOCKING loading
436    /// thread. Useful for custom codecs that use excess stack. Default 65,536 (64kb)
437    pub stack_size_non_blocking       : u32,
438    /// [r/w] Optional. Specify 0 to ignore. Specify the stack size for the FMOD mixer thread.
439    /// Useful for custom dsps that use excess stack. Default 49,152 (48kb)
440    pub stack_size_mixer              : u32,
441}
442
443impl Default for AdvancedSettings {
444    fn default() -> AdvancedSettings {
445        AdvancedSettings {
446            max_MPEG_codecs: 32i32,
447            max_ADPCM_codecs: 32i32,
448            max_XMA_codecs: 32i32,
449            max_CELT_codecs: 32i32,
450            max_VORBIS_codecs: 32i32,
451            max_AT9_codecs: 32i32,
452            max_PCM_codecs: 16i32,
453            ASIO_num_channels: 0i32,
454            ASIO_channel_list: Vec::new(),
455            ASIO_speaker_list: Vec::new(),
456            max_3D_reverb_DSPs: 0i32,
457            HRTF_min_angle: 180f32,
458            HRTF_max_angle: 360f32,
459            HRTF_freq: 4000f32,
460            vol0_virtual_vol: 0f32,
461            event_queue_size: 32i32,
462            default_decode_buffer_size: 400u32,
463            debug_log_filename: String::new(),
464            profile_port: 0u16,
465            geometry_max_fade_time: 0u32,
466            max_spectrum_wave_data_buffers: 0u32,
467            music_system_cache_delay: 400u32,
468            distance_filter_center_freq: 1500f32,
469            stack_size_stream: 49152u32,
470            stack_size_non_blocking: 65536u32,
471            stack_size_mixer: 49152u32,
472        }
473    }
474}
475
476/// Use this structure with [`Sys::create_sound`](struct.Sys.html#method.create_sound) when more
477/// control is needed over loading. The possible reasons to use this with
478/// [`Sys::create_sound`](struct.Sys.html#method.create_sound) are:
479///
480/// * Loading a file from memory.
481/// * Loading a file from within another larger (possibly wad/pak) file, by giving the loader an
482///   offset and length.
483/// * To create a user created / non file based sound.
484/// * To specify a starting subsound to seek to within a multi-sample sounds (ie FSB/DLS/SF2) when
485///   created as a stream.
486/// * To specify which subsounds to load for multi-sample sounds (ie FSB/DLS/SF2) so that memory is
487///   saved and only a subset is actually loaded/read from disk.
488/// * To specify 'piggyback' read and seek callbacks for capture of sound data as fmod reads and
489///   decodes it. Useful for ripping decoded PCM data from sounds as they are loaded / played.
490/// * To specify a MIDI DLS/SF2 sample set file to load when opening a MIDI file.
491///
492/// See below on what members to fill for each of the above types of sound you want to create.
493pub struct CreateSoundexInfo {
494    /// [w] Optional. Specify 0 to ignore. Size in bytes of file to load, or sound to create (in
495    /// this case only if FMOD_OPENUSER is used). Required if loading from memory. If 0 is
496    /// specified, then it will use the size of the file (unless loading from memory then an error
497    /// will be returned).
498    pub length                 : u32,
499    /// [w] Optional. Specify 0 to ignore. Offset from start of the file to start loading from. This
500    /// is useful for loading files from inside big data files.
501    pub file_offset            : u32,
502    /// [w] Optional. Specify 0 to ignore. Number of channels in a sound mandatory if FMOD_OPENUSER
503    /// or FMOD_OPENRAW is used.
504    pub num_channels           : i32,
505    /// [w] Optional. Specify 0 to ignore. Default frequency of sound in a sound mandatory if
506    /// FMOD_OPENUSER or FMOD_OPENRAW is used. Other formats use the frequency determined by the
507    /// file format.
508    pub default_frequency      : i32,
509    /// [w] Optional. Specify 0 or ::SoundFormatNone to ignore. Format of the sound mandatory if
510    /// FMOD_OPENUSER or FMOD_OPENRAW is used. Other formats use the format determined by the file
511    /// format.
512    pub format                 : ::SoundFormat,
513    /// [w] Optional. Specify 0 to ignore. For streams. This determines the size of the double
514    /// buffer (in PCM samples) that a stream uses. Use this for user created streams if you want to
515    /// determine the size of the callback buffer passed to you. Specify 0 to use FMOD's default
516    /// size which is currently equivalent to 400ms of the sound format created/loaded.
517    pub decode_buffer_size     : u32,
518    /// [w] Optional. Specify 0 to ignore. In a multi-sample file format such as .FSB/.DLS/.SF2,
519    /// specify the initial subsound to seek to, only if FMOD_CREATESTREAM is used.
520    pub initial_subsound       : i32,
521    /// [w] Optional. Specify 0 to ignore or have no subsounds. In a sound created with
522    /// FMOD_OPENUSER, specify the number of subsounds that are accessable with
523    /// [`Sound::get_sub_sound`](doc/rfmod/struct.Sound.html#method.get_sub_sound). If not created
524    /// with FMOD_OPENUSER, this will limit the number of subsounds loaded within a multi-subsound
525    /// file. If using FSB, then if FMOD_CREATESOUNDEXINFO::inclusionlist is used, this will shuffle
526    /// subsounds down so that there are not any gaps. It will mean that the indices of the sounds
527    /// will be different.
528    pub num_subsounds          : i32,
529    /// [w] Optional. Specify 0 to ignore. In a multi-sample format such as .FSB/.DLS/.SF2 it may be
530    /// desirable to specify only a subset of sounds to be loaded out of the whole file. This is an
531    /// array of subsound indices to load into memory when created.
532    pub inclusion_list         : Vec<i32>,
533    /// [w] Optional. Specify 0 to ignore. Callback to 'piggyback' on FMOD's read functions and
534    /// accept or even write PCM data while FMOD is opening the sound. Used for user sounds created
535    /// with FMOD_OPENUSER or for capturing decoded data as FMOD reads it.
536    pub pcm_read_callback      : SoundPcmReadCallback,
537    /// [w] Optional. Specify 0 to ignore. Callback for when the user calls a seeking function such
538    /// as [`Channel::set_time`](doc/rfmod/struct.Channel.html#method.set_time) or
539    /// [`Channel::set_position`](doc/rfmod/struct.Channel.html#method.set_position) within a
540    /// multi-sample sound, and for when it is opened.
541    pub pcm_set_pos_callback   : SoundPcmSetPosCallback,
542    /// [w] Optional. Specify 0 to ignore. Callback for successful completion, or error while
543    /// loading a sound that used the FMOD_NONBLOCKING flag. Also called duing seeking, when
544    /// setPosition is called or a stream is restarted.
545    pub non_block_callback     : SoundNonBlockCallback,
546    /// [w] Optional. Specify 0 to ignore. Filename for a DLS or SF2 sample set when loading a MIDI
547    /// file. If not specified, on Windows it will attempt to open /windows/system32/drivers/gm.dls
548    /// or /windows/system32/drivers/etc/gm.dls, on Mac it will attempt to load
549    /// /System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls,
550    /// otherwise the MIDI will fail to open. Current DLS support is for level 1 of the
551    /// specification.
552    pub dls_name               : String,
553    dls_name_c                 : CString,
554    /// [w] Optional. Specify 0 to ignore. Key for encrypted FSB file. Without this key an encrypted
555    /// FSB file will not load.
556    pub encryption_key         : String,
557    encryption_key_c           : CString,
558    /// [w] Optional. Specify 0 to ignore. For sequenced formats with dynamic channel allocation
559    /// such as .MID and .IT, this specifies the maximum voice count allowed while playing. .IT
560    /// defaults to 64. .MID defaults to 32.
561    pub max_polyphony          : i32,
562    /// [w] Optional. Specify 0 to ignore. This is user data to be attached to the sound during
563    /// creation. Access via
564    /// [`Sound::get_user_data`](doc/rfmod/struct.Sound.html#method.get_user_data). Note: This is
565    /// not passed to FMOD_FILE_OPENCALLBACK, that is a different userdata that is file specific.
566    user_data                  : Box<ffi::SoundData>,
567    /// [w] Optional. Specify 0 or SoundTypeUnknown to ignore. Instead of scanning all codec types,
568    /// use this to speed up loading by making it jump straight to this codec.
569    pub suggested_sound_type   : ::SoundType,
570    /// [w] Optional. Specify 0 to ignore. Callback for opening this file.
571    user_open                  : ffi::FMOD_FILE_OPENCALLBACK,
572    /// [w] Optional. Specify 0 to ignore. Callback for closing this file.
573    user_close                 : ffi::FMOD_FILE_CLOSECALLBACK,
574    /// [w] Optional. Specify 0 to ignore. Callback for reading from this file.
575    user_read                  : ffi::FMOD_FILE_READCALLBACK,
576    /// [w] Optional. Specify 0 to ignore. Callback for seeking within this file.
577    user_seek                  : ffi::FMOD_FILE_SEEKCALLBACK,
578    /// [w] Optional. Specify 0 to ignore. Callback for seeking within this file.
579    user_async_read            : ffi::FMOD_FILE_ASYNCREADCALLBACK,
580    /// [w] Optional. Specify 0 to ignore. Callback for seeking within this file.
581    user_async_cancel          : ffi::FMOD_FILE_ASYNCCANCELCALLBACK,
582    /// [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds
583    /// to speakers. See SpeakerMapType for more.
584    pub speaker_map            : ::SpeakerMapType,
585    /// [w] Optional. Specify 0 to ignore. Specify a sound group if required, to put sound in as it
586    /// is created.
587    pub initial_sound_group    : sound_group::SoundGroup,
588    /// [w] Optional. Specify 0 to ignore. For streams. Specify an initial position to seek the
589    /// stream to.
590    pub initial_seek_position  : u32,
591    /// [w] Optional. Specify 0 to ignore. For streams. Specify the time unit for the position set
592    /// in initialseekposition.
593    pub initial_seek_pos_type  : TimeUnit,
594    /// [w] Optional. Specify true to ignore. Set to false to use fmod's built in file system.
595    /// Ignores setFileSystem callbacks and also FMOD_CREATESOUNEXINFO file callbacks. Useful for
596    /// specific cases where you don't want to use your own file system but want to use fmod's file
597    /// system (ie net streaming).
598    pub ignore_set_file_system : bool,
599    /// [w] Optional. Specify 0 to ignore. For CDDA sounds only - if non-zero use ASPI instead of
600    /// NTSCSI to access the specified CD/DVD device.
601    pub cdda_force_aspi        : i32,
602    /// [w] Optional. Specify 0 or FMOD_AUDIOQUEUE_CODECPOLICY_DEFAULT to ignore. Policy used to
603    /// determine whether hardware or software is used for decoding, see FMOD_AUDIOQUEUE_CODECPOLICY
604    /// for options (iOS >= 3.0 required, otherwise only hardware is available)
605    pub audio_queue_policy     : u32,
606    /// [w] Optional. Specify 0 to ignore. Allows you to set a minimum desired MIDI mixer
607    /// granularity. Values smaller than 512 give greater than default accuracy at the cost of more
608    /// CPU and vice versa. Specify 0 for default (512 samples).
609    pub min_midi_granularity   : u32,
610    /// [w] Optional. Specify 0 to ignore. Specifies a thread index to execute non blocking load on.
611    /// Allows for up to 5 threads to be used for loading at once. This is to avoid one load
612    /// blocking another. Maximum value = 4.
613    pub non_block_thread_id    : i32,
614}
615
616impl Default for CreateSoundexInfo {
617    fn default() -> CreateSoundexInfo {
618        CreateSoundexInfo {
619            length: 0u32,
620            file_offset: 0u32,
621            num_channels: 0i32,
622            default_frequency: 0i32,
623            format: ::SoundFormat::None,
624            decode_buffer_size: 0u32,
625            initial_subsound: 0i32,
626            num_subsounds: 0i32,
627            inclusion_list: Vec::new(),
628            pcm_read_callback: None,
629            pcm_set_pos_callback: None,
630            non_block_callback: None,
631            dls_name: String::new(),
632            dls_name_c: CString::new("").expect("CString failed on empty string..."),
633            encryption_key: String::new(),
634            encryption_key_c: CString::new("").expect("CString failed on empty string..."),
635            max_polyphony: 0i32,
636            user_data: Box::new(ffi::SoundData::new()),
637            suggested_sound_type: ::SoundType::Unknown,
638            user_open: None,
639            user_close: None,
640            user_read: None,
641            user_seek: None,
642            user_async_read: None,
643            user_async_cancel: None,
644            speaker_map: ::SpeakerMapType::Default,
645            initial_sound_group: ffi::FFI::wrap(::std::ptr::null_mut()),
646            initial_seek_position: 0u32,
647            initial_seek_pos_type: TimeUnit(0u32),
648            ignore_set_file_system: true,
649            cdda_force_aspi: 0i32,
650            audio_queue_policy: 0u32,
651            min_midi_granularity: 0u32,
652            non_block_thread_id: 0i32,
653        }
654    }
655}
656
657impl CreateSoundexInfo {
658    fn convert_to_c(&mut self) -> ffi::FMOD_CREATESOUNDEXINFO {
659        self.dls_name_c = CString::new(self.dls_name.clone()).expect("CString failed");
660        self.encryption_key_c = CString::new(self.encryption_key.clone()).expect("CString failed");
661
662        ffi::FMOD_CREATESOUNDEXINFO{
663            cbsize: mem::size_of::<ffi::FMOD_CREATESOUNDEXINFO>() as i32,
664            length: self.length,
665            fileoffset: self.file_offset,
666            numchannels: self.num_channels,
667            defaultfrequency: self.default_frequency,
668            format: self.format,
669            decodebuffersize: self.decode_buffer_size,
670            initialsubsound: self.initial_subsound,
671            numsubsounds: self.num_subsounds,
672            inclusionlist: self.inclusion_list.as_mut_ptr(),
673            inclusionlistnum: self.inclusion_list.len() as i32,
674            pcmreadcallback: match self.pcm_read_callback {
675                Some(_) => Some(pcm_read_callback as extern "C" fn(*mut _, *mut _, _) -> _),
676                None => None
677            },
678            pcmsetposcallback: match self.pcm_set_pos_callback {
679                Some(_) => Some(pcm_set_pos_callback as extern "C" fn(*mut _, _, _, _) -> _),
680                None => None
681            },
682            nonblockcallback: match self.non_block_callback {
683                Some(_) => Some(non_block_callback as extern "C" fn(*mut _, _) -> _),
684                None => None
685            },
686            dlsname: if !self.dls_name.is_empty() {
687                self.dls_name_c.as_c_str().as_ptr() as *mut c_char
688            } else {
689                ::std::ptr::null_mut()
690            },
691            encryptionkey: if !self.encryption_key.is_empty() {
692                self.encryption_key_c.as_c_str().as_ptr() as *mut c_char
693            } else {
694                ::std::ptr::null_mut()
695            },
696            maxpolyphony: self.max_polyphony,
697            userdata: {
698                self.user_data.non_block = self.non_block_callback;
699                self.user_data.pcm_read = self.pcm_read_callback;
700                self.user_data.pcm_set_pos = self.pcm_set_pos_callback;
701                unsafe { ::std::mem::transmute::<&mut ffi::SoundData, *mut c_void>(&mut *self.user_data) }
702            },
703            suggestedsoundtype: self.suggested_sound_type,
704            useropen: self.user_open,
705            userclose: self.user_close,
706            userread: self.user_read,
707            userseek: self.user_seek,
708            userasynccancel: self.user_async_cancel,
709            userasyncread: self.user_async_read,
710            speakermap: self.speaker_map,
711            initialsoundgroup: ffi::FFI::unwrap(&self.initial_sound_group),
712            initialseekposition: self.initial_seek_position,
713            initialseekpostype: match self.initial_seek_pos_type {TimeUnit(v) => v},
714            ignoresetfilesystem: match self.ignore_set_file_system {
715                true => 0i32,
716                false => 1i32
717            },
718            cddaforceaspi: self.cdda_force_aspi,
719            audioqueuepolicy: self.audio_queue_policy,
720            minmidigranularity: self.min_midi_granularity,
721            nonblockthreadid: self.non_block_thread_id,
722        }
723    }
724}
725
726/// When creating a codec, declare one of these and provide the relevant callbacks and name for FMOD
727/// to use when it opens and reads a file.
728pub struct FmodCodecDescription {
729    /// [in] Name of the codec.
730    pub name             : String,
731    /// [in] Plugin writer's version number.
732    pub version          : u32,
733    /// [in] Tells FMOD to open the file as a stream when calling
734    /// [`Sys::create_sound`](doc/rfmod/struct.Sys.html#method.create_sound), and not a static
735    /// sample. Should normally be 0 (FALSE), because generally the user wants to decode the file
736    /// into memory when using [`Sys::create_sound`](doc/rfmod/struct.Sys.html#method.create_sound).
737    /// Mainly used for formats that decode for a very long time, or could use large amounts of
738    /// memory when decoded. Usually sequenced formats such as mod/s3m/xm/it/midi fall into this
739    /// category. It is mainly to stop users that don't know what they're doing from getting
740    /// FMOD_ERR_MEMORY returned from createSound when they should have in fact called
741    /// System::createStream or used FMOD_CREATESTREAM in
742    /// [`Sys::create_sound`](doc/rfmod/struct.Sys.html#method.create_sound).
743    pub default_as_stream: i32,
744    /// [in] When setposition codec is called, only these time formats will be passed to the codec.
745    /// Use bitwise OR to accumulate different
746    /// types.
747    pub time_units       : TimeUnit,
748    /// [in] Open callback for the codec for when FMOD tries to open a sound using this codec.
749    open                 : ffi::FMOD_CODEC_OPENCALLBACK,
750    /// [in] Close callback for the codec for when FMOD tries to close a sound using this codec.
751    close                : ffi::FMOD_CODEC_CLOSECALLBACK,
752    /// [in] Read callback for the codec for when FMOD tries to read some data from the file to the
753    /// destination format (specified in the open callback).
754    read                 : ffi::FMOD_CODEC_READCALLBACK,
755    /// [in] Callback to return the length of the song in whatever format required when
756    /// [`Sound::get_length`](doc/rfmod/struct.Sound.html#method.get_length).
757    /// is called.
758    get_length           : ffi::FMOD_CODEC_GETLENGTHCALLBACK,
759    /// [in] Seek callback for the codec for when FMOD tries to seek within the file with
760    /// [`Channel::set_position`](doc/rfmod/struct.Channel.html#method.set_position).
761    set_position         : ffi::FMOD_CODEC_SETPOSITIONCALLBACK,
762    /// [in] Tell callback for the codec for when FMOD tries to get the current position within the
763    /// with [`Channel::get_position`](doc/rfmod/struct.Channel.html#method.get_position).
764    get_position         : ffi::FMOD_CODEC_GETPOSITIONCALLBACK,
765    /// [in] Sound creation callback for the codec when FMOD finishes creating the sound. (So the
766    /// codec can set more parameters for the related created sound, ie loop points/mode or 3D
767    /// attributes etc).
768    sound_create         : ffi::FMOD_CODEC_SOUNDCREATECALLBACK,
769    /// [in] Callback to tell FMOD about the waveformat of a particular subsound. This is to save
770    /// memory, rather than saving 1000 FMOD_CODEC_WAVEFORMAT structures in the codec, the codec
771    /// might have a more optimal way of storing this information.
772    get_wave_format      : ffi::FMOD_CODEC_GETWAVEFORMAT,
773}
774
775impl Default for FmodCodecDescription {
776    fn default() -> FmodCodecDescription {
777        FmodCodecDescription {
778            name: String::new(),
779            version: 0u32,
780            default_as_stream: 0i32,
781            time_units: TimeUnit(0u32),
782            open: None,
783            close: None,
784            read: None,
785            get_length: None,
786            set_position: None,
787            get_position: None,
788            sound_create: None,
789            get_wave_format: None,
790        }
791    }
792}
793
794/// Wrapper for OutputHandle
795pub struct OutputHandle {
796    handle: *mut c_void
797}
798
799/// Structure to be filled with detailed memory usage information of a FMOD object
800#[derive(Clone, Copy)]
801pub struct MemoryUsageDetails
802{
803    /// [out] Memory not accounted for by other types
804    pub other                  : u32,
805    /// [out] String data
806    pub string                 : u32,
807    /// [out] System object and various internals
808    pub system                 : u32,
809    /// [out] Plugin objects and internals
810    pub plugins                : u32,
811    /// [out] Output module object and internals
812    pub output                 : u32,
813    /// [out] Channel related memory
814    pub channel                : u32,
815    /// [out] ChannelGroup objects and internals
816    pub channel_group          : u32,
817    /// [out] Codecs allocated for streaming
818    pub codec                  : u32,
819    /// [out] File buffers and structures
820    pub file                   : u32,
821    /// [out] Sound objects and internals
822    pub sound                  : u32,
823    /// [out] Sound data stored in secondary RAM
824    pub secondary_ram          : u32,
825    /// [out] SoundGroup objects and internals
826    pub sound_group            : u32,
827    /// [out] Stream buffer memory
828    pub stream_buffer          : u32,
829    /// [out] DSPConnection objects and internals
830    pub dsp_connection         : u32,
831    /// [out] DSP implementation objects
832    pub dsp                    : u32,
833    /// [out] Realtime file format decoding DSP objects
834    pub dsp_codec              : u32,
835    /// [out] Profiler memory footprint.
836    pub profile                : u32,
837    /// [out] Buffer used to store recorded data from microphone
838    pub record_buffer          : u32,
839    /// [out] Reverb implementation objects
840    pub reverb                 : u32,
841    /// [out] Reverb channel properties structs
842    pub reverb_channel_props   : u32,
843    /// [out] Geometry objects and internals
844    pub geometry               : u32,
845    /// [out] Sync point memory.
846    pub sync_point             : u32,
847    /// [out] EventSystem and various internals
848    pub event_system           : u32,
849    /// [out] MusicSystem and various internals
850    pub music_system           : u32,
851    /// [out] Definition of objects contained in all loaded projects e.g. events, groups, categories
852    pub fev                    : u32,
853    /// [out] Data loaded with preloadFSB
854    pub memory_fsb             : u32,
855    /// [out] EventProject objects and internals
856    pub event_project          : u32,
857    /// [out] EventGroup objects and internals
858    pub event_group_i          : u32,
859    /// [out] Objects used to manage wave banks
860    pub sound_bank_class       : u32,
861    /// [out] Data used to manage lists of wave bank usage
862    pub sound_bank_list        : u32,
863    /// [out] Stream objects and internals
864    pub stream_instance        : u32,
865    /// [out] Sound definition objects
866    pub sound_def_class        : u32,
867    /// [out] Sound definition static data objects
868    pub sound_def_def_class    : u32,
869    /// [out] Sound definition pool data
870    pub sound_def_pool         : u32,
871    /// [out] Reverb definition objects
872    pub reverb_def             : u32,
873    /// [out] Reverb objects
874    pub event_reverb           : u32,
875    /// [out] User property objects
876    pub user_property          : u32,
877    /// [out] Event instance base objects
878    pub event_instance         : u32,
879    /// [out] Complex event instance objects
880    pub event_instance_complex : u32,
881    /// [out] Simple event instance objects
882    pub event_instance_simple  : u32,
883    /// [out] Event layer instance objects
884    pub event_instance_layer   : u32,
885    /// [out] Event sound instance objects
886    pub event_instance_sound   : u32,
887    /// [out] Event envelope objects
888    pub event_envelope         : u32,
889    /// [out] Event envelope definition objects
890    pub event_envelope_def     : u32,
891    /// [out] Event parameter objects
892    pub event_parameter        : u32,
893    /// [out] Event category objects
894    pub event_category         : u32,
895    /// [out] Event envelope point objects
896    pub event_envelope_point   : u32,
897    /// [out] Event instance pool memory
898    pub event_instance_pool    : u32,
899}
900
901impl Default for MemoryUsageDetails {
902    fn default() -> MemoryUsageDetails {
903        MemoryUsageDetails {
904            other: 0u32,
905            string: 0u32,
906            system: 0u32,
907            plugins: 0u32,
908            output: 0u32,
909            channel: 0u32,
910            channel_group: 0u32,
911            codec: 0u32,
912            file: 0u32,
913            sound: 0u32,
914            secondary_ram: 0u32,
915            sound_group: 0u32,
916            stream_buffer: 0u32,
917            dsp_connection: 0u32,
918            dsp: 0u32,
919            dsp_codec: 0u32,
920            profile: 0u32,
921            record_buffer: 0u32,
922            reverb: 0u32,
923            reverb_channel_props: 0u32,
924            geometry: 0u32,
925            sync_point: 0u32,
926            event_system: 0u32,
927            music_system: 0u32,
928            fev: 0u32,
929            memory_fsb: 0u32,
930            event_project: 0u32,
931            event_group_i: 0u32,
932            sound_bank_class: 0u32,
933            sound_bank_list: 0u32,
934            stream_instance: 0u32,
935            sound_def_class: 0u32,
936            sound_def_def_class: 0u32,
937            sound_def_pool: 0u32,
938            reverb_def: 0u32,
939            event_reverb: 0u32,
940            user_property: 0u32,
941            event_instance: 0u32,
942            event_instance_complex: 0u32,
943            event_instance_simple: 0u32,
944            event_instance_layer: 0u32,
945            event_instance_sound: 0u32,
946            event_envelope: 0u32,
947            event_envelope_def: 0u32,
948            event_parameter: 0u32,
949            event_category: 0u32,
950            event_envelope_point: 0u32,
951            event_instance_pool: 0u32,
952        }
953    }
954}
955
956pub fn get_memory_usage_details_ffi(details: MemoryUsageDetails) -> ffi::FMOD_MEMORY_USAGE_DETAILS {
957    ffi::FMOD_MEMORY_USAGE_DETAILS {
958        other: details.other,
959        string: details.string,
960        system: details.system,
961        plugins: details.plugins,
962        output: details.output,
963        channel: details.channel,
964        channel_group: details.channel_group,
965        codec: details.codec,
966        file: details.file,
967        sound: details.sound,
968        secondary_ram: details.secondary_ram,
969        sound_group: details.sound_group,
970        stream_buffer: details.stream_buffer,
971        dsp_connection: details.dsp_connection,
972        dsp: details.dsp,
973        dsp_codec: details.dsp_codec,
974        profile: details.profile,
975        record_buffer: details.record_buffer,
976        reverb: details.reverb,
977        reverb_channel_props: details.reverb_channel_props,
978        geometry: details.geometry,
979        sync_point: details.sync_point,
980        event_system: details.event_system,
981        music_system: details.music_system,
982        fev: details.fev,
983        memory_fsb: details.memory_fsb,
984        event_project: details.event_project,
985        event_group_i: details.event_group_i,
986        sound_bank_class: details.sound_bank_class,
987        sound_bank_list: details.sound_bank_list,
988        stream_instance: details.stream_instance,
989        sound_def_class: details.sound_def_class,
990        sound_def_def_class: details.sound_def_def_class,
991        sound_def_pool: details.sound_def_pool,
992        reverb_def: details.reverb_def,
993        event_reverb: details.event_reverb,
994        user_property: details.user_property,
995        event_instance: details.event_instance,
996        event_instance_complex: details.event_instance_complex,
997        event_instance_simple: details.event_instance_simple,
998        event_instance_layer: details.event_instance_layer,
999        event_instance_sound: details.event_instance_sound,
1000        event_envelope: details.event_envelope,
1001        event_envelope_def: details.event_envelope_def,
1002        event_parameter: details.event_parameter,
1003        event_category: details.event_category,
1004        event_envelope_point: details.event_envelope_point,
1005        event_instance_pool: details.event_instance_pool,
1006    }
1007}
1008
1009pub fn from_memory_usage_details_ptr(details: ffi::FMOD_MEMORY_USAGE_DETAILS) -> MemoryUsageDetails {
1010    MemoryUsageDetails {
1011        other: details.other,
1012        string: details.string,
1013        system: details.system,
1014        plugins: details.plugins,
1015        output: details.output,
1016        channel: details.channel,
1017        channel_group: details.channel_group,
1018        codec: details.codec,
1019        file: details.file,
1020        sound: details.sound,
1021        secondary_ram: details.secondary_ram,
1022        sound_group: details.sound_group,
1023        stream_buffer: details.stream_buffer,
1024        dsp_connection: details.dsp_connection,
1025        dsp: details.dsp,
1026        dsp_codec: details.dsp_codec,
1027        profile: details.profile,
1028        record_buffer: details.record_buffer,
1029        reverb: details.reverb,
1030        reverb_channel_props: details.reverb_channel_props,
1031        geometry: details.geometry,
1032        sync_point: details.sync_point,
1033        event_system: details.event_system,
1034        music_system: details.music_system,
1035        fev: details.fev,
1036        memory_fsb: details.memory_fsb,
1037        event_project: details.event_project,
1038        event_group_i: details.event_group_i,
1039        sound_bank_class: details.sound_bank_class,
1040        sound_bank_list: details.sound_bank_list,
1041        stream_instance: details.stream_instance,
1042        sound_def_class: details.sound_def_class,
1043        sound_def_def_class: details.sound_def_def_class,
1044        sound_def_pool: details.sound_def_pool,
1045        reverb_def: details.reverb_def,
1046        event_reverb: details.event_reverb,
1047        user_property: details.user_property,
1048        event_instance: details.event_instance,
1049        event_instance_complex: details.event_instance_complex,
1050        event_instance_simple: details.event_instance_simple,
1051        event_instance_layer: details.event_instance_layer,
1052        event_instance_sound: details.event_instance_sound,
1053        event_envelope: details.event_envelope,
1054        event_envelope_def: details.event_envelope_def,
1055        event_parameter: details.event_parameter,
1056        event_category: details.event_category,
1057        event_envelope_point: details.event_envelope_point,
1058        event_instance_pool: details.event_instance_pool,
1059    }
1060}
1061
1062/// FMOD System Object
1063pub struct Sys {
1064    system: *mut ffi::FMOD_SYSTEM,
1065    is_first: bool
1066}
1067
1068impl ffi::FFI<ffi::FMOD_SYSTEM> for Sys {
1069    fn wrap(system: *mut ffi::FMOD_SYSTEM) -> Sys {
1070        Sys {system: system, is_first: false}
1071    }
1072
1073    fn unwrap(s: &Sys) -> *mut ffi::FMOD_SYSTEM {
1074        s.system
1075    }
1076}
1077
1078impl Drop for Sys {
1079    fn drop(&mut self) {
1080        self.release();
1081    }
1082}
1083
1084impl Sys {
1085    /* the first one created has to be the last one released */
1086    pub fn new() -> Result<Sys, ::Status> {
1087        let mut tmp = ::std::ptr::null_mut();
1088
1089        match unsafe { ffi::FMOD_System_Create(&mut tmp) } {
1090            ::Status::Ok => Ok(Sys{system: tmp, is_first: true}),
1091            err => Err(err)
1092        }
1093    }
1094
1095    pub fn init(&self) -> ::Status {
1096        unsafe { ffi::FMOD_System_Init(self.system, 1, ::INIT_NORMAL, ::std::ptr::null_mut()) }
1097    }
1098
1099    pub fn init_with_parameters(&self, max_channels: i32, InitFlag(flag): InitFlag) -> ::Status {
1100        unsafe { ffi::FMOD_System_Init(self.system, max_channels, flag, ::std::ptr::null_mut()) }
1101    }
1102
1103    pub fn update(&self) -> ::Status {
1104        unsafe { ffi::FMOD_System_Update(self.system) }
1105    }
1106
1107    pub fn release(&mut self) -> ::Status {
1108        if self.is_first && !self.system.is_null() {
1109            unsafe {
1110                match match ffi::FMOD_System_Close(self.system) {
1111                    ::Status::Ok => ffi::FMOD_System_Release(self.system),
1112                    e => e
1113                } {
1114                    ::Status::Ok => {
1115                        self.system = ::std::ptr::null_mut();
1116                       ::Status::Ok
1117                    }
1118                    e => e
1119                }
1120                
1121            }
1122        } else {
1123            ::Status::Ok
1124        }
1125    }
1126
1127    /// If music is empty, null is sent
1128    pub fn create_sound(&self, music: &str, options: Option<Mode>,
1129                        exinfo: Option<&mut CreateSoundexInfo>) -> Result<Sound, ::Status> {
1130        let mut sound = sound::from_ptr_first(::std::ptr::null_mut());
1131        let op = match options {
1132            Some(Mode(t)) => t,
1133            None => ::SOFTWARE | ::LOOP_OFF | ::_2D | ::CREATESTREAM
1134        };
1135        let mut ex = exinfo.map(|e| {
1136            let user_data = sound::get_user_data(&mut sound);
1137            user_data.non_block = e.non_block_callback;
1138            user_data.pcm_read = e.pcm_read_callback;
1139            user_data.pcm_set_pos = e.pcm_set_pos_callback;
1140            unsafe {
1141                user_data.user_data =
1142                    ::std::mem::transmute::<&mut ffi::SoundData, *mut c_void>(
1143                        &mut *e.user_data);
1144            }
1145            e.convert_to_c()
1146        });
1147        let exptr = ex.as_mut().map(|ex| ex as *mut ffi::FMOD_CREATESOUNDEXINFO)
1148            .unwrap_or (std::ptr::null_mut());
1149
1150        match if music.len() > 0 {
1151            let music_cstring = CString::new(music).expect("CString failed");
1152            unsafe { ffi::FMOD_System_CreateSound(self.system,
1153                                                  music_cstring.as_ptr() as *const c_char, op, exptr,
1154                                                  sound::get_fffi(&mut sound)) }
1155        } else {
1156            unsafe { ffi::FMOD_System_CreateSound(self.system, ::std::ptr::null(), op, exptr,
1157                                                  sound::get_fffi(&mut sound)) }
1158        } {
1159            ::Status::Ok => {
1160                Ok(sound)
1161            },
1162            e => Err(e)
1163        }
1164    }
1165
1166    /// Create sound from a file contained in a byte slice.
1167    ///
1168    /// Automatically adds the `OPENMEMORY` mode flag and uses the length of the
1169    /// slice as the exinfo length parameter. Ignores the `CREATESTREAM` mode
1170    /// flag since this would keep a pointer to the passed in buffer.
1171    pub fn create_sound_openmemory(&self, music: &[u8], options: Option<Mode>,
1172                        exinfo: Option<&mut CreateSoundexInfo>) -> Result<Sound, ::Status> {
1173        let mut sound = sound::from_ptr_first(::std::ptr::null_mut());
1174        let op = {
1175            let mut op = match options {
1176                Some(Mode(t)) => t,
1177                None => ::SOFTWARE | ::LOOP_OFF | ::_2D | ::CREATESTREAM
1178            };
1179            op |= ::OPENMEMORY;
1180            op &= !::CREATESTREAM;
1181            op
1182        };
1183        let mut ex = exinfo.map(|e| {
1184            let user_data = sound::get_user_data(&mut sound);
1185            user_data.non_block = e.non_block_callback;
1186            user_data.pcm_read = e.pcm_read_callback;
1187            user_data.pcm_set_pos = e.pcm_set_pos_callback;
1188            unsafe {
1189                user_data.user_data =
1190                    ::std::mem::transmute::<&mut ffi::SoundData, *mut c_void>(
1191                        &mut *e.user_data);
1192            }
1193            e.length = music.len() as u32;
1194            e.convert_to_c()
1195        });
1196        let mut exinfo_default = CreateSoundexInfo {
1197            length: music.len() as u32, .. Default::default()
1198        }.convert_to_c();
1199        let exptr = ex.as_mut().unwrap_or(&mut exinfo_default) as *mut ffi::FMOD_CREATESOUNDEXINFO;
1200
1201        match if music.len() > 0 {
1202            unsafe { ffi::FMOD_System_CreateSound(self.system,
1203                                                  music.as_ptr() as *const c_char, op, exptr,
1204                                                  sound::get_fffi(&mut sound)) }
1205        } else {
1206            unsafe { ffi::FMOD_System_CreateSound(self.system, ::std::ptr::null(), op, exptr,
1207                                                  sound::get_fffi(&mut sound)) }
1208        } {
1209            ::Status::Ok => {
1210                Ok(sound)
1211            },
1212            e => Err(e)
1213        }
1214    }
1215
1216    pub fn create_stream(&self, music: &str, options: Option<Mode>,
1217                         exinfo: Option<&mut CreateSoundexInfo>) -> Result<Sound, ::Status> {
1218        let mut sound = sound::from_ptr_first(::std::ptr::null_mut());
1219        let op = match options {
1220            Some(Mode(t)) => t,
1221            None => ::SOFTWARE | ::LOOP_OFF | ::_2D | ::CREATESTREAM
1222        };
1223        let ex = match exinfo {
1224            Some(e) => {
1225                let user_data = sound::get_user_data(&mut sound);
1226                user_data.non_block = e.non_block_callback;
1227                user_data.pcm_read = e.pcm_read_callback;
1228                user_data.pcm_set_pos = e.pcm_set_pos_callback;
1229                unsafe {
1230                    user_data.user_data =
1231                        ::std::mem::transmute::<&mut ffi::SoundData, *mut c_void>(
1232                            &mut *e.user_data);
1233                }
1234                &mut e.convert_to_c() as *mut ffi::FMOD_CREATESOUNDEXINFO
1235            },
1236            None => ::std::ptr::null_mut()
1237        };
1238
1239        match if music.len() > 0 {
1240            let music_cstring = CString::new(music).expect("CString failed");
1241            unsafe { ffi::FMOD_System_CreateStream(self.system,
1242                                                   music_cstring.as_ptr() as *const c_char, op, ex,
1243                                                   sound::get_fffi(&mut sound)) }
1244        } else {
1245            unsafe { ffi::FMOD_System_CreateStream(self.system, ::std::ptr::null(), op, ex,
1246                                                   sound::get_fffi(&mut sound)) }
1247        } {
1248            ::Status::Ok => Ok(sound),
1249            err => Err(err)
1250        }
1251    }
1252
1253    pub fn create_channel_group(&self, group_name: &str)
1254                                -> Result<channel_group::ChannelGroup, ::Status> {
1255        let mut channel_group = ::std::ptr::null_mut();
1256            let tmp_group_name = CString::new(group_name).expect("CString failed");
1257
1258        match unsafe { ffi::FMOD_System_CreateChannelGroup(self.system,
1259                                                          tmp_group_name.as_ptr() as *const c_char,
1260                                                          &mut channel_group) } {
1261            ::Status::Ok => Ok(ffi::FFI::wrap(channel_group)),
1262            e => Err(e)
1263        }
1264    }
1265
1266    pub fn create_sound_group(&self, group_name: &str)
1267                              -> Result<sound_group::SoundGroup, ::Status> {
1268        let mut sound_group = ::std::ptr::null_mut();
1269            let tmp_group_name = CString::new(group_name).expect("CString failed");
1270
1271        match unsafe { ffi::FMOD_System_CreateSoundGroup(self.system,
1272                                                         tmp_group_name.as_ptr() as *const c_char,
1273                                                         &mut sound_group) } {
1274            ::Status::Ok => Ok(ffi::FFI::wrap(sound_group)),
1275            e => Err(e)
1276        }
1277    }
1278
1279    pub fn create_reverb(&self) -> Result<reverb::Reverb, ::Status>{
1280        let mut t_reverb = ::std::ptr::null_mut();
1281
1282        match unsafe { ffi::FMOD_System_CreateReverb(self.system, &mut t_reverb) } {
1283            ::Status::Ok => Ok(ffi::FFI::wrap(t_reverb)),
1284            e => Err(e)
1285        }
1286    }
1287
1288    pub fn create_DSP(&self) -> Result<dsp::Dsp, ::Status> {
1289        let mut t_dsp = ::std::ptr::null_mut();
1290
1291        match unsafe { ffi::FMOD_System_CreateDSP(self.system, ::std::ptr::null_mut(),
1292                                                  &mut t_dsp) } {
1293            ::Status::Ok => Ok(dsp::from_ptr_first(t_dsp)),
1294            e => Err(e)
1295        }
1296    }
1297
1298    pub fn create_DSP_with_description(&self, description: &mut dsp::DspDescription)
1299                                       -> Result<dsp::Dsp, ::Status> {
1300        let mut t_dsp = ::std::ptr::null_mut();
1301        let mut t_description = dsp::get_description_ffi(description);
1302
1303        match unsafe { ffi::FMOD_System_CreateDSP(self.system, &mut t_description, &mut t_dsp) } {
1304            ::Status::Ok => Ok(dsp::from_ptr_first(t_dsp)),
1305            e => Err(e)
1306        }
1307    }
1308
1309    pub fn create_DSP_by_type(&self, _type: ::DspType) -> Result<dsp::Dsp, ::Status> {
1310        let mut t_dsp = ::std::ptr::null_mut();
1311
1312        match unsafe { ffi::FMOD_System_CreateDSPByType(self.system, _type, &mut t_dsp) } {
1313            ::Status::Ok => Ok(dsp::from_ptr_first(t_dsp)),
1314            e => Err(e)
1315        }
1316    }
1317
1318    pub fn set_output(&self, output_type: ::OutputType) -> ::Status {
1319        unsafe { ffi::FMOD_System_SetOutput(self.system, output_type) }
1320    }
1321
1322    pub fn get_output(&self) -> Result<::OutputType, ::Status> {
1323        let mut output_type = ::OutputType::AutoDetect;
1324        
1325        match unsafe { ffi::FMOD_System_GetOutput(self.system, &mut output_type) } {
1326            ::Status::Ok => Ok(output_type),
1327            e => Err(e)
1328        }
1329    }
1330
1331    pub fn get_num_drivers(&self) -> Result<i32, ::Status> {
1332        let mut num_drivers = 0i32;
1333
1334        match unsafe { ffi::FMOD_System_GetNumDrivers(self.system,
1335                                                      &mut num_drivers as *mut c_int) } {
1336            ::Status::Ok => Ok(num_drivers),
1337            e => Err(e)
1338        }
1339    }
1340
1341    pub fn get_driver_info(&self, id: i32, name_len: usize) -> Result<(Guid, String), ::RStatus> {
1342        let mut c = Vec::with_capacity(name_len + 1);
1343        let mut guid = ffi::FMOD_GUID {
1344                           Data1: 0,
1345                           Data2: 0,
1346                           Data3: 0,
1347                           Data4: [0, 0, 0, 0, 0, 0, 0, 0],
1348                       };
1349
1350        for _ in 0..(name_len + 1) {
1351            c.push(0);
1352        }
1353
1354        match unsafe { ffi::FMOD_System_GetDriverInfo(self.system, id as c_int,
1355                                                      c.as_mut_ptr() as *mut c_char,
1356                                                      name_len as c_int, &mut guid) } {
1357            ::Status::Ok => Ok((Guid { 
1358                                    data1: guid.Data1,
1359                                    data2: guid.Data2,
1360                                    data3: guid.Data3,
1361                                    data4: guid.Data4,
1362                                 }, from_utf8!(c))),
1363            e => Err(::RStatus::FMOD(e)),
1364        }
1365    }
1366
1367    pub fn get_driver_caps(&self, id: i32) -> Result<(FmodCaps, i32, ::SpeakerMode), ::Status> {
1368        let mut fmod_caps = 0u32;
1369        let mut speaker_mode = ::SpeakerMode::Raw;
1370        let mut control_panel_output_rate = 0i32;
1371
1372        match unsafe { ffi::FMOD_System_GetDriverCaps(self.system, id as c_int, &mut fmod_caps,
1373                                                      &mut control_panel_output_rate as *mut c_int,
1374                                                      &mut speaker_mode) } {
1375            ::Status::Ok => Ok((FmodCaps(fmod_caps), control_panel_output_rate, speaker_mode)),
1376            e => Err(e),
1377        }
1378    }
1379
1380    pub fn set_driver(&self, driver: i32) -> ::Status {
1381        unsafe { ffi::FMOD_System_SetDriver(self.system, driver as c_int) }
1382    }
1383
1384    pub fn get_driver(&self) -> Result<i32, ::Status> {
1385        let mut driver = 0i32;
1386
1387        match unsafe { ffi::FMOD_System_GetDriver(self.system, &mut driver as *mut c_int) } {
1388            ::Status::Ok => Ok(driver),
1389            e => Err(e),
1390        }
1391    }
1392
1393    pub fn set_hardware_channels(&self, num_hardware_channels: i32) -> ::Status {
1394        unsafe { ffi::FMOD_System_SetHardwareChannels(self.system, num_hardware_channels as c_int) }
1395    }
1396
1397    pub fn get_hardware_channels(&self) -> Result<i32, ::Status> {
1398        let mut num_hardware_channels = 0i32;
1399
1400        match unsafe {
1401            ffi::FMOD_System_GetHardwareChannels(self.system,
1402                                                 &mut num_hardware_channels as *mut c_int)
1403        } {
1404            ::Status::Ok => Ok(num_hardware_channels),
1405            e => Err(e),
1406        }
1407    }
1408
1409    pub fn set_software_channels(&self, num_software_channels: i32) -> ::Status {
1410        unsafe { ffi::FMOD_System_SetSoftwareChannels(self.system, num_software_channels as c_int) }
1411    }
1412
1413    pub fn get_software_channels(&self) -> Result<i32, ::Status> {
1414        let mut num_software_channels = 0i32;
1415
1416        match unsafe {
1417            ffi::FMOD_System_GetSoftwareChannels(self.system,
1418                                                 &mut num_software_channels as *mut c_int)
1419        } {
1420            ::Status::Ok => Ok(num_software_channels),
1421            e => Err(e),
1422        }
1423    }
1424
1425    pub fn set_software_format(&self, sample_rate: i32, format: ::SoundFormat,
1426                               num_output_channels: i32, max_input_channels: i32,
1427                               resample_method: ::DspResampler) -> ::Status {
1428        unsafe {
1429            ffi::FMOD_System_SetSoftwareFormat(self.system, sample_rate as c_int, format,
1430                                               num_output_channels as c_int,
1431                                               max_input_channels as c_int, resample_method)
1432        }
1433    }
1434
1435    pub fn get_software_format(&self) -> Result<SoftwareFormat, ::Status> {
1436        let mut t = SoftwareFormat {
1437            sample_rate: 0,
1438            format: ::SoundFormat::None,
1439            num_output_channels: 0,
1440            max_input_channels: 0,
1441            resample_method: ::DspResampler::NoInterp,
1442            bits: 0,
1443        };
1444
1445        match unsafe { ffi::FMOD_System_GetSoftwareFormat(self.system,
1446                                                          &mut t.sample_rate as *mut c_int,
1447                                                          &mut t.format,
1448                                                          &mut t.num_output_channels as *mut c_int,
1449                                                          &mut t.max_input_channels as *mut c_int,
1450                                                          &mut t.resample_method,
1451                                                          &mut t.bits as *mut c_int)
1452        } {
1453            ::Status::Ok => Ok(t),
1454            e => Err(e),
1455        }
1456    }
1457
1458    pub fn set_DSP_buffer_size(&self, buffer_length: u32, num_buffers: i32) -> ::Status {
1459        unsafe { ffi::FMOD_System_SetDSPBufferSize(self.system, buffer_length as c_uint,
1460                                                   num_buffers as c_int) }
1461    }
1462
1463    pub fn get_DSP_buffer_size(&self) -> Result<(u32, i32), ::Status> {
1464        let mut buffer_length = 0u32;
1465        let mut num_buffers = 0i32;
1466
1467        match unsafe { ffi::FMOD_System_GetDSPBufferSize(self.system,
1468                                                         &mut buffer_length as *mut c_uint,
1469                                                         &mut num_buffers as *mut c_int) } {
1470            ::Status::Ok => Ok((buffer_length, num_buffers)),
1471            e => Err(e),
1472        }
1473    }
1474
1475    pub fn set_advanced_settings(&self, settings: &mut AdvancedSettings) -> ::Status {
1476        let mut converted_c_char: Vec<*const c_char> =
1477            (0..settings.ASIO_channel_list.len()).map(|pos| {
1478            settings.ASIO_channel_list[pos].as_ptr() as *const c_char
1479        }).collect();
1480        let deb_log_filename = CString::new(settings.debug_log_filename.clone()).expect("cstring failed");
1481        let mut advanced_settings = ffi::FMOD_ADVANCEDSETTINGS{
1482            cbsize: mem::size_of::<ffi::FMOD_ADVANCEDSETTINGS>() as i32,
1483            maxMPEGcodecs: settings.max_MPEG_codecs,
1484            maxADPCMcodecs: settings.max_ADPCM_codecs,
1485            maxXMAcodecs: settings.max_XMA_codecs,
1486            maxCELTcodecs: settings.max_CELT_codecs,
1487            maxVORBIScodecs: settings.max_VORBIS_codecs,
1488            maxAT9Codecs: settings.max_AT9_codecs,
1489            maxPCMcodecs: settings.max_PCM_codecs,
1490            ASIONumChannels: settings.ASIO_num_channels,
1491            ASIOChannelList: converted_c_char.as_mut_ptr() as *mut *mut c_char,
1492            ASIOSpeakerList: settings.ASIO_speaker_list.as_mut_ptr(),
1493            max3DReverbDSPs: settings.max_3D_reverb_DSPs,
1494            HRTFMinAngle: settings.HRTF_min_angle,
1495            HRTFMaxAngle: settings.HRTF_max_angle,
1496            HRTFFreq: settings.HRTF_freq,
1497            vol0virtualvol: settings.vol0_virtual_vol,
1498            eventqueuesize: settings.event_queue_size,
1499            defaultDecodeBufferSize: settings.default_decode_buffer_size,
1500            debugLogFilename: deb_log_filename.as_ptr() as *mut c_char,
1501            profileport: settings.profile_port,
1502            geometryMaxFadeTime: settings.geometry_max_fade_time,
1503            maxSpectrumWaveDataBuffers: settings.max_spectrum_wave_data_buffers,
1504            musicSystemCacheDelay: settings.music_system_cache_delay,
1505            distanceFilterCenterFreq: settings.distance_filter_center_freq,
1506            stackSizeStream: settings.stack_size_stream,
1507            stackSizeNonBlocking: settings.stack_size_non_blocking,
1508            stackSizeMixer: settings.stack_size_mixer,
1509        };
1510
1511        unsafe { ffi::FMOD_System_SetAdvancedSettings(self.system, &mut advanced_settings) }
1512    }
1513
1514    pub fn get_advanced_settings(&self) -> Result<AdvancedSettings, ::Status> {
1515        let mut advanced_settings = ffi::FMOD_ADVANCEDSETTINGS{
1516            cbsize: mem::size_of::<ffi::FMOD_ADVANCEDSETTINGS>() as i32,
1517            maxMPEGcodecs: 0,
1518            maxADPCMcodecs: 0,
1519            maxXMAcodecs: 0,
1520            maxCELTcodecs: 0,
1521            maxVORBIScodecs: 0,
1522            maxAT9Codecs: 0,
1523            maxPCMcodecs: 0,
1524            ASIONumChannels: 0,
1525            ASIOChannelList: ::std::ptr::null_mut(),
1526            ASIOSpeakerList: ::std::ptr::null_mut(),
1527            max3DReverbDSPs: 0,
1528            HRTFMinAngle: 0f32,
1529            HRTFMaxAngle: 0f32,
1530            HRTFFreq: 0f32,
1531            vol0virtualvol: 0f32,
1532            eventqueuesize: 0,
1533            defaultDecodeBufferSize: 0,
1534            debugLogFilename: ::std::ptr::null_mut(),
1535            profileport: 0,
1536            geometryMaxFadeTime: 0,
1537            maxSpectrumWaveDataBuffers: 0,
1538            musicSystemCacheDelay: 0,
1539            distanceFilterCenterFreq: 0f32,
1540            stackSizeStream: 0,
1541            stackSizeNonBlocking: 0,
1542            stackSizeMixer: 0,
1543        };
1544
1545        match unsafe { ffi::FMOD_System_GetAdvancedSettings(self.system, &mut advanced_settings) } {
1546            ::Status::Ok => {
1547                let mut converted_ASIO_channel_vec = Vec::new();
1548                let mut converted_ASIO_speaker_vec = Vec::new();
1549
1550                unsafe {
1551                    if !advanced_settings.ASIOChannelList.is_null() {
1552                        let mut it = 0;
1553                        loop {
1554                            let tmp = advanced_settings.ASIOChannelList.offset(it);
1555
1556                            if (*tmp).is_null() {
1557                                break;
1558                            }
1559
1560                            let l = ffi::strlen(*tmp);
1561                            
1562                            converted_ASIO_channel_vec.push(
1563                                String::from_raw_parts(*tmp as *mut u8, l, l));
1564                            it += 1;
1565                        }
1566                    }
1567                    if !advanced_settings.ASIOSpeakerList.is_null() {
1568                        let mut it = 0;
1569                        loop {
1570                            let tmp = advanced_settings.ASIOSpeakerList.offset(it);
1571
1572                            if *tmp == ::Speaker::Null {
1573                                break;
1574                            }
1575                            converted_ASIO_speaker_vec.push(*tmp);
1576                            it += 1;
1577                        }
1578                    }
1579                }
1580                Ok(AdvancedSettings {
1581                    max_MPEG_codecs: advanced_settings.maxMPEGcodecs,
1582                    max_ADPCM_codecs: advanced_settings.maxADPCMcodecs,
1583                    max_XMA_codecs: advanced_settings.maxXMAcodecs,
1584                    max_CELT_codecs: advanced_settings.maxCELTcodecs,
1585                    max_VORBIS_codecs: advanced_settings.maxVORBIScodecs,
1586                    max_AT9_codecs: advanced_settings.maxAT9Codecs,
1587                    max_PCM_codecs: advanced_settings.maxPCMcodecs,
1588                    ASIO_num_channels: advanced_settings.ASIONumChannels,
1589                    ASIO_channel_list: converted_ASIO_channel_vec.clone(),
1590                    ASIO_speaker_list: converted_ASIO_speaker_vec,
1591                    max_3D_reverb_DSPs: advanced_settings.max3DReverbDSPs,
1592                    HRTF_min_angle: advanced_settings.HRTFMinAngle,
1593                    HRTF_max_angle: advanced_settings.HRTFMaxAngle,
1594                    HRTF_freq: advanced_settings.HRTFFreq,
1595                    vol0_virtual_vol: advanced_settings.vol0virtualvol,
1596                    event_queue_size: advanced_settings.eventqueuesize,
1597                    default_decode_buffer_size: advanced_settings.defaultDecodeBufferSize,
1598                    debug_log_filename: {
1599                        if !advanced_settings.debugLogFilename.is_null() {
1600                            let l = ffi::strlen(advanced_settings.debugLogFilename);
1601
1602                            unsafe { String::from_raw_parts(
1603                                advanced_settings.debugLogFilename as *mut u8, l, l) }
1604                        } else {
1605                            String::new()
1606                        }
1607                    },
1608                    profile_port: advanced_settings.profileport,
1609                    geometry_max_fade_time: advanced_settings.geometryMaxFadeTime,
1610                    max_spectrum_wave_data_buffers: advanced_settings.maxSpectrumWaveDataBuffers,
1611                    music_system_cache_delay: advanced_settings.musicSystemCacheDelay,
1612                    distance_filter_center_freq: advanced_settings.distanceFilterCenterFreq,
1613                    stack_size_stream: advanced_settings.stackSizeStream,
1614                    stack_size_non_blocking: advanced_settings.stackSizeNonBlocking,
1615                    stack_size_mixer: advanced_settings.stackSizeMixer,
1616                })
1617            }
1618            e => Err(e),
1619        }
1620    }
1621
1622    pub fn set_speaker_mode(&self, speaker_mode: ::SpeakerMode) -> ::Status {
1623        unsafe { ffi::FMOD_System_SetSpeakerMode(self.system, speaker_mode) }
1624    }
1625
1626    pub fn get_speaker_mode(&self) -> Result<::SpeakerMode, ::Status> {
1627        let mut speaker_mode = ::SpeakerMode::Raw;
1628
1629        match unsafe { ffi::FMOD_System_GetSpeakerMode(self.system, &mut speaker_mode) } {
1630            ::Status::Ok => Ok(speaker_mode),
1631            e => Err(e)
1632        }
1633    }
1634
1635    pub fn set_plugin_path(&self, path: &str) -> ::Status {
1636        let tmp_path = CString::new(path).expect("CString failed");
1637
1638        unsafe { ffi::FMOD_System_SetPluginPath(self.system, tmp_path.as_ptr() as *const c_char) }
1639    }
1640
1641    pub fn load_plugin(&self, filename: &str, priority: u32) -> Result<PluginHandle, ::Status> {
1642        let mut handle = 0u32;
1643        let tmp_filename = filename.as_ptr();
1644
1645        match unsafe { ffi::FMOD_System_LoadPlugin(self.system, tmp_filename as *const c_char,
1646                                                   &mut handle as *mut c_uint,
1647                                                   priority as c_uint) } {
1648            ::Status::Ok => Ok(PluginHandle(handle)),
1649            e => Err(e),
1650        }
1651    }
1652
1653    pub fn unload_plugin(&self, PluginHandle(handle): PluginHandle) -> ::Status {
1654        unsafe { ffi::FMOD_System_UnloadPlugin(self.system, handle) }
1655    }
1656
1657    pub fn get_num_plugins(&self, plugin_type: ::PluginType) -> Result<i32, ::Status> {
1658        let mut num_plugins = 0i32;
1659
1660        match unsafe { ffi::FMOD_System_GetNumPlugins(self.system, plugin_type,
1661                                                      &mut num_plugins) } {
1662            ::Status::Ok => Ok(num_plugins),
1663            e => Err(e),
1664        }
1665    }
1666
1667    pub fn get_plugin_handle(&self, plugin_type: ::PluginType,
1668                             index: i32) -> Result<PluginHandle, ::Status> {
1669        let mut handle = 0u32;
1670
1671        match unsafe { ffi::FMOD_System_GetPluginHandle(self.system, plugin_type, index as c_int,
1672                                                        &mut handle as *mut c_uint) } {
1673            ::Status::Ok => Ok(PluginHandle(handle)),
1674            e => Err(e),
1675        }
1676    }
1677
1678    pub fn get_plugin_info(&self, PluginHandle(handle): PluginHandle,
1679                           name_len: usize) -> Result<(String, ::PluginType, u32), ::RStatus> {
1680        let mut plugin_type = ::PluginType::Output;
1681        let mut version = 0u32;
1682        let mut c = Vec::with_capacity(name_len + 1);
1683
1684        for _ in 0..(name_len + 1) {
1685            c.push(0);
1686        }
1687
1688        match unsafe { ffi::FMOD_System_GetPluginInfo(self.system, handle, &mut plugin_type,
1689                                                      c.as_mut_ptr() as *mut c_char,
1690                                                      name_len as c_int,
1691                                                      &mut version as *mut c_uint) } {
1692            ::Status::Ok => Ok((from_utf8!(c), plugin_type, version)),
1693            e => Err(::RStatus::FMOD(e)),
1694        }
1695    }
1696
1697    pub fn set_output_by_plugin(&self, PluginHandle(handle): PluginHandle) -> ::Status {
1698        unsafe { ffi::FMOD_System_SetOutputByPlugin(self.system, handle) }
1699    }
1700
1701    pub fn get_output_by_plugin(&self) -> Result<PluginHandle, ::Status> {
1702        let mut handle = 0u32;
1703
1704        match unsafe { ffi::FMOD_System_GetOutputByPlugin(self.system, &mut handle) } {
1705            ::Status::Ok => Ok(PluginHandle(handle)),
1706            e => Err(e),
1707        }
1708    }
1709
1710    pub fn create_DSP_by_plugin(&self,
1711                                PluginHandle(handle): PluginHandle) -> Result<Dsp, ::Status> {
1712        let mut dsp = ::std::ptr::null_mut();
1713
1714        match unsafe { ffi::FMOD_System_CreateDSPByPlugin(self.system, handle, &mut dsp) } {
1715            ::Status::Ok => Ok(dsp::from_ptr_first(dsp)),
1716            e => Err(e),
1717        }
1718    }
1719
1720    pub fn set_3D_num_listeners(&self, num_listeners: i32) -> ::Status {
1721        unsafe { ffi::FMOD_System_Set3DNumListeners(self.system, num_listeners as c_int) }
1722    }
1723
1724    pub fn get_3D_num_listeners(&self) -> Result<i32, ::Status> {
1725        let mut num_listeners = 0i32;
1726
1727        match unsafe { ffi::FMOD_System_Get3DNumListeners(self.system,
1728                                                          &mut num_listeners as *mut c_int) } {
1729            ::Status::Ok => Ok(num_listeners),
1730            e => Err(e),
1731        }
1732    }
1733
1734    pub fn set_3D_listener_attributes(&self, listener: i32, pos: &vector::Vector,
1735                                      vel: &vector::Vector, forward: &vector::Vector,
1736                                      up: &vector::Vector) -> ::Status {
1737        let c_p = vector::get_ffi(pos);
1738        let c_v = vector::get_ffi(vel);
1739        let c_f = vector::get_ffi(forward);
1740        let c_u = vector::get_ffi(up);
1741
1742        unsafe { ffi::FMOD_System_Set3DListenerAttributes(self.system, listener as c_int, &c_p,
1743                                                          &c_v, &c_f, &c_u) }
1744    }
1745
1746    /// Returns:
1747    ///
1748    /// Ok(position, velocity, forward, up)
1749    pub fn get_3D_listener_attributes(&self, listener: i32)
1750                                      -> Result<(vector::Vector, vector::Vector, vector::Vector,
1751                                                 vector::Vector), ::Status> {
1752        let mut pos = vector::get_ffi(&vector::Vector::new());
1753        let mut vel = vector::get_ffi(&vector::Vector::new());
1754        let mut forward = vector::get_ffi(&vector::Vector::new());
1755        let mut up = vector::get_ffi(&vector::Vector::new());
1756
1757        match unsafe { ffi::FMOD_System_Get3DListenerAttributes(self.system, listener as c_int,
1758                                                                &mut pos, &mut vel, &mut forward,
1759                                                                &mut up) } {
1760            ::Status::Ok => Ok((vector::from_ptr(pos), vector::from_ptr(vel),
1761                                vector::from_ptr(forward), vector::from_ptr(up))),
1762            e => Err(e),
1763        }
1764    }
1765
1766    pub fn set_3D_speaker_position(&self, speaker: ::Speaker, x: f32, y: f32,
1767                                   active: bool) -> ::Status {
1768        let t_active : c_int = match active {
1769            true => 1,
1770            false => 0,
1771        };
1772        unsafe { ffi::FMOD_System_Set3DSpeakerPosition(self.system, speaker, x, y, t_active) }
1773    }
1774
1775    /// Returns:
1776    ///
1777    /// Ok(x, y, is_active)
1778    pub fn get_3D_speaker_position(&self,
1779                                   speaker: ::Speaker) -> Result<(f32, f32, bool), ::Status> {
1780        let mut x = 0f32;
1781        let mut y = 0f32;
1782        let mut active : c_int = 0;
1783
1784        match unsafe { ffi::FMOD_System_Get3DSpeakerPosition(self.system, speaker, &mut x, &mut y,
1785                                                             &mut active) } {
1786            ::Status::Ok => Ok((x, y, match active {
1787                0 => false,
1788                _ => true,
1789            })),
1790            e => Err(e),
1791        }
1792    }
1793
1794    pub fn set_3D_settings(&self, doppler_scale: f32, distance_factor: f32,
1795                           roll_off_scale: f32) -> ::Status {
1796        unsafe { ffi::FMOD_System_Set3DSettings(self.system, doppler_scale, distance_factor,
1797                                                roll_off_scale) }
1798    }
1799
1800    /// Returns:
1801    ///
1802    /// Ok(doppler_scale, distance_factor, roll_off_scale)
1803    pub fn get_3D_settings(&self) -> Result<(f32, f32, f32), ::Status> {
1804        let mut doppler_scale = 0f32;
1805        let mut distance_factor = 0f32;
1806        let mut roll_off_scale = 0f32;
1807
1808        match unsafe { ffi::FMOD_System_Get3DSettings(self.system, &mut doppler_scale,
1809                                                      &mut distance_factor, &mut roll_off_scale) } {
1810            ::Status::Ok => Ok((doppler_scale, distance_factor, roll_off_scale)),
1811            e => Err(e),
1812        }
1813    }
1814
1815    pub fn set_stream_buffer_size(&self, file_buffer_size: u32,
1816                                  TimeUnit(file_buffer_size_type): TimeUnit) -> ::Status {
1817        unsafe { ffi::FMOD_System_SetStreamBufferSize(self.system, file_buffer_size as c_uint,
1818                                                      file_buffer_size_type) }
1819    }
1820
1821    /// Returns:
1822    ///
1823    /// Ok(file_buffer_size, distance_factor, time)
1824    pub fn get_stream_buffer_size(&self) -> Result<(u32, TimeUnit), ::Status> {
1825        let mut file_buffer_size = 0u32;
1826        let mut file_buffer_size_type = 0u32;
1827
1828        match unsafe { ffi::FMOD_System_GetStreamBufferSize(self.system, &mut file_buffer_size,
1829                                                            &mut file_buffer_size_type) } {
1830            ::Status::Ok => Ok((file_buffer_size, TimeUnit(file_buffer_size_type))),
1831            e => Err(e),
1832        }
1833    }
1834
1835    pub fn get_version(&self) -> Result<u32, ::Status> {
1836        let mut version : c_uint = 0;
1837
1838        match unsafe { ffi::FMOD_System_GetVersion(self.system, &mut version) } {
1839            ::Status::Ok => Ok(version as u32),
1840            e => Err(e),
1841        }
1842    }
1843
1844    pub fn get_output_handle(&self) -> Result<OutputHandle, ::Status> {
1845        let mut output_h = ::std::ptr::null_mut();
1846
1847        match unsafe { ffi::FMOD_System_GetOutputHandle(self.system, &mut output_h) } {
1848            ::Status::Ok => Ok(OutputHandle{handle: output_h}),
1849            e => Err(e),
1850        }
1851    }
1852
1853    pub fn get_channels_playing(&self) -> Result<i32, ::Status> {
1854        let mut playing_chans : c_int = 0;
1855
1856        match unsafe { ffi::FMOD_System_GetChannelsPlaying(self.system, &mut playing_chans) } {
1857            ::Status::Ok => Ok(playing_chans as i32),
1858            e => Err(e),
1859        }
1860    }
1861
1862    /// Returns:
1863    ///
1864    /// Ok(dsp, stream, geometry, update, total)
1865    pub fn get_CPU_usage(&self) -> Result<(f32, f32, f32, f32, f32), ::Status> {
1866        let mut dsp = 0f32;
1867        let mut stream = 0f32;
1868        let mut geometry = 0f32;
1869        let mut update = 0f32;
1870        let mut total = 0f32;
1871
1872        match unsafe { ffi::FMOD_System_GetCPUUsage(self.system, &mut dsp, &mut stream,
1873                                                    &mut geometry, &mut update, &mut total) } {
1874            ::Status::Ok => Ok((dsp, stream, geometry, update, total)),
1875            e => Err(e),
1876        }
1877    }
1878
1879    /// Returns:
1880    ///
1881    /// Ok(current_alloced, max_allocated, total)
1882    pub fn get_sound_RAM(&self) -> Result<(i32, i32, i32), ::Status> {
1883        let mut current_alloced : c_int = 0;
1884        let mut max_allocated : c_int = 0;
1885        let mut total : c_int = 0;
1886
1887        match unsafe { ffi::FMOD_System_GetSoundRAM(self.system, &mut current_alloced,
1888                                                    &mut max_allocated, &mut total) } {
1889            ::Status::Ok => Ok((current_alloced as i32, max_allocated as i32, total as i32)),
1890            e => Err(e),
1891        }
1892    }
1893
1894    pub fn get_num_CDROM_drives(&self) -> Result<i32, ::Status> {
1895        let mut num_drives : c_int= 0;
1896
1897        match unsafe { ffi::FMOD_System_GetNumCDROMDrives(self.system, &mut num_drives) } {
1898            ::Status::Ok => Ok(num_drives as i32),
1899            e => Err(e)
1900        }
1901    }
1902
1903    /// Returns:
1904    ///
1905    /// Ok(drive_name, scsi_name, device_name)
1906    pub fn get_CDROM_drive_name(&self, drive: i32, drive_name_len: usize, scsi_name_len: usize,
1907                                device_name_len: usize)
1908                                -> Result<(String, String, String), ::RStatus> {
1909        let mut drive_name = Vec::with_capacity(drive_name_len + 1);
1910        let mut scsi_name = Vec::with_capacity(scsi_name_len + 1);
1911        let mut device_name = Vec::with_capacity(device_name_len + 1);
1912
1913        for _ in 0..(drive_name_len + 1) {
1914            drive_name.push(0);
1915        }
1916        for _ in 0..(scsi_name_len + 1) {
1917            scsi_name.push(0);
1918        }
1919        for _ in 0..(device_name_len + 1) {
1920            device_name.push(0);
1921        }
1922
1923        match unsafe { ffi::FMOD_System_GetCDROMDriveName(self.system, drive as c_int,
1924                                                          drive_name.as_mut_ptr() as *mut c_char,
1925                                                          drive_name_len as c_int,
1926                                                          scsi_name.as_mut_ptr() as *mut c_char,
1927                                                          scsi_name_len as c_int,
1928                                                          device_name.as_mut_ptr() as *mut c_char,
1929                                                          device_name_len as c_int) } {
1930            ::Status::Ok => {
1931                let drive_name = from_utf8!(drive_name);
1932                let scsi_name = from_utf8!(scsi_name);
1933                let device_name = from_utf8!(device_name);
1934                Ok((drive_name, scsi_name, device_name))
1935            }
1936            e => Err(::RStatus::FMOD(e)),
1937        }
1938    }
1939
1940    pub fn get_spectrum(&self, spectrum_size: usize, channel_offset: Option<i32>,
1941                        window_type: Option<::DspFftWindow>) -> Result<Vec<f32>, ::Status> {
1942        let mut ptr : Vec<f32> = ::std::iter::repeat(0f32).take(spectrum_size).collect();
1943        let c_window_type = match window_type {
1944            Some(wt) => wt,
1945            None => ::DspFftWindow::Rect
1946        };
1947        let c_channel_offset : c_int = match channel_offset {
1948            Some(co) => co as c_int,
1949            None => 0
1950        };
1951
1952        match unsafe { ffi::FMOD_System_GetSpectrum(self.system, ptr.as_mut_ptr(),
1953                                                    spectrum_size as c_int, c_channel_offset,
1954                                                    c_window_type) } {
1955            ::Status::Ok => Ok(ptr),
1956            e => Err(e),
1957        }
1958    }
1959
1960    pub fn get_wave_data(&self, wave_size: usize,
1961                         channel_offset: i32) -> Result<Vec<f32>, ::Status> {
1962        let mut ptr : Vec<f32> = ::std::iter::repeat(0f32).take(wave_size).collect();
1963
1964        match unsafe { ffi::FMOD_System_GetWaveData(self.system, ptr.as_mut_ptr(),
1965                                                    wave_size as c_int, channel_offset as c_int) } {
1966            ::Status::Ok => Ok(ptr),
1967            e => Err(e),
1968        }
1969    }
1970    
1971    pub fn get_channel(&self, channel_id: i32) -> Result<channel::Channel, ::Status> {
1972        let mut channel = ::std::ptr::null_mut();
1973
1974        match unsafe { ffi::FMOD_System_GetChannel(self.system, channel_id as c_int,
1975                                                   &mut channel) } {
1976            ::Status::Ok => Ok(ffi::FFI::wrap(channel)),
1977            e => Err(e),
1978        }
1979    }
1980
1981    pub fn get_master_channel_group(&self) -> Result<channel_group::ChannelGroup, ::Status> {
1982        let mut channel_group = ::std::ptr::null_mut();
1983
1984        match unsafe { ffi::FMOD_System_GetMasterChannelGroup(self.system, &mut channel_group) } {
1985            ::Status::Ok => Ok(ffi::FFI::wrap(channel_group)),
1986            e => Err(e),
1987        }
1988    }
1989
1990    pub fn get_master_sound_group(&self) -> Result<sound_group::SoundGroup, ::Status> {
1991        let mut sound_group = ::std::ptr::null_mut();
1992
1993        match unsafe { ffi::FMOD_System_GetMasterSoundGroup(self.system, &mut sound_group) } {
1994            ::Status::Ok => Ok(ffi::FFI::wrap(sound_group)),
1995            e => Err(e),
1996        }
1997    }
1998
1999    pub fn set_reverb_properties(&self,
2000                                 properties: reverb_properties::ReverbProperties) -> ::Status {
2001        let t_properties = reverb_properties::get_ffi(properties);
2002
2003        unsafe { ffi::FMOD_System_SetReverbProperties(self.system, &t_properties) }
2004    }
2005
2006    pub fn get_reverb_properties(&self) -> Result<reverb_properties::ReverbProperties, ::Status> {
2007        let mut properties = reverb_properties::get_ffi(Default::default());
2008
2009        match unsafe { ffi::FMOD_System_GetReverbProperties(self.system, &mut properties) } {
2010            ::Status::Ok => Ok(reverb_properties::from_ptr(properties)),
2011            e => Err(e),
2012        }
2013    }
2014
2015    pub fn set_reverb_ambient_properties(&self, properties: reverb_properties::ReverbProperties)
2016                                         -> ::Status {
2017        let mut t_properties = reverb_properties::get_ffi(properties);
2018
2019        unsafe { ffi::FMOD_System_SetReverbAmbientProperties(self.system, &mut t_properties) }
2020    }
2021
2022    pub fn get_reverb_ambient_properties(&self)
2023                                         -> Result<reverb_properties::ReverbProperties, ::Status> {
2024        let mut properties = reverb_properties::get_ffi(Default::default());
2025
2026        match unsafe { ffi::FMOD_System_GetReverbAmbientProperties(self.system, &mut properties) } {
2027            ::Status::Ok => Ok(reverb_properties::from_ptr(properties)),
2028            e => Err(e),
2029        }
2030    }
2031
2032    pub fn get_DSP_head(&self) -> Result<Dsp, ::Status> {
2033        let mut head = ::std::ptr::null_mut();
2034
2035        match unsafe { ffi::FMOD_System_GetDSPHead(self.system, &mut head) } {
2036            ::Status::Ok => Ok(ffi::FFI::wrap(head)),
2037            e => Err(e),
2038        }
2039    }
2040
2041    pub fn add_DSP(&self, dsp: &dsp::Dsp) -> Result<dsp_connection::DspConnection, ::Status> {
2042        let mut t_connection = ::std::ptr::null_mut();
2043
2044        match unsafe { ffi::FMOD_System_AddDSP(self.system, ffi::FFI::unwrap(dsp),
2045                                               &mut t_connection) } {
2046            ::Status::Ok => Ok(ffi::FFI::wrap(t_connection)),
2047            e => Err(e),
2048        }
2049    }
2050
2051    pub fn lock_DSP(&self) -> ::Status {
2052        unsafe { ffi::FMOD_System_LockDSP(self.system) }
2053    }
2054
2055    pub fn unlock_DSP(&self) -> ::Status {
2056        unsafe { ffi::FMOD_System_UnlockDSP(self.system) }
2057    }
2058
2059    /// Returns:
2060    ///
2061    /// Ok(hi, lo)
2062    pub fn get_DSP_clock(&self) -> Result<(u32, u32), ::Status> {
2063        let mut hi : c_uint = 0;
2064        let mut lo : c_uint = 0;
2065
2066        match unsafe { ffi::FMOD_System_GetDSPClock(self.system, &mut hi, &mut lo) } {
2067            ::Status::Ok => Ok((hi as u32, lo as u32)),
2068            e => Err(e),
2069        }
2070    }
2071
2072    pub fn get_record_num_drivers(&self) -> Result<i32, ::Status> {
2073        let mut num_drivers : c_int = 0;
2074
2075        match unsafe { ffi::FMOD_System_GetRecordNumDrivers(self.system, &mut num_drivers) } {
2076            ::Status::Ok => Ok(num_drivers as i32),
2077            e => Err(e),
2078        }
2079    }
2080
2081    pub fn get_record_driver_info(&self, id: i32,
2082                                  name_len: usize) -> Result<(Guid, String), ::RStatus> {
2083        let mut guid = ffi::FMOD_GUID{
2084            Data1: 0,
2085            Data2: 0,
2086            Data3: 0,
2087            Data4: [0, 0, 0, 0, 0, 0, 0, 0]
2088        };
2089        let mut c = Vec::with_capacity(name_len + 1);
2090
2091        for _ in 0..(name_len + 1) {
2092            c.push(0);
2093        }
2094
2095        match unsafe { ffi::FMOD_System_GetRecordDriverInfo(self.system, id as c_int,
2096                                                            c.as_mut_ptr() as *mut c_char,
2097                                                            name_len as c_int, &mut guid) } {
2098            ::Status::Ok => Ok((Guid {
2099                                    data1: guid.Data1,
2100                                    data2: guid.Data2,
2101                                    data3: guid.Data3,
2102                                    data4: guid.Data4
2103                                }, from_utf8!(c))),
2104            e => Err(::RStatus::FMOD(e)),
2105        }
2106    }
2107
2108    /// Returns:
2109    ///
2110    /// Ok(caps, min_frequency, max_frequency)
2111    pub fn get_record_driver_caps(&self, id: i32) -> Result<(FmodCaps, i32, i32), ::Status> {
2112        let mut fmod_caps : c_uint = 0;
2113        let mut min_frequency : c_int = 0;
2114        let mut max_frequency : c_int = 0;
2115
2116        match unsafe { ffi::FMOD_System_GetRecordDriverCaps(self.system, id as c_int,
2117                                                            &mut fmod_caps, &mut min_frequency,
2118                                                            &mut max_frequency) } {
2119            ::Status::Ok => Ok((FmodCaps(fmod_caps), min_frequency as i32, max_frequency as i32)),
2120            e => Err(e),
2121        }
2122    }
2123
2124    pub fn get_record_position(&self, id: i32) -> Result<u32, ::Status> {
2125        let mut position : c_uint = 0;
2126
2127        match unsafe { ffi::FMOD_System_GetRecordPosition(self.system, id as c_int,
2128                                                          &mut position) } {
2129            ::Status::Ok => Ok(position as u32),
2130            e => Err(e),
2131        }
2132    }
2133
2134    pub fn start_record(&self, id: i32, sound: &sound::Sound, _loop: bool) -> ::Status {
2135        let t_loop = match _loop {
2136            true => 1,
2137            _ => 0,
2138        };
2139
2140        unsafe { ffi::FMOD_System_RecordStart(self.system, id as c_int, ffi::FFI::unwrap(sound),
2141                                              t_loop) }
2142    }
2143
2144    pub fn stop_record(&self, id: i32) -> ::Status {
2145        unsafe { ffi::FMOD_System_RecordStop(self.system, id as c_int) }
2146    }
2147
2148    pub fn is_recording(&self, id: i32) -> Result<bool, ::Status> {
2149        let mut is_recording : c_int = 0;
2150        
2151        match unsafe { ffi::FMOD_System_IsRecording(self.system, id as c_int, &mut is_recording) } {
2152            ::Status::Ok => Ok(is_recording == 1),
2153            e => Err(e),
2154        }
2155    }
2156
2157    pub fn create_geometry(&self, max_polygons: i32,
2158                           max_vertices: i32) -> Result<geometry::Geometry, ::Status> {
2159        let mut geometry = ::std::ptr::null_mut();
2160
2161        match unsafe { ffi::FMOD_System_CreateGeometry(self.system, max_polygons as c_int,
2162                                                       max_vertices as c_int, &mut geometry) } {
2163            ::Status::Ok => Ok(ffi::FFI::wrap(geometry)),
2164            e => Err(e),
2165        }
2166    }
2167
2168    pub fn set_geometry_settings(&self, max_world_size: f32) -> ::Status {
2169        unsafe { ffi::FMOD_System_SetGeometrySettings(self.system, max_world_size) }
2170    }
2171
2172    pub fn get_geometry_settings(&self) -> Result<f32, ::Status> {
2173        let mut max_world_size = 0f32;
2174
2175        match unsafe { ffi::FMOD_System_GetGeometrySettings(self.system, &mut max_world_size) } {
2176            ::Status::Ok => Ok(max_world_size),
2177            e => Err(e),
2178        }
2179    }
2180
2181    /// Returns:
2182    ///
2183    /// Ok(listener, source, direct, reverb)
2184    pub fn get_geometry_occlusion(&self)
2185                                  -> Result<(vector::Vector, vector::Vector, f32, f32), ::Status> {
2186        let listener = vector::get_ffi(&vector::Vector::new());
2187        let source = vector::get_ffi(&vector::Vector::new());
2188        let mut direct = 0f32;
2189        let mut reverb = 0f32;
2190
2191        match unsafe { ffi::FMOD_System_GetGeometryOcclusion(self.system, &listener, &source,
2192                                                             &mut direct, &mut reverb) } {
2193            ::Status::Ok => Ok((vector::from_ptr(listener),
2194                                vector::from_ptr(source), direct, reverb)),
2195            e => Err(e),
2196        }
2197    }
2198
2199    /// Returns:
2200    ///
2201    /// Ok(memory_used, details)
2202    pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits,
2203                           EventMemoryBits(event_memory_bits): EventMemoryBits)
2204                           -> Result<(u32, MemoryUsageDetails), ::Status> {
2205        let mut details = get_memory_usage_details_ffi(Default::default());
2206        let mut memory_used : c_uint = 0;
2207
2208        match unsafe { ffi::FMOD_System_GetMemoryInfo(self.system, memory_bits, event_memory_bits,
2209                                                      &mut memory_used, &mut details) } {
2210            ::Status::Ok => Ok((memory_used as u32, from_memory_usage_details_ptr(details))),
2211            e => Err(e),
2212        }
2213    }
2214
2215    pub fn set_file_system(&self, user_open: FileOpenCallback, user_close: FileCloseCallback,
2216                           user_read: FileReadCallback, user_seek: FileSeekCallback,/*
2217                           user_async_read: ffi::FMOD_FILE_ASYNCREADCALLBACK,
2218                           user_async_cancel: ffi::FMOD_FILE_ASYNCCANCELCALLBACK,*/
2219                           block_align: i32) -> ::Status {
2220        let tmp = get_saved_sys_callback();
2221
2222        tmp.file_open = user_open;
2223        tmp.file_read = user_read;
2224        tmp.file_close = user_close;
2225        tmp.file_seek = user_seek;
2226        unsafe { ffi::FMOD_System_SetFileSystem(self.system,
2227            match user_open {
2228                Some(_) => Some(file_open_callback as extern "C" fn(*mut _, _, *mut _, *mut *mut _,
2229                                                                    *mut *mut _) -> _),
2230                None => None
2231            },
2232            match user_close {
2233                Some(_) => Some(file_close_callback as extern "C" fn(*mut _, *mut _) -> _),
2234                None => None
2235            },
2236            match user_read {
2237                Some(_) => Some(file_read_callback as extern "C" fn(*mut _, *mut _, _, *mut _,
2238                                                                    *mut _) -> _),
2239                None => None
2240            },
2241            match user_seek {
2242                Some(_) => Some(file_seek_callback as extern "C" fn(*mut _, _, *mut _) -> _),
2243                None => None
2244            },
2245            None,
2246            None,
2247            block_align)
2248        }
2249    }
2250}