1use std::{self, rc::Rc};
2use log;
3use riff_wave;
4use num_derive::FromPrimitive;
5use crate::{ll, fmod_result, dsp, reverb3d, sound, vector, ChannelGroup,
6 ChannelGroupRef, CpuUsage, DriverState, Dsp, Error, Guid, ListenerAttributes,
7 Mode, PluginHandle, Plugintype, Reverb3d, Sound, SoundRam, Speaker,
8 Speakermode, Timeunit};
9
10lazy_static!{
11 static ref FMOD_SYSTEM_CREATE_DESTROY_MUTEX : std::sync::Mutex <()> =
12 std::sync::Mutex::default();
13}
14
15#[derive(Clone, Debug, PartialEq)]
52pub struct System {
53 inner : Rc <Inner>
54}
55
56#[derive(PartialEq)]
57struct Inner (*mut ll::FMOD_SYSTEM);
58
59#[derive(Debug)]
60pub struct DriverInfo {
61 pub name : String,
62 pub guid : Guid,
63 pub systemrate : i32,
64 pub speakermode : Speakermode,
65 pub speakermodechannels : i32
66}
67
68bitflags!{
69 #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
70 pub struct CallbackType : u32 {
71 const DEVICELISTCHANGED = ll::FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED;
72 const DEVICELOST = ll::FMOD_SYSTEM_CALLBACK_DEVICELOST;
73 const MEMORYALLOCATIONFAILED = ll::FMOD_SYSTEM_CALLBACK_MEMORYALLOCATIONFAILED;
74 const THREADCREATED = ll::FMOD_SYSTEM_CALLBACK_THREADCREATED;
75 const BADDSPCONNECTION = ll::FMOD_SYSTEM_CALLBACK_BADDSPCONNECTION;
76 const PREMIX = ll::FMOD_SYSTEM_CALLBACK_PREMIX;
77 const POSTMIX = ll::FMOD_SYSTEM_CALLBACK_POSTMIX;
78 const ERROR = ll::FMOD_SYSTEM_CALLBACK_ERROR;
79 const MIDMIX = ll::FMOD_SYSTEM_CALLBACK_MIDMIX;
80 const THREADDESTROYED = ll::FMOD_SYSTEM_CALLBACK_THREADDESTROYED;
81 const PREUPDATE = ll::FMOD_SYSTEM_CALLBACK_PREUPDATE;
82 const POSTUPDATE = ll::FMOD_SYSTEM_CALLBACK_POSTUPDATE;
83 const RECORDLISTCHANGED = ll::FMOD_SYSTEM_CALLBACK_RECORDLISTCHANGED;
84 const ALL = ll::FMOD_SYSTEM_CALLBACK_ALL;
85 }
86}
87
88bitflags!{
89 #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
90 pub struct Initflags : u32 {
91 const NORMAL = ll::FMOD_INIT_NORMAL;
92 const STREAM_FROM_UPDATE = ll::FMOD_INIT_STREAM_FROM_UPDATE;
93 const MIX_FROM_UPDATE = ll::FMOD_INIT_MIX_FROM_UPDATE;
94 const _3D_RIGHTHANDED = ll::FMOD_INIT_3D_RIGHTHANDED;
95 const CHANNEL_LOWPASS = ll::FMOD_INIT_CHANNEL_LOWPASS;
96 const CHANNEL_DISTANCEFILTER = ll::FMOD_INIT_CHANNEL_DISTANCEFILTER;
97 const PROFILE_ENABLE = ll::FMOD_INIT_PROFILE_ENABLE;
98 const VOL0_BECOMES_VIRTUAL = ll::FMOD_INIT_VOL0_BECOMES_VIRTUAL;
99 const GEOMETRY_USECLOSEST = ll::FMOD_INIT_GEOMETRY_USECLOSEST;
100 const PREFER_DOLBY_DOWNMIX = ll::FMOD_INIT_PREFER_DOLBY_DOWNMIX;
101 const THREAD_UNSAFE = ll::FMOD_INIT_THREAD_UNSAFE;
102 const PROFILE_METER_ALL = ll::FMOD_INIT_PROFILE_METER_ALL;
103 const DISABLE_SRS_HIGHPASSFILTER = ll::FMOD_INIT_DISABLE_SRS_HIGHPASSFILTER;
104 }
105}
106
107#[derive(Copy, Clone, Debug, Eq, PartialEq, FromPrimitive)]
108pub enum Outputtype {
109 Autodetect = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_AUTODETECT as isize,
110 Unknown = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_UNKNOWN as isize,
111 Nosound = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_NOSOUND as isize,
112 Wavwriter = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WAVWRITER as isize,
113 NosoundNrt = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_NOSOUND_NRT as isize,
114 WavwriterNrt = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WAVWRITER_NRT as isize,
115 Dsound = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_DSOUND as isize,
116 Winmm = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WINMM as isize,
117 Wasapi = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WASAPI as isize,
118 Asio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_ASIO as isize,
119 Pulseaudio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_PULSEAUDIO as isize,
120 Alsa = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_ALSA as isize,
121 Coreaudio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_COREAUDIO as isize,
122 Xaudio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_XAUDIO as isize,
123 Ps3 = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_PS3 as isize,
124 Audiotrack = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_AUDIOTRACK as isize,
125 Opensl = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_OPENSL as isize,
126 Wiiu = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WIIU as isize,
127 Audioout = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_AUDIOOUT as isize,
128 Audio3d = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_AUDIO3D as isize,
129 Atmos = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_ATMOS as isize,
130 Webaudio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WEBAUDIO as isize,
131 Nnaudio = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_NNAUDIO as isize,
132 Winsonic = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_WINSONIC as isize,
133 MAX = ll::FMOD_OUTPUTTYPE_FMOD_OUTPUTTYPE_MAX as isize
134}
135
136impl System {
137 #[inline]
140 pub fn default() -> Result <Self, Error> {
141 Self::new (None, 256, Initflags::NORMAL)
142 }
143
144 #[inline]
150 pub fn new (
151 num_software_channels : Option <u16>,
152 num_virtual_channels : u16,
153 initflags : Initflags
154 ) -> Result <Self, Error> {
155 let mut system = Self::create()?;
156 if let Some (n) = num_software_channels {
157 system.set_software_channels (n as i32)?;
158 }
159 #[cfg(not(target_os = "windows"))]
163 system.set_output (Outputtype::Alsa)?;
164 system.init (num_virtual_channels, initflags)?;
165 Ok (system)
166 }
167
168 #[inline]
173 fn raw (&self) -> *mut ll::FMOD_SYSTEM {
174 (*self.inner).0
175 }
176
177 #[inline]
178 pub (crate) fn raw_mut (&mut self) -> *mut ll::FMOD_SYSTEM {
179 (*self.inner).0
180 }
181
182 #[inline]
183 pub fn update (&mut self) -> Result <(), Error> {
184 unsafe {
185 fmod_result!(ll::FMOD_System_Update (self.raw_mut()))
186 }
187 }
188
189 #[inline]
190 pub fn get_3d_listener_attributes (&self, listener : i32)
191 -> Result <ListenerAttributes, Error>
192 {
193 let zero = ll::FMOD_VECTOR { x: 0.0, y: 0.0, z: 0.0 };
194 let mut pos = zero;
195 let mut vel = zero;
196 let mut forward = zero;
197 let mut up = zero;
198 unsafe {
199 fmod_result!(
200 ll::FMOD_System_Get3DListenerAttributes (
201 self.raw(), listener, &mut pos, &mut vel, &mut forward, &mut up)
202 )?;
203 }
204 let listener_attributes =
205 ListenerAttributes::from_ll (pos, vel, forward, up);
206 Ok (listener_attributes)
207 }
208
209 #[inline]
210 pub fn get_3d_num_listeners (&self) -> Result <i32, Error> {
211 let mut numlisteners = 0;
212 unsafe {
213 fmod_result!(ll::FMOD_System_Get3DNumListeners (
214 self.raw(), &mut numlisteners)
215 )?;
216 }
217 Ok (numlisteners)
218 }
219
220 #[inline]
223 pub fn get_3d_settings (&self) -> Result <(f32, f32, f32), Error> {
224 let mut dopplerscale = 0.0;
225 let mut distancefactor = 0.0;
226 let mut rolloffscale = 0.0;
227 unsafe {
228 fmod_result!(ll::FMOD_System_Get3DSettings (
229 self.raw(), &mut dopplerscale, &mut distancefactor, &mut rolloffscale)
230 )?;
231 }
232 Ok ((dopplerscale, distancefactor, rolloffscale))
233 }
234
235 #[inline]
236 pub fn get_channels_playing (&self) -> Result <(i32, i32), Error> {
237 let mut channels = 0;
238 let mut realchannels = 0;
239 unsafe {
240 fmod_result!(
241 ll::FMOD_System_GetChannelsPlaying (
242 self.raw(), &mut channels, &mut realchannels)
243 )?;
244 }
245 Ok ((channels, realchannels))
246 }
247
248 #[inline]
249 pub fn get_cpu_usage (&self) -> Result <CpuUsage, Error> {
250 let mut usage = CpuUsage::default();
251 unsafe {
252 fmod_result!(
253 ll::FMOD_System_GetCPUUsage (
254 self.raw(),
255 &mut usage.dsp,
256 &mut usage.stream,
257 &mut usage.geometry,
258 &mut usage.update,
259 &mut usage.total)
260 )?;
261 }
262 Ok (usage)
263 }
264
265 #[inline]
267 pub fn get_driver (&self) -> Result <i32, Error> {
268 let mut driver = 0;
269 unsafe {
270 fmod_result!(ll::FMOD_System_GetDriver (self.raw(), &mut driver))?;
271 }
272 Ok (driver)
273 }
274
275 #[inline]
276 pub fn get_driver_info (&self, id : i32) -> Result <DriverInfo, Error> {
277 let name_len = 256;
279 let mut name = vec![0; name_len];
280 let mut guid = ll::FMOD_GUID {
281 Data1: 0, Data2: 0, Data3: 0, Data4: [0; 8]
282 };
283 let mut systemrate = 0;
284 let mut speakermode = 0;
285 let mut speakermodechannels = 0;
286 unsafe {
287 use std::os::raw;
288 fmod_result!(ll::FMOD_System_GetDriverInfo (
289 self.raw(),
290 id as raw::c_int,
291 name.as_mut_ptr() as *mut raw::c_char,
292 name_len as raw::c_int,
293 &mut guid,
294 &mut systemrate,
295 &mut speakermode,
296 &mut speakermodechannels
297 ))?;
298 }
299 let name = {
300 let name = name.split (|x| *x == 0).next().unwrap().to_vec();
301 String::from_utf8 (name).unwrap()
302 };
303 let guid = Guid::from (guid);
304 let speakermode = Speakermode::from_ll (speakermode);
305 let info = DriverInfo {
306 name, guid, systemrate, speakermode, speakermodechannels
307 };
308 Ok (info)
309 }
310
311 #[inline]
324 pub fn get_dsp_buffer_size (&self) -> Result <(u32, i32), Error> {
325 let mut bufferlength = 0;
326 let mut numbuffers = 0;
327 unsafe {
328 fmod_result!(
329 ll::FMOD_System_GetDSPBufferSize (
330 self.raw(), &mut bufferlength, &mut numbuffers)
331 )?;
332 }
333 Ok ((bufferlength, numbuffers))
334 }
335
336 #[inline]
340 pub fn get_geometry_occlusion (&self, listener : [f32; 3], source : [f32; 3])
341 -> Result <(f32, f32), Error>
342 {
343 let listener = vector::to_ll (listener);
344 let source = vector::to_ll (source);
345 let mut direct = 0.0;
346 let mut reverb = 0.0;
347 unsafe {
348 fmod_result!(
349 ll::FMOD_System_GetGeometryOcclusion (self.raw(),
350 &listener, &source, &mut direct, &mut reverb)
351 )?;
352 }
353 Ok ((direct, reverb))
354 }
355
356 #[inline]
358 pub fn get_geometry_settings (&self) -> Result <f32, Error> {
359 let mut maxworldsize = 0.0;
360 unsafe {
361 fmod_result!(
362 ll::FMOD_System_GetGeometrySettings (self.raw(), &mut maxworldsize)
363 )?;
364 }
365 Ok (maxworldsize)
366 }
367
368 #[inline]
369 pub fn get_master_channel_group (&self) -> Result <ChannelGroupRef, Error> {
370 let mut raw = std::ptr::null_mut();
371 unsafe {
372 fmod_result!(
373 ll::FMOD_System_GetMasterChannelGroup (self.raw(), &mut raw)
374 )?;
375 }
376 let channel_group =
377 ChannelGroup::from_raw_parts (raw, false, self.clone());
378 Ok (ChannelGroupRef { channel_group })
379 }
380
381 #[inline]
382 pub fn get_num_drivers (&self) -> Result <i32, Error> {
383 let mut numdrivers = 0;
384 unsafe {
385 fmod_result!(ll::FMOD_System_GetNumDrivers (self.raw(), &mut numdrivers))?;
386 }
387 Ok (numdrivers)
388 }
389
390 #[inline]
391 pub fn get_num_plugins (&self, plugintype : Plugintype)
392 -> Result <i32, Error>
393 {
394 let mut numplugins = 0;
395 unsafe {
396 fmod_result!(ll::FMOD_System_GetNumPlugins (
397 self.raw(), plugintype as ll::FMOD_PLUGINTYPE, &mut numplugins)
398 )?;
399 }
400 Ok (numplugins)
401 }
402
403 #[inline]
404 pub fn get_output (&self) -> Result <Outputtype, Error> {
405 let mut outputtype = 0;
406 unsafe {
407 fmod_result!(ll::FMOD_System_GetOutput (self.raw(), &mut outputtype))?;
408 }
409 Ok (Outputtype::from_ll (outputtype))
410 }
411
412 #[inline]
415 pub fn get_output_by_plugin (&self) -> Result <PluginHandle, Error> {
416 let mut handle = 0;
417 unsafe {
418 fmod_result!(ll::FMOD_System_GetOutputByPlugin (self.raw(), &mut handle))?;
419 }
420 Ok (PluginHandle (handle))
421 }
422
423 #[inline]
424 pub fn get_record_driver_info (&self, id : i32)
425 -> Result <(DriverInfo, DriverState), Error>
426 {
427 let name_len = 256;
429 let mut name = vec![0; name_len];
430 let mut guid = ll::FMOD_GUID {
431 Data1: 0, Data2: 0, Data3: 0, Data4: [0; 8]
432 };
433 let mut systemrate = 0;
434 let mut speakermode = 0;
435 let mut speakermodechannels = 0;
436 let mut state = 0;
437 unsafe {
438 use std::os::raw;
439 fmod_result!(ll::FMOD_System_GetRecordDriverInfo (
440 self.raw(),
441 id as raw::c_int,
442 name.as_mut_ptr() as *mut raw::c_char,
443 name_len as raw::c_int,
444 &mut guid,
445 &mut systemrate,
446 &mut speakermode,
447 &mut speakermodechannels,
448 &mut state
449 ))?;
450 }
451 let name = {
452 let name = name.split (|x| *x == 0).next().unwrap().to_vec();
453 String::from_utf8 (name).unwrap()
454 };
455 let guid = Guid::from (guid);
456 let speakermode = Speakermode::from_ll (speakermode);
457 let info = DriverInfo {
458 name, guid, systemrate, speakermode, speakermodechannels
459 };
460 let state = DriverState::from_bits (state).unwrap();
461 Ok ((info, state))
462 }
463
464 #[inline]
467 pub fn get_record_num_drivers (&self) -> Result <(i32, i32), Error> {
468 let mut numdrivers = 0;
469 let mut numconnected = 0;
470 unsafe {
471 fmod_result!(ll::FMOD_System_GetRecordNumDrivers (
472 self.raw(), &mut numdrivers, &mut numconnected
473 ))?;
474 }
475 Ok ((numdrivers, numconnected))
476 }
477
478 #[inline]
479 pub fn get_reverb_properties (&self, instance : i32)
480 -> Result <reverb3d::Properties, Error>
481 {
482 let mut properties = ll::FMOD_REVERB_PROPERTIES {
483 DecayTime: 0.0,
484 EarlyDelay: 0.0,
485 LateDelay: 0.0,
486 HFReference: 0.0,
487 HFDecayRatio: 0.0,
488 Diffusion: 0.0,
489 Density: 0.0,
490 LowShelfFrequency: 0.0,
491 LowShelfGain: 0.0,
492 HighCut: 0.0,
493 EarlyLateMix: 0.0,
494 WetLevel: 0.0
495 };
496 unsafe {
497 fmod_result!(
498 ll::FMOD_System_GetReverbProperties (self.raw(),
499 instance, &mut properties)
500 )?;
501 }
502 let properties = reverb3d::Properties::from_ll (&properties);
503 Ok (properties)
504 }
505
506 #[inline]
507 pub fn get_software_channels (&self) -> Result <i32, Error> {
508 let mut numsoftwarechannels = 0;
509 unsafe {
510 fmod_result!(
511 ll::FMOD_System_GetSoftwareChannels (
512 self.raw(), &mut numsoftwarechannels)
513 )?;
514 }
515 Ok (numsoftwarechannels)
516 }
517
518 #[inline]
522 pub fn get_software_format (&self)
523 -> Result <(i32, Speakermode, i32), Error>
524 {
525 let mut samplerate = 0;
526 let mut speakermode = 0;
527 let mut numrawspeakers = 0;
528 unsafe {
529 fmod_result!(
530 ll::FMOD_System_GetSoftwareFormat (
531 self.raw(), &mut samplerate, &mut speakermode, &mut numrawspeakers)
532 )?;
533 }
534 let speakermode = Speakermode::from_ll (speakermode);
535 Ok ((samplerate, speakermode, numrawspeakers))
536 }
537
538 #[inline]
539 pub fn get_sound_ram (&self) -> Result <SoundRam, Error> {
540 let mut ram = SoundRam::default();
541 unsafe {
542 fmod_result!(
543 ll::FMOD_System_GetSoundRAM (self.raw(),
544 &mut ram.currentalloced, &mut ram.maxalloced, &mut ram.total)
545 )?;
546 }
547 Ok (ram)
548 }
549
550 #[inline]
551 pub fn get_speaker_mode_channels (&self, mode : Speakermode)
552 -> Result <i32, Error>
553 {
554 let mut channels = 0;
555 unsafe {
556 fmod_result!(
557 ll::FMOD_System_GetSpeakerModeChannels (
558 self.raw(), mode as ll::FMOD_SPEAKERMODE, &mut channels)
559 )?;
560 }
561 Ok (channels)
562 }
563
564 #[inline]
569 pub fn get_speaker_position (&self, speaker : Speaker)
570 -> Result <(f32, f32, bool), Error>
571 {
572 let mut x = 0.0;
573 let mut y = 0.0;
574 let mut active = 0;
575 unsafe {
576 fmod_result!(
577 ll::FMOD_System_GetSpeakerPosition (
578 self.raw(), speaker as ll::FMOD_SPEAKER, &mut x, &mut y, &mut active)
579 )?;
580 }
581 Ok ((x, y, active != 0))
582 }
583
584 #[inline]
586 pub fn get_stream_buffer_size (&self)
587 -> Result <(u32, Timeunit), Error>
588 {
589 let mut filebuffersize = 0;
590 let mut filebuffersizetype = 0;
591 unsafe {
592 fmod_result!(
593 ll::FMOD_System_GetStreamBufferSize (
594 self.raw(), &mut filebuffersize, &mut filebuffersizetype)
595 )?;
596 }
597 Ok ((filebuffersize, Timeunit::from_bits (filebuffersizetype).unwrap()))
598 }
599
600 #[inline]
606 pub fn get_version (&self) -> Result <u32, Error> {
607 let mut version = 0;
608 unsafe {
609 fmod_result!(ll::FMOD_System_GetVersion (self.raw(), &mut version))?;
610 }
611 Ok (version)
612 }
613
614 #[inline]
616 pub fn get_version_string (&self) -> Result <String, Error> {
617 self.get_version().map (crate::version_string)
618 }
619
620 #[inline]
625 pub fn create_channel_group (&mut self, name : Option <&str>)
626 -> Result <ChannelGroup, Error>
627 {
628 let mut raw = std::ptr::null_mut();
629 let name_string = std::ffi::CString::new (name.unwrap_or ("")).unwrap();
630 let name_ptr = if name.is_some() {
631 name_string.as_ptr()
632 } else {
633 std::ptr::null()
634 };
635 unsafe {
636 fmod_result!(
637 ll::FMOD_System_CreateChannelGroup (self.raw(), name_ptr, &mut raw)
638 )?;
639 }
640 Ok (ChannelGroup::from_raw_parts (raw, true, self.clone()))
641 }
642
643 #[inline]
644 pub fn create_dsp (&mut self, description : &'static dsp::Description)
645 -> Result <Dsp, Error>
646 {
647 let mut raw = std::ptr::null_mut();
648 unsafe {
649 fmod_result!(
650 ll::FMOD_System_CreateDSP (self.raw(),
651 description.as_ref() as *const _, &mut raw)
652 )?;
653 }
654 Ok (Dsp::from_raw_parts (raw, true, self.clone()))
655 }
656
657 #[inline]
658 pub fn create_dsp_by_type (&mut self, type_ : dsp::Type)
659 -> Result <Dsp, Error>
660 {
661 let mut raw = std::ptr::null_mut();
662 unsafe {
663 fmod_result!(
664 ll::FMOD_System_CreateDSPByType (self.raw(), type_ as ll::FMOD_DSP_TYPE,
665 &mut raw)
666 )?;
667 }
668 Ok (Dsp::from_raw_parts (raw, true, self.clone()))
669 }
670
671 pub fn create_dsp_sfxreverb (&mut self,
674 properties : &reverb3d::Properties, dry_level : f32
675 ) -> Result <Dsp, Error> {
676 let mut raw = std::ptr::null_mut();
677 unsafe {
678 fmod_result!(
679 ll::FMOD_System_CreateDSPByType (
680 self.raw(),
681 dsp::Type::Sfxreverb as ll::FMOD_DSP_TYPE,
682 &mut raw
683 )
684 )?;
685 }
686 let mut dsp = Dsp::from_raw_parts (raw, true, self.clone());
687 dsp.set_parameters_sfxreverb (properties, dry_level)?;
688 Ok (dsp)
689 }
690
691 #[inline]
692 pub fn create_reverb3d (&mut self) -> Result <Reverb3d, Error> {
693 let mut raw = std::ptr::null_mut();
694 unsafe {
695 fmod_result!(ll::FMOD_System_CreateReverb3D (self.raw(), &mut raw))?;
696 }
697 Ok (Reverb3d::from_raw_parts (raw, self.clone()))
698 }
699
700 pub fn create_sound_from_file (&mut self,
701 filename : &str,
702 mode : Mode,
703 exinfo : Option <&mut sound::Createsoundexinfo>
704 ) -> Result <Sound, Error> {
705 let filename = std::ffi::CString::new (filename).unwrap();
706 let mut exinfo = exinfo.map (sound::Createsoundexinfo::to_ll);
707 let mut raw = std::ptr::null_mut();
708 unsafe {
709 fmod_result!(
710 ll::FMOD_System_CreateSound (
711 self.raw(),
712 filename.as_ptr(),
713 mode.bits(),
714 exinfo.as_mut()
715 .map (|exinfo| exinfo as *mut ll::FMOD_CREATESOUNDEXINFO)
716 .unwrap_or (std::ptr::null_mut()),
717 &mut raw)
718 )?;
719 }
720 Ok (Sound::from_raw_parts (raw, true, self.clone()))
721 }
722
723 pub fn create_sound_from_memory (&mut self,
724 data : &[u8],
725 mut mode : Mode,
726 exinfo : Option <&mut sound::Createsoundexinfo>
727 ) -> Result <Sound, Error> {
728 mode |= Mode::OPENMEMORY;
729 let mut exinfo_default = Default::default();
730 let mut exinfo = {
731 let exinfo = exinfo.unwrap_or (&mut exinfo_default);
732 exinfo.length = data.len() as u32;
733 sound::Createsoundexinfo::to_ll (exinfo)
734 };
735 let mut raw = std::ptr::null_mut();
736 let data = if data.len() > 0 {
737 data.as_ptr() as *const std::os::raw::c_char
738 } else {
739 std::ptr::null()
740 };
741 unsafe {
742 fmod_result!(
743 ll::FMOD_System_CreateSound (
744 self.raw(),
745 data,
746 mode.bits(),
747 &mut exinfo,
748 &mut raw)
749 )?;
750 }
751 Ok (Sound::from_raw_parts (raw, true, self.clone()))
752 }
753
754 pub fn create_sound_from_pcm (&mut self,
755 pcm : &[i16],
756 mode : Mode,
757 exinfo : Option <&mut sound::Createsoundexinfo>
758 ) -> Result <Sound, Error> {
759 const WAV_HEADER_LEN : usize = 44;
760 let pcm_bytelen = pcm.len() as usize * 2;
761 let wav_bytelen = WAV_HEADER_LEN + pcm_bytelen;
762 let mut wav = vec![0; wav_bytelen];
763 {
764 let cursor = std::io::Cursor::new (&mut wav);
765 let writer = std::io::BufWriter::new (cursor);
766 let mut wav_writer = riff_wave::WaveWriter::new (1, 44100, 16, writer)
767 .unwrap();
768 for sample in pcm.iter() {
769 wav_writer.write_sample_i16 (*sample).unwrap();
770 }
771 }
772 self.create_sound_from_memory (wav.as_slice(), mode, exinfo)
773 }
774
775 #[inline]
777 pub fn create_sound_from_file_default (&mut self, filename : &str)
778 -> Result <Sound, Error>
779 {
780 self.create_sound_from_file (filename, Mode::DEFAULT, None)
781 }
782
783 #[inline]
784 pub fn create_sound_from_memory_default (&mut self, data : &[u8])
785 -> Result <Sound, Error>
786 {
787 self.create_sound_from_memory (data, Mode::DEFAULT, None)
788 }
789
790 #[inline]
791 pub fn create_sound_from_pcm_default (&mut self, pcm : &[i16])
792 -> Result <Sound, Error>
793 {
794 self.create_sound_from_pcm (pcm, Mode::DEFAULT, None)
795 }
796
797 #[inline]
798 pub fn set_3d_listener_attributes (&mut self,
799 listener : i32, attributes : &ListenerAttributes
800 ) -> Result <(), Error> {
801 let pos = vector::to_ll (attributes.pos);
802 let vel = vector::to_ll (attributes.vel);
803 let forward = vector::to_ll (attributes.forward);
804 let up = vector::to_ll (attributes.up);
805 unsafe {
806 fmod_result!(
807 ll::FMOD_System_Set3DListenerAttributes (self.raw(),
808 listener, &pos, &vel, &forward, &up)
809 )
810 }
811 }
812
813 #[inline]
814 pub fn set_output (&mut self, output : Outputtype) -> Result <(), Error> {
815 unsafe {
816 fmod_result!(
817 ll::FMOD_System_SetOutput (self.raw(), output as ll::FMOD_OUTPUTTYPE))
818 }
819 }
820
821 #[inline]
830 pub fn set_reverb_properties (&mut self,
831 instance : i32, properties : &reverb3d::Properties
832 ) -> Result <(), Error> {
833 let properties = properties.to_ll();
834 unsafe {
835 fmod_result!(
836 ll::FMOD_System_SetReverbProperties (self.raw(), instance, &properties)
837 )
838 }
839 }
840
841 #[inline]
846 fn create() -> Result <Self, Error> {
847 let raw = {
848 let _lock = FMOD_SYSTEM_CREATE_DESTROY_MUTEX.lock().unwrap();
849 let mut raw = std::ptr::null_mut();
850 unsafe {
851 fmod_result!(ll::FMOD_System_Create (&mut raw))?;
852 }
853 raw
854 };
856 let inner = Rc::new (Inner (raw));
857 let system = System { inner };
858 let system_version = system.get_version_string()?;
859 if system_version != *crate::FMOD_VERSION_STRING {
860 log::error!(
861 "FMOD created system got shared library version {:?}, \
862 bindings were generated for version {:?}",
863 system_version, *crate::FMOD_VERSION_STRING);
864 panic!(
865 "FMOD created system got shared library version {:?}, \
866 bindings were generated for version {:?}",
867 system_version, *crate::FMOD_VERSION_STRING);
868 }
869 Ok (system)
870 }
871
872 #[inline]
874 fn init (&mut self, max_channels : u16, init_flags : Initflags)
875 -> Result <(), Error>
876 {
877 let max_channels = max_channels as i32;
878 unsafe {
879 fmod_result!(ll::FMOD_System_Init (
880 self.raw(), max_channels, init_flags.bits(), std::ptr::null_mut()))
881 }
882 }
883
884 #[inline]
887 fn set_software_channels (&mut self, numsoftwarechannels : i32)
888 -> Result <(), Error>
889 {
890 unsafe {
891 fmod_result!(
892 ll::FMOD_System_SetSoftwareChannels (self.raw(), numsoftwarechannels)
893 )
894 }
895 }
896
897}
898
899impl std::fmt::Debug for Inner {
900 fn fmt (&self, f : &mut std::fmt::Formatter) -> std::fmt::Result {
901 write!(f, "{:p}", self.0)
902 }
903}
904
905impl Drop for Inner {
906 fn drop (&mut self) {
907 let _lock = FMOD_SYSTEM_CREATE_DESTROY_MUTEX.lock().unwrap();
908 unsafe {
909 let _ = fmod_result!(ll::FMOD_System_Release (self.0)).map_err (
910 |err| log::error!("error releasing FMOD System@{:p}: {:?}", self.0, err));
911 }
912 }
914}
915
916impl From <ll::FMOD_GUID> for Guid {
917 fn from (guid : ll::FMOD_GUID) -> Self {
918 Guid {
919 data1: guid.Data1,
920 data2: guid.Data2,
921 data3: guid.Data3,
922 data4: guid.Data4
923 }
924 }
925}
926
927impl Outputtype {
928 pub fn from_ll (ll : ll::FMOD_OUTPUTTYPE) -> Self {
929 use num_traits::FromPrimitive;
930 Self::from_u32 (ll as u32).unwrap()
931 }
932}