├── .github ├── FUNDING.yml └── workflows │ └── main.yaml ├── .gitignore ├── Cargo.toml ├── LICENSE.TXT ├── README.md ├── examples ├── 3d │ └── 3d.rs ├── Cargo.toml ├── dsp_custom │ └── dsp_custom.rs ├── effects │ └── effects.rs ├── file_callbacks │ └── file_callbacks.rs ├── recording │ └── recording.rs ├── simple_music_player │ └── simple_music_player.rs └── user_created_sound │ └── user_created_sound.rs └── src ├── async_read_info.rs ├── callbacks.rs ├── channel.rs ├── channel_group.rs ├── dsp.rs ├── dsp_connection.rs ├── enums.rs ├── error.rs ├── ffi.rs ├── file.rs ├── fmod_sys.rs ├── geometry.rs ├── reverb.rs ├── reverb_properties.rs ├── rfmod.rs ├── sound.rs ├── sound_group.rs ├── types.rs ├── utils.rs └── vector.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [GuillaumeGomez] 4 | patreon: GuillaumeGomez 5 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: "rustdoc-stripper" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "*" 7 | push: 8 | branches: 9 | - "*" 10 | 11 | jobs: 12 | build: 13 | name: "Build/Test" 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | os: [ubuntu-latest] 19 | toolchain: [nightly, stable] 20 | env: 21 | LD_LIBRARY_PATH=/usr/local/lib 22 | 23 | defaults: 24 | run: 25 | shell: bash 26 | 27 | steps: 28 | - name: Acquire source code 29 | uses: actions/checkout@v2 30 | - name: Acquire Rust toolchain 31 | uses: actions-rs/toolchain@v1 32 | with: 33 | toolchain: ${{ matrix.toolchain }} 34 | override: true 35 | profile: minimal 36 | id: toolchain 37 | - name: "install fmod" 38 | run: | 39 | wget http://www.guillaume-gomez.fr/fmodapi44439linux.tar.gz 40 | tar xvf fmodapi44439linux.tar.gz 41 | sudo cp -r fmodapi44439linux/api/lib/* /usr/local/lib/. 42 | - name: "Run build" 43 | run: RUST_BACKTRACE=1 cargo build 44 | - name: "Build examples" 45 | run: RUST_BACKTRACE=1 cd examples && cargo build 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.lock 2 | 3 | # Generated by Cargo 4 | /target/ 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fmod" 3 | version = "0.10.2" 4 | authors = ["Guillaume Gomez "] 5 | 6 | description = "A rust binding for the FMOD library" 7 | repository = "https://github.com/GuillaumeGomez/rust-fmod" 8 | documentation = "http://docs.rs/fmod/" 9 | readme = "README.md" 10 | keywords = ["library", "sound", "3D", "fmod", "fmodex"] 11 | license-file = "LICENSE.TXT" 12 | 13 | [dependencies] 14 | c_vec = "~1.0" 15 | byteorder = "1.2" 16 | libc = "0.2.6" 17 | 18 | [lib] 19 | name = "rfmod" 20 | path = "src/rfmod.rs" 21 | crate-type = ["dylib", "rlib"] 22 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuillaumeGomez/rust-fmod/bf67e9198311fc9d5ebea96c3daae82ff1df4e93/LICENSE.TXT -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rust-fmod [![Build Status](https://api.travis-ci.org/GuillaumeGomez/rust-fmod.png?branch=master)](https://travis-ci.org/GuillaumeGomez/rust-fmod) 2 | ========= 3 | 4 | This is a rust binding for __FMOD__, the library developped by FIRELIGHT TECHNOLOGIES. 5 | 6 | __FMOD__ website : www.fmod.org 7 | 8 | You can also find it on [crates.io](https://crates.io/crates/fmod) ! 9 | 10 | ## Installation 11 | 12 | You must install on your computer the __FMOD__ library which is used for the binding. 13 | 14 | Since this project supports cargo, you can build it this way: 15 | 16 | ```Shell 17 | > cargo build 18 | ``` 19 | 20 | This isn't a binding to the lastest version. You can find the bound version [here](http://www.guillaume-gomez.fr/fmodapi44439linux.tar.gz). 21 | 22 | ## Documentation 23 | 24 | You can access the __rfmod__ documentation locally, just build it: 25 | 26 | ```Shell 27 | > cargo doc --open 28 | ``` 29 | 30 | You can also access the latest build of the documentation directly on [docs.rs](https://docs.rs/fmod/0.10.1/rfmod/). 31 | 32 | ## Short example 33 | 34 | Here is a short example on how to create a file and to play it : 35 | 36 | ```Rust 37 | extern crate rfmod; 38 | 39 | fn main() { 40 | let fmod = match rfmod::Sys::new() { 41 | Ok(f) => f, 42 | Err(e) => { 43 | panic!("Error code : {:?}", e); 44 | } 45 | }; 46 | 47 | match fmod.init() { 48 | rfmod::Result::Ok => {} 49 | e => { 50 | panic!("FmodSys.init failed : {:?}", e); 51 | } 52 | }; 53 | 54 | let sound = match fmod.create_sound("music.mp3", None, None) { 55 | Ok(s) => s, 56 | Err(err) => { 57 | panic!("Error code : {:?}", err); 58 | } 59 | }; 60 | 61 | match sound.play_to_the_end() { 62 | rfmod::Result::Ok => { 63 | println!("Ok !"); 64 | } 65 | err => { 66 | panic!("Error code : {:?}", err); 67 | } 68 | }; 69 | } 70 | ``` 71 | 72 | For a more complete example : https://github.com/GuillaumeGomez/rust-music-player 73 | 74 | ## License 75 | 76 | Please refer to the LICENSE.txt file for more details. 77 | If you want more information, here is the FMOD website : http://www.fmod.org/ 78 | -------------------------------------------------------------------------------- /examples/3d/3d.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use std::default::Default; 30 | use std::thread::sleep; 31 | use std::time::Duration; 32 | 33 | fn main() { 34 | let t_args = std::env::args(); 35 | let mut args = Vec::new(); 36 | 37 | for tmp in t_args { 38 | args.push(tmp); 39 | } 40 | let tmp = args[1..].to_owned(); 41 | 42 | if tmp.len() < 1 { 43 | panic!("USAGE: ./3d [music_file]"); 44 | } 45 | let fmod = match rfmod::Sys::new() { 46 | Ok(f) => f, 47 | Err(e) => { 48 | panic!("Sys::new() : {:?}", e); 49 | } 50 | }; 51 | 52 | match fmod.init_with_parameters(10i32, rfmod::InitFlag(rfmod::INIT_NORMAL)) { 53 | rfmod::Status::Ok => {} 54 | e => { 55 | panic!("FmodSys.init failed : {:?}", e); 56 | } 57 | }; 58 | 59 | println!("========================================="); 60 | println!("============== 3D example ==============="); 61 | println!("========================================="); 62 | 63 | let arg1 = tmp.get(0).unwrap(); 64 | let sound = match fmod.create_sound((*arg1).as_ref(), Some(rfmod::Mode(rfmod::_3D | rfmod::SOFTWARE)), None) { 65 | Ok(s) => s, 66 | Err(e) => panic!("create sound error: {:?}", e) 67 | }; 68 | sound.set_3D_min_max_distance(4f32, 10000f32); 69 | sound.set_mode(rfmod::Mode(rfmod::LOOP_NORMAL)); 70 | 71 | let chan = match sound.play() { 72 | Ok(c) => c, 73 | Err(e) => panic!("sound.play error: {:?}", e) 74 | }; 75 | chan.set_3D_attributes(&rfmod::Vector{x: -10f32, y: 0f32, z: 0f32}, &Default::default()); 76 | 77 | let mut last_pos = rfmod::Vector::new(); 78 | let mut listener_pos = rfmod::Vector::new(); 79 | let mut t = 0f32; 80 | let interface_update_time = 50f32; 81 | let compensate_time = 1000f32 / interface_update_time; 82 | 83 | while match chan.is_playing() { 84 | Ok(f) => f, 85 | Err(e) => { 86 | println!("channel.is_playing failed: {:?}", e); 87 | false 88 | } 89 | } { 90 | let forward = rfmod::Vector{x: 0f32, y: 0f32, z: 1f32}; 91 | let up = rfmod::Vector{x: 0f32, y: 1f32, z: 0f32}; 92 | let mut vel = rfmod::Vector::new(); 93 | 94 | listener_pos.x = (t * 0.05f32).sin() * 33f32; // left right ping-pong 95 | vel.x = (listener_pos.x - last_pos.x) * compensate_time; 96 | vel.y = (listener_pos.y - last_pos.y) * compensate_time; 97 | vel.z = (listener_pos.z - last_pos.z) * compensate_time; 98 | t += 30f32 * (1f32 / interface_update_time); 99 | 100 | last_pos = listener_pos; 101 | fmod.set_3D_listener_attributes(0, &listener_pos, &vel, &forward, &up); 102 | 103 | let mut tmp = "|.......................<1>......................<2>....................|\r".to_owned(); 104 | unsafe { (tmp.as_mut_vec().as_mut() as &mut [u8])[(listener_pos.x as isize + 35isize) as usize] = 'L' as u8; } 105 | print!("{}", tmp); 106 | fmod.update(); 107 | sleep(Duration::from_millis(interface_update_time as u64 - 1)); 108 | } 109 | } -------------------------------------------------------------------------------- /examples/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rfmod-examples" 3 | version = "0.9.6" 4 | authors = ["Guillaume Gomez "] 5 | 6 | [dependencies.fmod] 7 | path = "../" 8 | 9 | [[bin]] 10 | name = "3d" 11 | path = "./3d/3d.rs" 12 | 13 | [[bin]] 14 | name = "dsp_custom" 15 | path = "./dsp_custom/dsp_custom.rs" 16 | 17 | [[bin]] 18 | name = "effects" 19 | path = "./effects/effects.rs" 20 | 21 | [[bin]] 22 | name = "file_callbacks" 23 | path = "./file_callbacks/file_callbacks.rs" 24 | 25 | [[bin]] 26 | name = "recording" 27 | path = "./recording/recording.rs" 28 | 29 | [[bin]] 30 | name = "simple_music_player" 31 | path = "./simple_music_player/simple_music_player.rs" 32 | 33 | [[bin]] 34 | name = "user_created_sound" 35 | path = "./user_created_sound/user_created_sound.rs" -------------------------------------------------------------------------------- /examples/dsp_custom/dsp_custom.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | #![allow(non_snake_case)] 28 | #![allow(unused_variables)] 29 | 30 | extern crate rfmod; 31 | 32 | use std::default::Default; 33 | use std::io::{BufRead, Write}; 34 | 35 | #[allow(unused_must_use)] 36 | fn get_key() -> char { 37 | let stdout = ::std::io::stdout(); 38 | let mut io = stdout.lock(); 39 | let r = ::std::io::stdin(); 40 | let mut reader = r.lock(); 41 | let mut tmp = String::new(); 42 | 43 | write!(io, "> "); 44 | io.flush(); 45 | match reader.read_line(&mut tmp) { 46 | Ok(_) => { 47 | if tmp.len() < 2 { 48 | '\0' 49 | } else { 50 | let l = tmp.len() - 2; 51 | tmp.remove(l) 52 | } 53 | }, 54 | Err(_) => '\0' 55 | } 56 | } 57 | 58 | fn my_DSP_callback(dsp_state: &rfmod::DspState, inbuffer: &mut [f32], outbuffer: &mut [f32], length: u32, in_channels: i32, 59 | out_channels: i32) -> rfmod::Status { 60 | for it in 0usize..(inbuffer.len() - 1usize) { 61 | outbuffer[it] = inbuffer[it] * 0.2f32; 62 | } 63 | for count in 0..length { 64 | for count2 in 0..out_channels { 65 | /* 66 | This DSP filter just halves the volume! 67 | Input is modified, and sent to output. 68 | */ 69 | outbuffer[((count as i32 * out_channels) + count2) as usize] = inbuffer[((count as i32 * in_channels) + count2) as usize] * 0.2f32; 70 | } 71 | } 72 | 73 | rfmod::Status::Ok 74 | } 75 | 76 | fn main() { 77 | let t_args = std::env::args(); 78 | let mut args = Vec::new(); 79 | 80 | for tmp in t_args { 81 | args.push(tmp); 82 | } 83 | let tmp = args[1..].to_owned(); 84 | 85 | if tmp.len() < 1 { 86 | panic!("USAGE: ./dsp_custom [music_file]"); 87 | } 88 | let fmod = match rfmod::Sys::new() { 89 | Ok(f) => f, 90 | Err(e) => { 91 | panic!("Sys::new() : {:?}", e); 92 | } 93 | }; 94 | 95 | match fmod.init() { 96 | rfmod::Status::Ok => {} 97 | e => { 98 | panic!("FmodSys.init failed : {:?}", e); 99 | } 100 | }; 101 | 102 | let arg1 = tmp.get(0).unwrap(); 103 | 104 | let sound = match fmod.create_sound((*arg1).as_ref(), 105 | Some(rfmod::Mode(rfmod::SOFTWARE | rfmod::LOOP_NORMAL)), None) { 106 | Ok(s) => s, 107 | Err(err) => { 108 | panic!("FmodSys.create_sound failed : {:?}", err); 109 | } 110 | }; 111 | 112 | println!("============================"); 113 | println!("======== Custom DSP ========"); 114 | println!("============================\n"); 115 | println!("Enter 'f' to activate / deactivate user filter"); 116 | println!("Press 'Esc' case then 'Enter' case to quit"); 117 | 118 | let channel = match sound.play() { 119 | Ok(c) => c, 120 | Err(e) => { 121 | panic!("Sound.play failed : {:?}", e); 122 | } 123 | }; 124 | 125 | let mut description : rfmod::DspDescription = Default::default(); 126 | 127 | description.read = Some(my_DSP_callback as fn(&_, &mut _, &mut _, _, _, _) -> _); 128 | description.name = "test".to_owned(); 129 | 130 | let dsp = match fmod.create_DSP_with_description(&mut description) { 131 | Ok(dsp) => dsp, 132 | Err(e) => { 133 | panic!("FmodSys.create_DSP_with_description failed : {:?}", e); 134 | } 135 | }; 136 | 137 | dsp.set_bypass(true); 138 | let connection = match fmod.add_DSP(&dsp) { 139 | Ok(c) => c, 140 | Err(e) => { 141 | panic!("FmodSys.add_DSP failed : {:?}", e); 142 | } 143 | }; 144 | 145 | let mut active = false; 146 | loop { 147 | match get_key() as char { 148 | 'f' => { 149 | dsp.set_bypass(active); 150 | active = !active; 151 | fmod.update(); 152 | } 153 | c if c == 27u8 as char => break, 154 | _ => {} 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /examples/effects/effects.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use std::thread::sleep; 30 | use std::time::Duration; 31 | use std::io::{self, Error, BufRead}; 32 | 33 | fn get_key() -> Result { 34 | let r = io::stdin(); 35 | let mut reader = r.lock(); 36 | let mut line = String::new(); 37 | 38 | print!("> "); 39 | match reader.read_line(&mut line) { 40 | Ok(_) => { 41 | let length = line.len() - 1; 42 | line.truncate(length); 43 | if &line == "quit" { 44 | Ok(-1) 45 | } else { 46 | match line.parse() { 47 | Ok(s) => Ok(s), 48 | Err(_) => Ok(9) 49 | } 50 | } 51 | } 52 | Err(e) => Err(e) 53 | } 54 | } 55 | 56 | fn switch_dsp_state(dsp: &rfmod::Dsp, fmod: &rfmod::Sys, dsp_type: isize) { 57 | if match dsp.get_active() { 58 | Ok(c) => c, 59 | Err(_) => return 60 | } { 61 | dsp.remove(); 62 | } else { 63 | match fmod.add_DSP(dsp) { _ => {}}; 64 | match dsp_type { 65 | 3 => { 66 | dsp.set_parameter(rfmod::DspTypeEcho::Delay as i32, 50f32); 67 | }, 68 | 5 => { 69 | dsp.set_parameter(rfmod::DspDistortion::Level as i32, 0.8f32); 70 | }, 71 | 7 => { 72 | dsp.set_parameter(rfmod::DspTypeParameq::Center as i32, 5000f32); 73 | dsp.set_parameter(rfmod::DspTypeParameq::Gain as i32, 0f32); 74 | } 75 | _ => {} 76 | }; 77 | } 78 | } 79 | 80 | fn main() { 81 | let t_args = std::env::args(); 82 | let mut args = Vec::new(); 83 | 84 | for tmp in t_args { 85 | args.push(tmp); 86 | } 87 | let tmp = args[1..].to_owned(); 88 | 89 | if tmp.len() < 1 { 90 | panic!("USAGE: ./effects [music_file]"); 91 | } 92 | let fmod = match rfmod::Sys::new() { 93 | Ok(f) => f, 94 | Err(e) => { 95 | panic!("Sys::new() : {:?}", e); 96 | } 97 | }; 98 | 99 | match fmod.init_with_parameters(32i32, rfmod::InitFlag(rfmod::INIT_NORMAL)) { 100 | rfmod::Status::Ok => {} 101 | e => { 102 | panic!("Sys::init() failed : {:?}", e); 103 | } 104 | }; 105 | 106 | println!("=============================================="); 107 | println!("===== Effects example from FMOD examples ====="); 108 | println!("=============================================="); 109 | 110 | let arg1 = tmp.get(0).unwrap(); 111 | let sound = match fmod.create_sound(&(*arg1), Some(rfmod::Mode(rfmod::SOFTWARE)), None) { 112 | Ok(s) => s, 113 | Err(e) => panic!("create sound error: {:?}", e) 114 | }; 115 | sound.set_mode(rfmod::Mode(rfmod::LOOP_NORMAL)); 116 | 117 | match sound.play() { 118 | Ok(_) => {}, 119 | Err(e) => panic!("sound.play error: {:?}", e) 120 | }; 121 | let mut dsps = Vec::new(); 122 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::LowPass) { 123 | Ok(r) => r, 124 | Err(e) => panic!("fmod.create_DSP_by_type low_pass error: {:?}", e) 125 | }); 126 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::HighPass) { 127 | Ok(r) => r, 128 | Err(e) => panic!("fmod.create_DSP_by_type high_pass error: {:?}", e) 129 | }); 130 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::Echo) { 131 | Ok(r) => r, 132 | Err(e) => panic!("fmod.create_DSP_by_type echo error: {:?}", e) 133 | }); 134 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::Flange) { 135 | Ok(r) => r, 136 | Err(e) => panic!("fmod.create_DSP_by_type flange error: {:?}", e) 137 | }); 138 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::Distortion) { 139 | Ok(r) => r, 140 | Err(e) => panic!("fmod.create_DSP_by_type distortion error: {:?}", e) 141 | }); 142 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::Chorus) { 143 | Ok(r) => r, 144 | Err(e) => panic!("fmod.create_DSP_by_type chorus error: {:?}", e) 145 | }); 146 | dsps.push(match fmod.create_DSP_by_type(rfmod::DspType::Parameq) { 147 | Ok(r) => r, 148 | Err(e) => panic!("fmod.create_DSP_by_type parameq error: {:?}", e) 149 | }); 150 | 151 | println!("Enter '1' to toggle dsp low pass effect."); 152 | println!("Enter '2' to toggle dsp high pass effect."); 153 | println!("Enter '3' to toggle dsp echo effect."); 154 | println!("Enter '4' to toggle dsp flange effect."); 155 | println!("Enter '5' to toggle dsp distortion effect."); 156 | println!("Enter '6' to toggle dsp chorus effect."); 157 | println!("Enter '7' to toggle dsp parameq effect."); 158 | println!("Enter 'quit' to quit."); 159 | loop { 160 | println!("low pass[{}] high pass[{}] echo[{}] flange[{}] dist[{}] chorus[{}] parameq[{}]", 161 | match dsps[0].get_active() { Ok(true) => {'x'}, _ => {' '}}, 162 | match dsps[1].get_active() { Ok(true) => {'x'}, _ => {' '}}, 163 | match dsps[2].get_active() { Ok(true) => {'x'}, _ => {' '}}, 164 | match dsps[3].get_active() { Ok(true) => {'x'}, _ => {' '}}, 165 | match dsps[4].get_active() { Ok(true) => {'x'}, _ => {' '}}, 166 | match dsps[5].get_active() { Ok(true) => {'x'}, _ => {' '}}, 167 | match dsps[6].get_active() { Ok(true) => {'x'}, _ => {' '}}); 168 | match get_key() { 169 | Ok(v) => match v { 170 | -1 => break, 171 | x if x > 0 && x < 8 => { 172 | switch_dsp_state(&dsps[x as usize - 1], &fmod, x) 173 | }, 174 | _ => println!("Invalid entry") 175 | }, 176 | Err(e) => panic!("Entry error: {:?}", e) 177 | } 178 | fmod.update(); 179 | sleep(Duration::from_millis(30)); // let time to the system for update 180 | } 181 | } -------------------------------------------------------------------------------- /examples/file_callbacks/file_callbacks.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use rfmod::SeekStyle; 30 | 31 | #[allow(unused_variables)] 32 | fn my_open(music_name: &str, unicode: i32) -> Option<(rfmod::FmodFile, Option)> { 33 | println!("Let's start by opening {} !", music_name); 34 | let file = match rfmod::FmodFile::open(music_name) { 35 | Ok(f) => f, 36 | Err(e) => panic!("Couldn't open \"{}\": {}", music_name, e) 37 | }; 38 | 39 | Some((file, None)) 40 | } 41 | 42 | #[allow(unused_variables)] 43 | fn my_close(music_file: &mut rfmod::FmodFile, user_data: Option<&mut rfmod::UserData>) { 44 | println!("This is the end !"); 45 | music_file.close(); 46 | } 47 | 48 | #[allow(unused_variables)] 49 | fn my_read(handle: &mut rfmod::FmodFile, buffer: &mut [u8], size_to_read: u32, user_data: Option<&mut rfmod::UserData>) -> usize { 50 | handle.read(buffer) 51 | } 52 | 53 | #[allow(unused_variables)] 54 | fn my_seek(handle: &mut rfmod::FmodFile, pos: u32, user_data: Option<&mut rfmod::UserData>) { 55 | handle.seek(pos as i64, SeekStyle::SeekSet); 56 | } 57 | 58 | fn main() { 59 | let t_args = std::env::args(); 60 | let mut args = Vec::new(); 61 | 62 | for tmp in t_args { 63 | args.push(tmp); 64 | } 65 | let tmp = args[1..].to_owned(); 66 | 67 | if tmp.len() < 1 { 68 | panic!("USAGE: ./file_callback [music_file]"); 69 | } 70 | let fmod = match rfmod::Sys::new() { 71 | Ok(f) => f, 72 | Err(e) => { 73 | panic!("Sys::new() : {:?}", e); 74 | } 75 | }; 76 | 77 | match fmod.init_with_parameters(1i32, rfmod::InitFlag(rfmod::INIT_NORMAL)) { 78 | rfmod::Status::Ok => {} 79 | e => { 80 | panic!("Sys::init() failed : {:?}", e); 81 | } 82 | }; 83 | 84 | match fmod.set_file_system(Some(my_open as fn(&_, _) -> _), 85 | Some(my_close as fn(&mut _, Option<&mut _>)), 86 | Some(my_read as fn(&mut _, &mut _, _, Option<&mut _>) -> _), 87 | Some(my_seek as fn(&mut _, _, Option<&mut _>)), 88 | 2048i32) { 89 | rfmod::Status::Ok => {} 90 | e => { 91 | panic!("FmodSys.set_file_system failed : {:?}", e); 92 | } 93 | }; 94 | 95 | println!("============================================================================"); 96 | println!("================ File Callbacks Example from FMOD examples ================="); 97 | println!("============================================================================"); 98 | 99 | let arg1 = tmp.get(0).unwrap(); 100 | let sound = match fmod.create_stream((*arg1).as_ref(), 101 | Some(rfmod::Mode(rfmod::_2D | rfmod::HARDWARE | rfmod::LOOP_OFF)), None) 102 | { 103 | Ok(s) => s, 104 | Err(e) => panic!("create sound error: {:?}", e) 105 | }; 106 | 107 | let chan = match sound.play() { 108 | Ok(c) => c, 109 | Err(e) => panic!("sound.play error: {:?}", e) 110 | }; 111 | 112 | let length = match sound.get_length(rfmod::TIMEUNIT_MS) { 113 | Ok(l) => l, 114 | Err(e) => panic!("sound.get_length error: {:?}", e) 115 | }; 116 | while match chan.is_playing() { 117 | Ok(p) => p, 118 | Err(e) => { 119 | println!("channel.is_playing failed: {:?}", e); 120 | false 121 | } 122 | } { 123 | let position = match chan.get_position(rfmod::TIMEUNIT_MS) { 124 | Ok(p) => p, 125 | Err(e) => { 126 | println!("channel.get_position failed: {:?}", e); 127 | return; 128 | } 129 | }; 130 | 131 | print!("{:02}:{:02} / {:02}:{:02}\r", position / 1000 / 60, position / 1000 % 60, length / 1000 / 60, length / 1000 % 60); 132 | ::std::thread::sleep_ms(30); 133 | } 134 | } -------------------------------------------------------------------------------- /examples/recording/recording.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use std::mem; 30 | use std::default::Default; 31 | use std::io::{self, Error, BufRead}; 32 | use std::thread::sleep; 33 | use std::time::Duration; 34 | 35 | fn get_key() -> Result { 36 | let r = io::stdin(); 37 | let mut reader = r.lock(); 38 | let mut line = String::new(); 39 | 40 | println!("\nEnter a corresponding number or \"ESC\" to quit:"); 41 | print!("> "); 42 | match reader.read_line(&mut line) { 43 | Ok(_) => { 44 | let length = line.len() - 1; 45 | line.truncate(length); 46 | if &line == "ESC" { 47 | Ok(-1) 48 | } else { 49 | Ok(line.parse().unwrap()) 50 | } 51 | } 52 | Err(e) => Err(e) 53 | } 54 | } 55 | 56 | fn main() { 57 | let fmod = match rfmod::Sys::new() { 58 | Ok(f) => f, 59 | Err(e) => { 60 | panic!("Sys::new() : {:?}", e); 61 | } 62 | }; 63 | 64 | println!("--------------------------"); 65 | println!("--- SELECT OUTPUT TYPE ---"); 66 | println!("--------------------------"); 67 | println!("1 : OSS - Open Sound System"); 68 | println!("2 : ALSA - Advanced Linux Sound Architecture"); 69 | println!("3 : ESD - Enlightenment Sound Daemon"); 70 | println!("4 : PULSEAUDIO - Pulse Audio Sound Server"); 71 | println!("--------------------------"); 72 | 73 | let mut done = false; 74 | 75 | while done == false { 76 | match get_key() { 77 | Ok(n) => { 78 | match match n { 79 | 1 => Some(fmod.set_output(rfmod::OutputType::OSS)), 80 | 2 => Some(fmod.set_output(rfmod::OutputType::ALSA)), 81 | 3 => Some(fmod.set_output(rfmod::OutputType::ESD)), 82 | 4 => Some(fmod.set_output(rfmod::OutputType::PulseAudio)), 83 | -1 => { 84 | return; 85 | } 86 | _ => None 87 | } { 88 | Some(_) => { 89 | done = true; 90 | } 91 | _ => {} 92 | } 93 | } 94 | Err(e) => panic!("Input type error: {}", e), 95 | } 96 | } 97 | 98 | let num_drivers = match match fmod.get_num_drivers() { 99 | Ok(n) => n as usize, 100 | Err(e) => panic!("rfmod.get_num_drivers failed: {:?}", e) 101 | } { 102 | 0 => panic!("No driver available for this output type"), 103 | val => val 104 | }; 105 | let mut it = 0i32; 106 | 107 | println!("\n\n--------------------------------"); 108 | println!("--- CHOOSE A PLAYBACK DRIVER ---"); 109 | println!("--------------------------------"); 110 | while it < num_drivers as i32 { 111 | //check this function 112 | let t = match fmod.get_driver_info(it, 256usize) { 113 | Ok((_, name)) => name, 114 | Err(e) => panic!("get_driver_info error: {:?}", e) 115 | }; 116 | println!("{} : {}", it, t); 117 | it = it + 1; 118 | } 119 | 120 | loop { 121 | match get_key() { 122 | Ok(nb) => { 123 | match nb { 124 | -1 => return, 125 | nb if nb < num_drivers as isize => { 126 | fmod.set_driver(nb as i32); 127 | break; 128 | } 129 | _ => { 130 | print!("\nPlease press a corresponding number or ESC to quit\n> "); 131 | } 132 | } 133 | } 134 | Err(e) => { 135 | panic!("Input type error: {:?}", e); 136 | } 137 | } 138 | } 139 | 140 | match fmod.init() { 141 | rfmod::Status::Ok => {} 142 | e => { 143 | panic!("FmodSys.init failed : {:?}", e); 144 | } 145 | }; 146 | 147 | let mut exinfo : rfmod::CreateSoundexInfo = Default::default(); 148 | let secs = 5i32; 149 | 150 | exinfo.num_channels = 2; 151 | exinfo.format = rfmod::SoundFormat::PCM16; 152 | exinfo.default_frequency = 44100; 153 | exinfo.length = (exinfo.default_frequency * mem::size_of::() as i32 * exinfo.num_channels * secs) as u32; 154 | 155 | let sound = match fmod.create_sound("", Some(rfmod::Mode(rfmod::_2D | rfmod::SOFTWARE | rfmod::OPENUSER)), 156 | Some(&mut exinfo)) { 157 | Ok(s) => s, 158 | Err(e) => panic!("create sound error: {:?}", e) 159 | }; 160 | 161 | println!("\n========================="); 162 | println!("=== Recording example ==="); 163 | println!("=========================\n"); 164 | println!("Press '0' to record a {} seconds segment of audio.", secs); 165 | println!("Press '1' to play the {} seconds segment of audio.", secs); 166 | println!("Press '2' to save the {} seconds segment of audio into a file.", secs); 167 | 168 | let record_driver = 0; 169 | 170 | loop { 171 | match get_key() { 172 | Ok(nb) => { 173 | match match nb { 174 | 0 => { 175 | match fmod.start_record(record_driver, &sound, false) { 176 | rfmod::Status::Ok => { 177 | while match fmod.is_recording(record_driver) { 178 | Ok(r) => r, 179 | Err(e) => { 180 | println!("Error on rfmod.is_recording: {:?}", e); 181 | false 182 | } 183 | } { 184 | print!("\rRecording : {}", match fmod.get_record_position(record_driver) { 185 | Ok(p) => p, 186 | Err(e) => { 187 | println!("rfmod.get_record_position failed: {:?}", e); 188 | return; 189 | } 190 | }); 191 | fmod.update(); 192 | sleep(Duration::from_millis(15)) 193 | } 194 | Some(rfmod::Status::Ok) 195 | } 196 | e => Some(e) 197 | } 198 | }, 199 | 1 => { 200 | match sound.play() { 201 | Ok(chan) => { 202 | fmod.update(); 203 | while match chan.is_playing() { 204 | Ok(p) => p, 205 | Err(e) => { 206 | println!("channel.is_playing failed: {:?}", e); 207 | false 208 | } 209 | } { 210 | print!("\rPlaying : {} / {}", match chan.get_position(rfmod::TIMEUNIT_MS) { 211 | Ok(l) => l, 212 | Err(e) => { 213 | println!("channel.get_position failed: {:?}", e); 214 | return; 215 | } 216 | }, match sound.get_length(rfmod::TIMEUNIT_MS) { 217 | Ok(l) => l, 218 | Err(e) => { 219 | println!("sound.get_length failed: {:?}", e); 220 | return; 221 | } 222 | }); 223 | fmod.update(); 224 | sleep(Duration::from_millis(15)); 225 | } 226 | Some(rfmod::Status::Ok) 227 | } 228 | Err(e) => Some(e) 229 | } 230 | }, 231 | 2 => { 232 | print!("Please enter the output file name : "); 233 | let r = io::stdin(); 234 | let mut reader = r.lock(); 235 | let mut name = String::new(); 236 | 237 | match reader.read_line(&mut name) { 238 | Ok(_) => { 239 | name.pop().unwrap(); 240 | match sound.save_to_wav(&name) { 241 | Ok(b) => if b { 242 | println!("export succeeded"); 243 | None 244 | } else { 245 | println!("export failed"); 246 | None 247 | }, 248 | Err(e) => { 249 | println!("save_to_wav error: {}", e); 250 | None 251 | } 252 | } 253 | }, 254 | Err(_) => None 255 | } 256 | }, 257 | -1 => break, 258 | _ => None 259 | } { 260 | Some(r) if r == rfmod::Status::Ok => {} 261 | Some(e) => { 262 | println!("Error : {:?}", e); 263 | break; 264 | } 265 | None => {} 266 | } 267 | } 268 | Err(e) => { 269 | panic!("Input type error: {}", e) 270 | } 271 | } 272 | } 273 | } -------------------------------------------------------------------------------- /examples/simple_music_player/simple_music_player.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use std::thread::sleep; 30 | use std::time::Duration; 31 | 32 | fn play_to_the_end(sound: rfmod::Sound, len: usize) -> rfmod::Status { 33 | let length = match sound.get_length(rfmod::TIMEUNIT_MS) { 34 | Ok(l) => l, 35 | Err(e) => panic!("sound.get_length error: {:?}", e) 36 | }; 37 | let name = match sound.get_name(len) { 38 | Ok(n) => n, 39 | Err(e) => panic!("sound.get_name error: {:?}", e) 40 | }; 41 | let mut old_position = 100usize; 42 | 43 | match sound.play() { 44 | Ok(chan) => { 45 | loop { 46 | match chan.is_playing() { 47 | Ok(b) => { 48 | if b == true { 49 | let position = match chan.get_position(rfmod::TIMEUNIT_MS) { 50 | Ok(p) => p, 51 | Err(e) => { 52 | panic!("channel.get_position failed: {:?}", e) 53 | } 54 | }; 55 | 56 | if position != old_position { 57 | old_position = position; 58 | print!("\r{} : {:02}:{:02} / {:02}:{:02}", name, position / 1000 / 60, position / 1000 % 60, 59 | length / 1000 / 60, length / 1000 % 60); 60 | } 61 | sleep(Duration::from_millis(5)) 62 | } else { 63 | break; 64 | } 65 | }, 66 | Err(e) => return e, 67 | } 68 | } 69 | rfmod::Status::Ok 70 | } 71 | Err(err) => err, 72 | } 73 | } 74 | 75 | fn main() { 76 | let t_args = std::env::args(); 77 | let mut args = Vec::new(); 78 | 79 | for tmp in t_args { 80 | args.push(tmp); 81 | } 82 | let tmp = args[1..].to_owned(); 83 | 84 | if tmp.len() < 1 { 85 | panic!("USAGE: ./simple_music_player [music_file]"); 86 | } 87 | let fmod = match rfmod::Sys::new() { 88 | Ok(f) => f, 89 | Err(e) => { 90 | panic!("Sys::new() : {:?}", e); 91 | } 92 | }; 93 | 94 | match fmod.init() { 95 | rfmod::Status::Ok => {} 96 | e => { 97 | panic!("Sys::init() failed : {:?}", e); 98 | } 99 | }; 100 | 101 | let arg1 = tmp.get(0).unwrap(); 102 | 103 | let sound = match fmod.create_sound(&(*arg1), None, None) { 104 | Ok(s) => s, 105 | Err(err) => { 106 | panic!("Sys::create_sound() failed : {:?}", err); 107 | }, 108 | }; 109 | 110 | match play_to_the_end(sound, arg1.len()) { 111 | rfmod::Status::Ok => { 112 | println!("Ok !"); 113 | }, 114 | err => { 115 | panic!("Sys::play_to_the_end() : {:?}", err); 116 | } 117 | }; 118 | } -------------------------------------------------------------------------------- /examples/user_created_sound/user_created_sound.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | #![crate_type = "bin"] 26 | 27 | extern crate rfmod; 28 | 29 | use std::default::Default; 30 | use std::thread::sleep; 31 | use std::time::Duration; 32 | use std::io::{self, BufRead, Error}; 33 | 34 | #[allow(unused_variables)] 35 | fn pcmreadcallback(sound: &rfmod::Sound, data: &mut [i16]) -> rfmod::Status { 36 | static mut t1 : f32 = 0f32; // time 37 | static mut t2 : f32 = 0f32; // time 38 | static mut v1 : f32 = 0f32; // velocity 39 | static mut v2 : f32 = 0f32; // velocity 40 | let mut count = 0usize; 41 | 42 | while count < data.len() { 43 | unsafe { 44 | data[count] = (t1.sin() * 32767f32) as i16; // left channel 45 | count += 1; 46 | data[count] = (t2.sin() * 32767f32) as i16; // right channel 47 | count += 1; 48 | 49 | t1 += 0.01f32 + v1; 50 | t2 += 0.0142f32 + v2; 51 | v1 += t1.sin() * 0.002f32; 52 | v2 += t2.sin() * 0.002f32; 53 | } 54 | } 55 | 56 | rfmod::Status::Ok 57 | } 58 | 59 | fn get_key() -> Result { 60 | let r = io::stdin(); 61 | let mut reader = r.lock(); 62 | let mut line = String::new(); 63 | 64 | print!("> "); 65 | match reader.read_line(&mut line) { 66 | Ok(_) => { 67 | let length = line.len() - 1; 68 | 69 | line.truncate(length); 70 | if &line == "Quit" { 71 | Ok(-1) 72 | } else { 73 | Ok(line.parse().unwrap()) 74 | } 75 | } 76 | Err(e) => Err(e) 77 | } 78 | } 79 | 80 | fn main() { 81 | let channels = 2i32; 82 | let fmod = match rfmod::Sys::new() { 83 | Ok(f) => f, 84 | Err(e) => { 85 | panic!("Sys::new() : {:?}", e); 86 | } 87 | }; 88 | 89 | match fmod.init_with_parameters(32i32, rfmod::InitFlag(rfmod::INIT_NORMAL)) { 90 | rfmod::Status::Ok => {} 91 | e => { 92 | panic!("Sys::init() failed : {:?}", e); 93 | } 94 | }; 95 | 96 | println!("============================================================================"); 97 | println!("============== User Created Sound Example from FMOD examples ==============="); 98 | println!("============================================================================"); 99 | println!("Sound played here is generated in realtime. It will either play as a stream"); 100 | println!("which means it is continually filled as it is playing, or it will play as a"); 101 | println!("static sample, which means it is filled once as the sound is created, then"); 102 | println!("when played it will just play that short loop of data."); 103 | println!("============================================================================\n"); 104 | println!("Enter '1' to play as a runtime decoded stream. (will carry on infinitely)"); 105 | println!("Enter '2' to play as a static in memory sample. (loops a short block of data)"); 106 | println!("Enter 'Quit' to quit."); 107 | 108 | 109 | let mut ret = get_key().unwrap(); 110 | while ret != -1 && ret != 1 && ret != 2 { 111 | println!("Invalid entry"); 112 | ret = get_key().unwrap(); 113 | } 114 | let mut exinfo : rfmod::CreateSoundexInfo = Default::default(); 115 | 116 | exinfo.decode_buffer_size = 44100; 117 | exinfo.length = 44100u32 * channels as u32 * std::mem::size_of::() as u32 * 5u32; 118 | exinfo.num_channels = channels; 119 | exinfo.default_frequency = 44100; 120 | exinfo.format = rfmod::SoundFormat::PCM16; 121 | exinfo.pcm_read_callback = Some(pcmreadcallback as fn(&_, &mut _) -> _); 122 | 123 | let sound = match match ret { 124 | 1 => fmod.create_sound("", 125 | Some(rfmod::Mode(rfmod::_2D | rfmod::OPENUSER | rfmod::HARDWARE | rfmod::LOOP_NORMAL 126 | | rfmod::CREATESTREAM)), Some(&mut exinfo)), 127 | 2 => fmod.create_sound("", 128 | Some(rfmod::Mode(rfmod::_2D | rfmod::OPENUSER | rfmod::HARDWARE | rfmod::LOOP_NORMAL)), 129 | Some(&mut exinfo)), 130 | _ => return 131 | } { 132 | Ok(s) => s, 133 | Err(e) => panic!("create sound error: {:?}", e) 134 | }; 135 | 136 | let chan = match sound.play() { 137 | Ok(c) => c, 138 | Err(e) => panic!("sound.play error: {:?}", e) 139 | }; 140 | 141 | let length = match sound.get_length(rfmod::TIMEUNIT_MS) { 142 | Ok(l) => l, 143 | Err(e) => panic!("sound.get_length failed: {:?}", e) 144 | }; 145 | while match chan.is_playing() { 146 | Ok(p) => p, 147 | Err(e) => { 148 | println!("chan.is_playing failed: {:?}", e); 149 | false 150 | } 151 | } { 152 | let position = match chan.get_position(rfmod::TIMEUNIT_MS) { 153 | Ok(p) => p, 154 | Err(e) => { 155 | println!("channel.get_position failed: {:?}", e); 156 | return; 157 | } 158 | }; 159 | 160 | print!("{:02}:{:02} / {:02}:{:02}\r", position / 1000 / 60, position / 1000 % 60, length / 1000 / 60, length / 1000 % 60); 161 | sleep(Duration::from_millis(30)) 162 | } 163 | } -------------------------------------------------------------------------------- /src/async_read_info.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | use FmodFile; 26 | use ffi::FMOD_ASYNCREADINFO; 27 | 28 | use libc; 29 | 30 | pub struct AsyncReadInfo { 31 | /// [r] The file handle that was filled out in the open callback. 32 | pub handle : FmodFile, 33 | /// [r] Seek position, make sure you read from this file offset. 34 | pub offset : u32, 35 | /// [r] how many bytes requested for read. 36 | pub sizebytes : u32, 37 | /// [r] 0 = low importance. 100 = extremely important (ie 'must read now or stuttering may 38 | /// occur') 39 | pub priority : u32, 40 | /// [w] Buffer to read file data into. 41 | pub buffer : Vec, 42 | /// [r/w] Result code, Ok tells the system it is ready to consume the data. Set this last! 43 | /// 44 | /// Default value = FMOD_ERR_NOTREADY. 45 | pub result : ::Status, 46 | #[doc(hidden)] 47 | ffi: *mut ffi::FMOD_ASYNCREADINFO, 48 | } 49 | 50 | impl AsyncReadInfo { 51 | #[doc(hidden)] 52 | pub fn new(a: *mut ffi::FMOD_ASYNCREADINFO) -> AsyncReadInfo { 53 | unsafe { 54 | AsyncReadInfo { 55 | handle: file::from_ffi((*a).handle), 56 | offset: (*a).offset, 57 | sizebytes: (*a).sizebytes, 58 | priority: (*a).priority, 59 | buffer: Vec::new(), 60 | result: (*a).result, 61 | } 62 | } 63 | } 64 | 65 | #[doc(hidden)] 66 | pub fn to_ffi(self) -> *mut ffi::FMOD_ASYNCREADINFO { 67 | let mut out = self.ffi; 68 | 69 | unsafe { 70 | (*out).offset = self.offset; 71 | (*out).sizebytes = self.sizebytes; 72 | (*out).priority = self.priority; 73 | (*out).buffer = ::libc::malloc(self.buffer.len()); 74 | for (pos, i) in self.buffer.iter().enumerate() { 75 | *(out.offset(pos)) = i; 76 | } 77 | (*out).bytesread = self.buffer.len(); 78 | (*out).result = self.result; 79 | } 80 | out 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/callbacks.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | use dsp; 26 | use sound; 27 | use types::TimeUnit; 28 | use fmod_sys; 29 | use file; 30 | 31 | /*pub type SystemCallback = Option ::Status>;*/ 33 | 34 | /* file callbacks */ 35 | pub type FileOpenCallback = Option Option<(file::FmodFile, Option)>>; 36 | pub type FileCloseCallback = Option)>; 37 | pub type FileReadCallback = Option) -> usize>; 38 | pub type FileSeekCallback = Option)>; 39 | /*pub type FMOD_FILE_ASYNCREADCALLBACK = Option ::Status>; 40 | pub type FMOD_FILE_ASYNCCANCELCALLBACK = Option ::Status>;*/ 41 | 42 | /// sound callback 43 | pub type SoundNonBlockCallback = Option ::Status>; 44 | /// callback which allow to set/change data that will be played 45 | pub type SoundPcmReadCallback = Option ::Status>; 46 | /// notify the user that music position has changed 47 | pub type SoundPcmSetPosCallback = Option ::Status>; 48 | 49 | /* codec callbacks */ 50 | /*pub type FMOD_CODEC_OPENCALLBACK = Option ::Status>; 51 | pub type FMOD_CODEC_CLOSECALLBACK = Option ::Status>; 52 | pub type FMOD_CODEC_READCALLBACK = Option ::Status>; 53 | pub type FMOD_CODEC_GETLENGTHCALLBACK = Option ::Status>; 54 | pub type FMOD_CODEC_SETPOSITIONCALLBACK = Option ::Status>; 55 | pub type FMOD_CODEC_GETPOSITIONCALLBACK = Option ::Status>; 56 | pub type FMOD_CODEC_SOUNDCREATECALLBACK = Option ::Status>; 57 | pub type FMOD_CODEC_METADATACALLBACK = Option ::Status>; 59 | pub type FMOD_CODEC_GETWAVEFORMAT = Option ::Status>; 60 | pub type FMOD_3D_ROLLOFFCALLBACK = Option ::Status>;*/ 61 | 62 | /// notify the user that the DSP has been created 63 | pub type DspCreateCallback = Option ::Status>; 64 | /// notify the user that the DSP has been released 65 | pub type DspReleaseCallback = Option ::Status>; 66 | /// notify the user that the DSP has been reset 67 | pub type DspResetCallback = Option ::Status>; 68 | /// allow the user to modify data that will be read 69 | pub type DspReadCallback = Option ::Status>; 70 | /// notify the user that DSP position has changed 71 | pub type DspSetPositionCallback = Option ::Status>; 72 | /// DSP callback 73 | pub type DspSetParamCallback = Option ::Status>; 74 | /// DSP callback 75 | pub type DspGetParamCallback = Option ::Status>; 76 | /// DSP callback, not implemented yet 77 | pub type DspDialogCallback = Option ::Status>; 78 | -------------------------------------------------------------------------------- /src/channel.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 | 25 | use types::*; 26 | use libc::{c_int, c_void}; 27 | use ffi; 28 | use dsp::Dsp; 29 | use dsp_connection::DspConnection; 30 | use channel_group::ChannelGroup; 31 | use fmod_sys; 32 | use fmod_sys::{MemoryUsageDetails, Sys}; 33 | use vector; 34 | use sound::Sound; 35 | use std::mem::transmute; 36 | use std::default::Default; 37 | 38 | /// Structure which contains data for 39 | /// [`Channel::set_speaker_mix`](struct.Channel.html#method.set_speaker_mix) and 40 | /// [`Channel::get_speaker_mix`](struct.Channel.html#method.get_speaker_mix) 41 | #[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] 42 | pub struct SpeakerMixOptions { 43 | pub front_left : f32, 44 | pub front_right: f32, 45 | pub center : f32, 46 | pub lfe : f32, 47 | pub back_left : f32, 48 | pub back_right : f32, 49 | pub side_left : f32, 50 | pub side_right : f32 51 | } 52 | 53 | impl Default for SpeakerMixOptions { 54 | fn default() -> SpeakerMixOptions { 55 | SpeakerMixOptions { 56 | front_left: 0f32, 57 | front_right: 0f32, 58 | center: 0f32, 59 | lfe: 0f32, 60 | back_left: 0f32, 61 | back_right: 0f32, 62 | side_left: 0f32, 63 | side_right: 0f32 64 | } 65 | } 66 | } 67 | 68 | /// Structure defining the properties for a reverb source, related to a FMOD channel. 69 | pub struct ReverbChannelProperties { 70 | /// [r/w] MIN: -10000 MAX: 1000 DEFAULT: 0 71 | /// Direct path level 72 | pub direct : i32, 73 | /// [r/w] MIN: -10000 MAX: 1000 DEFAULT: 0 74 | /// Room effect level 75 | pub room : i32, 76 | /// [r/w] FMOD_REVERB_CHANNELFLAGS 77 | /// modifies the behavior of properties 78 | pub flags : u32, 79 | /// [r/w] See remarks. 80 | /// DSP network location to connect reverb for this channel. 81 | pub connection_point: Dsp 82 | } 83 | 84 | /// Channel Object 85 | pub struct Channel { 86 | channel: *mut ffi::FMOD_CHANNEL 87 | } 88 | 89 | impl Drop for Channel { 90 | fn drop(&mut self) { 91 | self.release(); 92 | } 93 | } 94 | 95 | impl ffi::FFI for Channel { 96 | fn wrap(channel: *mut ffi::FMOD_CHANNEL) -> Channel { 97 | Channel {channel: channel} 98 | } 99 | 100 | fn unwrap(c: &Channel) -> *mut ffi::FMOD_CHANNEL { 101 | c.channel 102 | } 103 | } 104 | 105 | impl Channel { 106 | pub fn new() -> Channel { 107 | Channel {channel: ::std::ptr::null_mut()} 108 | } 109 | 110 | pub fn release(&mut self) { 111 | self.channel = ::std::ptr::null_mut(); 112 | } 113 | 114 | pub fn get_system_object(&self) -> Result { 115 | let mut system = ::std::ptr::null_mut(); 116 | 117 | match unsafe { ffi::FMOD_Channel_GetSystemObject(self.channel, &mut system) } { 118 | ::Status::Ok => Ok(ffi::FFI::wrap(system)), 119 | e => Err(e) 120 | } 121 | } 122 | 123 | pub fn stop(&self) -> ::Status { 124 | unsafe { ffi::FMOD_Channel_Stop(self.channel) } 125 | } 126 | 127 | /// channel_offset: 0/1 -> left channel/right channel 128 | pub fn get_spectrum(&self, spectrum_size: usize, channel_offset: Option, window_type: Option<::DspFftWindow>) -> Result, ::Status> { 129 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(spectrum_size).collect(); 130 | let c_window_type = match window_type { 131 | Some(wt) => wt, 132 | None => ::DspFftWindow::Rect 133 | }; 134 | let c_channel_offset = match channel_offset { 135 | Some(co) => co, 136 | None => 0i32 137 | }; 138 | 139 | match unsafe { ffi::FMOD_Channel_GetSpectrum(self.channel, ptr.as_mut_ptr(), spectrum_size as c_int, c_channel_offset, c_window_type) } { 140 | ::Status::Ok => Ok(ptr), 141 | e => Err(e), 142 | } 143 | } 144 | 145 | pub fn get_wave_data(&self, wave_size: usize, channel_offset: i32) -> Result, ::Status> { 146 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(wave_size).collect(); 147 | 148 | match unsafe { ffi::FMOD_Channel_GetWaveData(self.channel, ptr.as_mut_ptr(), wave_size as c_int, channel_offset) } { 149 | ::Status::Ok => Ok(ptr), 150 | e => Err(e) 151 | } 152 | } 153 | 154 | pub fn is_init(&self) -> bool { 155 | !self.channel.is_null() 156 | } 157 | 158 | pub fn is_playing(&self) -> Result { 159 | let mut is_playing = 0; 160 | 161 | match unsafe { ffi::FMOD_Channel_IsPlaying(self.channel, &mut is_playing) } { 162 | ::Status::Ok => Ok(is_playing == 1), 163 | err => Err(err), 164 | } 165 | } 166 | 167 | pub fn is_virtual(&self) -> Result { 168 | let mut is_virtual = 0i32; 169 | 170 | match unsafe { ffi::FMOD_Channel_IsVirtual(self.channel, &mut is_virtual) } { 171 | ::Status::Ok => Ok(is_virtual == 1), 172 | e => Err(e) 173 | } 174 | } 175 | 176 | pub fn get_audibility(&self) -> Result { 177 | let mut audibility = 0f32; 178 | 179 | match unsafe { ffi::FMOD_Channel_GetAudibility(self.channel, &mut audibility) } { 180 | ::Status::Ok => Ok(audibility), 181 | e => Err(e) 182 | } 183 | } 184 | 185 | pub fn get_current_sound(&self) -> Result { 186 | let mut sound = ::std::ptr::null_mut(); 187 | 188 | match unsafe { ffi::FMOD_Channel_GetCurrentSound(self.channel, &mut sound) } { 189 | ::Status::Ok => Ok(ffi::FFI::wrap(sound)), 190 | e => Err(e) 191 | } 192 | } 193 | 194 | pub fn get_index(&self) -> Result { 195 | let mut index = 0i32; 196 | 197 | match unsafe { ffi::FMOD_Channel_GetIndex(self.channel, &mut index) } { 198 | ::Status::Ok => Ok(index), 199 | e => Err(e) 200 | } 201 | } 202 | 203 | pub fn set_volume(&self, volume: f32) -> ::Status { 204 | unsafe { ffi::FMOD_Channel_SetVolume(self.channel, volume) } 205 | } 206 | 207 | pub fn get_volume(&self) -> Result { 208 | let mut volume = 0f32; 209 | 210 | match unsafe { ffi::FMOD_Channel_GetVolume(self.channel, &mut volume) } { 211 | ::Status::Ok => Ok(volume), 212 | e => Err(e), 213 | } 214 | } 215 | 216 | pub fn set_frequency(&self, frequency: f32) -> ::Status { 217 | unsafe { ffi::FMOD_Channel_SetFrequency(self.channel, frequency) } 218 | } 219 | 220 | pub fn get_frequency(&self) -> Result { 221 | let mut frequency = 0f32; 222 | 223 | match unsafe { ffi::FMOD_Channel_GetFrequency(self.channel, &mut frequency) } { 224 | ::Status::Ok => Ok(frequency), 225 | e => Err(e), 226 | } 227 | } 228 | 229 | pub fn set_pan(&self, pan: f32) -> ::Status { 230 | unsafe { ffi::FMOD_Channel_SetPan(self.channel, pan) } 231 | } 232 | 233 | pub fn get_pan(&self) -> Result { 234 | let mut pan = 0f32; 235 | 236 | match unsafe { ffi::FMOD_Channel_GetPan(self.channel, &mut pan) } { 237 | ::Status::Ok => Ok(pan), 238 | e => Err(e), 239 | } 240 | } 241 | 242 | pub fn set_mute(&self, mute: bool) -> ::Status { 243 | let t = match mute { 244 | true => 1, 245 | false => 0, 246 | }; 247 | unsafe { ffi::FMOD_Channel_SetMute(self.channel, t) } 248 | } 249 | 250 | pub fn get_mute(&self) -> Result { 251 | let mut mute = 0; 252 | 253 | match unsafe { ffi::FMOD_Channel_GetMute(self.channel, &mut mute) } { 254 | ::Status::Ok => Ok(match mute { 255 | 1 => true, 256 | _ => false, 257 | }), 258 | e => Err(e), 259 | } 260 | } 261 | 262 | pub fn set_paused(&self, paused: bool) -> ::Status { 263 | let t: ffi::FMOD_BOOL = match paused { 264 | true => 1, 265 | false => 0, 266 | }; 267 | unsafe { ffi::FMOD_Channel_SetPaused(self.channel, t) } 268 | } 269 | 270 | pub fn get_paused(&self) -> Result { 271 | let mut t = 0; 272 | 273 | match unsafe { ffi::FMOD_Channel_GetPaused(self.channel, &mut t) } { 274 | ::Status::Ok => Ok(match t { 275 | 1 => true, 276 | _ => false, 277 | }), 278 | e => Err(e), 279 | } 280 | } 281 | 282 | pub fn set_delay(&self, delay_type: ::DelayType, delay_hi: usize, 283 | delay_lo: usize) -> ::Status { 284 | unsafe { ffi::FMOD_Channel_SetDelay(self.channel, delay_type, delay_hi as u32, 285 | delay_lo as u32) } 286 | } 287 | 288 | pub fn get_delay(&self, delay_type: ::DelayType) 289 | -> Result<(::DelayType, usize, usize), ::Status> { 290 | let mut delaylo = 0u32; 291 | let mut delayhi = 0u32; 292 | 293 | match unsafe { ffi::FMOD_Channel_GetDelay(self.channel, delay_type, &mut delayhi, 294 | &mut delaylo) } { 295 | ::Status::Ok => Ok((delay_type, delayhi as usize, delaylo as usize)), 296 | e => Err(e), 297 | } 298 | } 299 | 300 | pub fn set_speaker_mix(&self, smo: &SpeakerMixOptions) -> ::Status { 301 | unsafe { ffi::FMOD_Channel_SetSpeakerMix(self.channel, smo.front_left, smo.front_right, 302 | smo.center, smo.lfe, smo.back_left, smo.back_right, 303 | smo.side_left, smo.side_right) } 304 | } 305 | 306 | pub fn get_speaker_mix(&self) -> Result { 307 | let mut smo = SpeakerMixOptions{ 308 | front_left: 0f32, 309 | front_right: 0f32, 310 | center: 0f32, 311 | lfe: 0f32, 312 | back_left: 0f32, 313 | back_right: 0f32, 314 | side_left: 0f32, 315 | side_right: 0f32 316 | }; 317 | 318 | match unsafe { ffi::FMOD_Channel_GetSpeakerMix(self.channel, &mut smo.front_left, 319 | &mut smo.front_right, &mut smo.center, 320 | &mut smo.lfe, &mut smo.back_left, 321 | &mut smo.back_right, &mut smo.side_left, 322 | &mut smo.side_right) } { 323 | ::Status::Ok => Ok(smo), 324 | e => Err(e), 325 | } 326 | } 327 | 328 | pub fn set_speaker_level(&self, speaker: ::Speaker, levels: &mut Vec) -> ::Status { 329 | unsafe { ffi::FMOD_Channel_SetSpeakerLevels(self.channel, speaker, levels.as_mut_ptr(), 330 | levels.len() as i32) } 331 | } 332 | 333 | pub fn get_speaker_level(&self, speaker: ::Speaker, 334 | num_levels: usize) -> Result, ::Status> { 335 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(num_levels).collect(); 336 | 337 | match unsafe { ffi::FMOD_Channel_GetSpeakerLevels(self.channel, speaker, ptr.as_mut_ptr(), 338 | num_levels as i32) } { 339 | ::Status::Ok => Ok(ptr), 340 | e => Err(e), 341 | } 342 | } 343 | 344 | pub fn set_input_channel_mix(&self, levels: &mut Vec) -> ::Status { 345 | unsafe { ffi::FMOD_Channel_SetInputChannelMix(self.channel, levels.as_mut_ptr(), 346 | levels.len() as i32) } 347 | } 348 | 349 | pub fn get_input_channel_mix(&self, num_levels: usize) -> Result, ::Status> { 350 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(num_levels).collect(); 351 | 352 | match unsafe { ffi::FMOD_Channel_GetInputChannelMix(self.channel, ptr.as_mut_ptr(), 353 | num_levels as i32) } { 354 | ::Status::Ok => Ok(ptr), 355 | e => Err(e), 356 | } 357 | } 358 | 359 | pub fn set_priority(&self, priority: i32) -> ::Status { 360 | unsafe { ffi::FMOD_Channel_SetPriority(self.channel, priority) } 361 | } 362 | 363 | pub fn get_priority(&self) -> Result { 364 | let mut t = 0i32; 365 | 366 | match unsafe { ffi::FMOD_Channel_GetPriority(self.channel, &mut t) } { 367 | ::Status::Ok => Ok(t), 368 | e => Err(e), 369 | } 370 | } 371 | 372 | pub fn set_position(&self, position: usize, TimeUnit(postype): TimeUnit) -> ::Status { 373 | unsafe { ffi::FMOD_Channel_SetPosition(self.channel, position as u32, postype) } 374 | } 375 | 376 | pub fn get_position(&self, TimeUnit(postype): TimeUnit) -> Result { 377 | let mut t = 0u32; 378 | 379 | match unsafe { ffi::FMOD_Channel_GetPosition(self.channel, &mut t, postype) } { 380 | ::Status::Ok => Ok(t as usize), 381 | e => Err(e), 382 | } 383 | } 384 | 385 | pub fn set_reverb_properties(&self, prop: &ReverbChannelProperties) -> ::Status { 386 | let t = ffi::FMOD_REVERB_CHANNELPROPERTIES{ 387 | Direct: prop.direct, 388 | Room: prop.room, 389 | Flags: prop.flags, 390 | ConnectionPoint: ::std::ptr::null_mut() 391 | }; 392 | 393 | unsafe { ffi::FMOD_Channel_SetReverbProperties(self.channel, &t) } 394 | } 395 | 396 | pub fn get_reverb_properties(&self) -> Result { 397 | let mut t = ffi::FMOD_REVERB_CHANNELPROPERTIES{ 398 | Direct: 0, 399 | Room: 0, 400 | Flags: 0, 401 | ConnectionPoint: ::std::ptr::null_mut() 402 | }; 403 | 404 | match unsafe { ffi::FMOD_Channel_GetReverbProperties(self.channel, &mut t) } { 405 | ::Status::Ok => Ok(ReverbChannelProperties{ 406 | direct: t.Direct, 407 | room: t.Room, 408 | flags: t.Flags, 409 | connection_point: ffi::FFI::wrap(t.ConnectionPoint)}), 410 | e => Err(e), 411 | } 412 | } 413 | 414 | pub fn set_low_pass_gain(&self, gain: f32) -> ::Status { 415 | unsafe { ffi::FMOD_Channel_SetLowPassGain(self.channel, gain) } 416 | } 417 | 418 | pub fn get_low_pass_gain(&self) -> Result { 419 | let mut t = 0f32; 420 | 421 | match unsafe { ffi::FMOD_Channel_GetLowPassGain(self.channel, &mut t) } { 422 | ::Status::Ok => Ok(t), 423 | e => Err(e), 424 | } 425 | } 426 | 427 | pub fn set_channel_group(&mut self, channel_group: &ChannelGroup) -> ::Status { 428 | unsafe { ffi::FMOD_Channel_SetChannelGroup(self.channel, ffi::FFI::unwrap(channel_group)) } 429 | } 430 | 431 | pub fn get_channel_group(&self) -> Result { 432 | let mut channel_group = ::std::ptr::null_mut(); 433 | 434 | match unsafe { ffi::FMOD_Channel_GetChannelGroup(self.channel, &mut channel_group) } { 435 | ::Status::Ok => Ok(ffi::FFI::wrap(channel_group)), 436 | e => Err(e) 437 | } 438 | } 439 | 440 | pub fn set_3D_attributes(&self, position: &vector::Vector, 441 | velocity: &vector::Vector) -> ::Status { 442 | let mut t_position = vector::get_ffi(position); 443 | let mut t_velocity = vector::get_ffi(velocity); 444 | 445 | unsafe { ffi::FMOD_Channel_Set3DAttributes(self.channel, &mut t_position, &mut t_velocity) } 446 | } 447 | 448 | pub fn get_3D_attributes(&self) -> Result<(vector::Vector, vector::Vector), ::Status> { 449 | let mut position = vector::get_ffi(&vector::Vector::new()); 450 | let mut velocity = vector::get_ffi(&vector::Vector::new()); 451 | 452 | match unsafe { ffi::FMOD_Channel_Get3DAttributes(self.channel, &mut position, 453 | &mut velocity) } { 454 | ::Status::Ok => Ok((vector::from_ptr(position), vector::from_ptr(velocity))), 455 | e => Err(e) 456 | } 457 | } 458 | 459 | pub fn set_3D_min_max_distance(&self, min_distance: f32, max_distance: f32) -> ::Status { 460 | unsafe { ffi::FMOD_Channel_Set3DMinMaxDistance(self.channel, min_distance, max_distance) } 461 | } 462 | 463 | pub fn get_3D_min_max_distance(&self) -> Result<(f32, f32), ::Status> { 464 | let mut min_distance = 0f32; 465 | let mut max_distance = 0f32; 466 | 467 | match unsafe { ffi::FMOD_Channel_Get3DMinMaxDistance(self.channel, &mut min_distance, 468 | &mut max_distance) } { 469 | ::Status::Ok => Ok((min_distance, max_distance)), 470 | e => Err(e) 471 | } 472 | } 473 | 474 | pub fn set_3D_cone_settings(&self, inside_cone_angle: f32, outside_cone_angle: f32, 475 | outside_volume: f32) -> ::Status { 476 | unsafe { ffi::FMOD_Channel_Set3DConeSettings(self.channel, inside_cone_angle, 477 | outside_cone_angle, outside_volume) } 478 | } 479 | 480 | pub fn get_3D_cone_settings(&self) -> Result<(f32, f32, f32), ::Status> { 481 | let mut inside_cone_angle = 0f32; 482 | let mut outside_cone_angle = 0f32; 483 | let mut outside_volume = 0f32; 484 | 485 | match unsafe { ffi::FMOD_Channel_Get3DConeSettings(self.channel, &mut inside_cone_angle, 486 | &mut outside_cone_angle, 487 | &mut outside_volume) } { 488 | ::Status::Ok => Ok((inside_cone_angle, outside_cone_angle, outside_volume)), 489 | e => Err(e) 490 | } 491 | } 492 | 493 | pub fn set_3D_cone_orientation(&self, orientation: &vector::Vector) -> ::Status { 494 | let mut t_orientation = vector::get_ffi(orientation); 495 | 496 | unsafe { ffi::FMOD_Channel_Set3DConeOrientation(self.channel, &mut t_orientation) } 497 | } 498 | 499 | pub fn get_3D_cone_orientation(&self) -> Result { 500 | let mut orientation = vector::get_ffi(&vector::Vector::new()); 501 | 502 | match unsafe { ffi::FMOD_Channel_Get3DConeOrientation(self.channel, &mut orientation) } { 503 | ::Status::Ok => Ok(vector::from_ptr(orientation)), 504 | e => Err(e) 505 | } 506 | } 507 | 508 | pub fn set_3D_custom_rolloff(&self, points: &Vec) -> ::Status { 509 | let mut t_points = Vec::new(); 510 | 511 | for tmp in points.iter() { 512 | t_points.push(vector::get_ffi(tmp)); 513 | } 514 | unsafe { ffi::FMOD_Channel_Set3DCustomRolloff(self.channel, t_points.as_mut_ptr(), 515 | points.len() as c_int) } 516 | } 517 | 518 | pub fn get_3D_custom_rolloff(&self) -> Result, ::Status> { 519 | let mut points = ::std::ptr::null_mut(); 520 | let mut num_points = 0i32; 521 | 522 | unsafe { 523 | match ffi::FMOD_Channel_Get3DCustomRolloff(self.channel, &mut points, &mut num_points) { 524 | ::Status::Ok => { 525 | let mut ret_points = Vec::new(); 526 | 527 | for it in 0i32..num_points { 528 | ret_points.push(vector::from_ptr(::std::ptr::read( 529 | points.offset(it as isize) as *const ffi::FMOD_VECTOR))); 530 | } 531 | Ok(ret_points) 532 | } 533 | e => Err(e) 534 | } 535 | } 536 | } 537 | 538 | pub fn set_3D_occlusion(&self, direct_occlusion: f32, reverb_occlusion: f32) -> ::Status { 539 | unsafe { ffi::FMOD_Channel_Set3DOcclusion(self.channel, direct_occlusion, 540 | reverb_occlusion) } 541 | } 542 | 543 | pub fn get_3D_occlusion(&self) -> Result<(f32, f32), ::Status> { 544 | let mut direct_occlusion = 0f32; 545 | let mut reverb_occlusion = 0f32; 546 | 547 | match unsafe { ffi::FMOD_Channel_Get3DOcclusion(self.channel, &mut direct_occlusion, 548 | &mut reverb_occlusion) } { 549 | ::Status::Ok => Ok((direct_occlusion, reverb_occlusion)), 550 | e => Err(e) 551 | } 552 | } 553 | 554 | pub fn set_3D_spread(&self, angle: f32) -> ::Status { 555 | unsafe { ffi::FMOD_Channel_Set3DSpread(self.channel, angle) } 556 | } 557 | 558 | pub fn get_3D_spread(&self) -> Result { 559 | let mut angle = 0f32; 560 | 561 | match unsafe { ffi::FMOD_Channel_Get3DSpread(self.channel, &mut angle) } { 562 | ::Status::Ok => Ok(angle), 563 | e => Err(e) 564 | } 565 | } 566 | 567 | pub fn set_3D_pan_level(&self, level: f32) -> ::Status { 568 | unsafe { ffi::FMOD_Channel_Set3DPanLevel(self.channel, level) } 569 | } 570 | 571 | pub fn get_3D_pan_level(&self) -> Result { 572 | let mut level = 0f32; 573 | 574 | match unsafe { ffi::FMOD_Channel_Get3DPanLevel(self.channel, &mut level) } { 575 | ::Status::Ok => Ok(level), 576 | e => Err(e) 577 | } 578 | } 579 | 580 | pub fn set_3D_doppler_level(&self, level: f32) -> ::Status { 581 | unsafe { ffi::FMOD_Channel_Set3DDopplerLevel(self.channel, level) } 582 | } 583 | 584 | pub fn get_3D_doppler_level(&self) -> Result { 585 | let mut level = 0f32; 586 | 587 | match unsafe { ffi::FMOD_Channel_Get3DDopplerLevel(self.channel, &mut level) } { 588 | ::Status::Ok => Ok(level), 589 | e => Err(e) 590 | } 591 | } 592 | 593 | pub fn set_3D_distance_filter(&self, custom: bool, custom_level: f32, 594 | center_freq: f32) -> ::Status { 595 | unsafe { ffi::FMOD_Channel_Set3DDistanceFilter(self.channel, if custom { 596 | 1 597 | } else { 598 | 0 599 | }, custom_level, center_freq) } 600 | } 601 | 602 | pub fn get_3D_distance_filter(&self) -> Result<(bool, f32, f32), ::Status> { 603 | let mut custom = 0i32; 604 | let mut custom_level = 0f32; 605 | let mut center_freq = 0f32; 606 | 607 | match unsafe { ffi::FMOD_Channel_Get3DDistanceFilter(self.channel, &mut custom, 608 | &mut custom_level, 609 | &mut center_freq) } { 610 | ::Status::Ok => Ok((custom == 1, custom_level, center_freq)), 611 | e => Err(e) 612 | } 613 | } 614 | 615 | pub fn get_DSP_head(&self) -> Result { 616 | let mut dsp = ::std::ptr::null_mut(); 617 | 618 | match unsafe { ffi::FMOD_Channel_GetDSPHead(self.channel, &mut dsp) } { 619 | ::Status::Ok => Ok(ffi::FFI::wrap(dsp)), 620 | e => Err(e) 621 | } 622 | } 623 | 624 | pub fn add_DSP(&self, dsp: &Dsp) -> Result { 625 | let mut connection = ::std::ptr::null_mut(); 626 | 627 | match unsafe { ffi::FMOD_Channel_AddDSP(self.channel, ffi::FFI::unwrap(dsp), 628 | &mut connection) } { 629 | ::Status::Ok => Ok(ffi::FFI::wrap(connection)), 630 | e => Err(e) 631 | } 632 | } 633 | 634 | pub fn set_mode(&self, Mode(mode): Mode) -> ::Status { 635 | unsafe { ffi::FMOD_Channel_SetMode(self.channel, mode) } 636 | } 637 | 638 | pub fn get_mode(&self) -> Result { 639 | let mut mode = 0u32; 640 | 641 | match unsafe { ffi::FMOD_Channel_GetMode(self.channel, &mut mode) } { 642 | ::Status::Ok => Ok(Mode(mode)), 643 | e => Err(e) 644 | } 645 | } 646 | 647 | pub fn set_loop_count(&self, loop_count: i32) -> ::Status { 648 | unsafe { ffi::FMOD_Channel_SetLoopCount(self.channel, loop_count) } 649 | } 650 | 651 | pub fn get_loop_count(&self) -> Result { 652 | let mut loop_count = 0i32; 653 | 654 | match unsafe { ffi::FMOD_Channel_GetLoopCount(self.channel, &mut loop_count) } { 655 | ::Status::Ok => Ok(loop_count), 656 | e => Err(e) 657 | } 658 | } 659 | 660 | pub fn set_loop_points(&self, loop_start: u32, TimeUnit(loop_start_type): TimeUnit, 661 | loop_end: u32, TimeUnit(loop_end_type): TimeUnit) -> ::Status { 662 | unsafe { ffi::FMOD_Channel_SetLoopPoints(self.channel, loop_start, loop_start_type, 663 | loop_end, loop_end_type) } 664 | } 665 | 666 | pub fn get_loop_points(&self, TimeUnit(loop_start_type): TimeUnit, 667 | TimeUnit(loop_end_type): TimeUnit) -> Result<(u32, u32), ::Status> { 668 | let mut loop_start = 0u32; 669 | let mut loop_end = 0u32; 670 | 671 | match unsafe { ffi::FMOD_Channel_GetLoopPoints(self.channel, &mut loop_start, 672 | loop_start_type, &mut loop_end, 673 | loop_end_type) } { 674 | ::Status::Ok => Ok((loop_start, loop_end)), 675 | e => Err(e) 676 | } 677 | } 678 | 679 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 680 | unsafe { ffi::FMOD_Channel_SetUserData(self.channel, transmute(user_data)) } 681 | } 682 | 683 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 684 | unsafe { 685 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 686 | 687 | match ffi::FMOD_Channel_GetUserData(self.channel, &mut user_data) { 688 | ::Status::Ok => { 689 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 690 | 691 | Ok(tmp) 692 | }, 693 | e => Err(e) 694 | } 695 | } 696 | } 697 | 698 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 699 | EventMemoryBits(event_memory_bits): EventMemoryBits) 700 | -> Result<(u32, MemoryUsageDetails), ::Status> { 701 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 702 | let mut memory_used = 0u32; 703 | 704 | match unsafe { ffi::FMOD_Channel_GetMemoryInfo(self.channel, memory_bits, event_memory_bits, 705 | &mut memory_used, &mut details) } { 706 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 707 | e => Err(e) 708 | } 709 | } 710 | } 711 | -------------------------------------------------------------------------------- /src/channel_group.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 | 25 | use types::*; 26 | use ffi; 27 | use channel; 28 | use dsp; 29 | use dsp_connection; 30 | use libc::{c_int, c_void}; 31 | use vector; 32 | use fmod_sys; 33 | use fmod_sys::MemoryUsageDetails; 34 | use std::mem::transmute; 35 | use libc::{c_char}; 36 | use std::default::Default; 37 | 38 | /// ChannelGroup object 39 | pub struct ChannelGroup { 40 | channel_group: *mut ffi::FMOD_CHANNELGROUP, 41 | } 42 | 43 | impl Drop for ChannelGroup { 44 | fn drop(&mut self) { 45 | self.release(); 46 | } 47 | } 48 | 49 | impl ffi::FFI for ChannelGroup { 50 | fn wrap(channel_group: *mut ffi::FMOD_CHANNELGROUP) -> ChannelGroup { 51 | ChannelGroup {channel_group: channel_group} 52 | } 53 | 54 | fn unwrap(c: &ChannelGroup) -> *mut ffi::FMOD_CHANNELGROUP { 55 | c.channel_group 56 | } 57 | } 58 | 59 | impl ChannelGroup { 60 | pub fn release(&mut self) -> ::Status { 61 | if !self.channel_group.is_null() { 62 | match unsafe { ffi::FMOD_ChannelGroup_Release(self.channel_group) } { 63 | ::Status::Ok => { 64 | self.channel_group = ::std::ptr::null_mut(); 65 | ::Status::Ok 66 | } 67 | e => e 68 | } 69 | } else { 70 | ::Status::Ok 71 | } 72 | } 73 | 74 | pub fn set_volume(&self, volume: f32) -> ::Status { 75 | unsafe { ffi::FMOD_ChannelGroup_SetVolume(self.channel_group, volume) } 76 | } 77 | 78 | pub fn get_volume(&self) -> Result { 79 | let mut volume = 0f32; 80 | 81 | match unsafe { ffi::FMOD_ChannelGroup_GetVolume(self.channel_group, &mut volume) } { 82 | ::Status::Ok => Ok(volume), 83 | e => Err(e) 84 | } 85 | } 86 | 87 | pub fn set_pitch(&self, pitch: f32) -> ::Status { 88 | unsafe { ffi::FMOD_ChannelGroup_SetPitch(self.channel_group, pitch) } 89 | } 90 | 91 | pub fn get_pitch(&self) -> Result { 92 | let mut pitch = 0f32; 93 | 94 | match unsafe { ffi::FMOD_ChannelGroup_GetPitch(self.channel_group, &mut pitch) } { 95 | ::Status::Ok => Ok(pitch), 96 | e => Err(e) 97 | } 98 | } 99 | 100 | pub fn set_paused(&self, paused: bool) -> ::Status { 101 | let t_paused = match paused { 102 | true => 1, 103 | _ => 0 104 | }; 105 | 106 | unsafe { ffi::FMOD_ChannelGroup_SetPaused(self.channel_group, t_paused) } 107 | } 108 | 109 | pub fn get_paused(&self) -> Result { 110 | let mut paused = 0; 111 | 112 | match unsafe { ffi::FMOD_ChannelGroup_GetPaused(self.channel_group, &mut paused) } { 113 | ::Status::Ok => Ok(match paused { 114 | 1 => true, 115 | _ => false 116 | }), 117 | e => Err(e) 118 | } 119 | } 120 | 121 | pub fn set_mute(&self, mute: bool) -> ::Status { 122 | let t_mute = match mute { 123 | true => 1, 124 | _ => 0 125 | }; 126 | 127 | unsafe { ffi::FMOD_ChannelGroup_SetMute(self.channel_group, t_mute) } 128 | } 129 | 130 | pub fn get_mute(&self) -> Result { 131 | let mut mute = 0; 132 | 133 | match unsafe { ffi::FMOD_ChannelGroup_GetMute(self.channel_group, &mut mute) } { 134 | ::Status::Ok => Ok(match mute { 135 | 1 => true, 136 | _ => false 137 | }), 138 | e => Err(e) 139 | } 140 | } 141 | 142 | pub fn set_3D_occlusion(&self, direct_occlusion: f32, reverb_occlusion: f32) -> ::Status { 143 | unsafe { ffi::FMOD_ChannelGroup_Set3DOcclusion(self.channel_group, direct_occlusion, 144 | reverb_occlusion) } 145 | } 146 | 147 | pub fn get_3D_occlusion(&self) -> Result<(f32, f32), ::Status> { 148 | let mut direct_occlusion = 0f32; 149 | let mut reverb_occlusion = 0f32; 150 | 151 | match unsafe { ffi::FMOD_ChannelGroup_Get3DOcclusion(self.channel_group, 152 | &mut direct_occlusion, 153 | &mut reverb_occlusion) } { 154 | ::Status::Ok => Ok((direct_occlusion, reverb_occlusion)), 155 | e => Err(e) 156 | } 157 | } 158 | 159 | pub fn stop(&self) -> ::Status { 160 | unsafe { ffi::FMOD_ChannelGroup_Stop(self.channel_group) } 161 | } 162 | 163 | pub fn override_volume(&self, volume: f32) -> ::Status { 164 | unsafe { ffi::FMOD_ChannelGroup_OverrideVolume(self.channel_group, volume) } 165 | } 166 | 167 | pub fn override_frequency(&self, frequency: f32) -> ::Status { 168 | unsafe { ffi::FMOD_ChannelGroup_OverrideFrequency(self.channel_group, frequency) } 169 | } 170 | 171 | pub fn override_pan(&self, pan: f32) -> ::Status { 172 | unsafe { ffi::FMOD_ChannelGroup_OverridePan(self.channel_group, pan) } 173 | } 174 | 175 | pub fn override_reverb_properties(&self, properties: &channel::ReverbChannelProperties) 176 | -> ::Status { 177 | let prop = ffi::FMOD_REVERB_CHANNELPROPERTIES{ 178 | Direct: properties.direct, 179 | Room: properties.room, 180 | Flags: properties.flags, 181 | ConnectionPoint: ffi::FFI::unwrap(&properties.connection_point) 182 | }; 183 | 184 | unsafe { ffi::FMOD_ChannelGroup_OverrideReverbProperties(self.channel_group, &prop) } 185 | } 186 | 187 | pub fn override_3D_attributes(&self, pos: &vector::Vector, vel: &vector::Vector) -> ::Status { 188 | let mut t_pos = vector::get_ffi(pos); 189 | let mut t_vel = vector::get_ffi(vel); 190 | 191 | unsafe { ffi::FMOD_ChannelGroup_Override3DAttributes(self.channel_group, &mut t_pos, 192 | &mut t_vel) } 193 | } 194 | 195 | pub fn override_speaker_mix(&self, front_left: f32, front_right: f32, center: f32, lfe: f32, 196 | back_left: f32, back_right: f32, side_left: f32, 197 | side_right: f32) -> ::Status { 198 | unsafe { ffi::FMOD_ChannelGroup_OverrideSpeakerMix(self.channel_group, front_left, 199 | front_right, center, lfe, back_left, 200 | back_right, side_left, side_right) } 201 | } 202 | 203 | pub fn add_group(&self, group: &ChannelGroup) -> ::Status { 204 | unsafe { ffi::FMOD_ChannelGroup_AddGroup(self.channel_group, group.channel_group) } 205 | } 206 | 207 | pub fn get_num_groups(&self) -> Result { 208 | let mut index = 0i32; 209 | 210 | match unsafe { ffi::FMOD_ChannelGroup_GetNumGroups(self.channel_group, &mut index) } { 211 | ::Status::Ok => Ok(index), 212 | e => Err(e) 213 | } 214 | } 215 | 216 | pub fn get_group(&self, index: i32) -> Result { 217 | let mut group = ::std::ptr::null_mut(); 218 | 219 | match unsafe { ffi::FMOD_ChannelGroup_GetGroup(self.channel_group, index, &mut group) } { 220 | ::Status::Ok => Ok(ChannelGroup{channel_group: group}), 221 | e => Err(e) 222 | } 223 | } 224 | 225 | pub fn get_parent_group(&self) -> Result { 226 | let mut parent_group = ::std::ptr::null_mut(); 227 | 228 | match unsafe { ffi::FMOD_ChannelGroup_GetParentGroup(self.channel_group, 229 | &mut parent_group) } { 230 | ::Status::Ok => Ok(ChannelGroup{channel_group: parent_group}), 231 | e => Err(e) 232 | } 233 | } 234 | 235 | pub fn get_DSP_head(&self) -> Result { 236 | let mut dsp = ::std::ptr::null_mut(); 237 | 238 | match unsafe { ffi::FMOD_ChannelGroup_GetDSPHead(self.channel_group, &mut dsp) } { 239 | ::Status::Ok => Ok(ffi::FFI::wrap(dsp)), 240 | e => Err(e) 241 | } 242 | } 243 | 244 | pub fn add_DSP(&self, dsp: &dsp::Dsp) -> Result { 245 | let mut dsp_connection = ::std::ptr::null_mut(); 246 | 247 | match unsafe { ffi::FMOD_ChannelGroup_AddDSP(self.channel_group, ffi::FFI::unwrap(dsp), 248 | &mut dsp_connection) } { 249 | ::Status::Ok => Ok(ffi::FFI::wrap(dsp_connection)), 250 | e => Err(e) 251 | } 252 | } 253 | 254 | pub fn get_name(&self, name_len: usize) -> Result { 255 | let mut c = Vec::with_capacity(name_len + 1); 256 | 257 | for _ in 0..(name_len + 1) { 258 | c.push(0); 259 | } 260 | 261 | match unsafe { ffi::FMOD_ChannelGroup_GetName(self.channel_group, 262 | c.as_mut_ptr() as *mut c_char, 263 | name_len as i32) } { 264 | ::Status::Ok => Ok(from_utf8!(c)), 265 | e => Err(::RStatus::FMOD(e)), 266 | } 267 | } 268 | 269 | pub fn get_num_channels(&self) -> Result { 270 | let mut num_channels = 0i32; 271 | 272 | match unsafe { ffi::FMOD_ChannelGroup_GetNumChannels(self.channel_group, 273 | &mut num_channels) } { 274 | ::Status::Ok => Ok(num_channels as u32), 275 | e => Err(e) 276 | } 277 | } 278 | 279 | pub fn get_channel(&self, index: i32) -> Result { 280 | let mut channel = ::std::ptr::null_mut(); 281 | 282 | match unsafe { ffi::FMOD_ChannelGroup_GetChannel(self.channel_group, index, 283 | &mut channel) } { 284 | ::Status::Ok => Ok(ffi::FFI::wrap(channel)), 285 | e => Err(e) 286 | } 287 | } 288 | 289 | pub fn get_spectrum(&self, spectrum_size: usize, channel_offset: Option, 290 | window_type: Option<::DspFftWindow>) -> Result, ::Status> { 291 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(spectrum_size).collect(); 292 | let c_window_type = match window_type { 293 | Some(wt) => wt, 294 | None => ::DspFftWindow::Rect 295 | }; 296 | let c_channel_offset = channel_offset.unwrap_or(0); 297 | 298 | match unsafe { ffi::FMOD_ChannelGroup_GetSpectrum(self.channel_group, ptr.as_mut_ptr(), 299 | spectrum_size as c_int, c_channel_offset, 300 | c_window_type) } { 301 | ::Status::Ok => Ok(ptr), 302 | e => Err(e), 303 | } 304 | } 305 | 306 | pub fn get_wave_data(&self, wave_size: usize, 307 | channel_offset: i32) -> Result, ::Status> { 308 | let mut ptr : Vec = ::std::iter::repeat(0f32).take(wave_size).collect(); 309 | 310 | match unsafe { ffi::FMOD_ChannelGroup_GetWaveData(self.channel_group, ptr.as_mut_ptr(), 311 | wave_size as c_int, channel_offset) } { 312 | ::Status::Ok => Ok(ptr), 313 | e => Err(e) 314 | } 315 | } 316 | 317 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 318 | EventMemoryBits(event_memory_bits): EventMemoryBits) 319 | -> Result<(u32, MemoryUsageDetails), ::Status> { 320 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 321 | let mut memory_used = 0u32; 322 | 323 | match unsafe { ffi::FMOD_ChannelGroup_GetMemoryInfo(self.channel_group, memory_bits, 324 | event_memory_bits, &mut memory_used, 325 | &mut details) } { 326 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 327 | e => Err(e) 328 | } 329 | } 330 | 331 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 332 | unsafe { ffi::FMOD_ChannelGroup_SetUserData(self.channel_group, transmute(user_data)) } 333 | } 334 | 335 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 336 | unsafe { 337 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 338 | 339 | match ffi::FMOD_ChannelGroup_GetUserData(self.channel_group, &mut user_data) { 340 | ::Status::Ok => { 341 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 342 | Ok(tmp) 343 | }, 344 | e => Err(e) 345 | } 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /src/dsp_connection.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | use ffi; 26 | use types::*; 27 | use dsp; 28 | use libc::{c_int, c_void}; 29 | use fmod_sys; 30 | use fmod_sys::MemoryUsageDetails; 31 | use std::mem::transmute; 32 | use std::default::Default; 33 | 34 | /// DspConnection object 35 | pub struct DspConnection { 36 | dsp_connection: *mut ffi::FMOD_DSPCONNECTION 37 | } 38 | 39 | impl ffi::FFI for DspConnection { 40 | fn wrap(d: *mut ffi::FMOD_DSPCONNECTION) -> DspConnection { 41 | DspConnection {dsp_connection: d} 42 | } 43 | 44 | fn unwrap(d: &DspConnection) -> *mut ffi::FMOD_DSPCONNECTION { 45 | d.dsp_connection 46 | } 47 | } 48 | 49 | impl Drop for DspConnection { 50 | fn drop(&mut self) { 51 | self.release(); 52 | } 53 | } 54 | 55 | impl DspConnection { 56 | pub fn release(&mut self) { 57 | self.dsp_connection = ::std::ptr::null_mut(); 58 | } 59 | 60 | pub fn get_input(&self) -> Result { 61 | let mut input = ::std::ptr::null_mut(); 62 | 63 | match unsafe { ffi::FMOD_DSPConnection_GetInput(self.dsp_connection, &mut input) } { 64 | ::Status::Ok => Ok(ffi::FFI::wrap(input)), 65 | e => Err(e) 66 | } 67 | } 68 | 69 | pub fn get_output(&self) -> Result { 70 | let mut output = ::std::ptr::null_mut(); 71 | 72 | match unsafe { ffi::FMOD_DSPConnection_GetOutput(self.dsp_connection, &mut output) } { 73 | ::Status::Ok => Ok(ffi::FFI::wrap(output)), 74 | e => Err(e) 75 | } 76 | } 77 | 78 | pub fn set_mix(&self, volume: f32) -> ::Status { 79 | unsafe { ffi::FMOD_DSPConnection_SetMix(self.dsp_connection, volume) } 80 | } 81 | 82 | pub fn get_mix(&self) -> Result { 83 | let mut volume = 0f32; 84 | 85 | match unsafe { ffi::FMOD_DSPConnection_GetMix(self.dsp_connection, &mut volume) } { 86 | ::Status::Ok => Ok(volume), 87 | e => Err(e) 88 | } 89 | } 90 | 91 | pub fn set_levels(&self, speaker: ::Speaker, levels: &mut Vec) -> ::Status { 92 | unsafe { ffi::FMOD_DSPConnection_SetLevels(self.dsp_connection, speaker, 93 | levels.as_mut_ptr(), levels.len() as c_int) } 94 | } 95 | 96 | pub fn get_levels(&self, speaker: ::Speaker, num_levels: usize) -> Result, ::Status> { 97 | let mut levels : Vec = ::std::iter::repeat(0f32).take(num_levels).collect(); 98 | 99 | match unsafe { ffi::FMOD_DSPConnection_GetLevels(self.dsp_connection, speaker, 100 | levels.as_mut_ptr(), 101 | levels.len() as c_int) } { 102 | ::Status::Ok => Ok(levels), 103 | e => Err(e), 104 | } 105 | } 106 | 107 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 108 | EventMemoryBits(event_memory_bits): EventMemoryBits) 109 | -> Result<(u32, MemoryUsageDetails), ::Status> { 110 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 111 | let mut memory_used = 0u32; 112 | 113 | match unsafe { ffi::FMOD_DSPConnection_GetMemoryInfo(self.dsp_connection, memory_bits, 114 | event_memory_bits, &mut memory_used, 115 | &mut details) } { 116 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 117 | e => Err(e), 118 | } 119 | } 120 | 121 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 122 | unsafe { ffi::FMOD_DSPConnection_SetUserData(self.dsp_connection, transmute(user_data)) } 123 | } 124 | 125 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 126 | unsafe { 127 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 128 | 129 | match ffi::FMOD_DSPConnection_GetUserData(self.dsp_connection, &mut user_data) { 130 | ::Status::Ok => { 131 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 132 | 133 | Ok(tmp) 134 | } 135 | e => Err(e), 136 | } 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2014 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | pub fn error_string(errcode: ::Status) -> &'static str { 26 | match errcode { 27 | ::Status::AlreadyLocked => "Tried to call lock a second time before unlock was called.", 28 | ::Status::BadCommand => "Tried to call a function on a data type that does not allow this \ 29 | type of functionality (ie calling Sound::lock on a streaming \ 30 | sound).", 31 | ::Status::CDDADrivers => "Neither NTSCSI nor ASPI could be initialised.", 32 | ::Status::CDDAInit => "An error occurred while initialising the CDDA subsystem.", 33 | ::Status::CDDAInvalidDevice => "Couldn't find the specified device.", 34 | ::Status::CDDANoAudio => "No audio tracks on the specified disc.", 35 | ::Status::CDDANoDevices => "No CD/DVD devices were found.", 36 | ::Status::CDDANoDisc => "No disc present in the specified drive.", 37 | ::Status::CDDARead => "A CDDA read error occurred.", 38 | ::Status::ChannelAlloc => "Error trying to allocate a channel.", 39 | ::Status::ChannelStolen => "The specified channel has been reused to play another sound.", 40 | ::Status::COM => "A Win32 COM related error occured. COM failed to initialize or a \ 41 | QueryInterface failed meaning a Windows codec or driver was not \ 42 | installed properly.", 43 | ::Status::DMA => "DMA Failure. See debug output for more information.", 44 | ::Status::DSPConnection => "DSP connection error. Connection possibly caused a cyclic \ 45 | dependency. Or tried to connect a tree too many units deep \ 46 | (more than 128).", 47 | ::Status::DSPFormat => "DSP Format error. A DSP unit may have attempted to connect to \ 48 | this network with the wrong format.", 49 | ::Status::DSPNotFound => "DSP connection error. Couldn't find the DSP unit specified.", 50 | ::Status::DSPRunning => "DSP error. Cannot perform this operation while the network is in \ 51 | the middle of running. This will most likely happen if a \ 52 | connection or disconnection is attempted in a DSP callback.", 53 | ::Status::DSPTooManyConnections => "DSP connection error. The unit being connected to or \ 54 | disconnected should only have 1 input or output.", 55 | ::Status::EventAlreadyLoaded => "The specified project or bank has already been loaded. \ 56 | Having multiple copies of the same project loaded \ 57 | simultaneously is forbidden.", 58 | ::Status::EventFailed => "An Event failed to be retrieved, most likely due to 'just fail' \ 59 | being specified as the max playbacks behavior.", 60 | ::Status::EventGuidConflict => "An event with the same GUID already exists.", 61 | ::Status::EventInfoOnly => "An event with the same GUID already exists.", 62 | ::Status::EventInternal => "An error occured that wasn't supposed to. See debug log for \ 63 | reason.", 64 | ::Status::EventMaxStreams => "Event failed because 'Max streams' was hit when \ 65 | FMOD_EVENT_INIT_FAIL_ON_MAXSTREAMS was specified.", 66 | ::Status::EventMismatch => "FSB mismatches the FEV it was compiled with, the stream/sample \ 67 | mode it was meant to be created with was different, or the FEV \ 68 | was built for a different platform.", 69 | ::Status::EventNameConflict => "A category with the same name already exists.", 70 | ::Status::EventNeedsSimple => "Tried to call a function on a complex event that's only \ 71 | supported by simple events.", 72 | ::Status::EventNotFound => "The requested event, event group, event category or event \ 73 | property could not be found.", 74 | ::Status::FileBad => "Error loading file.", 75 | ::Status::FileCouldNotSeek => "Couldn't perform seek operation. This is a limitation of \ 76 | the medium (ie netstreams) or the file format.", 77 | ::Status::FileDiskEjected => "Media was ejected while reading.", 78 | ::Status::FileEOF => "End of file unexpectedly reached while trying to read essential data \ 79 | (truncated data?).", 80 | ::Status::FileNotFound => "File not found.", 81 | ::Status::FileUnwanted => "Unwanted file access occured.", 82 | ::Status::Format => "Unsupported file or audio format.", 83 | ::Status::HTTP => "A HTTP error occurred. This is a catch-all for HTTP errors not listed \ 84 | elsewhere.", 85 | ::Status::HTTPAccess => "The specified resource requires authentication or is forbidden.", 86 | ::Status::HTTPProxyAuth => "Proxy authentication is required to access the specified \ 87 | resource.", 88 | ::Status::HTTPServerError => "A HTTP server error occurred.", 89 | ::Status::HTTPTimeout => "The HTTP request timed out.", 90 | ::Status::Initialization => "FMOD was not initialized correctly to support this function.", 91 | ::Status::Initialized => "Cannot call this command after System::init.", 92 | ::Status::Internal => "An error occured that wasn't supposed to. Contact support.", 93 | ::Status::InvalidAddress => "On Xbox 360, this memory address passed to FMOD must be \ 94 | physical, (ie allocated with XPhysicalAlloc.)", 95 | ::Status::InvalidFloat => "Value passed in was a NaN, Inf or denormalized float.", 96 | ::Status::InvalidHandle => "An invalid object handle was used.", 97 | ::Status::InvalidParam => "An invalid parameter was passed to this function.", 98 | ::Status::InvalidPosition => "An invalid seek position was passed to this function.", 99 | ::Status::InvalidSpeaker => "An invalid speaker was passed to this function based on the \ 100 | current speaker mode.", 101 | ::Status::InvalidSyncPoint => "The syncpoint did not come from this sound handle.", 102 | ::Status::InvalidVector => "The vectors passed in are not unit length, or perpendicular.", 103 | ::Status::MaxAudible => "Reached maximum audible playback count for this sound's \ 104 | soundgroup.", 105 | ::Status::Memory => "Not enough memory or resources.", 106 | ::Status::MemoryCantPoint => "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or \ 107 | non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was \ 108 | used.", 109 | ::Status::MemorySRAM => "Not enough memory or resources on console sound ram.", 110 | ::Status::MusicNoCallback => "The music callback is required, but it has not been set.", 111 | ::Status::MusicNotFound => "The requested music entity could not be found.", 112 | ::Status::MusicUninitialized => "Music system is not initialized probably because no music \ 113 | data is loaded.", 114 | ::Status::Needs2D => "Tried to call a command on a 3d sound when the command was meant for \ 115 | 2d sound.", 116 | ::Status::Needs3D => "Tried to call a command on a 2d sound when the command was meant for \ 117 | 3d sound.", 118 | ::Status::NeedsHardware => "Tried to use a feature that requires hardware support. (ie \ 119 | trying to play a GCADPCM compressed sound in software on Wii).", 120 | ::Status::NeedsSoftware => "Tried to use a feature that requires the software engine. \ 121 | Software engine has either been turned off, or command was \ 122 | executed on a hardware channel which does not support this \ 123 | feature.", 124 | ::Status::NetConnect => "Couldn't connect to the specified host.", 125 | ::Status::NetSocketError => "A socket error occurred. This is a catch-all for \ 126 | socket-related errors not listed elsewhere.", 127 | ::Status::NetURL => "The specified URL couldn't be resolved.", 128 | ::Status::NetWouldBlock => "Operation on a non-blocking socket could not complete \ 129 | immediately.", 130 | ::Status::NotReady => "Operation could not be performed because specified sound/DSP \ 131 | connection is not ready.", 132 | ::Status::OutputAllocated => "Error initializing output device, but more specifically, the \ 133 | output device is already in use and cannot be reused.", 134 | ::Status::OutputCreateBuffer => "Error creating hardware sound buffer.", 135 | ::Status::OutputDriverCall => "A call to a standard soundcard driver failed, which could \ 136 | possibly mean a bug in the driver or resources were missing \ 137 | or exhausted.", 138 | ::Status::OutputEnumeration => "Error enumerating the available driver list. List may be \ 139 | inconsistent due to a recent device addition or removal.", 140 | ::Status::OutputFormat => "Soundcard does not support the minimum features needed for this \ 141 | soundsystem (16bit stereo output).", 142 | ::Status::OutputInit => "Error initializing output device.", 143 | ::Status::OutputNoHardware => "FMOD_HARDWARE was specified but the sound card does not \ 144 | have the resources necessary to play it.", 145 | ::Status::OutputNoSoftware => "Attempted to create a software sound but no software \ 146 | channels were specified in System::init.", 147 | ::Status::Pan => "Panning only works with mono or stereo sound sources.", 148 | ::Status::Plugin => "An unspecified error has been returned from a 3rd party plugin.", 149 | ::Status::PluginInstances => "The number of allowed instances of a plugin has been \ 150 | exceeded.", 151 | ::Status::PluginMissing => "A requested output, dsp unit type or codec was not available.", 152 | ::Status::PluginResource => "A resource that the plugin requires cannot be found. (ie the \ 153 | DLS file for MIDI playback or other DLLs that it needs to \ 154 | load)", 155 | ::Status::Preloaded => "The specified sound is still in use by the event system, call \ 156 | EventSystem::unloadFSB before trying to release it.", 157 | ::Status::ProgrammerSound => "The specified sound is still in use by the event system, \ 158 | wait for the event which is using it finish with it.", 159 | ::Status::Record => "An error occured trying to initialize the recording device.", 160 | ::Status::ReverbInstance => "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. \ 161 | Most likely because it is an invalid instance number or the \ 162 | reverb doesnt exist.", 163 | ::Status::Subsounds => "The error occured because the sound referenced contains subsounds \ 164 | when it shouldn't have, or it doesn't contain subsounds when it \ 165 | should have. The operation may also not be able to be performed on \ 166 | a parent sound, or a parent sound was played without setting up a \ 167 | sentence first.", 168 | ::Status::SubsoundAllocated => "This subsound is already being used by another sound, you \ 169 | cannot have more than one parent to a sound. Null out the \ 170 | other parent's entry first.", 171 | ::Status::SubsoundCantMove => "Shared subsounds cannot be replaced or moved from their \ 172 | parent stream, such as when the parent stream is an FSB \ 173 | file.", 174 | ::Status::SubsoundMode => "The subsound's mode bits do not match with the parent sound's \ 175 | mode bits. See documentation for function that it was called \ 176 | with.", 177 | ::Status::TagNotFound => "The specified tag could not be found or there are no tags.", 178 | ::Status::TooManyChannels => "The sound created exceeds the allowable input channel count. \ 179 | This can be increased using the maxinputchannels parameter \ 180 | in System::setSoftwareFormat.", 181 | ::Status::Unimplemented => "Something in FMOD hasn't been implemented when it should be! \ 182 | Contact support!", 183 | ::Status::Uninitialized => "This command failed because System::init or System::setDriver \ 184 | was not called.", 185 | ::Status::Unsupported => "A command issued was not supported by this object. Possibly a \ 186 | plugin without certain callbacks specified.", 187 | ::Status::Update => "An error caused by System::update occured.", 188 | ::Status::Version => "The version number of this file format is not supported.", 189 | ::Status::Ok => "No errors.", 190 | _ => "Unknown error." 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/file.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 | 25 | use libc::{fopen, fread, fclose, fseek, ftell}; 26 | use libc::{SEEK_SET, SEEK_CUR, SEEK_END}; 27 | use libc::FILE; 28 | use libc::stat; 29 | use std::mem::zeroed; 30 | use libc::fstat; 31 | use libc::fileno; 32 | use libc::{c_void, c_char, c_long}; 33 | use std::ffi::CString; 34 | 35 | #[doc(hidden)] 36 | pub fn get_ffi(file: &FmodFile) -> *mut FILE { 37 | file.fd 38 | } 39 | 40 | #[doc(hidden)] 41 | pub fn from_ffi(fd: *mut FILE) -> FmodFile { 42 | FmodFile { 43 | fd: fd, 44 | } 45 | } 46 | 47 | #[derive(Debug, PartialOrd, PartialEq)] 48 | pub enum SeekStyle { 49 | /// Seek from the beginning of the stream 50 | SeekSet, 51 | /// Seek from the end of the stream 52 | SeekEnd, 53 | /// Seek from the current position 54 | SeekCur, 55 | } 56 | 57 | /// A little struct to wrap C files. 58 | /// 59 | /// IMPORTANT: it doesn't close the file when dropped! 60 | /// 61 | /// I'll try to improve this or to replace it by File. 62 | pub struct FmodFile { 63 | fd: *mut FILE, 64 | } 65 | 66 | impl FmodFile { 67 | pub fn open(file_name: &str) -> Result { 68 | let tmp_file_name = match CString::new(file_name) { 69 | Ok(s) => s, 70 | Err(e) => return Err(::RStatus::Other(format!("invalid file name: {}", e))), 71 | }; 72 | unsafe { 73 | let tmp = fopen(tmp_file_name.as_ptr() as *const c_char, 74 | "rb".as_ptr() as *const c_char); 75 | 76 | if tmp.is_null() { 77 | Err(::RStatus::Other(format!("fopen call failed"))) 78 | } else { 79 | Ok(FmodFile{fd: tmp}) 80 | } 81 | } 82 | } 83 | 84 | pub fn read(&self, buffer: &mut [u8]) -> usize { 85 | unsafe { 86 | if self.fd.is_null() { 87 | 0usize 88 | } else { 89 | fread(buffer.as_mut_ptr() as *mut c_void, buffer.len() as usize, 1usize, 90 | self.fd) as usize 91 | } 92 | } 93 | } 94 | 95 | pub fn seek(&self, pos: i64, style: self::SeekStyle) -> usize { 96 | unsafe { 97 | if self.fd.is_null() { 98 | 0usize 99 | } else { 100 | fseek(self.fd, pos as c_long, match style { 101 | self::SeekStyle::SeekSet => SEEK_SET, 102 | self::SeekStyle::SeekEnd => SEEK_END, 103 | self::SeekStyle::SeekCur => SEEK_CUR 104 | }) as usize 105 | } 106 | } 107 | } 108 | 109 | pub fn get_file_size(&self) -> i64 { 110 | unsafe { 111 | if self.fd.is_null() { 112 | 0i64 113 | } else { 114 | let mut tmp : stat = zeroed::(); 115 | let id = fileno(self.fd); 116 | match fstat(id, &mut tmp) { 117 | 0 => tmp.st_size, 118 | _ => 0i64 119 | } 120 | } 121 | } 122 | } 123 | 124 | pub fn tell(&self) -> i64 { 125 | unsafe { 126 | if self.fd.is_null() { 127 | 0i64 128 | } else { 129 | ftell(self.fd) as i64 130 | } 131 | } 132 | } 133 | 134 | pub fn close(&mut self) { 135 | unsafe { 136 | if !self.fd.is_null() { 137 | fclose(self.fd); 138 | self.fd = ::std::ptr::null_mut(); 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/geometry.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | use ffi; 26 | use types::*; 27 | use vector; 28 | use libc::{c_int, c_void}; 29 | use fmod_sys; 30 | use fmod_sys::MemoryUsageDetails; 31 | use std::mem::transmute; 32 | use std::default::Default; 33 | 34 | /// Geometry object 35 | pub struct Geometry { 36 | geometry: *mut ffi::FMOD_GEOMETRY 37 | } 38 | 39 | impl ffi::FFI for Geometry { 40 | fn wrap(g: *mut ffi::FMOD_GEOMETRY) -> Geometry { 41 | Geometry {geometry: g} 42 | } 43 | 44 | fn unwrap(g: &Geometry) -> *mut ffi::FMOD_GEOMETRY { 45 | g.geometry 46 | } 47 | } 48 | 49 | impl Drop for Geometry { 50 | fn drop(&mut self) { 51 | self.release(); 52 | } 53 | } 54 | 55 | impl Geometry { 56 | pub fn release(&mut self) -> ::Status { 57 | if self.geometry !=::std::ptr::null_mut() { 58 | match unsafe { ffi::FMOD_Geometry_Release(self.geometry) } { 59 | ::Status::Ok => { 60 | self.geometry = ::std::ptr::null_mut(); 61 | ::Status::Ok 62 | } 63 | e => e, 64 | } 65 | } else { 66 | ::Status::Ok 67 | } 68 | } 69 | 70 | pub fn add_polygon(&self, direct_occlusion: f32, reverb_occlusion: f32, double_sided: bool, 71 | vertices: Vec) -> Result { 72 | let t_double_sided = if double_sided == true { 73 | 1 74 | } else { 75 | 0 76 | }; 77 | let mut index = 0i32; 78 | let t_vertices = Vec::with_capacity(vertices.len()); 79 | 80 | for tmp in vertices.iter() { 81 | vector::get_ffi(tmp); 82 | } 83 | 84 | match unsafe { ffi::FMOD_Geometry_AddPolygon(self.geometry, direct_occlusion, 85 | reverb_occlusion, t_double_sided, 86 | vertices.len() as c_int, t_vertices.as_ptr(), 87 | &mut index) } { 88 | ::Status::Ok => Ok(index), 89 | e => Err(e), 90 | } 91 | } 92 | 93 | pub fn get_num_polygons(&self) -> Result { 94 | let mut num = 0i32; 95 | 96 | match unsafe { ffi::FMOD_Geometry_GetNumPolygons(self.geometry, &mut num) } { 97 | ::Status::Ok => Ok(num), 98 | e => Err(e) 99 | } 100 | } 101 | 102 | pub fn get_max_polygons(&self) -> Result<(i32, i32), ::Status> { 103 | let mut max_polygons = 0i32; 104 | let mut max_vertices = 0i32; 105 | 106 | match unsafe { ffi::FMOD_Geometry_GetMaxPolygons(self.geometry, &mut max_polygons, 107 | &mut max_vertices) } { 108 | ::Status::Ok => Ok((max_polygons, max_vertices)), 109 | e => Err(e), 110 | } 111 | } 112 | 113 | pub fn get_polygon_num_vertices(&self, index: i32) -> Result { 114 | let mut num = 0i32; 115 | 116 | match unsafe { ffi::FMOD_Geometry_GetPolygonNumVertices(self.geometry, index, &mut num) } { 117 | ::Status::Ok => Ok(num), 118 | e => Err(e), 119 | } 120 | } 121 | 122 | pub fn set_polygon_vertex(&self, index: i32, vertex_index: i32, 123 | vertex: vector::Vector) -> ::Status { 124 | let t_vertex = vector::get_ffi(&vertex); 125 | 126 | unsafe { ffi::FMOD_Geometry_SetPolygonVertex(self.geometry, index, vertex_index, 127 | &t_vertex) } 128 | } 129 | 130 | pub fn get_polygon_vertex(&self, index: i32, 131 | vertex_index: i32) -> Result { 132 | let mut vertex = vector::get_ffi(&vector::Vector::new()); 133 | 134 | match unsafe { ffi::FMOD_Geometry_GetPolygonVertex(self.geometry, index, vertex_index, 135 | &mut vertex) } { 136 | ::Status::Ok => Ok(vector::from_ptr(vertex)), 137 | e => Err(e), 138 | } 139 | } 140 | 141 | pub fn set_polygon_attributes(&self, index: i32, direct_occlusion: f32, reverb_occlusion: f32, 142 | double_sided: bool) -> ::Status { 143 | let t_double_sided = if double_sided == true { 144 | 1 145 | } else { 146 | 0 147 | }; 148 | 149 | unsafe { ffi::FMOD_Geometry_SetPolygonAttributes(self.geometry, index, direct_occlusion, 150 | reverb_occlusion, t_double_sided) } 151 | } 152 | 153 | /// Returns: 154 | /// 155 | /// Ok(direct_occlusion, reverb_occlusion, double_sided) 156 | pub fn get_polygon_attributes(&self, index: i32) -> Result<(f32, f32, bool), ::Status> { 157 | let mut direct_occlusion = 0f32; 158 | let mut reverb_occlusion = 0f32; 159 | let mut double_sided = 0; 160 | 161 | match unsafe { ffi::FMOD_Geometry_GetPolygonAttributes(self.geometry, index, 162 | &mut direct_occlusion, 163 | &mut reverb_occlusion, 164 | &mut double_sided) } { 165 | ::Status::Ok => Ok((direct_occlusion, reverb_occlusion, double_sided == 1)), 166 | e => Err(e), 167 | } 168 | } 169 | 170 | pub fn set_active(&self, active: bool) -> ::Status { 171 | let t_active = if active == true { 172 | 1 173 | } else { 174 | 0 175 | }; 176 | 177 | unsafe { ffi::FMOD_Geometry_SetActive(self.geometry, t_active) } 178 | } 179 | 180 | pub fn get_active(&self) -> Result { 181 | let mut active = 0; 182 | 183 | match unsafe { ffi::FMOD_Geometry_GetActive(self.geometry, &mut active) } { 184 | ::Status::Ok => Ok(active == 1), 185 | e => Err(e) 186 | } 187 | } 188 | 189 | pub fn set_rotation(&self, forward: vector::Vector, up: vector::Vector) -> ::Status { 190 | let t_forward = vector::get_ffi(&forward); 191 | let t_up = vector::get_ffi(&up); 192 | 193 | unsafe { ffi::FMOD_Geometry_SetRotation(self.geometry, &t_forward, &t_up) } 194 | } 195 | 196 | /// Returns: 197 | /// 198 | /// Ok(forward, up) 199 | pub fn get_rotation(&self) -> Result<(vector::Vector, vector::Vector), ::Status> { 200 | let mut forward = vector::get_ffi(&vector::Vector::new()); 201 | let mut up = vector::get_ffi(&vector::Vector::new()); 202 | 203 | match unsafe { ffi::FMOD_Geometry_GetRotation(self.geometry, &mut forward, &mut up) } { 204 | ::Status::Ok => Ok((vector::from_ptr(forward), vector::from_ptr(up))), 205 | e => Err(e) 206 | } 207 | } 208 | 209 | pub fn set_position(&self, position: vector::Vector) -> ::Status { 210 | let t_position = vector::get_ffi(&position); 211 | 212 | unsafe { ffi::FMOD_Geometry_SetPosition(self.geometry, &t_position) } 213 | } 214 | 215 | pub fn get_position(&self) -> Result { 216 | let mut position = vector::get_ffi(&vector::Vector::new()); 217 | 218 | match unsafe { ffi::FMOD_Geometry_GetPosition(self.geometry, &mut position) } { 219 | ::Status::Ok => Ok(vector::from_ptr(position)), 220 | e => Err(e) 221 | } 222 | } 223 | 224 | pub fn set_scale(&self, scale: vector::Vector) -> ::Status { 225 | let t_scale = vector::get_ffi(&scale); 226 | 227 | unsafe { ffi::FMOD_Geometry_SetScale(self.geometry, &t_scale) } 228 | } 229 | 230 | pub fn get_scale(&self) -> Result { 231 | let mut scale = vector::get_ffi(&vector::Vector::new()); 232 | 233 | match unsafe { ffi::FMOD_Geometry_GetScale(self.geometry, &mut scale) } { 234 | ::Status::Ok => Ok(vector::from_ptr(scale)), 235 | e => Err(e) 236 | } 237 | } 238 | 239 | /// Returns: 240 | /// 241 | /// Ok(memory_used, details) 242 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 243 | EventMemoryBits(event_memory_bits): EventMemoryBits) 244 | -> Result<(u32, MemoryUsageDetails), ::Status> { 245 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 246 | let mut memory_used = 0u32; 247 | 248 | match unsafe { ffi::FMOD_Geometry_GetMemoryInfo(self.geometry, memory_bits, event_memory_bits, &mut memory_used, &mut details) } { 249 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 250 | e => Err(e) 251 | } 252 | } 253 | 254 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 255 | unsafe { ffi::FMOD_Geometry_SetUserData(self.geometry, transmute(user_data)) } 256 | } 257 | 258 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 259 | unsafe { 260 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 261 | 262 | match ffi::FMOD_Geometry_GetUserData(self.geometry, &mut user_data) { 263 | ::Status::Ok => { 264 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 265 | 266 | Ok(tmp) 267 | }, 268 | e => Err(e) 269 | } 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /src/reverb.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | use ffi; 26 | use types::*; 27 | use vector; 28 | use reverb_properties; 29 | use fmod_sys; 30 | use fmod_sys::MemoryUsageDetails; 31 | use std::mem::transmute; 32 | use libc::{c_void}; 33 | use std::default::Default; 34 | 35 | /// Reverb object 36 | pub struct Reverb { 37 | reverb: *mut ffi::FMOD_REVERB, 38 | } 39 | 40 | impl Drop for Reverb { 41 | fn drop(&mut self) { 42 | self.release(); 43 | } 44 | } 45 | 46 | impl ffi::FFI for Reverb { 47 | fn wrap(r: *mut ffi::FMOD_REVERB) -> Reverb { 48 | Reverb {reverb: r} 49 | } 50 | 51 | fn unwrap(r: &Reverb) -> *mut ffi::FMOD_REVERB { 52 | r.reverb 53 | } 54 | } 55 | 56 | impl Reverb { 57 | pub fn release(&mut self) -> ::Status { 58 | if self.reverb !=::std::ptr::null_mut() { 59 | match unsafe { ffi::FMOD_Reverb_Release(self.reverb) } { 60 | ::Status::Ok => { 61 | self.reverb = ::std::ptr::null_mut(); 62 | ::Status::Ok 63 | } 64 | e => e, 65 | } 66 | } else { 67 | ::Status::Ok 68 | } 69 | } 70 | 71 | pub fn set_3D_attributes(&self, position: vector::Vector, min_distance: f32, 72 | max_distance: f32) -> ::Status { 73 | let t_position = vector::get_ffi(&position); 74 | 75 | unsafe { ffi::FMOD_Reverb_Set3DAttributes(self.reverb, &t_position, min_distance, 76 | max_distance) } 77 | } 78 | 79 | pub fn get_3D_attributes(&self) -> Result<(vector::Vector, f32, f32), ::Status> { 80 | let mut position = vector::get_ffi(&vector::Vector::new()); 81 | let mut min_distance = 0f32; 82 | let mut max_distance = 0f32; 83 | 84 | match unsafe { ffi::FMOD_Reverb_Get3DAttributes(self.reverb, &mut position, 85 | &mut min_distance, &mut max_distance) } { 86 | ::Status::Ok => Ok((vector::from_ptr(position), min_distance, max_distance)), 87 | e => Err(e), 88 | } 89 | } 90 | 91 | pub fn set_properties(&self, 92 | reverb_properties: reverb_properties::ReverbProperties) -> ::Status { 93 | let t_reverb_properties = reverb_properties::get_ffi(reverb_properties); 94 | 95 | unsafe { ffi::FMOD_Reverb_SetProperties(self.reverb, &t_reverb_properties) } 96 | } 97 | 98 | pub fn get_properties(&self, reverb_properties: reverb_properties::ReverbProperties) 99 | -> Result { 100 | let mut t_reverb_properties = reverb_properties::get_ffi(reverb_properties); 101 | 102 | match unsafe { ffi::FMOD_Reverb_GetProperties(self.reverb, &mut t_reverb_properties) } { 103 | ::Status::Ok => Ok(reverb_properties::from_ptr(t_reverb_properties)), 104 | e => Err(e), 105 | } 106 | } 107 | 108 | pub fn set_active(&self, active: bool) -> ::Status { 109 | let t_active = if active == true { 110 | 1 111 | } else { 112 | 0 113 | }; 114 | 115 | unsafe { ffi::FMOD_Reverb_SetActive(self.reverb, t_active) } 116 | } 117 | 118 | pub fn get_active(&self) -> Result { 119 | let mut active = 0i32; 120 | 121 | match unsafe { ffi::FMOD_Reverb_GetActive(self.reverb, &mut active) } { 122 | ::Status::Ok => Ok(active == 1), 123 | e => Err(e) 124 | } 125 | } 126 | 127 | /// Returns: 128 | /// 129 | /// Ok(memory_used, details) 130 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 131 | EventMemoryBits(event_memory_bits): EventMemoryBits) 132 | -> Result<(u32, MemoryUsageDetails), ::Status> { 133 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 134 | let mut memory_used = 0u32; 135 | 136 | match unsafe { ffi::FMOD_Reverb_GetMemoryInfo(self.reverb, memory_bits, event_memory_bits, 137 | &mut memory_used, &mut details) } { 138 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 139 | e => Err(e) 140 | } 141 | } 142 | 143 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 144 | unsafe { ffi::FMOD_Reverb_SetUserData(self.reverb, transmute(user_data)) } 145 | } 146 | 147 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 148 | unsafe { 149 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 150 | 151 | match ffi::FMOD_Reverb_GetUserData(self.reverb, &mut user_data) { 152 | ::Status::Ok => { 153 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 154 | 155 | Ok(tmp) 156 | }, 157 | e => Err(e) 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/reverb_properties.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 Gomez Guillaume. 3 | * 4 | * The Original software, FMOD 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 | 25 | use ffi; 26 | use std::default::Default; 27 | 28 | pub fn from_ptr(pointer: ffi::FMOD_REVERB_PROPERTIES) -> ReverbProperties { 29 | ReverbProperties { 30 | instance: pointer.Instance, 31 | environment: pointer.Environment, 32 | env_diffusion: pointer.EnvDiffusion, 33 | room: pointer.Room, 34 | room_HF: pointer.RoomHF, 35 | room_LF: pointer.RoomLF, 36 | decay_time: pointer.DecayTime, 37 | decay_HF_ratio: pointer.DecayHFRatio, 38 | decay_LF_ratio: pointer.DecayLFRatio, 39 | reflections: pointer.Reflections, 40 | reflections_delay: pointer.ReflectionsDelay, 41 | reverb: pointer.Reverb, 42 | reverb_delay: pointer.ReverbDelay, 43 | modulation_time: pointer.ModulationTime, 44 | modulation_depth: pointer.ModulationDepth, 45 | HF_reference: pointer.HFReference, 46 | LF_reference: pointer.LFReference, 47 | diffusion: pointer.Diffusion, 48 | density: pointer.Density, 49 | flags: pointer.Flags, 50 | } 51 | } 52 | 53 | pub fn get_ffi(reverb: ReverbProperties) -> ffi::FMOD_REVERB_PROPERTIES { 54 | ffi::FMOD_REVERB_PROPERTIES { 55 | Instance: reverb.instance, 56 | Environment: reverb.environment, 57 | EnvDiffusion: reverb.env_diffusion, 58 | Room: reverb.room, 59 | RoomHF: reverb.room_HF, 60 | RoomLF: reverb.room_LF, 61 | DecayTime: reverb.decay_time, 62 | DecayHFRatio: reverb.decay_HF_ratio, 63 | DecayLFRatio: reverb.decay_LF_ratio, 64 | Reflections: reverb.reflections, 65 | ReflectionsDelay: reverb.reflections_delay, 66 | Reverb: reverb.reverb, 67 | ReverbDelay: reverb.reverb_delay, 68 | ModulationTime: reverb.modulation_time, 69 | ModulationDepth: reverb.modulation_depth, 70 | HFReference: reverb.HF_reference, 71 | LFReference: reverb.LF_reference, 72 | Diffusion: reverb.diffusion, 73 | Density: reverb.density, 74 | Flags: reverb.flags, 75 | } 76 | } 77 | 78 | /// Structure defining a reverb environment. 79 | #[derive(Clone, Copy)] 80 | pub struct ReverbProperties { 81 | /// [w] Min: 0 - Max: 3 - Default: 0 - Environment Instance. (SUPPORTED:SFX(4 instances) and Wii (3 instances)) 82 | pub instance : i32, 83 | /// [r/w] Min: -1 - Max: 25 - Default: -1 - Sets all listener properties. -1 = OFF. (SUPPORTED:SFX(-1 only)/PSP) 84 | pub environment : i32, 85 | /// [r/w] Min: 0.0 - Max: 1.0 - Default: 1.0 - Environment diffusion (SUPPORTED:WII) 86 | pub env_diffusion : f32, 87 | /// [r/w] Min: -10000 - Max: 0 - Default: -1000 - Room effect level (at mid frequencies) (SUPPORTED:SFX/WII/PSP) 88 | pub room : i32, 89 | /// [r/w] Min: -10000 - Max: 0 - Default: -100 - Relative room effect level at high frequencies (SUPPORTED:SFX) 90 | pub room_HF : i32, 91 | /// [r/w] Min: -10000 - Max: 0 Default: 0 - Relative room effect level at low frequencies (SUPPORTED:SFX) 92 | pub room_LF : i32, 93 | /// [r/w] Min: 0.1 - Max: 20.0 - Default: 1.49 - Reverberation decay time at mid frequencies (SUPPORTED:SFX/WII) 94 | pub decay_time : f32, 95 | /// [r/w] Min: 0.1 - Max: 2.0 - Default: 0.83 - High-frequency to mid-frequency decay time ratio (SUPPORTED:SFX) 96 | pub decay_HF_ratio : f32, 97 | /// [r/w] Min: 0.1 - Max: 2.0 - Default: 1.0 - Low-frequency to mid-frequency decay time ratio (SUPPORTED:---) 98 | pub decay_LF_ratio : f32, 99 | /// [r/w] Min: -10000 - Max: 1000 - Default: -2602 - Early reflections level relative to room effect (SUPPORTED:SFX/WII) 100 | pub reflections : i32, 101 | /// [r/w] Min: 0.0 - Max: 0.3 - Default: 0.007 - Initial reflection delay time (SUPPORTED:SFX) 102 | pub reflections_delay: f32, 103 | /// [r/w] Min: -10000 - Max: 2000 - Default: 200 - Late reverberation level relative to room effect (SUPPORTED:SFX) 104 | pub reverb : i32, 105 | /// [r/w] Min: 0.0 - Max: 0.1 - Default: 0.011 - Late reverberation delay time relative to initial reflection (SUPPORTED:SFX/WII) 106 | pub reverb_delay : f32, 107 | /// [r/w] Min: 0.04 - Max: 4.0 - Default: 0.25 - Modulation time (SUPPORTED:---) 108 | pub modulation_time : f32, 109 | /// [r/w] Min: 0.0 - Max: 1.0 - Default: 0.0 - Modulation depth (SUPPORTED:WII) 110 | pub modulation_depth : f32, 111 | /// [r/w] Min: 20.0 - Max: 20000.0 - Default: 5000.0 - Reference high frequency (hz) (SUPPORTED:SFX) 112 | pub HF_reference : f32, 113 | /// [r/w] Min: 20.0 - Max: 1000.0 - Default: 250.0 - Reference low frequency (hz) (SUPPORTED:SFX) 114 | pub LF_reference : f32, 115 | /// [r/w] Min: 0.0 - Max: 100.0 - Default: 100.0 - Value that controls the echo density in the late reverberation decay. (SUPPORTED:SFX) 116 | pub diffusion : f32, 117 | /// [r/w] Min: 0.0 - Max: 100.0 - Default: 100.0 - Value that controls the modal density in the late reverberation decay (SUPPORTED:SFX) 118 | pub density : f32, 119 | /// [r/w] FMOD_REVERB_FLAGS - modifies the behavior of above properties (SUPPORTED:WII) 120 | pub flags : u32 121 | } 122 | 123 | impl Default for ReverbProperties { 124 | fn default() -> ReverbProperties { 125 | ReverbProperties { 126 | instance: 0i32, 127 | environment: -1i32, 128 | env_diffusion: 1.0f32, 129 | room: -1000i32, 130 | room_HF: -100i32, 131 | room_LF: 0i32, 132 | decay_time: 1.49f32, 133 | decay_HF_ratio: 0.83f32, 134 | decay_LF_ratio: 1f32, 135 | reflections: -2602i32, 136 | reflections_delay: 0.007f32, 137 | reverb: 200i32, 138 | reverb_delay: 0.011f32, 139 | modulation_time: 0.25f32, 140 | modulation_depth: 0f32, 141 | HF_reference: 5000f32, 142 | LF_reference: 250f32, 143 | diffusion: 100f32, 144 | density: 100f32, 145 | flags: 0u32, 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/rfmod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | /*! 26 | # rust-fmod 27 | 28 | This is a rust binding for __FMOD__, the library developped by FIRELIGHT TECHNOLOGIES. 29 | 30 | __FMOD__ website: 31 | 32 | ## Installation 33 | 34 | You must install on your computer the __FMOD__ library which is used for the binding. 35 | 36 | ## Short example 37 | 38 | Here is a short example on how to create a file and to play it: 39 | 40 | ```Rust 41 | extern crate libc; 42 | extern crate rfmod; 43 | 44 | use std::os; 45 | 46 | fn main() { 47 | let fmod = match rfmod::Sys::new() { 48 | Ok(f) => f, 49 | Err(e) => { 50 | panic!("Error code : {}", e); 51 | } 52 | }; 53 | 54 | match fmod.init() { 55 | rfmod::Status::Ok => {} 56 | e => { 57 | panic!("Sys.init failed : {}", e); 58 | } 59 | }; 60 | 61 | let mut sound = match fmod.create_sound(StrBuf::from_str("music.mp3"), None, None) { 62 | Ok(s) => s, 63 | Err(err) => { 64 | panic!("Error code : {}", err); 65 | } 66 | }; 67 | 68 | match sound.play_to_the_end() { 69 | rfmod::Status::Ok => { 70 | println!("Ok !"); 71 | } 72 | err => { 73 | panic!("Error code : {}", err); 74 | } 75 | }; 76 | } 77 | ``` 78 | 79 | For a more complete example: https://github.com/GuillaumeGomez/rust-music-player 80 | 81 | ## License 82 | 83 | ```text 84 | Copyright (c) 2014 Guillaume Gomez 85 | 86 | The license of this project is available in the LICENSE.TXT file. Please refer to it. 87 | If you want more information, here is the website for FMOD : http://www.fmod.org/ 88 | ``` 89 | 90 | ### Notes 91 | 92 | * Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value. 93 | * Members marked with [w] mean the variable can be written to. The user can set the value. 94 | 95 | 96 | Here is the list of all modules : 97 | !*/ 98 | 99 | #![crate_name = "rfmod"] 100 | #![crate_type = "rlib"] 101 | #![crate_type = "dylib"] 102 | 103 | #![allow(non_camel_case_types)] 104 | #![allow(non_snake_case)] 105 | #![allow(dead_code)] 106 | #![allow(improper_ctypes)] 107 | 108 | extern crate libc; 109 | extern crate c_vec; 110 | extern crate byteorder; 111 | 112 | pub use channel::{ 113 | Channel, 114 | SpeakerMixOptions, 115 | ReverbChannelProperties 116 | }; 117 | pub use fmod_sys::{ 118 | Sys, 119 | Guid, 120 | SoftwareFormat, 121 | AdvancedSettings, 122 | OutputHandle, 123 | CreateSoundexInfo, 124 | MemoryUsageDetails, 125 | UserData 126 | }; 127 | pub use sound::{ 128 | Sound, 129 | FmodTag, 130 | FmodSyncPoint 131 | }; 132 | pub use channel_group::{ 133 | ChannelGroup 134 | }; 135 | pub use sound_group::SoundGroup; 136 | pub use dsp::{ 137 | Dsp, 138 | DspParameterDesc, 139 | DspDescription, 140 | DspState 141 | }; 142 | pub use dsp_connection::DspConnection; 143 | pub use reverb::Reverb; 144 | pub use reverb_properties::ReverbProperties; 145 | pub use vector::Vector; 146 | pub use geometry::Geometry; 147 | pub use file::{ 148 | FmodFile, 149 | SeekStyle 150 | }; 151 | pub use self::enums::{ 152 | Status, 153 | RStatus, 154 | SpeakerMapType, 155 | SoundFormat, 156 | SoundType, 157 | TagType, 158 | TagDataType, 159 | ChannelIndex, 160 | DspFftWindow, 161 | DelayType, 162 | OutputType, 163 | Speaker, 164 | SpeakerMode, 165 | DspResampler, 166 | PluginType, 167 | OpenState, 168 | SystemCallbackType, 169 | SoundGroupBehavior, 170 | DspType, 171 | DspOscillator, 172 | DspLowPass, 173 | DspITLowPass, 174 | DspHighPass, 175 | DspTypeEcho, 176 | DspDelay, 177 | DspFlange, 178 | DspTremolo, 179 | DspDistortion, 180 | DspNormalize, 181 | DspTypeParameq, 182 | DspPitchShift, 183 | DspChorus, 184 | DspITEcho, 185 | DspCompressor, 186 | DspSfxReverb, 187 | DspLowPassSimple, 188 | DspHighPassSimple 189 | }; 190 | pub use self::types::{ 191 | Mode, 192 | TimeUnit, 193 | FmodCaps, 194 | PluginHandle, 195 | InitFlag, 196 | MemoryBits, 197 | EventMemoryBits, 198 | }; 199 | 200 | #[macro_use] 201 | mod utils; 202 | 203 | mod ffi; 204 | mod sound; 205 | mod channel; 206 | mod channel_group; 207 | mod sound_group; 208 | mod fmod_sys; 209 | mod dsp; 210 | mod dsp_connection; 211 | mod geometry; 212 | mod vector; 213 | mod reverb; 214 | mod reverb_properties; 215 | mod file; 216 | mod enums; 217 | pub mod types; 218 | pub mod callbacks; 219 | pub mod error; 220 | 221 | /// Default for all modes listed below. LOOP_OFF, 2D, HARDWARE 222 | pub const DEFAULT : u32 = 0x00000000; 223 | /// For non looping sounds. (DEFAULT). Overrides LOOP_NORMAL / LOOP_BIDI. 224 | pub const LOOP_OFF : u32 = 0x00000001; 225 | /// For forward looping sounds. 226 | pub const LOOP_NORMAL : u32 = 0x00000002; 227 | /// For bidirectional looping sounds. (only works on software mixed static sounds). 228 | pub const LOOP_BIDI : u32 = 0x00000004; 229 | /// Ignores any 3d processing. (DEFAULT). 230 | pub const _2D : u32 = 0x00000008; 231 | /// Makes the sound positionable in 3D. Overrides 2D 232 | pub const _3D : u32 = 0x00000010; 233 | /// Attempts to make sounds use hardware acceleration. (DEFAULT). Note on platforms that don't support HARDWARE (only 3DS, PS Vita, PSP, Wii and Wii U support HARDWARE), this will be internally treated as SOFTWARE. 234 | pub const HARDWARE : u32 = 0x00000020; 235 | /// Makes the sound be mixed by the FMOD CPU based software mixer. Overrides HARDWARE. Use this for FFT, DSP, compressed sample support, 2D multi-speaker support and other software related features. 236 | pub const SOFTWARE : u32 = 0x00000040; 237 | /// Decompress at runtime, streaming from the source provided (ie from disk). Overrides CREATESAMPLE and CREATECOMPRESSEDSAMPLE. Note a stream can only be played once at a time due to a stream only having 1 stream buffer and file handle. Open multiple streams to have them play concurrently. 238 | pub const CREATESTREAM : u32 = 0x00000080; 239 | /// Decompress at loadtime, decompressing or decoding whole file into memory as the target sample format (ie PCM). Fastest for SOFTWARE based playback and most flexible. 240 | pub const CREATESAMPLE : u32 = 0x00000100; 241 | /// Load MP2/MP3/IMAADPCM/CELT/Vorbis/AT9 or XMA into memory and leave it compressed. CELT/Vorbis/AT9 encoding only supported in the FSB file format. During playback the FMOD software mixer will decode it in realtime as a 'compressed sample'. Can only be used in combination with SOFTWARE. Overrides CREATESAMPLE. If the sound data is not one of the supported formats, it will behave as if it was created with CREATESAMPLE and decode the sound into PCM. 242 | pub const CREATECOMPRESSEDSAMPLE : u32 = 0x00000200; 243 | /// Opens a user created static sample or stream. Use CREATESOUNDEXINFO to specify format and/or read callbacks. If a user created 'sample' is created with no read callback, the sample will be empty. Use [`Sound::lock`](../struct.Sound.html#method.lock) and [`Sound::unlock`](../struct.Sound.html#method.unlock) to place sound data into the sound if this is the case. 244 | pub const OPENUSER : u32 = 0x00000400; 245 | /// "name_or_data" will be interpreted as a pointer to memory instead of filename for creating sounds. Use CREATESOUNDEXINFO to specify length. If used with CREATESAMPLE or CREATECOMPRESSEDSAMPLE, FMOD duplicates the memory into its own buffers. Your own buffer can be freed after open. If used with CREATESTREAM, FMOD will stream out of the buffer whose pointer you passed in. In this case, your own buffer should not be freed until you have finished with and released the stream. 246 | pub const OPENMEMORY : u32 = 0x00000800; 247 | /// "name_or_data" will be interpreted as a pointer to memory instead of filename for creating sounds. Use CREATESOUNDEXINFO to specify length. This differs to OPENMEMORY in that it uses the memory as is, without duplicating the memory into its own buffers. For Wii/PSP HARDWARE supports this flag for the GCADPCM/VAG formats. On other platforms SOFTWARE must be used, as sound hardware on the other platforms (ie PC) cannot access main ram. Cannot be freed after open, only after [`Sound::release`](../struct.Sound.html#method.release). Will not work if the data is compressed and CREATECOMPRESSEDSAMPLE is not used. 248 | pub const OPENMEMORY_POINT : u32 = 0x10000000; 249 | /// Will ignore file format and treat as raw pcm. Use CREATESOUNDEXINFO to specify format. Requires at least defaultfrequency, numchannels and format to be specified before it will open. Must be little endian data. 250 | pub const OPENRAW : u32 = 0x00001000; 251 | /// Just open the file, dont prebuffer or read. Good for fast opens for info, or when sound::readData is to be used. 252 | pub const OPENONLY : u32 = 0x00002000; 253 | /// For [`Sys::create_sound`](../struct.Sys.html#method.create_sound) - for accurate [`Sound::get_length`](../struct.Sound.html#method.get_length) / [`Channel::set_position`](../struct.Channel.html#method.set_position) on VBR MP3, and MOD/S3M/XM/IT/MIDI files. Scans file first, so takes longer to open. OPENONLY does not affect this. 254 | pub const ACCURATETIME : u32 = 0x00004000; 255 | /// For corrupted / bad MP3 files. This will search all the way through the file until it hits a valid MPEG header. Normally only searches for 4k. 256 | pub const MPEGSEARCH : u32 = 0x00008000; 257 | /// For opening sounds and getting streamed subsounds (seeking) asyncronously. Use [`Sound::get_open_state`](../struct.Sound.html#method.get_open_state) to poll the state of the sound as it opens or retrieves the subsound in the background. 258 | pub const NONBLOCKING : u32 = 0x00010000; 259 | /// Unique sound, can only be played one at a time 260 | pub const UNIQUE : u32 = 0x00020000; 261 | /// Make the sound's position, velocity and orientation relative to the listener. 262 | pub const _3D_HEADRELATIVE : u32 = 0x00040000; 263 | /// Make the sound's position, velocity and orientation absolute (relative to the world). (DEFAULT) 264 | pub const _3D_WORLDRELATIVE : u32 = 0x00080000; 265 | /// This sound will follow the inverse rolloff model where mindistance = full volume, maxdistance = where sound stops attenuating, and rolloff is fixed according to the global rolloff factor. (DEFAULT) 266 | pub const _3D_INVERSEROLLOFF : u32 = 0x00100000; 267 | /// This sound will follow a linear rolloff model where mindistance = full volume, maxdistance = silence. Rolloffscale is ignored. 268 | pub const _3D_LINEARROLLOFF : u32 = 0x00200000; 269 | /// This sound will follow a linear-square rolloff model where mindistance = full volume, maxdistance = silence. Rolloffscale is ignored. 270 | pub const _3D_LINEARSQUAREROLLOFF : u32 = 0x00400000; 271 | /// This sound will follow a rolloff model defined by [`Sound::set_3D_custom_rolloff`](../struct.Sound.html#method.set_3D_custom_rolloff) / [`Channel::set_3D_custom_rolloff`](../struct.Channel.html#method.set_3D_custom_rolloff). 272 | pub const _3D_CUSTOMROLLOFF : u32 = 0x04000000; 273 | /// Is not affect by geometry occlusion. If not specified in [`Sound::set_mode`](../struct.Sound.html#method.set_mode), or [`Channel::set_mode`](../struct.Channel.html#method.set_mode), the flag is cleared and it is affected by geometry again. 274 | pub const _3D_IGNOREGEOMETRY : u32 = 0x40000000; 275 | /// Filename is double-byte unicode. 276 | pub const UNICODE : u32 = 0x01000000; 277 | /// Skips id3v2/asf/etc tag checks when opening a sound, to reduce seek/read overhead when opening files (helps with CD performance). 278 | pub const IGNORETAGS : u32 = 0x02000000; 279 | /// Removes some features from samples to give a lower memory overhead, like [`Sound::get_name`](../struct.Sound.html#method.get_name). See remarks. 280 | pub const LOWMEM : u32 = 0x08000000; 281 | /// Load sound into the secondary RAM of supported platform. On PS3, sounds will be loaded into RSX/VRAM. 282 | pub const LOADSECONDARYRAM : u32 = 0x20000000; 283 | /// For sounds that start virtual (due to being quiet or low importance), instead of swapping back to audible, and playing at the correct offset according to time, this flag makes the sound play from the start. 284 | pub const VIRTUAL_PLAYFROMSTART : u32 = 0x80000000; 285 | 286 | /// All platforms - Initialize normally 287 | pub const INIT_NORMAL : u32 = 0x00000000; 288 | /// All platforms - No stream thread is created internally. Streams are driven from [`Sys::update`](../struct.Sys.html#method.update). Mainly used with non-realtime outputs. 289 | pub const INIT_STREAM_FROM_UPDATE : u32 = 0x00000001; 290 | /// All platforms - FMOD will treat +X as right, +Y as up and +Z as backwards (towards you). 291 | pub const INIT_3D_RIGHTHANDED : u32 = 0x00000002; 292 | /// All platforms - Disable software mixer to save memory. Anything created with SOFTWARE will fail and DSP will not work. 293 | pub const INIT_SOFTWARE_DISABLE : u32 = 0x00000004; 294 | /// All platforms - All SOFTWARE (and HARDWARE on 3DS and NGP) with 3D based voices will add a software lowpass filter effect into the DSP chain which is automatically used when [`Channel::set_3D_occlusion`](../struct.Channel.html#method.set_3D_occlusion) is used or the geometry API. 295 | pub const INIT_OCCLUSION_LOWPASS : u32 = 0x00000008; 296 | /// All platforms - All SOFTWARE (and HARDWARE on 3DS and NGP) with 3D based voices will add a software lowpass filter effect into the DSP chain which causes sounds to sound duller when the sound goes behind the listener. Use [`Sys::set_advanced_settings`](../struct.Sys.html#method.set_advanced_settings) to adjust Cutoff frequency. 297 | pub const INIT_HRTF_LOWPASS : u32 = 0x00000010; 298 | /// All platforms - All SOFTWARE with 3D based voices will add a software lowpass and highpass filter effect into the DSP chain which will act as a distance-automated bandpass filter. Use [`Sys::set_advanced_settings`](../struct.Sys.html#method.set_advanced_settings) to adjust the center frequency. 299 | pub const INIT_DISTANCE_FILTERING : u32 = 0x00000200; 300 | /// All platforms - FMOD Software reverb will preallocate enough buffers for reverb per channel, rather than allocating them and freeing them at runtime. 301 | pub const INIT_REVERB_PREALLOCBUFFERS : u32 = 0x00000040; 302 | /// All platforms - Enable TCP/IP based host which allows FMOD Designer or FMOD Profiler to connect to it, and view memory, CPU and the DSP network graph in real-time. 303 | pub const INIT_ENABLE_PROFILE : u32 = 0x00000020; 304 | /// All platforms - Any sounds that are 0 volume will go virtual and not be processed except for having their positions updated virtually. Use [`Sys::set_advanced_settings`](../struct.Sys.html#method.set_advanced_settings) to adjust what volume besides zero to switch to virtual at. 305 | pub const INIT_VOL0_BECOMES_VIRTUAL : u32 = 0x00000080; 306 | /// Win32 Vista only - for WASAPI output - Enable exclusive access to hardware, lower latency at the expense of excluding other applications from accessing the audio hardware. 307 | pub const INIT_WASAPI_EXCLUSIVE : u32 = 0x00000100; 308 | /// PS3 only - Prefer DTS over Dolby Digital if both are supported. Note: 8 and 6 channel LPCM is always preferred over both DTS and Dolby Digital. 309 | pub const INIT_PS3_PREFERDTS : u32 = 0x00800000; 310 | /// PS3 only - Force PS3 system output mode to 2 channel LPCM. 311 | pub const INIT_PS3_FORCE2CHLPCM : u32 = 0x01000000; 312 | /// Wii / 3DS - Disable Dolby Pro Logic surround. will be set to STEREO even if user has selected surround in the system settings. 313 | pub const INIT_DISABLEDOLBY : u32 = 0x00100000; 314 | /// Xbox 360 / PS3 - The "music" channelgroup which by default pauses when custom 360 dashboard / PS3 BGM music is played, can be changed to mute (therefore continues playing) instead of pausing, by using this flag. 315 | pub const INIT_SYSTEM_MUSICMUTENOTPAUSE : u32 = 0x00200000; 316 | /// Win32/Wii/PS3/Xbox/Xbox 360 - FMOD Mixer thread is woken up to do a mix when [`Sys::update`](../struct.Sys.html#method.update) is called rather than waking periodically on its own timer. 317 | pub const INIT_SYNCMIXERWITHUPDATE : u32 = 0x00400000; 318 | /// All platforms - With the geometry engine, only process the closest polygon rather than accumulating all polygons the sound to listener line intersects. 319 | pub const INIT_GEOMETRY_USECLOSEST : u32 = 0x04000000; 320 | /// Win32 - Disables automatic setting of of _STEREO to _MYEARS if the MyEars profile exists on the PC. MyEars is HRTF 7.1 downmixing through headphones. 321 | pub const INIT_DISABLE_MYEARS_AUTODETECT : u32 = 0x08000000; 322 | /// PS3 only - Disable DTS output mode selection 323 | pub const INIT_PS3_DISABLEDTS : u32 = 0x10000000; 324 | /// PS3 only - Disable Dolby Digital output mode selection 325 | pub const INIT_PS3_DISABLEDOLBYDIGITAL : u32 = 0x20000000; 326 | /// PS3/PS4 only - FMOD uses the WAVEFORMATEX Microsoft 7.1 speaker mapping where the last 2 pairs of speakers are 'rears' then 'sides', but on PS3/PS4 these are mapped to 'surrounds' and 'backs'. Use this flag to swap fmod's last 2 pair of speakers on PS3/PS4 to avoid needing to do a special case for these platforms. 327 | pub const INIT_7POINT1_DOLBYMAPPING : u32 = 0x40000000; 328 | 329 | /// Milliseconds. 330 | pub const TIMEUNIT_MS : TimeUnit = TimeUnit(0x00000001); 331 | /// PCM samples, related to milliseconds * samplerate / 1000. 332 | pub const TIMEUNIT_PCM : TimeUnit = TimeUnit(0x00000002); 333 | /// Bytes, related to PCM samples * channels * datawidth (ie 16bit = 2 bytes). 334 | pub const TIMEUNIT_PCMBYTES : TimeUnit = TimeUnit(0x00000004); 335 | /// Raw file bytes of (compressed) sound data (does not include headers). Only used by [`Sound::get_length`](../struct.Sound.html#method.get_length) and [`Channel::get_position`](../struct.Channel.html#method.get_position). 336 | pub const TIMEUNIT_RAWBYTES : TimeUnit = TimeUnit(0x00000008); 337 | /// Fractions of 1 PCM sample. Unsigned int range 0 to 0xFFFFFFFF. Used for sub-sample granularity for DSP purposes. 338 | pub const TIMEUNIT_PCMFRACTION : TimeUnit = TimeUnit(0x00000010); 339 | /// MOD/S3M/XM/IT. Order in a sequenced module format. Use [`Sound::get_format`](../struct.Sound.html#method.get_format) to determine the PCM format being decoded to. 340 | pub const TIMEUNIT_MODORDER : TimeUnit = TimeUnit(0x00000100); 341 | /// MOD/S3M/XM/IT. Current row in a sequenced module format. [`Sound::get_length`](../struct.Sound.html#method.get_length) will return the number of rows in the currently playing or seeked to pattern. 342 | pub const TIMEUNIT_MODROW : TimeUnit = TimeUnit(0x00000200); 343 | /// MOD/S3M/XM/IT. Current pattern in a sequenced module format. [`Sound::get_length`](../struct.Sound.html#method.get_length) will return the number of patterns in the song and [`Channel::get_position`](../struct.Channel.html#method.get_position) will return the currently playing pattern. 344 | pub const TIMEUNIT_MODPATTERN : TimeUnit = TimeUnit(0x00000400); 345 | /// Currently playing subsound in a sentence time in milliseconds. 346 | pub const TIMEUNIT_SENTENCE_MS : TimeUnit = TimeUnit(0x00010000); 347 | /// Currently playing subsound in a sentence time in PCM Samples, related to milliseconds * samplerate / 1000. 348 | pub const TIMEUNIT_SENTENCE_PCM : TimeUnit = TimeUnit(0x00020000); 349 | /// Currently playing subsound in a sentence time in bytes, related to PCM samples * channels * datawidth (ie 16bit = 2 bytes). 350 | pub const TIMEUNIT_SENTENCE_PCMBYTES: TimeUnit = TimeUnit(0x00040000); 351 | /// Currently playing sentence index according to the channel. 352 | pub const TIMEUNIT_SENTENCE : TimeUnit = TimeUnit(0x00080000); 353 | /// Currently playing subsound index in a sentence. 354 | pub const TIMEUNIT_SENTENCE_SUBSOUND: TimeUnit = TimeUnit(0x00100000); 355 | /// Time value as seen by buffered stream. This is always ahead of audible time, and is only used for processing. 356 | pub const TIMEUNIT_BUFFERED : TimeUnit = TimeUnit(0x10000000); 357 | 358 | /// Memory not accounted for by other types 359 | pub const MEMBITS_OTHER : MemoryBits = MemoryBits(0x00000001); 360 | /// String data 361 | pub const MEMBITS_STRING : MemoryBits = MemoryBits(0x00000002); 362 | /// [`Sys`](../struct.Sys.html) object and various internals 363 | pub const MEMBITS_SYSTEM : MemoryBits = MemoryBits(0x00000004); 364 | /// Plugin objects and internals 365 | pub const MEMBITS_PLUGINS : MemoryBits = MemoryBits(0x00000008); 366 | /// Output module object and internals 367 | pub const MEMBITS_OUTPUT : MemoryBits = MemoryBits(0x00000010); 368 | /// [`Channel`](../struct.Channel.html) related memory 369 | pub const MEMBITS_CHANNEL : MemoryBits = MemoryBits(0x00000020); 370 | /// [`ChannelGroup`](../struct.ChannelGroup.html) objects and internals 371 | pub const MEMBITS_CHANNELGROUP : MemoryBits = MemoryBits(0x00000040); 372 | /// Codecs allocated for streaming 373 | pub const MEMBITS_CODEC : MemoryBits = MemoryBits(0x00000080); 374 | /// Codecs allocated for streaming 375 | pub const MEMBITS_FILE : MemoryBits = MemoryBits(0x00000100); 376 | /// [`Sound`](../struct.Sound.html) objects and internals 377 | pub const MEMBITS_SOUND : MemoryBits = MemoryBits(0x00000200); 378 | /// Sound data stored in secondary RAM 379 | pub const MEMBITS_SOUND_SECONDARYRAM: MemoryBits = MemoryBits(0x00000400); 380 | /// [`SoundGroup`](../struct.SoundGroup.html) objects and internals 381 | pub const MEMBITS_SOUNDGROUP : MemoryBits = MemoryBits(0x00000800); 382 | /// Stream buffer memory 383 | pub const MEMBITS_STREAMBUFFER : MemoryBits = MemoryBits(0x00001000); 384 | /// [`DspConnection`](../struct.DspConnection.html) objects and internals 385 | pub const MEMBITS_DSPCONNECTION : MemoryBits = MemoryBits(0x00002000); 386 | /// [`Dsp`](../struct.Dsp.html) implementation objects 387 | pub const MEMBITS_DSP : MemoryBits = MemoryBits(0x00004000); 388 | /// Realtime file format decoding [`Dsp`](../struct.Dsp.html) objects 389 | pub const MEMBITS_DSPCODEC : MemoryBits = MemoryBits(0x00008000); 390 | /// Profiler memory footprint. 391 | pub const MEMBITS_PROFILE : MemoryBits = MemoryBits(0x00010000); 392 | /// Buffer used to store recorded data from microphone 393 | pub const MEMBITS_RECORDBUFFER : MemoryBits = MemoryBits(0x00020000); 394 | /// [`Reverb`](../struct.Reverb.html) implementation objects 395 | pub const MEMBITS_REVERB : MemoryBits = MemoryBits(0x00040000); 396 | /// Reverb channel properties structs 397 | pub const MEMBITS_REVERBCHANNELPROPS: MemoryBits = MemoryBits(0x00080000); 398 | /// [`Geometry`](../struct.Geometry.html) objects and internals 399 | pub const MEMBITS_GEOMETRY : MemoryBits = MemoryBits(0x00100000); 400 | /// Sync point memory. 401 | pub const MEMBITS_SYNCPOINT : MemoryBits = MemoryBits(0x00200000); 402 | /// All memory used by FMOD Ex 403 | pub const MEMBITS_ALL : MemoryBits = MemoryBits(0xffffffff); 404 | 405 | /// EventSystem and various internals 406 | pub const EVENT_MEMBITS_EVENTSYSTEM : u32 = 0x00000001; 407 | /// MusicSystem and various internals 408 | pub const EVENT_MEMBITS_MUSICSYSTEM : u32 = 0x00000002; 409 | /// Definition of objects contained in all loaded projects e.g. events, groups, categories 410 | pub const EVENT_MEMBITS_FEV : u32 = 0x00000004; 411 | /// Data loaded with preloadFSB 412 | pub const EVENT_MEMBITS_MEMORYFSB : u32 = 0x00000008; 413 | /// EventProject objects and internals 414 | pub const EVENT_MEMBITS_EVENTPROJECT : u32 = 0x00000010; 415 | /// EventGroup objects and internals 416 | pub const EVENT_MEMBITS_EVENTGROUPI : u32 = 0x00000020; 417 | /// Objects used to manage wave banks 418 | pub const EVENT_MEMBITS_SOUNDBANKCLASS : u32 = 0x00000040; 419 | /// Data used to manage lists of wave bank usage 420 | pub const EVENT_MEMBITS_SOUNDBANKLIST : u32 = 0x00000080; 421 | /// Stream objects and internals 422 | pub const EVENT_MEMBITS_STREAMINSTANCE : u32 = 0x00000100; 423 | /// Sound definition objects 424 | pub const EVENT_MEMBITS_SOUNDDEFCLASS : u32 = 0x00000200; 425 | /// Sound definition static data objects 426 | pub const EVENT_MEMBITS_SOUNDDEFDEFCLASS : u32 = 0x00000400; 427 | /// Sound definition pool data 428 | pub const EVENT_MEMBITS_SOUNDDEFPOOL : u32 = 0x00000800; 429 | /// Reverb definition objects 430 | pub const EVENT_MEMBITS_REVERBDEF : u32 = 0x00001000; 431 | /// Reverb objects 432 | pub const EVENT_MEMBITS_EVENTREVERB : u32 = 0x00002000; 433 | /// User property objects 434 | pub const EVENT_MEMBITS_USERPROPERTY : u32 = 0x00004000; 435 | /// Event instance base objects 436 | pub const EVENT_MEMBITS_EVENTINSTANCE : u32 = 0x00008000; 437 | /// Complex event instance objects 438 | pub const EVENT_MEMBITS_EVENTINSTANCE_COMPLEX: u32 = 0x00010000; 439 | /// Simple event instance objects 440 | pub const EVENT_MEMBITS_EVENTINSTANCE_SIMPLE : u32 = 0x00020000; 441 | /// Event layer instance objects 442 | pub const EVENT_MEMBITS_EVENTINSTANCE_LAYER : u32 = 0x00040000; 443 | /// Event sound instance objects 444 | pub const EVENT_MEMBITS_EVENTINSTANCE_SOUND : u32 = 0x00080000; 445 | /// Event envelope objects 446 | pub const EVENT_MEMBITS_EVENTENVELOPE : u32 = 0x00100000; 447 | /// Event envelope definition objects 448 | pub const EVENT_MEMBITS_EVENTENVELOPEDEF : u32 = 0x00200000; 449 | /// Event parameter objects 450 | pub const EVENT_MEMBITS_EVENTPARAMETER : u32 = 0x00400000; 451 | /// Event category objects 452 | pub const EVENT_MEMBITS_EVENTCATEGORY : u32 = 0x00800000; 453 | /// Event envelope point objects 454 | pub const EVENT_MEMBITS_EVENTENVELOPEPOINT : u32 = 0x01000000; 455 | /// Event instance pool data 456 | pub const EVENT_MEMBITS_EVENTINSTANCEPOOL : u32 = 0x02000000; 457 | /// All memory used by FMOD Event System 458 | pub const EVENT_MEMBITS_ALL : u32 = 0xffffffff; 459 | 460 | /// All event instance memory 461 | pub const EVENT_MEMBITS_EVENTINSTANCE_GROUP : u32 = EVENT_MEMBITS_EVENTINSTANCE | EVENT_MEMBITS_EVENTINSTANCE_COMPLEX | EVENT_MEMBITS_EVENTINSTANCE_SIMPLE | EVENT_MEMBITS_EVENTINSTANCE_LAYER | EVENT_MEMBITS_EVENTINSTANCE_SOUND; 462 | /// All sound definition memory 463 | pub const EVENT_MEMBITS_SOUNDDEF_GROUP : u32 = EVENT_MEMBITS_SOUNDDEFCLASS | EVENT_MEMBITS_SOUNDDEFDEFCLASS | EVENT_MEMBITS_SOUNDDEFPOOL; 464 | 465 | #[cfg(target_os = "linux")] 466 | mod platform { 467 | #[cfg(target_arch="x86")] 468 | #[link(name = "fmodex")] extern{} 469 | #[cfg(target_arch="x86_64")] 470 | #[link(name = "fmodex64")] extern{} 471 | } 472 | 473 | #[cfg(target_os = "macos")] 474 | mod platform { 475 | #[link(name = "fmodex")] extern{} 476 | } 477 | 478 | #[cfg(target_os = "windows")] 479 | mod platform { 480 | #[cfg(target_arch="x86")] 481 | #[link(name = "fmodex_vc")] extern{} 482 | #[cfg(target_arch="x86_64")] 483 | #[link(name = "fmodex64_vc")] extern{} 484 | } 485 | -------------------------------------------------------------------------------- /src/sound.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | use types::*; 26 | use libc::{c_int, c_uint, c_char, c_ushort, c_void}; 27 | use ffi; 28 | use channel; 29 | use sound_group; 30 | use vector; 31 | use fmod_sys; 32 | use fmod_sys::{MemoryUsageDetails, Sys}; 33 | use std::mem::transmute; 34 | use std::fs::File; 35 | use std::mem; 36 | use std::slice; 37 | use std::default::Default; 38 | use byteorder::{WriteBytesExt, LittleEndian}; 39 | use std::io::Write; 40 | use std::ffi::CString; 41 | use std::time::Duration; 42 | 43 | struct RiffChunk { 44 | id: [c_char; 4], 45 | size: c_int 46 | } 47 | 48 | struct FmtChunk { 49 | chunk: RiffChunk, 50 | w_format_tag: c_ushort, /* format type */ 51 | n_channels: c_ushort, /* number of channels (i.e. mono, stereo...) */ 52 | n_samples_per_sec: c_uint, /* sample rate */ 53 | n_avg_bytes_per_sec: c_uint,/* for buffer estimation */ 54 | n_block_align: c_ushort, /* block size of data */ 55 | w_bits_per_sample: c_ushort /* number of bits per sample of mono data */ 56 | } 57 | 58 | struct DataChunk { 59 | chunk: RiffChunk 60 | } 61 | 62 | struct WavHeader { 63 | chunk: RiffChunk, 64 | riff_type: [c_char; 4] 65 | } 66 | 67 | /// Wrapper for SyncPoint object 68 | pub struct FmodSyncPoint { 69 | sync_point: *mut ffi::FMOD_SYNCPOINT 70 | } 71 | 72 | impl FmodSyncPoint { 73 | fn from_ptr(pointer: *mut ffi::FMOD_SYNCPOINT) -> FmodSyncPoint { 74 | FmodSyncPoint{sync_point: pointer} 75 | } 76 | } 77 | 78 | /// Structure describing a piece of tag data. 79 | pub struct FmodTag { 80 | /// [r] The type of this tag. 81 | pub _type : ::TagType, 82 | /// [r] The type of data that this tag contains 83 | pub data_type: ::TagDataType, 84 | /// [r] The name of this tag i.e. "TITLE", "ARTIST" etc. 85 | pub name : String, 86 | /// [r] Pointer to the tag data - its format is determined by the datatype member 87 | data : *mut c_void, 88 | /// [r] Length of the data contained in this tag 89 | data_len : c_uint, 90 | /// [r] True if this tag has been updated since last being accessed with 91 | /// [`Sound::get_tag`](struct.Sound.html#method.get_tag) 92 | pub updated : bool, 93 | } 94 | 95 | impl 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 | 108 | impl 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 | 154 | /// Sound object 155 | pub struct Sound { 156 | sound: *mut ffi::FMOD_SOUND, 157 | can_be_deleted: bool, 158 | user_data: ffi::SoundData, 159 | } 160 | 161 | impl ffi::FFI 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 | 171 | pub fn get_fffi<'r>(sound: &'r mut Sound) -> &'r mut *mut ffi::FMOD_SOUND { 172 | &mut sound.sound 173 | } 174 | 175 | pub 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 | 179 | pub fn get_user_data<'r>(sound: &'r mut Sound) -> &'r mut ffi::SoundData { 180 | &mut sound.user_data 181 | } 182 | 183 | impl Drop for Sound { 184 | fn drop(&mut self) { 185 | self.release(); 186 | } 187 | } 188 | 189 | impl Sound { 190 | pub fn get_system_object(&self) -> Result { 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 { 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 | /// Returns: 285 | /// 286 | /// Ok(frequency_var, volume_var, pan_var) 287 | 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 | /// Returns: 304 | /// 305 | /// Ok(min, max) 306 | 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 | /// Returns: 323 | /// 324 | /// Ok(inside_cone_angle, outside_cone_angle, outside_volume) 325 | 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) -> ::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 | // to test 349 | pub fn get_3D_custom_rolloff(&self, num_points: u32) -> Result, ::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 { 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 { 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 { 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 | /// Returns: 404 | /// 405 | /// Ok(type, format, channels, bits) 406 | 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 { 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 | /// Returns: 429 | /// 430 | /// Ok(num_tags, num_tags_updated) 431 | 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 | //to test if tag's data needs to be filled by user 442 | pub fn get_tag(&self, name: &str, index: i32) -> Result { 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 { 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 { 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 { 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 { 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 { 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 { 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 | /// Returns: 581 | /// 582 | /// Ok(loop_start, loop_end) 583 | 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 { 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 | // TODO: see how to replace i32 channel by Channel struct 605 | 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 | // TODO: see how to replace i32 channel by Channel struct 610 | pub fn get_music_channel_volume(&self, channel: i32) -> Result { 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 { 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) -> ::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 | /// Returns: 642 | /// 643 | /// Ok(memory_used, details) 644 | 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 | /// Returns: 658 | /// 659 | /// Ok(ptr1, ptr2) 660 | /// 661 | /// ptr1: Address of a pointer that will point to the first part of the locked data. 662 | /// 663 | /// ptr2: Address of a pointer that will point to the second part of the locked data. This will 664 | /// be null if the data locked hasn't wrapped at the end of the buffer. 665 | pub fn lock(&self, offset: u32, length: u32) -> Result<(Vec, Vec), ::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, v_ptr2: Vec) -> ::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 | // ? 730 | Err(::Status::Ok) 731 | } 732 | }, 733 | e => Err(e) 734 | } 735 | } 736 | } 737 | 738 | pub fn save_to_wav(&self, file_name: &str) -> Result { 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::() as i32 - mem::size_of::() 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::() as i32 + mem::size_of::() 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 | /* wav header */ 796 | 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::(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 | /* wav chunk */ 811 | 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::(fmt_chunk.chunk.size) { 817 | return Err(format!("write_i32 failed: {}", e)); 818 | } 819 | if let Err(e) = wtr.write_u16::(fmt_chunk.w_format_tag) { 820 | return Err(format!("write_u16 failed: {}", e)); 821 | } 822 | if let Err(e) = wtr.write_u16::(fmt_chunk.n_channels) { 823 | return Err(format!("write_u16 failed: {}", e)); 824 | } 825 | if let Err(e) = wtr.write_u32::(fmt_chunk.n_samples_per_sec) { 826 | return Err(format!("write_u32 failed: {}", e)); 827 | } 828 | if let Err(e) = wtr.write_u32::(fmt_chunk.n_avg_bytes_per_sec) { 829 | return Err(format!("write_u32 failed: {}", e)); 830 | } 831 | if let Err(e) = wtr.write_u16::(fmt_chunk.n_block_align) { 832 | return Err(format!("write_u16 failed: {}", e)); 833 | } 834 | if let Err(e) = wtr.write_u16::(fmt_chunk.w_bits_per_sample) { 835 | return Err(format!("write_u16 failed: {}", e)); 836 | } 837 | 838 | /* wav data chunk */ 839 | 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::(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 | } 859 | -------------------------------------------------------------------------------- /src/sound_group.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | use types::*; 26 | use ffi; 27 | use sound; 28 | use libc::c_void; 29 | use fmod_sys; 30 | use fmod_sys::MemoryUsageDetails; 31 | use std::mem::transmute; 32 | use libc::{c_char}; 33 | use std::default::Default; 34 | 35 | /// SoundGroup object 36 | pub struct SoundGroup { 37 | sound_group: *mut ffi::FMOD_SOUNDGROUP, 38 | } 39 | 40 | impl ffi::FFI for SoundGroup { 41 | fn wrap(s: *mut ffi::FMOD_SOUNDGROUP) -> SoundGroup { 42 | SoundGroup {sound_group: s} 43 | } 44 | 45 | fn unwrap(s: &SoundGroup) -> *mut ffi::FMOD_SOUNDGROUP { 46 | s.sound_group 47 | } 48 | } 49 | 50 | impl Drop for SoundGroup { 51 | fn drop(&mut self) { 52 | self.release(); 53 | } 54 | } 55 | 56 | impl SoundGroup { 57 | pub fn release(&mut self) -> ::Status { 58 | if !self.sound_group.is_null() { 59 | match unsafe { ffi::FMOD_SoundGroup_Release(self.sound_group) } { 60 | ::Status::Ok => { 61 | self.sound_group =::std::ptr::null_mut(); 62 | ::Status::Ok 63 | } 64 | e => e 65 | } 66 | } else { 67 | ::Status::Ok 68 | } 69 | } 70 | 71 | pub fn set_max_audible(&self, max_audible: i32) -> ::Status { 72 | unsafe { ffi::FMOD_SoundGroup_SetMaxAudible(self.sound_group, max_audible) } 73 | } 74 | 75 | pub fn get_max_audible(&self) -> Result { 76 | let mut max_audible = 0i32; 77 | 78 | match unsafe { ffi::FMOD_SoundGroup_GetMaxAudible(self.sound_group, &mut max_audible) } { 79 | ::Status::Ok => Ok(max_audible), 80 | e => Err(e) 81 | } 82 | } 83 | 84 | pub fn set_max_audible_behavior(&self, max_audible_behavior: ::SoundGroupBehavior) -> ::Status { 85 | unsafe { ffi::FMOD_SoundGroup_SetMaxAudibleBehavior(self.sound_group, 86 | max_audible_behavior) } 87 | } 88 | 89 | pub fn get_max_audible_behavior(&self) -> Result<::SoundGroupBehavior, ::Status> { 90 | let mut max_audible_behavior = ::SoundGroupBehavior::Fail; 91 | 92 | match unsafe { ffi::FMOD_SoundGroup_GetMaxAudibleBehavior(self.sound_group, 93 | &mut max_audible_behavior) } { 94 | ::Status::Ok => Ok(max_audible_behavior), 95 | e => Err(e) 96 | } 97 | } 98 | 99 | pub fn set_mute_fade_speed(&self, speed: f32) -> ::Status { 100 | unsafe { ffi::FMOD_SoundGroup_SetMuteFadeSpeed(self.sound_group, speed) } 101 | } 102 | 103 | pub fn get_mute_fade_speed(&self) -> Result { 104 | let mut speed = 0f32; 105 | 106 | match unsafe { ffi::FMOD_SoundGroup_GetMuteFadeSpeed(self.sound_group, &mut speed) } { 107 | ::Status::Ok => Ok(speed), 108 | e => Err(e) 109 | } 110 | } 111 | 112 | pub fn set_volume(&self, volume: f32) -> ::Status { 113 | unsafe { ffi::FMOD_SoundGroup_SetVolume(self.sound_group, volume) } 114 | } 115 | 116 | pub fn get_volume(&self) -> Result { 117 | let mut volume = 0f32; 118 | 119 | match unsafe { ffi::FMOD_SoundGroup_GetVolume(self.sound_group, &mut volume) } { 120 | ::Status::Ok => Ok(volume), 121 | e => Err(e) 122 | } 123 | } 124 | 125 | pub fn stop(&self) -> ::Status { 126 | unsafe { ffi::FMOD_SoundGroup_Stop(self.sound_group) } 127 | } 128 | 129 | pub fn get_name(&self, name_len: usize) -> Result { 130 | let mut c = Vec::with_capacity(name_len + 1); 131 | 132 | for _ in 0..(name_len + 1) { 133 | c.push(0); 134 | } 135 | 136 | match unsafe { ffi::FMOD_SoundGroup_GetName(self.sound_group, c.as_mut_ptr() as *mut c_char, 137 | name_len as i32) } { 138 | ::Status::Ok => Ok(from_utf8!(c)), 139 | e => Err(::RStatus::FMOD(e)), 140 | } 141 | } 142 | 143 | pub fn get_num_sounds(&self) -> Result { 144 | let mut num_sounds = 0i32; 145 | 146 | match unsafe { ffi::FMOD_SoundGroup_GetNumSounds(self.sound_group, &mut num_sounds) } { 147 | ::Status::Ok => Ok(num_sounds), 148 | e => Err(e) 149 | } 150 | } 151 | 152 | pub fn get_sound(&self, index: i32) -> Result { 153 | let mut sound = ::std::ptr::null_mut(); 154 | 155 | match unsafe { ffi::FMOD_SoundGroup_GetSound(self.sound_group, index, &mut sound) } { 156 | ::Status::Ok => Ok(ffi::FFI::wrap(sound)), 157 | e => Err(e) 158 | } 159 | } 160 | 161 | pub fn get_num_playing(&self) -> Result { 162 | let mut num_playing = 0i32; 163 | 164 | match unsafe { ffi::FMOD_SoundGroup_GetNumPlaying(self.sound_group, &mut num_playing) } { 165 | ::Status::Ok => Ok(num_playing), 166 | e => Err(e) 167 | } 168 | } 169 | 170 | /// Returns: 171 | /// 172 | /// Ok(memory_used, details) 173 | pub fn get_memory_info(&self, MemoryBits(memory_bits): MemoryBits, 174 | EventMemoryBits(event_memory_bits): EventMemoryBits) 175 | -> Result<(u32, MemoryUsageDetails), ::Status> { 176 | let mut details = fmod_sys::get_memory_usage_details_ffi(Default::default()); 177 | let mut memory_used = 0u32; 178 | 179 | match unsafe { ffi::FMOD_SoundGroup_GetMemoryInfo(self.sound_group, memory_bits, event_memory_bits, &mut memory_used, &mut details) } { 180 | ::Status::Ok => Ok((memory_used, fmod_sys::from_memory_usage_details_ptr(details))), 181 | e => Err(e) 182 | } 183 | } 184 | 185 | pub fn set_user_data<'r, T>(&'r self, user_data: &'r mut T) -> ::Status { 186 | unsafe { ffi::FMOD_SoundGroup_SetUserData(self.sound_group, transmute(user_data)) } 187 | } 188 | 189 | pub fn get_user_data<'r, T>(&'r self) -> Result<&'r mut T, ::Status> { 190 | unsafe { 191 | let mut user_data : *mut c_void = ::std::ptr::null_mut(); 192 | 193 | match ffi::FMOD_SoundGroup_GetUserData(self.sound_group, &mut user_data) { 194 | ::Status::Ok => { 195 | let tmp : &mut T = transmute::<*mut c_void, &mut T>(user_data); 196 | 197 | Ok(tmp) 198 | }, 199 | e => Err(e) 200 | } 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | #[derive(Clone, Copy)] 26 | pub struct Mode(pub u32); 27 | #[derive(Clone, Copy)] 28 | pub struct TimeUnit(pub u32); 29 | #[derive(Clone, Copy)] 30 | pub struct FmodCaps(pub u32); 31 | #[derive(Clone, Copy)] 32 | pub struct PluginHandle(pub u32); 33 | #[derive(Clone, Copy)] 34 | pub struct InitFlag(pub u32); 35 | #[derive(Clone, Copy)] 36 | pub struct MemoryBits(pub u32); 37 | #[derive(Clone, Copy)] 38 | pub struct EventMemoryBits(pub u32); 39 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2018 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 | 25 | #[macro_export] 26 | macro_rules! from_utf8 { 27 | ($vec:expr) => {{ 28 | let mut pos = 0; 29 | 30 | for x in $vec.iter() { 31 | pos += 1; 32 | if *x == 0 { 33 | break 34 | } 35 | } 36 | unsafe { $vec.set_len(pos); } 37 | String::from_utf8_lossy(&$vec).into() 38 | }} 39 | } 40 | -------------------------------------------------------------------------------- /src/vector.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Rust-FMOD - Copyright (c) 2016 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 | 25 | use ffi; 26 | use std::default::Default; 27 | 28 | pub fn from_ptr(vec: ffi::FMOD_VECTOR) -> Vector { 29 | Vector { 30 | x: vec.x, 31 | y: vec.y, 32 | z: vec.z, 33 | } 34 | } 35 | 36 | pub fn get_ffi(vec: &Vector) -> ffi::FMOD_VECTOR { 37 | ffi::FMOD_VECTOR { 38 | x: vec.x, 39 | y: vec.y, 40 | z: vec.z, 41 | } 42 | } 43 | 44 | #[derive(Debug, Clone, Copy)] 45 | /// Structure describing a point in 3D space. 46 | pub struct Vector { 47 | /// X co-ordinate in 3D space. 48 | pub x: f32, 49 | /// Y co-ordinate in 3D space. 50 | pub y: f32, 51 | /// Z co-ordinate in 3D space. 52 | pub z: f32, 53 | } 54 | 55 | impl Default for Vector { 56 | fn default() -> Vector { 57 | Vector::new() 58 | } 59 | } 60 | 61 | impl Vector { 62 | pub fn new() -> Vector { 63 | Vector { 64 | x: 0f32, 65 | y: 0f32, 66 | z: 0f32, 67 | } 68 | } 69 | } 70 | 71 | impl PartialEq for Vector { 72 | fn eq(&self, other: &Vector) -> bool { 73 | self.x == other.x && self.y == other.y && self.z == other.z 74 | } 75 | 76 | fn ne(&self, other: &Vector) -> bool { 77 | !self.eq(other) 78 | } 79 | } 80 | --------------------------------------------------------------------------------