1use types::*;
26use libc::{c_int, c_uint, c_char, c_ushort, c_void};
27use ffi;
28use channel;
29use sound_group;
30use vector;
31use fmod_sys;
32use fmod_sys::{MemoryUsageDetails, Sys};
33use std::mem::transmute;
34use std::fs::File;
35use std::mem;
36use std::slice;
37use std::default::Default;
38use byteorder::{WriteBytesExt, LittleEndian};
39use std::io::Write;
40use std::ffi::CString;
41use std::time::Duration;
42
43struct RiffChunk {
44 id: [c_char; 4],
45 size: c_int
46}
47
48struct FmtChunk {
49 chunk: RiffChunk,
50 w_format_tag: c_ushort, n_channels: c_ushort, n_samples_per_sec: c_uint, n_avg_bytes_per_sec: c_uint,n_block_align: c_ushort, w_bits_per_sample: c_ushort }
57
58struct DataChunk {
59 chunk: RiffChunk
60}
61
62struct WavHeader {
63 chunk: RiffChunk,
64 riff_type: [c_char; 4]
65}
66
67pub struct FmodSyncPoint {
69 sync_point: *mut ffi::FMOD_SYNCPOINT
70}
71
72impl FmodSyncPoint {
73 fn from_ptr(pointer: *mut ffi::FMOD_SYNCPOINT) -> FmodSyncPoint {
74 FmodSyncPoint{sync_point: pointer}
75 }
76}
77
78pub struct FmodTag {
80 pub _type : ::TagType,
82 pub data_type: ::TagDataType,
84 pub name : String,
86 data : *mut c_void,
88 data_len : c_uint,
90 pub updated : bool,
93}
94
95impl Default for FmodTag {
96 fn default() -> FmodTag {
97 FmodTag {
98 _type: ::TagType::Unknown,
99 data_type: ::TagDataType::Binary,
100 name: String::new(),
101 data: ::std::ptr::null_mut(),
102 data_len: 0u32,
103 updated: false,
104 }
105 }
106}
107
108impl FmodTag {
109 fn from_ptr(pointer: ffi::FMOD_TAG) -> FmodTag {
110 FmodTag{
111 _type: pointer._type,
112 data_type: pointer.datatype,
113 name: {
114 if !pointer.name.is_null() {
115 let l = ffi::strlen(pointer.name);
116
117 unsafe { String::from_raw_parts(pointer.name as *mut u8, l, l) }
118 } else {
119 String::new()
120 }
121 },
122 data: pointer.data,
123 data_len: pointer.datalen,
124 updated: {
125 if pointer.updated == 1 {
126 true
127 } else {
128 false
129 }
130 },
131 }
132 }
133
134 fn convert_to_c(&self) -> ffi::FMOD_TAG {
135 let tmp = CString::new(self.name.clone()).expect("CString failed");
136
137 ffi::FMOD_TAG {
138 _type: self._type,
139 datatype: self.data_type,
140 name: tmp.as_ptr() as *mut c_char,
141 data: self.data,
142 datalen: self.data_len,
143 updated: {
144 if self.updated == true {
145 1
146 } else {
147 0
148 }
149 },
150 }
151 }
152}
153
154pub struct Sound {
156 sound: *mut ffi::FMOD_SOUND,
157 can_be_deleted: bool,
158 user_data: ffi::SoundData,
159}
160
161impl ffi::FFI<ffi::FMOD_SOUND> for Sound {
162 fn wrap(s: *mut ffi::FMOD_SOUND) -> Sound {
163 Sound {sound: s, can_be_deleted: false, user_data: ffi::SoundData::new()}
164 }
165
166 fn unwrap(s: &Sound) -> *mut ffi::FMOD_SOUND {
167 s.sound
168 }
169}
170
171pub fn get_fffi<'r>(sound: &'r mut Sound) -> &'r mut *mut ffi::FMOD_SOUND {
172 &mut sound.sound
173}
174
175pub fn from_ptr_first(sound: *mut ffi::FMOD_SOUND) -> Sound {
176 Sound{sound: sound, can_be_deleted: true, user_data: ffi::SoundData::new()}
177}
178
179pub fn get_user_data<'r>(sound: &'r mut Sound) -> &'r mut ffi::SoundData {
180 &mut sound.user_data
181}
182
183impl Drop for Sound {
184 fn drop(&mut self) {
185 self.release();
186 }
187}
188
189impl Sound {
190 pub fn get_system_object(&self) -> Result<Sys, ::Status> {
191 let mut system = ::std::ptr::null_mut();
192
193 match unsafe { ffi::FMOD_Sound_GetSystemObject(self.sound, &mut system) } {
194 ::Status::Ok => Ok(ffi::FFI::wrap(system)),
195 e => Err(e),
196 }
197 }
198
199 pub fn release(&mut self) -> ::Status {
200 if self.can_be_deleted && !self.sound.is_null() {
201 match unsafe { ffi::FMOD_Sound_Release(self.sound) } {
202 ::Status::Ok => {
203 self.sound = ::std::ptr::null_mut();
204 ::Status::Ok
205 }
206 e => e,
207 }
208 } else {
209 ::Status::Ok
210 }
211 }
212
213 pub fn play(&self) -> Result<channel::Channel, ::Status> {
214 let mut channel = ::std::ptr::null_mut();
215
216 match match self.get_system_object() {
217 Ok(s) => {
218 unsafe { ffi::FMOD_System_PlaySound(ffi::FFI::unwrap(&s), ::ChannelIndex::Free, self.sound, 0, &mut channel) }
219 }
220 Err(e) => e,
221 } {
222 ::Status::Ok => Ok(ffi::FFI::wrap(channel)),
223 e => Err(e),
224 }
225 }
226
227 pub fn play_with_parameters(&self, paused: bool, channel: &mut channel::Channel) -> ::Status {
228 let mut chan = ffi::FFI::unwrap(channel);
229
230 match self.get_system_object() {
231 Ok(s) => {
232 unsafe { ffi::FMOD_System_PlaySound(ffi::FFI::unwrap(&s), ::ChannelIndex::ReUse, self.sound, match paused {
233 true => 1,
234 false => 0,
235 }, &mut chan) }
236 }
237 Err(e) => e,
238 }
239 }
240
241 pub fn play_to_the_end(&self) -> ::Status {
242 match self.play() {
243 Ok(mut chan) => {
244 loop {
245 match chan.is_playing() {
246 Ok(b) => {
247 if b == true {
248 ::std::thread::sleep(Duration::from_millis(30))
249 } else {
250 break;
251 }
252 },
253 Err(e) => return e,
254 }
255 }
256 chan.release();
257 ::Status::Ok
258 }
259 Err(err) => err,
260 }
261 }
262
263 pub fn set_defaults(&self, frequency: f32, volume: f32, pan: f32, priority: i32) -> ::Status {
264 unsafe { ffi::FMOD_Sound_SetDefaults(self.sound, frequency, volume, pan, priority) }
265 }
266
267 pub fn get_defaults(&self) -> Result<(f32, f32, f32, i32), ::Status> {
268 let mut frequency = 0f32;
269 let mut volume = 0f32;
270 let mut pan = 0f32;
271 let mut priority = 0i32;
272
273 match unsafe { ffi::FMOD_Sound_GetDefaults(self.sound, &mut frequency, &mut volume,
274 &mut pan, &mut priority) } {
275 ::Status::Ok => Ok((frequency, volume, pan, priority)),
276 e => Err(e),
277 }
278 }
279
280 pub fn set_variations(&self, frequency_var: f32, volume_var: f32, pan_var: f32) -> ::Status {
281 unsafe { ffi::FMOD_Sound_SetVariations(self.sound, frequency_var, volume_var, pan_var) }
282 }
283
284 pub fn get_variations(&self) -> Result<(f32, f32, f32), ::Status> {
288 let mut frequency_var = 0f32;
289 let mut volume_var = 0f32;
290 let mut pan_var = 0f32;
291
292 match unsafe { ffi::FMOD_Sound_GetVariations(self.sound, &mut frequency_var,
293 &mut volume_var, &mut pan_var) } {
294 ::Status::Ok => Ok((frequency_var, volume_var, pan_var)),
295 e => Err(e),
296 }
297 }
298
299 pub fn set_3D_min_max_distance(&self, min: f32, max: f32) -> ::Status {
300 unsafe { ffi::FMOD_Sound_Set3DMinMaxDistance(self.sound, min, max) }
301 }
302
303 pub fn get_3D_min_max_distance(&self) -> Result<(f32, f32), ::Status> {
307 let mut max = 0f32;
308 let mut min = 0f32;
309
310 match unsafe { ffi::FMOD_Sound_Get3DMinMaxDistance(self.sound, &mut min, &mut max) } {
311 ::Status::Ok => Ok((min, max)),
312 e => Err(e),
313 }
314 }
315
316 pub fn set_3D_cone_settings(&self, inside_cone_angle: f32, outside_cone_angle: f32,
317 outside_volume: f32) -> ::Status {
318 unsafe { ffi::FMOD_Sound_Set3DConeSettings(self.sound, inside_cone_angle,
319 outside_cone_angle, outside_volume) }
320 }
321
322 pub fn get_3D_cone_settings(&self) -> Result<(f32, f32, f32), ::Status> {
326 let mut inside_cone_angle = 0f32;
327 let mut outside_cone_angle = 0f32;
328 let mut outside_volume = 0f32;
329
330 match unsafe { ffi::FMOD_Sound_Get3DConeSettings(self.sound, &mut inside_cone_angle,
331 &mut outside_cone_angle,
332 &mut outside_volume) } {
333 ::Status::Ok => Ok((inside_cone_angle, outside_cone_angle, outside_volume)),
334 e => Err(e),
335 }
336 }
337
338 pub fn set_3D_custom_rolloff(&self, points: Vec<vector::Vector>) -> ::Status {
339 let mut points_vec = Vec::with_capacity(points.len());
340
341 for tmp in points.into_iter() {
342 points_vec.push(vector::get_ffi(&tmp));
343 }
344 unsafe { ffi::FMOD_Sound_Set3DCustomRolloff(self.sound, points_vec.as_mut_ptr(),
345 points_vec.len() as i32) }
346 }
347
348 pub fn get_3D_custom_rolloff(&self, num_points: u32) -> Result<Vec<vector::Vector>, ::Status> {
350 let mut points_vec = Vec::with_capacity(num_points as usize);
351 let mut pointer = points_vec.as_mut_ptr();
352
353 match unsafe { ffi::FMOD_Sound_Get3DCustomRolloff(self.sound, &mut pointer,
354 num_points as i32) } {
355 ::Status::Ok => {
356 let mut points = Vec::with_capacity(points_vec.len());
357
358 for tmp in points_vec.into_iter() {
359 points.push(vector::from_ptr(tmp));
360 }
361 Ok(points)
362 }
363 e => Err(e),
364 }
365 }
366
367 pub fn set_sub_sound(&self, index: i32, sub_sound: Sound) -> ::Status {
368 unsafe { ffi::FMOD_Sound_SetSubSound(self.sound, index, sub_sound.sound) }
369 }
370
371 pub fn get_sub_sound(&self, index: i32) -> Result<Sound, ::Status> {
372 let mut sub_sound = ::std::ptr::null_mut();
373
374 match unsafe { ffi::FMOD_Sound_GetSubSound(self.sound, index, &mut sub_sound) } {
375 ::Status::Ok => Ok(ffi::FFI::wrap(sub_sound)),
376 e => Err(e),
377 }
378 }
379
380 pub fn get_name(&self, name_len: usize) -> Result<String, ::RStatus> {
381 let mut c = Vec::with_capacity(name_len + 1);
382
383 for _ in 0..(name_len + 1) {
384 c.push(0);
385 }
386
387 match unsafe { ffi::FMOD_Sound_GetName(self.sound, c.as_mut_ptr() as *mut c_char,
388 name_len as i32) } {
389 ::Status::Ok => Ok(from_utf8!(c)),
390 e => Err(::RStatus::FMOD(e)),
391 }
392 }
393
394 pub fn get_length(&self, TimeUnit(length_type): TimeUnit) -> Result<u32, ::Status> {
395 let mut length = 0u32;
396
397 match unsafe { ffi::FMOD_Sound_GetLength(self.sound, &mut length, length_type) } {
398 ::Status::Ok => Ok(length),
399 e => Err(e),
400 }
401 }
402
403 pub fn get_format(&self) -> Result<(::SoundType, ::SoundFormat, i32, i32), ::Status> {
407 let mut _type = ::SoundType::Unknown;
408 let mut format = ::SoundFormat::None;
409 let mut channels = 0i32;
410 let mut bits = 0i32;
411
412 match unsafe { ffi::FMOD_Sound_GetFormat(self.sound, &mut _type, &mut format, &mut channels,
413 &mut bits) } {
414 ::Status::Ok => Ok((_type, format, channels, bits)),
415 e => Err(e),
416 }
417 }
418
419 pub fn get_num_sub_sounds(&self) -> Result<i32, ::Status> {
420 let mut num_sub_sound = 0i32;
421
422 match unsafe { ffi::FMOD_Sound_GetNumSubSounds(self.sound, &mut num_sub_sound) } {
423 ::Status::Ok => Ok(num_sub_sound),
424 e => Err(e),
425 }
426 }
427
428 pub fn get_num_tags(&self) -> Result<(i32, i32), ::Status> {
432 let mut num_tags = 0i32;
433 let mut num_tags_updated = 0i32;
434
435 match unsafe { ffi::FMOD_Sound_GetNumTags(self.sound, &mut num_tags, &mut num_tags_updated) } {
436 ::Status::Ok => Ok((num_tags, num_tags_updated)),
437 e => Err(e),
438 }
439 }
440
441 pub fn get_tag(&self, name: &str, index: i32) -> Result<FmodTag, ::Status> {
443 let mut tag = ffi::FMOD_TAG {
444 _type: ::TagType::Unknown,
445 datatype: ::TagDataType::Binary,
446 name: ::std::ptr::null_mut(),
447 data: ::std::ptr::null_mut(),
448 datalen: 0,
449 updated: 0,
450 };
451
452 match unsafe { ffi::FMOD_Sound_GetTag(self.sound, name.as_ptr() as *const c_char, index,
453 &mut tag) } {
454 ::Status::Ok => Ok(FmodTag::from_ptr(tag)),
455 e => Err(e),
456 }
457 }
458
459 pub fn get_open_state(&self) -> Result<(::OpenState, u32, bool, bool), ::Status> {
460 let mut open_state = ::OpenState::Ready;
461 let mut percent_buffered = 0u32;
462 let mut starving = 0;
463 let mut disk_busy = 0;
464
465 match unsafe { ffi::FMOD_Sound_GetOpenState(self.sound, &mut open_state,
466 &mut percent_buffered, &mut starving,
467 &mut disk_busy) } {
468 ::Status::Ok => Ok((open_state, percent_buffered,
469 if starving == 1 {
470 true
471 } else {
472 false
473 },
474 if disk_busy == 1 {
475 true
476 } else {
477 false
478 })),
479 e => Err(e),
480 }
481 }
482
483 pub fn set_sound_group(&self, sound_group: sound_group::SoundGroup) -> ::Status {
484 unsafe { ffi::FMOD_Sound_SetSoundGroup(self.sound, ffi::FFI::unwrap(&sound_group)) }
485 }
486
487 pub fn get_sound_group(&self) -> Result<sound_group::SoundGroup, ::Status> {
488 let mut sound_group = ::std::ptr::null_mut();
489
490 match unsafe { ffi::FMOD_Sound_GetSoundGroup(self.sound, &mut sound_group) } {
491 ::Status::Ok => Ok(ffi::FFI::wrap(sound_group)),
492 e => Err(e),
493 }
494 }
495
496 pub fn get_num_sync_points(&self) -> Result<i32, ::Status> {
497 let mut num_sync_points = 0i32;
498
499 match unsafe { ffi::FMOD_Sound_GetNumSyncPoints(self.sound, &mut num_sync_points) } {
500 ::Status::Ok => Ok(num_sync_points),
501 e => Err(e),
502 }
503 }
504
505 pub fn get_sync_point(&self, index: i32) -> Result<FmodSyncPoint, ::Status> {
506 let mut sync_point = ::std::ptr::null_mut();
507
508 match unsafe { ffi::FMOD_Sound_GetSyncPoint(self.sound, index, &mut sync_point) } {
509 ::Status::Ok => Ok(FmodSyncPoint::from_ptr(sync_point)),
510 e => Err(e),
511 }
512 }
513
514 pub fn get_sync_point_info(&self, sync_point: FmodSyncPoint, name_len: usize,
515 TimeUnit(offset_type): TimeUnit) -> Result<(String, u32), ::RStatus> {
516 let mut offset = 0u32;
517 let mut c = Vec::with_capacity(name_len + 1);
518
519 for _ in 0..(name_len + 1) {
520 c.push(0);
521 }
522
523 match unsafe { ffi::FMOD_Sound_GetSyncPointInfo(self.sound, sync_point.sync_point,
524 c.as_mut_ptr() as *mut c_char,
525 name_len as i32, &mut offset,
526 offset_type) } {
527 ::Status::Ok => Ok((from_utf8!(c), offset)),
528 e => Err(::RStatus::FMOD(e)),
529 }
530 }
531
532 pub fn add_sync_point(&self, offset: u32, TimeUnit(offset_type): TimeUnit,
533 name: String) -> Result<FmodSyncPoint, ::Status> {
534 let mut sync_point = ::std::ptr::null_mut();
535
536 match unsafe { ffi::FMOD_Sound_AddSyncPoint(self.sound, offset, offset_type,
537 name.as_ptr() as *const c_char,
538 &mut sync_point) } {
539 ::Status::Ok => Ok(FmodSyncPoint::from_ptr(sync_point)),
540 e => Err(e),
541 }
542 }
543
544 pub fn delete_sync_point(&self, sync_point: FmodSyncPoint) -> ::Status {
545 unsafe { ffi::FMOD_Sound_DeleteSyncPoint(self.sound, sync_point.sync_point) }
546 }
547
548 pub fn set_mode(&self, Mode(mode): Mode) -> ::Status {
549 unsafe { ffi::FMOD_Sound_SetMode(self.sound, mode) }
550 }
551
552 pub fn get_mode(&self) -> Result<Mode, ::Status> {
553 let mut mode = 0u32;
554
555 match unsafe { ffi::FMOD_Sound_GetMode(self.sound, &mut mode) } {
556 ::Status::Ok => Ok(Mode(mode)),
557 e => Err(e),
558 }
559 }
560
561 pub fn set_loop_count(&self, loop_count: i32) -> ::Status {
562 unsafe { ffi::FMOD_Sound_SetLoopCount(self.sound, loop_count) }
563 }
564
565 pub fn get_loop_count(&self) -> Result<i32, ::Status> {
566 let mut loop_count = 0i32;
567
568 match unsafe { ffi::FMOD_Sound_GetLoopCount(self.sound, &mut loop_count) } {
569 ::Status::Ok => Ok(loop_count),
570 e => Err(e),
571 }
572 }
573
574 pub fn set_loop_points(&self, loop_start: u32, TimeUnit(loop_start_type): TimeUnit,
575 loop_end: u32, TimeUnit(loop_end_type): TimeUnit) -> ::Status {
576 unsafe { ffi::FMOD_Sound_SetLoopPoints(self.sound, loop_start, loop_start_type, loop_end,
577 loop_end_type) }
578 }
579
580 pub fn get_loop_points(&self, TimeUnit(loop_start_type): TimeUnit,
584 TimeUnit(loop_end_type): TimeUnit) -> Result<(u32, u32), ::Status> {
585 let mut loop_start = 0u32;
586 let mut loop_end = 0u32;
587
588 match unsafe { ffi::FMOD_Sound_GetLoopPoints(self.sound, &mut loop_start, loop_start_type,
589 &mut loop_end, loop_end_type) } {
590 ::Status::Ok => Ok((loop_start, loop_end)),
591 e => Err(e)
592 }
593 }
594
595 pub fn get_num_channels(&self) -> Result<i32, ::Status> {
596 let mut num_channels = 0i32;
597
598 match unsafe { ffi::FMOD_Sound_GetMusicNumChannels(self.sound, &mut num_channels) } {
599 ::Status::Ok => Ok(num_channels),
600 e => Err(e)
601 }
602 }
603
604 pub fn set_music_channel_volume(&self, channel: i32, volume: f32) -> ::Status {
606 unsafe { ffi::FMOD_Sound_SetMusicChannelVolume(self.sound, channel, volume) }
607 }
608
609 pub fn get_music_channel_volume(&self, channel: i32) -> Result<f32, ::Status> {
611 let mut volume = 0f32;
612
613 match unsafe { ffi::FMOD_Sound_GetMusicChannelVolume(self.sound, channel, &mut volume) } {
614 ::Status::Ok => Ok(volume),
615 e => Err(e)
616 }
617 }
618
619 pub fn set_music_speed(&self, speed: f32) -> ::Status {
620 unsafe { ffi::FMOD_Sound_SetMusicSpeed(self.sound, speed) }
621 }
622
623 pub fn get_music_speed(&self) -> Result<f32, ::Status> {
624 let mut speed = 0f32;
625
626 match unsafe { ffi::FMOD_Sound_GetMusicSpeed(self.sound, &mut speed) } {
627 ::Status::Ok => Ok(speed),
628 e => Err(e),
629 }
630 }
631
632 pub fn set_sub_sound_sentence(&self, sub_sounds: &mut Vec<i32>) -> ::Status {
633 unsafe { ffi::FMOD_Sound_SetSubSoundSentence(self.sound, sub_sounds.as_mut_ptr(),
634 sub_sounds.len() as c_int) }
635 }
636
637 pub fn seek_data(&self, pcm: u32) -> ::Status {
638 unsafe { ffi::FMOD_Sound_SeekData(self.sound, pcm) }
639 }
640
641 pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits,
645 EventMemoryBits(event_memory_bits): EventMemoryBits)
646 -> Result<(u32, MemoryUsageDetails), ::Status> {
647 let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default());
648 let mut memory_used = 0u32;
649
650 match unsafe { ffi::FMOD_Sound_GetMemoryInfo(self.sound, memory_bits, event_memory_bits,
651 &mut memory_used, &mut details) } {
652 ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))),
653 e => Err(e),
654 }
655 }
656
657 pub fn lock(&self, offset: u32, length: u32) -> Result<(Vec<u8>, Vec<u8>), ::Status> {
666 let mut len1 = 0u32;
667 let mut len2 = 0u32;
668 let mut ptr1 = ::std::ptr::null_mut();
669 let mut ptr2 = ::std::ptr::null_mut();
670
671 match unsafe { ffi::FMOD_Sound_Lock(self.sound, offset, length, &mut ptr1, &mut ptr2,
672 &mut len1, &mut len2) } {
673 ::Status::Ok => {
674 unsafe {
675 Ok((slice::from_raw_parts(ptr1 as *const u8, len1 as usize).clone().to_vec(),
676 slice::from_raw_parts(ptr2 as *const u8, len2 as usize).clone().to_vec()))
677 }
678 }
679 e => Err(e),
680 }
681 }
682
683 pub fn unlock(&self, v_ptr1: Vec<u8>, v_ptr2: Vec<u8>) -> ::Status {
684 unsafe { ffi::FMOD_Sound_Unlock(self.sound, v_ptr1.as_ptr() as *mut c_void,
685 v_ptr2.as_ptr() as *mut c_void, v_ptr1.len() as c_uint,
686 v_ptr2.len() as c_uint) }
687 }
688
689 pub fn set_user_data<'r, T>(&'r mut self, user_data: &'r mut T) -> ::Status {
690 let mut data : *mut c_void = ::std::ptr::null_mut();
691
692 unsafe {
693 match ffi::FMOD_Sound_GetUserData(self.sound, &mut data) {
694 ::Status::Ok => {
695 if data.is_null() {
696 self.user_data.user_data = ::std::ptr::null_mut();
697
698 ffi::FMOD_Sound_SetUserData(self.sound, transmute(&mut self.user_data))
699 } else {
700 let tmp: &mut ffi::SoundData =
701 transmute::<*mut c_void, &mut ffi::SoundData>(data);
702
703 tmp.user_data = transmute::<&mut T, *mut c_void>(user_data);
704 ffi::FMOD_Sound_SetUserData(self.sound, transmute(tmp))
705 }
706 }
707 _ => {
708 self.user_data.user_data = transmute::<&mut T, *mut c_void>(user_data);
709
710 ffi::FMOD_Sound_SetUserData(self.sound, transmute(&mut self.user_data))
711 }
712 }
713 }
714 }
715
716 pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> {
717 unsafe {
718 let mut user_data : *mut c_void = ::std::ptr::null_mut();
719
720 match ffi::FMOD_Sound_GetUserData(self.sound, &mut user_data) {
721 ::Status::Ok => {
722 if !user_data.is_null() {
723 let tmp: &mut ffi::SoundData =
724 transmute::<*mut c_void, &mut ffi::SoundData>(user_data);
725 let tmp2: &mut T = transmute::<*mut c_void, &mut T>(tmp.user_data);
726
727 Ok(tmp2)
728 } else {
729 Err(::Status::Ok)
731 }
732 },
733 e => Err(e)
734 }
735 }
736 }
737
738 pub fn save_to_wav(&self, file_name: &str) -> Result<bool, String> {
739 unsafe {
740 let mut channels = 0i32;
741 let mut bits = 0i32;
742 let mut rate = 0f32;
743 let len_bytes = match self.get_length(::TIMEUNIT_PCMBYTES) {
744 Ok(l) => l,
745 Err(e) => return Err(format!("{:?}", e))
746 };
747 let mut len1 = 0u32;
748 let mut len2 = 0u32;
749 let mut ptr1: *mut c_void =::std::ptr::null_mut();
750 let mut ptr2: *mut c_void =::std::ptr::null_mut();
751
752 match ffi::FMOD_Sound_GetFormat(self.sound, ::std::ptr::null_mut(),
753 ::std::ptr::null_mut(), &mut channels, &mut bits) {
754 ::Status::Ok => match ffi::FMOD_Sound_GetDefaults(self.sound, &mut rate,
755 ::std::ptr::null_mut(),
756 ::std::ptr::null_mut(),
757 ::std::ptr::null_mut()) {
758 ::Status::Ok => {}
759 e => return Err(format!("{:?}", e))
760 },
761 e => return Err(format!("{:?}", e))
762 };
763 let fmt_chunk = FmtChunk {
764 chunk: RiffChunk {
765 id: ['f' as i8, 'm' as i8, 't' as i8, ' ' as i8],
766 size: mem::size_of::<FmtChunk>() as i32 - mem::size_of::<RiffChunk>() as i32
767 },
768 w_format_tag: 1,
769 n_channels: channels as u16,
770 n_samples_per_sec: rate as u32,
771 n_avg_bytes_per_sec: rate as u32 * channels as u32 * bits as u32 / 8u32,
772 n_block_align: 1u16 * channels as u16 * bits as u16 / 8u16,
773 w_bits_per_sample: bits as u16
774 };
775 let data_chunk = DataChunk {
776 chunk: RiffChunk {
777 id: ['d' as i8, 'a' as i8, 't' as i8, 'a' as i8],
778 size: len_bytes as i32
779 }
780 };
781 let wav_header = WavHeader {
782 chunk: RiffChunk {
783 id: ['R' as i8, 'I' as i8, 'F' as i8, 'F' as i8],
784 size: mem::size_of::<FmtChunk>() as i32 + mem::size_of::<RiffChunk>() as i32 + len_bytes as i32
785 },
786 riff_type: ['W' as i8, 'A' as i8, 'V' as i8, 'E' as i8]
787 };
788
789 let mut file = match File::create(file_name) {
790 Ok(f) => f,
791 Err(e) => return Err(format!("{}", e))
792 };
793 let mut wtr = vec![];
794
795 for it in 0usize..4usize {
797 if let Err(e) = wtr.write_i8(wav_header.chunk.id[it]) {
798 return Err(format!("write_i8 failed: {}", e));
799 }
800 }
801 if let Err(e) = wtr.write_i32::<LittleEndian>(wav_header.chunk.size) {
802 return Err(format!("write_i32 failed: {}", e));
803 }
804 for it in 0usize..4usize {
805 if let Err(e) = wtr.write_i8(wav_header.riff_type[it]) {
806 return Err(format!("write_i8 failed: {}", e));
807 }
808 }
809
810 for it in 0usize..4usize {
812 if let Err(e) = wtr.write_i8(fmt_chunk.chunk.id[it]) {
813 return Err(format!("write_i8 failed: {}", e));
814 }
815 }
816 if let Err(e) = wtr.write_i32::<LittleEndian>(fmt_chunk.chunk.size) {
817 return Err(format!("write_i32 failed: {}", e));
818 }
819 if let Err(e) = wtr.write_u16::<LittleEndian>(fmt_chunk.w_format_tag) {
820 return Err(format!("write_u16 failed: {}", e));
821 }
822 if let Err(e) = wtr.write_u16::<LittleEndian>(fmt_chunk.n_channels) {
823 return Err(format!("write_u16 failed: {}", e));
824 }
825 if let Err(e) = wtr.write_u32::<LittleEndian>(fmt_chunk.n_samples_per_sec) {
826 return Err(format!("write_u32 failed: {}", e));
827 }
828 if let Err(e) = wtr.write_u32::<LittleEndian>(fmt_chunk.n_avg_bytes_per_sec) {
829 return Err(format!("write_u32 failed: {}", e));
830 }
831 if let Err(e) = wtr.write_u16::<LittleEndian>(fmt_chunk.n_block_align) {
832 return Err(format!("write_u16 failed: {}", e));
833 }
834 if let Err(e) = wtr.write_u16::<LittleEndian>(fmt_chunk.w_bits_per_sample) {
835 return Err(format!("write_u16 failed: {}", e));
836 }
837
838 for it in 0usize..4usize {
840 if let Err(e) = wtr.write_i8(data_chunk.chunk.id[it]) {
841 return Err(format!("write_i8 failed: {}", e));
842 }
843 }
844 if let Err(e) = wtr.write_i32::<LittleEndian>(data_chunk.chunk.size) {
845 return Err(format!("write_i32 failed: {}", e));
846 }
847
848 ffi::FMOD_Sound_Lock(self.sound, 0, len_bytes, &mut ptr1, &mut ptr2, &mut len1, &mut len2);
849
850 if let Err(e) = file.write_all(&wtr) {
851 return Err(format!("write_all failed: {}", e));
852 }
853
854 ffi::FMOD_Sound_Unlock(self.sound, ptr1, ptr2, len1, len2);
855 }
856 Ok(true)
857 }
858}