diff --git a/.gitignore b/.gitignore index 090a1f0..5364633 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea .DS_Store +FMOD\ Programmers\ API/ +.fmod203/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6fc4fbe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +## [Unreleased] - 2025-11-06 + +### Added +- Support for FMOD 2.03.09 +- Parser grammar support for variadic macros with `##__VA_ARGS__` +- Integration test for macro parsing + +### Changed +- `System::getVersion()` returns `(version, buildnumber)` tuple +- Generator uses patching system for removed/renamed structure fields + +### Breaking Changes +- `System::getVersion()` signature changed +- `FMOD_ADVANCEDSETTINGS.commandQueueSize` removed +- Requires FMOD 2.03.09 SDK \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..239509b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,125 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +libfmod is a Rust bindings library for FMOD Engine audio middleware. The project consists of two main components: +- **libfmod-gen**: A code generator that parses FMOD C headers and generates Rust FFI bindings +- **libfmod**: The main library providing safe Rust wrappers around FMOD's C API + +**Current Focus**: Migrating from FMOD 2.02.22 to 2.03.09 (see docs/ folder for detailed plans) + +## Build Commands + +### Building the main library +```bash +cd libfmod +cargo build +cargo build --features logging # Build with FMOD logging libraries +``` + +### Running the generator +```bash +cd libfmod-gen +cargo run -- [fmod_sdk_path] [output_dir] +# Default: cargo run -- ./fmod/20222 ../libfmod +``` + +### Testing +```bash +# Run library tests (requires FMOD libraries installed) +cd libfmod +export LD_LIBRARY_PATH=$FMOD_SDK_PATH/api/core/lib/x86_64:$LD_LIBRARY_PATH +cargo test -- --test-threads=1 + +# Run specific test +cargo test test_name -- --nocapture + +# Run manual tests +cargo test --test manual -- --ignored +``` + +### Code formatting and linting +```bash +cargo fmt +cargo clippy +``` + +## Architecture + +### Code Generation Pipeline +1. **Parser** (libfmod-gen/src/parsers/): Uses pest grammar to parse FMOD C headers + - Extracts structures, functions, enums, callbacks, constants + - Parses documentation from HTML files for parameter modifiers + +2. **Patching** (libfmod-gen/src/patching/): Applies manual corrections to parsed data + - Fixes FFI type mappings + - Handles special cases and FMOD-specific patterns + +3. **Generator** (libfmod-gen/src/generators/): Creates Rust code from parsed API + - `ffi.rs`: Raw FFI bindings + - `lib.rs`: Safe Rust wrappers + - `flags.rs`: Bitflags for FMOD flags + - `errors.rs`: Error type definitions + +### Key Components + +**libfmod-gen/src/main.rs**: Entry point that orchestrates the generation process +- Reads FMOD headers from SDK +- Invokes parsers for each header file +- Patches the combined API model +- Generates Rust files + +**libfmod/build.rs**: Build script that links appropriate FMOD libraries based on platform and features + +## Important Implementation Details + +- The library uses dynamic linking only (FMOD doesn't support static linking) +- String ownership is managed by moving String fields to C when passing structures +- The generator automatically runs `cargo fmt` after generating code +- Test files require FMOD development libraries to be installed as per README + +## FMOD 2.03.09 Migration (Current Focus) + +### Critical Breaking Changes +- **No ABI compatibility** between FMOD 2.02 and 2.03 +- `System::getVersion` signature changed (adds buildnumber parameter) +- `FMOD_ADVANCEDSETTINGS.commandQueueSize` field removed +- `FMOD_STUDIO_ADVANCEDSETTINGS.encryptionkey` field added +- `FMOD_OUTPUT_DESCRIPTION.polling` renamed to `method` + +### Migration Phases (see docs/fmod-update-plan.md) +1. **Setup**: Download and verify FMOD 2.03.09 SDK +2. **Generator Updates**: Fix breaking changes in libfmod-gen +3. **Core libfmod**: Update system, studio, and event APIs +4. **Test Harness**: Interactive testing tool +5. **bevy_fmod**: Minimal Bevy plugin implementation +6. **Validation**: Complete test suite + +### Test-Driven Approach +Each migration step has specific tests to verify correctness before proceeding. Run tests after any changes: +```bash +# After libfmod-gen changes +cd libfmod-gen && cargo test + +# After libfmod changes +cd libfmod && cargo test -- --test-threads=1 + +# Interactive testing +cargo run --example test_harness +``` + +## Quick Reference + +### Common Issues +- **Dangling pointer warnings**: Temporary Vec issues in FFI code (needs fixing) +- **Missing FMOD libraries**: Follow README installation instructions +- **Test failures**: Ensure FMOD libraries are in LD_LIBRARY_PATH + +### File Locations +- Generated FFI: `libfmod/src/ffi.rs` +- Safe wrappers: `libfmod/src/lib.rs` +- Parser grammar: `libfmod-gen/src/parsers/*.rs` +- Patching rules: `libfmod-gen/src/patching/` +- Migration docs: `docs/fmod-*.md` \ No newline at end of file diff --git a/README.md b/README.md index 6af4317..1964caf 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,10 @@ libfmod = "~2.222" Choose one of FMOD supported versions: -| libfmod | FMOD | Status | End of life | -|---------|---------|--------|-------------| -| 2.222 | 2.02.22 | active | | -| 2.206 | 2.02.06 | frozen | 2024-09-03 | +| libfmod | FMOD | Status | +|---------|---------|--------| +| dev | 2.03.09 | active | +| 2.222 | 2.02.22 | frozen | Active: new features, bugfixes, and security fixes are accepted, new crates are still released. @@ -119,6 +119,50 @@ fn test_playing_sound() -> Result<(), Error> { See more examples in [tests](libfmod/tests) folder. +### Interactive Demos + +For interactive demos and feature demonstrations, see the separate **[libfmod-demos](https://github.com/chainhackers/libfmod-demos)** repository: + +- **harness_demo** - Non-interactive demonstrations of 3D audio, spatial positioning, parameters, and events +- **interactive_harness** - Real-time keyboard-controlled testing with 3D audio positioning +- **play_sound** - Simple audio file playback +- Plus comprehensive test suites for Studio banks, events, and parameters + +```bash +# Clone and run demos +git clone https://github.com/chainhackers/libfmod-demos +cd libfmod-demos +./run_demos.sh harness_demo +``` + +### Running Tests + +Tests require FMOD SDK libraries to be available at runtime. + +**1. Download and extract FMOD SDK:** + +```bash +# Download FMOD Studio API from https://www.fmod.com/download +# Extract it in the parent directory (or adjust paths accordingly) +cd /path/to/libfmod +tar -xzf fmodstudioapi20310linux.tar.gz +``` + +**2. Run tests with the provided script:** + +```bash +cd libfmod +./test.sh +``` + +Or manually set the library path: + +```bash +LD_LIBRARY_PATH=../fmodstudioapi20310linux/api/core/lib/x86_64:../fmodstudioapi20310linux/api/studio/lib/x86_64 cargo test -- --test-threads=1 +``` + +**Note:** Tests must run serially (`--test-threads=1`) because they share the audio device. + ### Contributing This library is generated by [libfmod-gen](libfmod-gen) and can't be changed manually. diff --git a/RUN_FMOD_2.03.md b/RUN_FMOD_2.03.md new file mode 100644 index 0000000..e9f7b46 --- /dev/null +++ b/RUN_FMOD_2.03.md @@ -0,0 +1,120 @@ +# How to Run FMOD 2.03.09 Examples + +## Quick Start (Copy & Paste) + +From the `libfmod` directory, run: + +```bash +# Set library path and run +export LD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib/x86_64:../libfmod-gen/fmod/20309/api/studio/lib/x86_64:$LD_LIBRARY_PATH" +./target/debug/examples/play_sound /usr/share/sounds/freedesktop/stereo/bell.oga +``` + +## The Problem + +The error `libfmod.so.14: cannot open shared object file` happens because Linux can't find the FMOD 2.03.09 libraries. They're in `libfmod-gen/fmod/20309/` but the system doesn't know that. + +## Solution 1: Set LD_LIBRARY_PATH (Temporary) + +Every time you open a new terminal, run: + +```bash +cd ~/devenv/gamedev/dg/src/libfmod/libfmod +export LD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib/x86_64:../libfmod-gen/fmod/20309/api/studio/lib/x86_64:$LD_LIBRARY_PATH" +``` + +Then you can run examples: +```bash +./target/debug/examples/play_sound /usr/share/sounds/freedesktop/stereo/bell.oga +./target/debug/examples/verify_203 +``` + +## Solution 2: Use the Run Script (Easier!) + +Use the provided script that sets everything up: + +```bash +cd ~/devenv/gamedev/dg/src/libfmod/libfmod +./run_fmod.sh play_sound /usr/share/sounds/freedesktop/stereo/bell.oga +./run_fmod.sh verify_203 +``` + +## Solution 3: Install Libraries (Permanent) + +To avoid setting paths every time: + +```bash +# Copy to user library directory (no sudo needed) +mkdir -p ~/lib +cp ../libfmod-gen/fmod/20309/api/core/lib/x86_64/*.so* ~/lib/ +cp ../libfmod-gen/fmod/20309/api/studio/lib/x86_64/*.so* ~/lib/ + +# Add to .bashrc or .zshrc +echo 'export LD_LIBRARY_PATH="$HOME/lib:$LD_LIBRARY_PATH"' >> ~/.bashrc +source ~/.bashrc +``` + +## Building Examples + +When building, you need to tell Rust where the libraries are: + +```bash +cd ~/devenv/gamedev/dg/src/libfmod/libfmod +RUSTFLAGS="-L $(pwd)/../libfmod-gen/fmod/20309/api/core/lib/x86_64 -L $(pwd)/../libfmod-gen/fmod/20309/api/studio/lib/x86_64" cargo build --example play_sound +``` + +## Available Examples + +1. **play_sound** - Play any audio file + ```bash + ./run_fmod.sh play_sound ~/Music/song.mp3 + ``` + +2. **verify_203** - Quick version check + ```bash + ./run_fmod.sh verify_203 + ``` + +3. **quick_test** - Comprehensive test + ```bash + ./run_fmod.sh quick_test + ``` + +## Common Audio Files to Test + +```bash +# System sounds (usually available) +/usr/share/sounds/freedesktop/stereo/bell.oga +/usr/share/sounds/freedesktop/stereo/complete.oga +/usr/share/sounds/freedesktop/stereo/message.oga + +# Your own files +~/Music/*.mp3 +~/Music/*.wav +~/Downloads/*.ogg +``` + +## Troubleshooting + +If you still get library errors: + +1. **Check libraries exist:** + ```bash + ls ../libfmod-gen/fmod/20309/api/core/lib/x86_64/ + ``` + Should show: libfmod.so, libfmod.so.14, libfmod.so.14.9 + +2. **Check current LD_LIBRARY_PATH:** + ```bash + echo $LD_LIBRARY_PATH + ``` + +3. **Check what libraries the program needs:** + ```bash + ldd ./target/debug/examples/play_sound + ``` + +4. **Full path approach:** + ```bash + LD_LIBRARY_PATH=/full/path/to/fmod/libs:$LD_LIBRARY_PATH ./target/debug/examples/play_sound + ``` \ No newline at end of file diff --git a/docs/FMOD_SETUP_MANUAL.md b/docs/FMOD_SETUP_MANUAL.md new file mode 100644 index 0000000..b44e444 --- /dev/null +++ b/docs/FMOD_SETUP_MANUAL.md @@ -0,0 +1,107 @@ +# FMOD Setup Manual for libfmod + +Quick guide for setting up FMOD libraries to test libfmod on Linux and macOS. + +## Step 1: Download FMOD SDK + +1. Go to https://www.fmod.com/download +2. Create an account and sign in +3. Download FMOD Engine 2.03.09 for your platform: + - Linux: `fmodstudioapi20309linux.tar.gz` + - macOS: `fmodstudioapi20309mac-installer.dmg` + +## Step 2: Extract/Install FMOD + +### Linux + +```bash +cd libfmod/libfmod-gen +mkdir -p fmod/20309 +tar -xzf ~/Downloads/fmodstudioapi20309linux.tar.gz -C fmod/20309 --strip-components=1 +``` + +### macOS + +```bash +# Mount the DMG and extract the SDK +hdiutil attach ~/Downloads/fmodstudioapi20309mac-installer.dmg +cd libfmod/libfmod-gen +mkdir -p fmod/20309 + +# Copy the SDK files (adjust path if needed) +cp -r /Volumes/FMOD\ Programmers\ API/FMOD\ Programmers\ API/* fmod/20309/ + +# Unmount +hdiutil detach /Volumes/FMOD\ Programmers\ API/ +``` + +## Step 3: Run Examples + +### Linux + +```bash +cd libfmod/libfmod + +# Test FMOD version +./run_fmod.sh verify_203 + +# Play a sound +./run_fmod.sh play_sound /usr/share/sounds/freedesktop/stereo/bell.oga + +# Test Studio features +./run_fmod.sh studio_banks_test +``` + +### macOS + +```bash +cd libfmod/libfmod + +# Build with library paths +RUSTFLAGS="-L ../libfmod-gen/fmod/20309/api/core/lib -L ../libfmod-gen/fmod/20309/api/studio/lib" \ +cargo build --example verify_203 + +# Run with library path +DYLD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib:../libfmod-gen/fmod/20309/api/studio/lib" \ +./target/debug/examples/verify_203 + +# Play a sound (use macOS system sound) +DYLD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib:../libfmod-gen/fmod/20309/api/studio/lib" \ +./target/debug/examples/play_sound /System/Library/Sounds/Glass.aiff +``` + +## Directory Structure After Setup + +``` +libfmod-gen/fmod/20309/ +├── api/ +│ ├── core/ +│ │ ├── inc/ # Headers +│ │ └── lib/ # Libraries +│ │ ├── x86_64/ # Linux +│ │ └── *.dylib # macOS +│ └── studio/ +│ └── examples/ +│ └── media/ # Sample banks +└── doc/ +``` + +## Troubleshooting + +### Linux: "libraries not found" +```bash +export LD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib/x86_64:../libfmod-gen/fmod/20309/api/studio/lib/x86_64:$LD_LIBRARY_PATH" +``` + +### macOS: "dylib not found" +```bash +export DYLD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib:../libfmod-gen/fmod/20309/api/studio/lib:$DYLD_LIBRARY_PATH" +``` + +### macOS: Security warnings +If macOS blocks the libraries: +```bash +# Remove quarantine attribute +xattr -d com.apple.quarantine libfmod-gen/fmod/20309/api/core/lib/*.dylib +xattr -d com.apple.quarantine libfmod-gen/fmod/20309/api/studio/lib/*.dylib +``` \ No newline at end of file diff --git a/libfmod-gen/src/generators/ffi.rs b/libfmod-gen/src/generators/ffi.rs index c04181c..f104da4 100644 --- a/libfmod-gen/src/generators/ffi.rs +++ b/libfmod-gen/src/generators/ffi.rs @@ -6,8 +6,8 @@ use quote::quote; use crate::models::Type::FundamentalType; use crate::models::{ - Api, Argument, Callback, Constant, Enumeration, Error, ErrorStringMapping, Field, Flags, - Function, OpaqueType, Pointer, Preset, Structure, Type, TypeAlias, Union, + Api, Argument, Callback, Constant, Enumeration, Error, Field, Flags, Function, OpaqueType, + Pointer, Preset, Structure, Type, TypeAlias, Union, }; impl From for Error { @@ -261,7 +261,7 @@ pub fn generate_structure_union(name: &Ident, union: &Union) -> TokenStream { } } -pub fn generate_structure(structure: &Structure) -> TokenStream { +pub fn generate_structure(structure: &Structure, _api: &Api) -> TokenStream { let name = format_ident!("{}", structure.name); let fields = structure.fields.iter().map(generate_field); let default = generate_structure_default(&structure); @@ -336,7 +336,6 @@ pub fn generate_preset(structure: &Structure, preset: &Preset) -> Result Result { let opaque_types: Vec = api.opaque_types.iter().map(generate_opaque_type).collect(); @@ -362,7 +361,7 @@ pub fn generate_ffi_code(api: &Api) -> Result { let mut structures = vec![]; for structure in &api.structures { - structures.push(generate_structure(structure)); + structures.push(generate_structure(structure, api)); } let mut libraries = vec![]; @@ -385,6 +384,7 @@ pub fn generate_ffi_code(api: &Api) -> Result { #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(unused_parens)] + #![allow(clippy::unnecessary_cast)] use std::os::raw::{c_char, c_float, c_int, c_longlong, c_short, c_uchar, c_uint, c_ulonglong, c_ushort, c_void}; #(#opaque_types)* diff --git a/libfmod-gen/src/generators/flags.rs b/libfmod-gen/src/generators/flags.rs index a0eabee..ecce38d 100644 --- a/libfmod-gen/src/generators/flags.rs +++ b/libfmod-gen/src/generators/flags.rs @@ -82,9 +82,9 @@ pub fn generate_flags(flags: &Flags) -> (String, String) { ); let into = format!( r#" -impl Into for {name} {{ - fn into(self) -> ffi::{flags} {{ - self.bits +impl From<{name}> for ffi::{flags} {{ + fn from(value: {name}) -> ffi::{flags} {{ + value.bits }} }} "# diff --git a/libfmod-gen/src/generators/lib.rs b/libfmod-gen/src/generators/lib.rs index d579bf9..5cf472b 100644 --- a/libfmod-gen/src/generators/lib.rs +++ b/libfmod-gen/src/generators/lib.rs @@ -12,18 +12,6 @@ use crate::models::{ Api, Argument, Enumeration, Error, Field, Function, Modifier, Pointer, Structure, Type, }; -#[derive(Debug, Clone, PartialEq)] -pub struct Struct { - pub structure: Structure, - pub constructor: Function, - pub methods: Vec, -} - -#[derive(Debug, Default)] -pub struct Lib { - pub structs: Vec, -} - fn extract_struct_key(name: &str) -> String { match name.rfind('_') { Some(index) => name[..index].to_uppercase(), @@ -288,24 +276,24 @@ pub fn generate_into_field(structure: &str, field: &Field, api: &Api) -> TokenSt Some(expression) => expression, _ => match &field.field_type { FundamentalType(name) => match (ptr, &name[..]) { - ("*const", "char") => quote! { move_string_to_c!(self.#self_name) }, - ("*mut", "char") => quote! { move_string_to_c!(self.#self_name) as *mut _ }, - _ => quote! { self.#self_name }, + ("*const", "char") => quote! { move_string_to_c!(value.#self_name) }, + ("*mut", "char") => quote! { move_string_to_c!(value.#self_name) as *mut _ }, + _ => quote! { value.#self_name }, }, UserType(name) => match (ptr, api.describe_user_type(name)) { ("*mut", UserTypeDesc::OpaqueType) => { - quote! { self.#self_name.as_mut_ptr() } + quote! { value.#self_name.as_mut_ptr() } } ("*mut", UserTypeDesc::Structure) => { - quote! { &mut self.#self_name.into() } + quote! { &mut value.#self_name.into() } } ("", UserTypeDesc::Structure) => { - quote! { self.#self_name.into() } + quote! { value.#self_name.into() } } ("", UserTypeDesc::Enumeration) => { - quote! { self.#self_name.into() } + quote! { value.#self_name.into() } } - _ => quote! { self.#self_name }, + _ => quote! { value.#self_name }, }, }, }; @@ -349,13 +337,13 @@ pub fn generate_structure_into(structure: &Structure, api: &Api) -> TokenStream .iter() .map(|field| generate_into_field(&structure.name, field, api)); let union = if structure.union.is_some() { - Some(quote! { ,union: self.union }) + Some(quote! { ,union: value.union }) } else { None }; quote! { - impl Into for #name { - fn into(self) -> ffi::#ident { + impl From<#name> for ffi::#ident { + fn from(value: #name) -> ffi::#ident { ffi::#ident { #(#conversion),* #union @@ -440,6 +428,7 @@ struct OutArgument { struct InArgument { pub param: TokenStream, pub input: TokenStream, + pub target: Option, } pub fn quote_tuple(items: &Vec) -> TokenStream { @@ -461,30 +450,42 @@ fn map_optional(argument: &Argument, api: &Api) -> InArgument { ":int" => InArgument { param: quote! { #name: Option }, input: quote! { #name.unwrap_or(0) }, + target: None, }, ":float" => InArgument { param: quote! { #name: Option }, input: quote! { #name.unwrap_or(0.0) }, + target: None, }, ":unsigned long long" => InArgument { param: quote! { #name: Option }, input: quote! { #name.unwrap_or(0) }, + target: None, }, ":unsigned int" => InArgument { param: quote! { #name: Option }, input: quote! { #name.unwrap_or(0) }, + target: None, }, "*mut:float" => InArgument { param: quote! { #name: Option<*mut f32> }, input: quote! { #name.unwrap_or(null_mut()) }, + target: None, }, - "*const:char" => InArgument { - param: quote! { #name: Option }, - input: quote! { #name.map(|value| CString::new(value).map(|value| value.as_ptr())).unwrap_or(Ok(null_mut()))? }, - }, + "*const:char" => { + let c_name = format_ident!("c_{}", name); + InArgument { + param: quote! { #name: Option }, + input: quote! { #c_name.as_ref().map_or(null_mut(), |s| s.as_ptr()) }, + target: Some( + quote! { let #c_name = #name.map(|s| CString::new(s)).transpose()?; }, + ), + } + } "*mut:void" => InArgument { param: quote! { #name: Option<*mut c_void> }, input: quote! { #name.unwrap_or(null_mut()) }, + target: None, }, argument_type => { unimplemented!("opt {}", argument_type) @@ -497,22 +498,27 @@ fn map_optional(argument: &Argument, api: &Api) -> InArgument { ("*mut", UserTypeDesc::Structure) => InArgument { param: quote! { #name: Option<#tp> }, input: quote! { #name.map(|value| &mut value.into() as *mut _).unwrap_or(null_mut()) }, + target: None, }, ("*mut", UserTypeDesc::OpaqueType) => InArgument { param: quote! { #name: Option<#tp> }, input: quote! { #name.map(|value| value.as_mut_ptr()).unwrap_or(null_mut()) }, + target: None, }, ("*const", UserTypeDesc::Structure) => InArgument { param: quote! { #name: Option<#tp> }, input: quote! { #name.map(#tp::into).as_ref().map(from_ref).unwrap_or_else(null) }, + target: None, }, ("", UserTypeDesc::Enumeration) => InArgument { param: quote! { #name: Option<#tp> }, input: quote! { #name.map(|value| value.into()).unwrap_or(0) }, + target: None, }, ("", UserTypeDesc::Callback) => InArgument { param: quote! { #name: ffi::#ident }, input: quote! { #name }, + target: None, }, user_type => unimplemented!("opt {:?}", user_type), } @@ -529,34 +535,45 @@ fn map_input(argument: &Argument, api: &Api) -> InArgument { ":float" => InArgument { param: quote! { #argument: f32 }, input: quote! { #argument }, + target: None, }, ":int" => InArgument { param: quote! { #argument: i32 }, input: quote! { #argument }, + target: None, }, ":unsigned int" => InArgument { param: quote! { #argument: u32 }, input: quote! { #argument }, + target: None, }, ":unsigned long long" => InArgument { param: quote! { #argument: u64 }, input: quote! { #argument }, + target: None, }, - "*const:char" => InArgument { - param: quote! { #argument: &str }, - input: quote! { CString::new(#argument)?.as_ptr() }, - }, + "*const:char" => { + let c_arg = format_ident!("c_{}", argument); + InArgument { + param: quote! { #argument: &str }, + input: quote! { #c_arg.as_ptr() }, + target: Some(quote! { let #c_arg = CString::new(#argument)?; }), + } + } "*mut:void" => InArgument { param: quote! { #argument: *mut c_void }, input: quote! { #argument }, + target: None, }, "*const:void" => InArgument { param: quote! { #argument: *const c_void }, input: quote! { #argument }, + target: None, }, "*mut:float" => InArgument { param: quote! { #argument: *mut f32 }, input: quote! { #argument }, + target: None, }, _ => unimplemented!(), }, @@ -567,39 +584,48 @@ fn map_input(argument: &Argument, api: &Api) -> InArgument { ("*mut", UserTypeDesc::OpaqueType) => InArgument { param: quote! { #argument: #rust_type }, input: quote! { #argument.as_mut_ptr() }, + target: None, }, ("*const", UserTypeDesc::Structure) => InArgument { param: quote! { #argument: #rust_type }, input: quote! { &#argument.into() }, + target: None, }, ("*mut", UserTypeDesc::Structure) => InArgument { param: quote! { #argument: #rust_type }, input: quote! { &mut #argument.into() }, + target: None, }, ("", UserTypeDesc::Structure) => InArgument { param: quote! { #argument: #rust_type }, input: quote! { #argument.into() }, + target: None, }, ("", UserTypeDesc::Flags) => InArgument { param: quote! { #argument: impl Into }, input: quote! { #argument.into() }, + target: None, }, ("", UserTypeDesc::Enumeration) => InArgument { param: quote! { #argument: #rust_type }, input: quote! { #argument.into() }, + target: None, }, ("", UserTypeDesc::Callback) => InArgument { param: quote! { #argument: ffi::#ident }, input: quote! { #argument }, + target: None, }, ("", UserTypeDesc::TypeAlias) => match &type_name[..] { "FMOD_BOOL" => InArgument { param: quote! { #argument: bool }, input: quote! { from_bool!(#argument) }, + target: None, }, "FMOD_PORT_INDEX" => InArgument { param: quote! { #argument: u64 }, input: quote! { #argument }, + target: None, }, _ => unimplemented!(), }, @@ -769,6 +795,9 @@ impl AddAssign for Signature { fn add_assign(&mut self, argument: InArgument) { self.arguments.push(argument.param); self.inputs.push(argument.input); + if let Some(target) = argument.target { + self.targets.push(target); + } } } @@ -983,6 +1012,7 @@ pub fn generate_lib_code(api: &Api) -> Result { Ok(quote! { #![allow(unused_unsafe)] + #![allow(clippy::unnecessary_cast)] use std::os::raw::{c_char}; use std::ffi::{c_void, CStr, CString, IntoStringError, NulError}; use std::fmt::{Display, Formatter}; @@ -1133,8 +1163,8 @@ pub fn generate_lib_code(api: &Api) -> Result { where F: FnMut(T) -> O, { - let mut values = values.into_iter().map(map).collect::>(); - Box::into_raw(values.into_boxed_slice()) as *mut _ + let values = values.into_iter().map(map).collect::>(); + Box::leak(values.into_boxed_slice()).as_mut_ptr() } const fn from_ref(value: &T) -> *const T { diff --git a/libfmod-gen/src/generators/mod.rs b/libfmod-gen/src/generators/mod.rs index cb409ed..eda5ed3 100644 --- a/libfmod-gen/src/generators/mod.rs +++ b/libfmod-gen/src/generators/mod.rs @@ -1,4 +1,4 @@ +pub mod errors; pub mod ffi; pub mod flags; pub mod lib; -pub mod errors; diff --git a/libfmod-gen/src/grammars/fmod_codec.pest b/libfmod-gen/src/grammars/fmod_codec.pest index b42e5d0..9cf91bf 100644 --- a/libfmod-gen/src/grammars/fmod_codec.pest +++ b/libfmod-gen/src/grammars/fmod_codec.pest @@ -60,7 +60,11 @@ return_type = { FundamentalType | UserType} varargs = { "," ~ "..." } Callback = { "typedef" ~ return_type ~ pointer? ~ ("(F_CALLBACK *" | "(F_CALL *") ~ name ~ ")" ~ "(" ~ arguments ~ varargs? ~ ")" ~ ";" } -Macros = {"#define" ~ name ~ "(" ~ (!"#" ~ ANY)* } +// FMOD 2.03.09 introduced variadic logging macros (FMOD_CODEC_LOG) with line continuations +// and token pasting (##__VA_ARGS__). These rules parse them without bash preprocessing. +line_continuation = _{ "\\" ~ WHITESPACE* ~ NEWLINE } +macro_body_char = _{ line_continuation | (!"#define" ~ !EOI ~ ANY) } +Macros = { "#define" ~ name ~ "(" ~ macro_body_char* } declaration = _{ OpaqueType | @@ -72,4 +76,4 @@ declaration = _{ Callback } -api = { SOI ~ declaration* ~ EOI } \ No newline at end of file +api = { SOI ~ declaration* ~ EOI } diff --git a/libfmod-gen/src/grammars/fmod_dsp.pest b/libfmod-gen/src/grammars/fmod_dsp.pest index 86dccae..ffb798e 100644 --- a/libfmod-gen/src/grammars/fmod_dsp.pest +++ b/libfmod-gen/src/grammars/fmod_dsp.pest @@ -67,7 +67,11 @@ return_type = { FundamentalType | UserType} varargs = { "," ~ "..." } Callback = { "typedef" ~ return_type ~ pointer? ~ ("(F_CALLBACK *" | "(F_CALL *") ~ name ~ ")" ~ "(" ~ arguments ~ varargs? ~ ")" ~ ";" } -Macros = {"#define" ~ name ~ "(" ~ (!"#" ~ ANY)* } +// FMOD 2.03.09 introduced variadic logging macros (FMOD_DSP_LOG) with line continuations +// and token pasting (##__VA_ARGS__). These rules parse them without bash preprocessing. +line_continuation = _{ "\\" ~ WHITESPACE* ~ NEWLINE } +macro_body_char = _{ line_continuation | (!"#define" ~ !EOI ~ ANY) } +Macros = { "#define" ~ name ~ "(" ~ macro_body_char* } declaration = _{ OpaqueType | @@ -81,4 +85,4 @@ declaration = _{ Callback } -api = { SOI ~ declaration* ~ EOI } \ No newline at end of file +api = { SOI ~ declaration* ~ EOI } diff --git a/libfmod-gen/src/grammars/fmod_output.pest b/libfmod-gen/src/grammars/fmod_output.pest index df18180..04f1f7a 100644 --- a/libfmod-gen/src/grammars/fmod_output.pest +++ b/libfmod-gen/src/grammars/fmod_output.pest @@ -59,7 +59,11 @@ return_type = { FundamentalType | UserType} varargs = { "," ~ "..." } Callback = { "typedef" ~ return_type ~ pointer? ~ ("(F_CALLBACK *" | "(F_CALL *") ~ name ~ ")" ~ "(" ~ arguments ~ varargs? ~ ")" ~ ";" } -Macros = {"#define" ~ name ~ "(" ~ (!"#end" ~ ANY)* } +// FMOD 2.03.09 introduced variadic logging macros (FMOD_OUTPUT_LOG) with line continuations +// and token pasting (##__VA_ARGS__). These rules parse them without bash preprocessing. +line_continuation = _{ "\\" ~ WHITESPACE* ~ NEWLINE } +macro_body_char = _{ line_continuation | (!"#define" ~ !EOI ~ ANY) } +Macros = { "#define" ~ name ~ "(" ~ macro_body_char* } declaration = _{ OpaqueType | @@ -71,4 +75,4 @@ declaration = _{ Callback } -api = { SOI ~ declaration* ~ EOI } \ No newline at end of file +api = { SOI ~ declaration* ~ EOI } diff --git a/libfmod-gen/src/main.rs b/libfmod-gen/src/main.rs index 4cb6cdc..78c357d 100644 --- a/libfmod-gen/src/main.rs +++ b/libfmod-gen/src/main.rs @@ -16,8 +16,8 @@ use crate::parsers::{ fmod_studio, fmod_studio_common, }; use std::path::Path; -use std::{env, fs}; use std::process::Command; +use std::{env, fs}; mod generators; mod models; @@ -191,20 +191,49 @@ fn generate_lib_fmod(source: &str, destination: &str) -> Result<(), Error> { Ok(()) } -const FMOD_SDK_PATH: &str = "./fmod/20222"; +const FMOD_SDK_PATH: &str = "./fmod/20309"; const OUTPUT_DIR: &str = "../libfmod"; +const FMOD_VERSION: &str = "2.03.09"; fn main() { + println!("libfmod-gen for FMOD {}", FMOD_VERSION); + let args: Vec = env::args().collect(); - let source = match args.get(1) { - None => FMOD_SDK_PATH, - Some(source) => source, + + // Support --version flag + if args.iter().any(|arg| arg == "--version") { + println!("libfmod-gen for FMOD {}", FMOD_VERSION); + return; + } + + // Support --dry-run flag (for testing) + let dry_run = args.iter().any(|arg| arg == "--dry-run"); + + let source = match args.iter().find(|arg| arg.starts_with("--sdk-path=")) { + Some(arg) => &arg[11..], + None => match args.get(1) { + None => FMOD_SDK_PATH, + Some(source) if !source.starts_with("--") => source, + _ => FMOD_SDK_PATH, + }, }; - let destination = match args.get(2) { - None => OUTPUT_DIR, - Some(destination) => destination, + + let destination = match args.iter().find(|arg| arg.starts_with("--output=")) { + Some(arg) => &arg[9..], + None => match args.get(2) { + None => OUTPUT_DIR, + Some(dest) if !dest.starts_with("--") => dest, + _ => OUTPUT_DIR, + }, }; - println!("source {} {}", source, destination); + + println!("Source: {} | Output: {}", source, destination); + + if dry_run { + println!("Dry run mode - not generating files"); + // TODO: Parse and report what would be generated + return; + } if let Err(error) = generate_lib_fmod(&source, &destination) { println!("Unable to generate libfmod, {:?}", error); } diff --git a/libfmod-gen/src/patching/fields.rs b/libfmod-gen/src/patching/fields.rs index de6a4a1..0155886 100644 --- a/libfmod-gen/src/patching/fields.rs +++ b/libfmod-gen/src/patching/fields.rs @@ -119,22 +119,22 @@ impl Api { pub fn patch_field_into(&self, structure: &str, field: &str) -> Option { let expression = match (structure, field) { ("FMOD_CREATESOUNDEXINFO", "inclusionlist") => { - quote! { opt_ptr!(self.inclusionlist.clone(), |v| v.as_slice().as_ptr()as *mut _) } + quote! { opt_ptr!(value.inclusionlist.clone(), |v| v.as_slice().as_ptr()as *mut _) } } ("FMOD_CREATESOUNDEXINFO", "inclusionlistnum") => { - quote! { self.inclusionlist.map(|v| v.len()).unwrap_or(0) as _ } + quote! { value.inclusionlist.map(|v| v.len()).unwrap_or(0) as _ } } ("FMOD_CREATESOUNDEXINFO", "dlsname") => { - quote! { opt_ptr!(self.dlsname.map(|v| CString::new(v).unwrap()), |v| v.as_ptr()) } + quote! { opt_ptr!(value.dlsname.map(|v| Box::leak(CString::new(v).unwrap().into_boxed_c_str())), |v| v.as_ptr()) } } ("FMOD_CREATESOUNDEXINFO", "encryptionkey") => { - quote! { opt_ptr!(self.encryptionkey.map(|v| CString::new(v).unwrap()), |v| v.as_ptr()) } + quote! { opt_ptr!(value.encryptionkey.map(|v| Box::leak(CString::new(v).unwrap().into_boxed_c_str())), |v| v.as_ptr()) } } ("FMOD_CREATESOUNDEXINFO", "initialsoundgroup") => { - quote! { opt_ptr!(self.initialsoundgroup, |v| v.as_mut_ptr()) } + quote! { opt_ptr!(value.initialsoundgroup, |v| v.as_mut_ptr()) } } ("FMOD_CREATESOUNDEXINFO", "fsbguid") => { - quote! { opt_ptr!(self.fsbguid, |v| &mut v.into() as *mut _) } + quote! { opt_ptr!(value.fsbguid, |v| &mut v.into() as *mut _) } } ("FMOD_CREATESOUNDEXINFO", "cbsize") => { quote! { size_of::() as i32 } @@ -146,49 +146,49 @@ impl Api { quote! { size_of::() as i32 } } ("FMOD_DSP_DESCRIPTION", "numparameters") => { - quote! { self.paramdesc.len() as i32 } + quote! { value.paramdesc.len() as i32 } } ("FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI", "relative") => { - quote! { self.relative.map(Attributes3d::into) } + quote! { value.relative.map(Attributes3d::into) } } ("FMOD_OUTPUT_OBJECT3DINFO", "buffer") => { - quote! { self.buffer.as_ptr() as *mut _ } + quote! { value.buffer.as_ptr() as *mut _ } } ("FMOD_ADVANCEDSETTINGS", "ASIOChannelList") => { - quote! { self.asio_channel_list.into_iter().map(|val| val.as_ptr()).collect::>().as_mut_ptr().cast() } + quote! { vec_as_mut_ptr(value.asio_channel_list, |val| val.as_ptr()).cast() } } ("FMOD_ADVANCEDSETTINGS", "ASIOSpeakerList") => { - quote! { self.asio_speaker_list.into_iter().map(|val| val.into()).collect::>().as_mut_ptr() } + quote! { vec_as_mut_ptr(value.asio_speaker_list, |val| val.into()) } } ("FMOD_DSP_BUFFER_ARRAY", "buffernumchannels") => { - quote! { self.buffernumchannels.as_ptr() as *mut _ } + quote! { value.buffernumchannels.as_ptr() as *mut _ } } ("FMOD_DSP_BUFFER_ARRAY", "bufferchannelmask") => { - quote! { self.bufferchannelmask.as_ptr() as *mut _ } + quote! { value.bufferchannelmask.as_ptr() as *mut _ } } ("FMOD_DSP_BUFFER_ARRAY", "buffers") => { - quote! { self.buffers.as_ptr() as *mut _ } + quote! { value.buffers.as_ptr() as *mut _ } } ("FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR", "pointparamvalues") => { - quote! { self.pointparamvalues.as_ptr() as *mut _ } + quote! { value.pointparamvalues.as_ptr() as *mut _ } } ("FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR", "pointpositions") => { - quote! { self.pointpositions.as_ptr() as *mut _ } + quote! { value.pointpositions.as_ptr() as *mut _ } } ("FMOD_DSP_PARAMETER_DESC_INT", "valuenames") => { - quote! { self.valuenames.as_ptr() as *mut _ } + quote! { value.valuenames.as_ptr() as *mut _ } } ("FMOD_DSP_PARAMETER_DESC_BOOL", "valuenames") => { - quote! { self.valuenames.as_ptr() as *mut _ } + quote! { value.valuenames.as_ptr() as *mut _ } } ("FMOD_DSP_DESCRIPTION", "paramdesc") => { - quote! { vec_as_mut_ptr(self.paramdesc, |param| Box::into_raw(Box::new(param.into()))) } + quote! { vec_as_mut_ptr(value.paramdesc, |param| Box::leak(Box::new(param.into())) as *mut _) } } ("FMOD_DSP_STATE", "sidechaindata") => { - quote! { self.sidechaindata.as_ptr() as *mut _ } + quote! { value.sidechaindata.as_ptr() as *mut _ } } ("FMOD_DSP_PARAMETER_FFT", "numchannels") => { - quote! { self.spectrum.len() as i32 } + quote! { value.spectrum.len() as i32 } } ("FMOD_DSP_PARAMETER_FFT", "spectrum") => { quote! { [null_mut(); 32] } diff --git a/libfmod-gen/src/patching/functions.rs b/libfmod-gen/src/patching/functions.rs index 3aaefcc..b108da0 100644 --- a/libfmod-gen/src/patching/functions.rs +++ b/libfmod-gen/src/patching/functions.rs @@ -30,6 +30,26 @@ impl Signature { return true; } + // FMOD 2.03.09: System_GetVersion now has buildnumber parameter + if function.name == "FMOD_System_GetVersion" && argument.name == "buildnumber" { + self.targets.push(quote! { let mut buildnumber = 0u32; }); + self.inputs.push(quote! { &mut buildnumber }); + // Don't duplicate the outputs - will be handled when we process version + return true; + } + + if function.name == "FMOD_System_GetVersion" && argument.name == "version" { + // Set the complete return for both version and buildnumber + self.targets + .push(quote! { let mut version = u32::default(); }); + self.inputs.push(quote! { &mut version }); + self.outputs.clear(); + self.outputs.push(quote! { (version, buildnumber) }); + self.return_types.clear(); + self.return_types.push(quote! { (u32, u32) }); + return true; + } + // FMOD_Sound_Set3DCustomRolloff if function.name == "FMOD_Sound_Set3DCustomRolloff" && argument.name == "numpoints" { self.targets diff --git a/libfmod-gen/src/patching/structures.rs b/libfmod-gen/src/patching/structures.rs index 6b57689..024efc4 100644 --- a/libfmod-gen/src/patching/structures.rs +++ b/libfmod-gen/src/patching/structures.rs @@ -5,6 +5,9 @@ use quote::__private::TokenStream; impl Api { pub fn patch_structures(&mut self) { + // FMOD 2.03.09: Add renamed/new fields + // Field renaming is handled during parsing + // encryptionkey field for FMOD_STUDIO_ADVANCEDSETTINGS is added automatically self.structure_patches.insert("FMOD_DSP_PARAMETER_FFT".to_string(), quote! { impl TryFrom for DspParameterFft { type Error = Error; diff --git a/libfmod-gen/tests/test_variadic_macros.rs b/libfmod-gen/tests/test_variadic_macros.rs new file mode 100644 index 0000000..097ff84 --- /dev/null +++ b/libfmod-gen/tests/test_variadic_macros.rs @@ -0,0 +1,58 @@ +/// Integration test: Verify that the parser can handle FMOD 2.03.09 variadic macros +/// with line continuations and token pasting operators (##__VA_ARGS__) +/// +/// This test addresses PR #23 feedback: macro handling must be in parser grammar, not bash scripts. +/// Before the fix, these macros would cause parsing errors at the ## token. +use std::path::Path; +use std::process::Command; + +#[test] +fn test_parse_original_fmod_headers() { + let sdk_path = Path::new("./fmod/20309"); + + // Skip test if FMOD SDK not present + if !sdk_path.exists() { + eprintln!("Skipping test: FMOD SDK not found at {:?}", sdk_path); + return; + } + + // Run the generator - it should succeed without preprocessing + let output = Command::new("cargo") + .arg("run") + .arg("--") + .arg(sdk_path) + .arg("/tmp/test_parser_output") + .output() + .expect("Failed to execute generator"); + + // Check if the command succeeded + assert!( + output.status.success(), + "Generator failed to parse original FMOD headers.\n\ + This likely means variadic macros with ##__VA_ARGS__ are not being handled correctly.\n\ + stdout: {}\n\ + stderr: {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + + // Verify we see the expected parsing output + let stdout = String::from_utf8_lossy(&output.stdout); + + // Should see successful parsing stats + assert!( + stdout.contains("Opaque Types:"), + "Expected to see parsing statistics in output" + ); + + assert!( + stdout.contains("Structures:"), + "Expected to see structure count in output" + ); + + // Should NOT see pest parsing errors about ##__VA_ARGS__ + assert!( + !stdout.contains("##__VA_ARGS__"), + "Parser should handle ##__VA_ARGS__ macros without error" + ); +} diff --git a/libfmod/.gitignore b/libfmod/.gitignore index 6bba78f..3a7332e 100644 --- a/libfmod/.gitignore +++ b/libfmod/.gitignore @@ -6,3 +6,4 @@ Cargo.lock .idea .DS_Store +.cargo/ diff --git a/libfmod/Cargo.toml b/libfmod/Cargo.toml index 106ffc7..09b053c 100644 --- a/libfmod/Cargo.toml +++ b/libfmod/Cargo.toml @@ -21,3 +21,6 @@ logging = [] [dependencies] bitflags = { version = "1", optional = true } +[dev-dependencies] +crossterm = "0.27" + diff --git a/libfmod/README.md b/libfmod/README.md new file mode 100644 index 0000000..1639cb6 --- /dev/null +++ b/libfmod/README.md @@ -0,0 +1,69 @@ +# libfmod Examples + +## Quick Start + +```bash +# Run examples using the helper script +./run_fmod.sh [args] +``` + +## Available Examples + +### Basic Audio +- `play_sound ` - Play an audio file +- `verify_203` - Verify FMOD 2.03.09 installation + +### Studio Examples +- `harness_demo [demo]` - Non-interactive demos of FMOD Studio features + - `explosion` - Simple event playback + - `spatial` - 3D spatial audio with stereo panning + - `rpm` - Real-time parameter control + - `footsteps` - Multiple event instances + - `all` (default) - Run all demos + +- `interactive_harness` - Interactive 3D audio testing + - Keys 1-6: Play/stop events + - WASD/QE: Move sound source in 3D space + - Space: Stop all events + - H: Show help + +### Test Suites +- `studio_banks_test` - Test bank loading +- `studio_events_test` - Test event system +- `studio_parameters_test` - Test parameter control +- `quick_test` - Comprehensive test suite + +## Requirements + +FMOD libraries must be installed. The script expects them at: +- Core: `../libfmod-gen/fmod/20309/api/core/lib/x86_64/` +- Studio: `../libfmod-gen/fmod/20309/api/studio/lib/x86_64/` + +## Testing + +For running tests, create `.cargo/config.toml` with library paths: + +```toml +[build] +rustflags = [ + "-L", "../fmodstudioapi20310linux/api/core/lib/x86_64", + "-L", "../fmodstudioapi20310linux/api/studio/lib/x86_64", +] +``` + +Then run tests: + +```bash +cargo test --test version_test --test init_test --test system_test -- --test-threads=1 +``` + +## Manual Execution + +```bash +# Set library paths +export LD_LIBRARY_PATH="../libfmod-gen/fmod/20309/api/core/lib/x86_64:../libfmod-gen/fmod/20309/api/studio/lib/x86_64:$LD_LIBRARY_PATH" + +# Build and run +cargo build --example harness_demo +./target/debug/examples/harness_demo +``` \ No newline at end of file diff --git a/libfmod/src/ffi.rs b/libfmod/src/ffi.rs index 199b3d3..6c398ca 100644 --- a/libfmod/src/ffi.rs +++ b/libfmod/src/ffi.rs @@ -1,6 +1,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(unused_parens)] +#![allow(clippy::unnecessary_cast)] use std::os::raw::{ c_char, c_float, c_int, c_longlong, c_short, c_uchar, c_uint, c_ulonglong, c_ushort, c_void, }; @@ -101,7 +102,8 @@ pub struct FMOD_SYNCPOINT { } pub type FMOD_BOOL = c_int; pub const FMOD_STUDIO_LOAD_MEMORY_ALIGNMENT: c_uint = 32; -pub const FMOD_VERSION: c_uint = 0x00020222; +pub const FMOD_VERSION: c_uint = 0x00020309; +pub const FMOD_BUILDNUMBER: c_uint = 155273; pub const FMOD_MAX_CHANNEL_WIDTH: c_uint = 32; pub const FMOD_MAX_SYSTEMS: c_uint = 8; pub const FMOD_MAX_LISTENERS: c_uint = 8; @@ -459,7 +461,8 @@ pub const FMOD_DSPCONNECTION_TYPE_STANDARD: FMOD_DSPCONNECTION_TYPE = 0; pub const FMOD_DSPCONNECTION_TYPE_SIDECHAIN: FMOD_DSPCONNECTION_TYPE = 1; pub const FMOD_DSPCONNECTION_TYPE_SEND: FMOD_DSPCONNECTION_TYPE = 2; pub const FMOD_DSPCONNECTION_TYPE_SEND_SIDECHAIN: FMOD_DSPCONNECTION_TYPE = 3; -pub const FMOD_DSPCONNECTION_TYPE_MAX: FMOD_DSPCONNECTION_TYPE = 4; +pub const FMOD_DSPCONNECTION_TYPE_PREALLOCATED: FMOD_DSPCONNECTION_TYPE = 4; +pub const FMOD_DSPCONNECTION_TYPE_MAX: FMOD_DSPCONNECTION_TYPE = 5; pub const FMOD_DSPCONNECTION_TYPE_FORCEINT: FMOD_DSPCONNECTION_TYPE = 65536; pub type FMOD_TAGTYPE = c_int; pub const FMOD_TAGTYPE_UNKNOWN: FMOD_TAGTYPE = 0; @@ -493,7 +496,9 @@ pub const FMOD_PORT_TYPE_CONTROLLER: FMOD_PORT_TYPE = 3; pub const FMOD_PORT_TYPE_PERSONAL: FMOD_PORT_TYPE = 4; pub const FMOD_PORT_TYPE_VIBRATION: FMOD_PORT_TYPE = 5; pub const FMOD_PORT_TYPE_AUX: FMOD_PORT_TYPE = 6; -pub const FMOD_PORT_TYPE_MAX: FMOD_PORT_TYPE = 7; +pub const FMOD_PORT_TYPE_PASSTHROUGH: FMOD_PORT_TYPE = 7; +pub const FMOD_PORT_TYPE_VR_VIBRATION: FMOD_PORT_TYPE = 8; +pub const FMOD_PORT_TYPE_MAX: FMOD_PORT_TYPE = 9; pub const FMOD_PORT_TYPE_FORCEINT: FMOD_PORT_TYPE = 65536; pub type FMOD_DSP_PROCESS_OPERATION = c_int; pub const FMOD_DSP_PROCESS_PERFORM: FMOD_DSP_PROCESS_OPERATION = 0; @@ -524,6 +529,7 @@ pub const FMOD_DSP_PARAMETER_DATA_TYPE_SIDECHAIN: FMOD_DSP_PARAMETER_DATA_TYPE = pub const FMOD_DSP_PARAMETER_DATA_TYPE_FFT: FMOD_DSP_PARAMETER_DATA_TYPE = -4; pub const FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI: FMOD_DSP_PARAMETER_DATA_TYPE = -5; pub const FMOD_DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE: FMOD_DSP_PARAMETER_DATA_TYPE = -6; +pub const FMOD_DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE: FMOD_DSP_PARAMETER_DATA_TYPE = -7; pub type FMOD_DSP_TYPE = c_int; pub const FMOD_DSP_TYPE_UNKNOWN: FMOD_DSP_TYPE = 0; pub const FMOD_DSP_TYPE_MIXER: FMOD_DSP_TYPE = 1; @@ -540,29 +546,26 @@ pub const FMOD_DSP_TYPE_LIMITER: FMOD_DSP_TYPE = 11; pub const FMOD_DSP_TYPE_PARAMEQ: FMOD_DSP_TYPE = 12; pub const FMOD_DSP_TYPE_PITCHSHIFT: FMOD_DSP_TYPE = 13; pub const FMOD_DSP_TYPE_CHORUS: FMOD_DSP_TYPE = 14; -pub const FMOD_DSP_TYPE_VSTPLUGIN: FMOD_DSP_TYPE = 15; -pub const FMOD_DSP_TYPE_WINAMPPLUGIN: FMOD_DSP_TYPE = 16; -pub const FMOD_DSP_TYPE_ITECHO: FMOD_DSP_TYPE = 17; -pub const FMOD_DSP_TYPE_COMPRESSOR: FMOD_DSP_TYPE = 18; -pub const FMOD_DSP_TYPE_SFXREVERB: FMOD_DSP_TYPE = 19; -pub const FMOD_DSP_TYPE_LOWPASS_SIMPLE: FMOD_DSP_TYPE = 20; -pub const FMOD_DSP_TYPE_DELAY: FMOD_DSP_TYPE = 21; -pub const FMOD_DSP_TYPE_TREMOLO: FMOD_DSP_TYPE = 22; -pub const FMOD_DSP_TYPE_LADSPAPLUGIN: FMOD_DSP_TYPE = 23; -pub const FMOD_DSP_TYPE_SEND: FMOD_DSP_TYPE = 24; -pub const FMOD_DSP_TYPE_RETURN: FMOD_DSP_TYPE = 25; -pub const FMOD_DSP_TYPE_HIGHPASS_SIMPLE: FMOD_DSP_TYPE = 26; -pub const FMOD_DSP_TYPE_PAN: FMOD_DSP_TYPE = 27; -pub const FMOD_DSP_TYPE_THREE_EQ: FMOD_DSP_TYPE = 28; -pub const FMOD_DSP_TYPE_FFT: FMOD_DSP_TYPE = 29; -pub const FMOD_DSP_TYPE_LOUDNESS_METER: FMOD_DSP_TYPE = 30; -pub const FMOD_DSP_TYPE_ENVELOPEFOLLOWER: FMOD_DSP_TYPE = 31; -pub const FMOD_DSP_TYPE_CONVOLUTIONREVERB: FMOD_DSP_TYPE = 32; -pub const FMOD_DSP_TYPE_CHANNELMIX: FMOD_DSP_TYPE = 33; -pub const FMOD_DSP_TYPE_TRANSCEIVER: FMOD_DSP_TYPE = 34; -pub const FMOD_DSP_TYPE_OBJECTPAN: FMOD_DSP_TYPE = 35; -pub const FMOD_DSP_TYPE_MULTIBAND_EQ: FMOD_DSP_TYPE = 36; -pub const FMOD_DSP_TYPE_MAX: FMOD_DSP_TYPE = 37; +pub const FMOD_DSP_TYPE_ITECHO: FMOD_DSP_TYPE = 15; +pub const FMOD_DSP_TYPE_COMPRESSOR: FMOD_DSP_TYPE = 16; +pub const FMOD_DSP_TYPE_SFXREVERB: FMOD_DSP_TYPE = 17; +pub const FMOD_DSP_TYPE_LOWPASS_SIMPLE: FMOD_DSP_TYPE = 18; +pub const FMOD_DSP_TYPE_DELAY: FMOD_DSP_TYPE = 19; +pub const FMOD_DSP_TYPE_TREMOLO: FMOD_DSP_TYPE = 20; +pub const FMOD_DSP_TYPE_SEND: FMOD_DSP_TYPE = 21; +pub const FMOD_DSP_TYPE_RETURN: FMOD_DSP_TYPE = 22; +pub const FMOD_DSP_TYPE_HIGHPASS_SIMPLE: FMOD_DSP_TYPE = 23; +pub const FMOD_DSP_TYPE_PAN: FMOD_DSP_TYPE = 24; +pub const FMOD_DSP_TYPE_THREE_EQ: FMOD_DSP_TYPE = 25; +pub const FMOD_DSP_TYPE_FFT: FMOD_DSP_TYPE = 26; +pub const FMOD_DSP_TYPE_LOUDNESS_METER: FMOD_DSP_TYPE = 27; +pub const FMOD_DSP_TYPE_CONVOLUTIONREVERB: FMOD_DSP_TYPE = 28; +pub const FMOD_DSP_TYPE_CHANNELMIX: FMOD_DSP_TYPE = 29; +pub const FMOD_DSP_TYPE_TRANSCEIVER: FMOD_DSP_TYPE = 30; +pub const FMOD_DSP_TYPE_OBJECTPAN: FMOD_DSP_TYPE = 31; +pub const FMOD_DSP_TYPE_MULTIBAND_EQ: FMOD_DSP_TYPE = 32; +pub const FMOD_DSP_TYPE_MULTIBAND_DYNAMICS: FMOD_DSP_TYPE = 33; +pub const FMOD_DSP_TYPE_MAX: FMOD_DSP_TYPE = 34; pub const FMOD_DSP_TYPE_FORCEINT: FMOD_DSP_TYPE = 65536; pub type FMOD_DSP_OSCILLATOR = c_int; pub const FMOD_DSP_OSCILLATOR_TYPE: FMOD_DSP_OSCILLATOR = 0; @@ -581,6 +584,11 @@ pub const FMOD_DSP_ECHO_DELAY: FMOD_DSP_ECHO = 0; pub const FMOD_DSP_ECHO_FEEDBACK: FMOD_DSP_ECHO = 1; pub const FMOD_DSP_ECHO_DRYLEVEL: FMOD_DSP_ECHO = 2; pub const FMOD_DSP_ECHO_WETLEVEL: FMOD_DSP_ECHO = 3; +pub const FMOD_DSP_ECHO_DELAYCHANGEMODE: FMOD_DSP_ECHO = 4; +pub type FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE = c_int; +pub const FMOD_DSP_ECHO_DELAYCHANGEMODE_FADE: FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE = 0; +pub const FMOD_DSP_ECHO_DELAYCHANGEMODE_LERP: FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE = 1; +pub const FMOD_DSP_ECHO_DELAYCHANGEMODE_NONE: FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE = 2; pub type FMOD_DSP_FADER = c_int; pub const FMOD_DSP_FADER_GAIN: FMOD_DSP_FADER = 0; pub const FMOD_DSP_FADER_OVERALL_GAIN: FMOD_DSP_FADER = 1; @@ -638,6 +646,43 @@ pub const FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING: FMOD_DSP_MULTIBAND_EQ_FILTER_TYP pub const FMOD_DSP_MULTIBAND_EQ_FILTER_BANDPASS: FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE = 10; pub const FMOD_DSP_MULTIBAND_EQ_FILTER_NOTCH: FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE = 11; pub const FMOD_DSP_MULTIBAND_EQ_FILTER_ALLPASS: FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE = 12; +pub const FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_6DB: FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE = 13; +pub const FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_6DB: FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE = 14; +pub type FMOD_DSP_MULTIBAND_DYNAMICS = c_int; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_LOWER_FREQUENCY: FMOD_DSP_MULTIBAND_DYNAMICS = 0; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_UPPER_FREQUENCY: FMOD_DSP_MULTIBAND_DYNAMICS = 1; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_LINKED: FMOD_DSP_MULTIBAND_DYNAMICS = 2; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_USE_SIDECHAIN: FMOD_DSP_MULTIBAND_DYNAMICS = 3; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_MODE: FMOD_DSP_MULTIBAND_DYNAMICS = 4; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN: FMOD_DSP_MULTIBAND_DYNAMICS = 5; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_THRESHOLD: FMOD_DSP_MULTIBAND_DYNAMICS = 6; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_RATIO: FMOD_DSP_MULTIBAND_DYNAMICS = 7; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_ATTACK: FMOD_DSP_MULTIBAND_DYNAMICS = 8; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_RELEASE: FMOD_DSP_MULTIBAND_DYNAMICS = 9; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN_MAKEUP: FMOD_DSP_MULTIBAND_DYNAMICS = 10; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_A_RESPONSE_DATA: FMOD_DSP_MULTIBAND_DYNAMICS = 11; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_MODE: FMOD_DSP_MULTIBAND_DYNAMICS = 12; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN: FMOD_DSP_MULTIBAND_DYNAMICS = 13; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_THRESHOLD: FMOD_DSP_MULTIBAND_DYNAMICS = 14; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_RATIO: FMOD_DSP_MULTIBAND_DYNAMICS = 15; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_ATTACK: FMOD_DSP_MULTIBAND_DYNAMICS = 16; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_RELEASE: FMOD_DSP_MULTIBAND_DYNAMICS = 17; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN_MAKEUP: FMOD_DSP_MULTIBAND_DYNAMICS = 18; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_B_RESPONSE_DATA: FMOD_DSP_MULTIBAND_DYNAMICS = 19; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_MODE: FMOD_DSP_MULTIBAND_DYNAMICS = 20; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN: FMOD_DSP_MULTIBAND_DYNAMICS = 21; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_THRESHOLD: FMOD_DSP_MULTIBAND_DYNAMICS = 22; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_RATIO: FMOD_DSP_MULTIBAND_DYNAMICS = 23; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_ATTACK: FMOD_DSP_MULTIBAND_DYNAMICS = 24; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_RELEASE: FMOD_DSP_MULTIBAND_DYNAMICS = 25; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN_MAKEUP: FMOD_DSP_MULTIBAND_DYNAMICS = 26; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_C_RESPONSE_DATA: FMOD_DSP_MULTIBAND_DYNAMICS = 27; +pub type FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = c_int; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_MODE_DISABLED: FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = 0; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_UP: FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = 1; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_DOWN: FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = 2; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_UP: FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = 3; +pub const FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_DOWN: FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE = 4; pub type FMOD_DSP_PITCHSHIFT = c_int; pub const FMOD_DSP_PITCHSHIFT_PITCH: FMOD_DSP_PITCHSHIFT = 0; pub const FMOD_DSP_PITCHSHIFT_FFTSIZE: FMOD_DSP_PITCHSHIFT = 1; @@ -765,18 +810,27 @@ pub const FMOD_DSP_THREE_EQ_HIGHGAIN: FMOD_DSP_THREE_EQ = 2; pub const FMOD_DSP_THREE_EQ_LOWCROSSOVER: FMOD_DSP_THREE_EQ = 3; pub const FMOD_DSP_THREE_EQ_HIGHCROSSOVER: FMOD_DSP_THREE_EQ = 4; pub const FMOD_DSP_THREE_EQ_CROSSOVERSLOPE: FMOD_DSP_THREE_EQ = 5; -pub type FMOD_DSP_FFT_WINDOW = c_int; -pub const FMOD_DSP_FFT_WINDOW_RECT: FMOD_DSP_FFT_WINDOW = 0; -pub const FMOD_DSP_FFT_WINDOW_TRIANGLE: FMOD_DSP_FFT_WINDOW = 1; -pub const FMOD_DSP_FFT_WINDOW_HAMMING: FMOD_DSP_FFT_WINDOW = 2; -pub const FMOD_DSP_FFT_WINDOW_HANNING: FMOD_DSP_FFT_WINDOW = 3; -pub const FMOD_DSP_FFT_WINDOW_BLACKMAN: FMOD_DSP_FFT_WINDOW = 4; -pub const FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS: FMOD_DSP_FFT_WINDOW = 5; +pub type FMOD_DSP_FFT_WINDOW_TYPE = c_int; +pub const FMOD_DSP_FFT_WINDOW_RECT: FMOD_DSP_FFT_WINDOW_TYPE = 0; +pub const FMOD_DSP_FFT_WINDOW_TRIANGLE: FMOD_DSP_FFT_WINDOW_TYPE = 1; +pub const FMOD_DSP_FFT_WINDOW_HAMMING: FMOD_DSP_FFT_WINDOW_TYPE = 2; +pub const FMOD_DSP_FFT_WINDOW_HANNING: FMOD_DSP_FFT_WINDOW_TYPE = 3; +pub const FMOD_DSP_FFT_WINDOW_BLACKMAN: FMOD_DSP_FFT_WINDOW_TYPE = 4; +pub const FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS: FMOD_DSP_FFT_WINDOW_TYPE = 5; +pub type FMOD_DSP_FFT_DOWNMIX_TYPE = c_int; +pub const FMOD_DSP_FFT_DOWNMIX_NONE: FMOD_DSP_FFT_DOWNMIX_TYPE = 0; +pub const FMOD_DSP_FFT_DOWNMIX_MONO: FMOD_DSP_FFT_DOWNMIX_TYPE = 1; pub type FMOD_DSP_FFT = c_int; pub const FMOD_DSP_FFT_WINDOWSIZE: FMOD_DSP_FFT = 0; -pub const FMOD_DSP_FFT_WINDOWTYPE: FMOD_DSP_FFT = 1; -pub const FMOD_DSP_FFT_SPECTRUMDATA: FMOD_DSP_FFT = 2; -pub const FMOD_DSP_FFT_DOMINANT_FREQ: FMOD_DSP_FFT = 3; +pub const FMOD_DSP_FFT_WINDOW: FMOD_DSP_FFT = 1; +pub const FMOD_DSP_FFT_BAND_START_FREQ: FMOD_DSP_FFT = 2; +pub const FMOD_DSP_FFT_BAND_STOP_FREQ: FMOD_DSP_FFT = 3; +pub const FMOD_DSP_FFT_SPECTRUMDATA: FMOD_DSP_FFT = 4; +pub const FMOD_DSP_FFT_RMS: FMOD_DSP_FFT = 5; +pub const FMOD_DSP_FFT_SPECTRAL_CENTROID: FMOD_DSP_FFT = 6; +pub const FMOD_DSP_FFT_IMMEDIATE_MODE: FMOD_DSP_FFT = 7; +pub const FMOD_DSP_FFT_DOWNMIX: FMOD_DSP_FFT = 8; +pub const FMOD_DSP_FFT_CHANNEL: FMOD_DSP_FFT = 9; pub type FMOD_DSP_LOUDNESS_METER = c_int; pub const FMOD_DSP_LOUDNESS_METER_STATE: FMOD_DSP_LOUDNESS_METER = 0; pub const FMOD_DSP_LOUDNESS_METER_WEIGHTING: FMOD_DSP_LOUDNESS_METER = 1; @@ -787,11 +841,6 @@ pub const FMOD_DSP_LOUDNESS_METER_STATE_RESET_MAXPEAK: FMOD_DSP_LOUDNESS_METER_S pub const FMOD_DSP_LOUDNESS_METER_STATE_RESET_ALL: FMOD_DSP_LOUDNESS_METER_STATE_TYPE = -1; pub const FMOD_DSP_LOUDNESS_METER_STATE_PAUSED: FMOD_DSP_LOUDNESS_METER_STATE_TYPE = 0; pub const FMOD_DSP_LOUDNESS_METER_STATE_ANALYZING: FMOD_DSP_LOUDNESS_METER_STATE_TYPE = 1; -pub type FMOD_DSP_ENVELOPEFOLLOWER = c_int; -pub const FMOD_DSP_ENVELOPEFOLLOWER_ATTACK: FMOD_DSP_ENVELOPEFOLLOWER = 0; -pub const FMOD_DSP_ENVELOPEFOLLOWER_RELEASE: FMOD_DSP_ENVELOPEFOLLOWER = 1; -pub const FMOD_DSP_ENVELOPEFOLLOWER_ENVELOPE: FMOD_DSP_ENVELOPEFOLLOWER = 2; -pub const FMOD_DSP_ENVELOPEFOLLOWER_USESIDECHAIN: FMOD_DSP_ENVELOPEFOLLOWER = 3; pub type FMOD_DSP_CONVOLUTION_REVERB = c_int; pub const FMOD_DSP_CONVOLUTION_REVERB_PARAM_IR: FMOD_DSP_CONVOLUTION_REVERB = 0; pub const FMOD_DSP_CONVOLUTION_REVERB_PARAM_WET: FMOD_DSP_CONVOLUTION_REVERB = 1; @@ -966,6 +1015,7 @@ pub const FMOD_DEBUG_TYPE_MEMORY: FMOD_DEBUG_FLAGS = 0x00000100; pub const FMOD_DEBUG_TYPE_FILE: FMOD_DEBUG_FLAGS = 0x00000200; pub const FMOD_DEBUG_TYPE_CODEC: FMOD_DEBUG_FLAGS = 0x00000400; pub const FMOD_DEBUG_TYPE_TRACE: FMOD_DEBUG_FLAGS = 0x00000800; +pub const FMOD_DEBUG_TYPE_VIRTUAL: FMOD_DEBUG_FLAGS = 0x00001000; pub const FMOD_DEBUG_DISPLAY_TIMESTAMPS: FMOD_DEBUG_FLAGS = 0x00010000; pub const FMOD_DEBUG_DISPLAY_LINENUMBERS: FMOD_DEBUG_FLAGS = 0x00020000; pub const FMOD_DEBUG_DISPLAY_THREAD: FMOD_DEBUG_FLAGS = 0x00040000; @@ -1014,15 +1064,14 @@ pub const FMOD_SYSTEM_CALLBACK_BADDSPCONNECTION: FMOD_SYSTEM_CALLBACK_TYPE = 0x0 pub const FMOD_SYSTEM_CALLBACK_PREMIX: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000020; pub const FMOD_SYSTEM_CALLBACK_POSTMIX: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000040; pub const FMOD_SYSTEM_CALLBACK_ERROR: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000080; -pub const FMOD_SYSTEM_CALLBACK_MIDMIX: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000100; -pub const FMOD_SYSTEM_CALLBACK_THREADDESTROYED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000200; -pub const FMOD_SYSTEM_CALLBACK_PREUPDATE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000400; -pub const FMOD_SYSTEM_CALLBACK_POSTUPDATE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000800; -pub const FMOD_SYSTEM_CALLBACK_RECORDLISTCHANGED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00001000; -pub const FMOD_SYSTEM_CALLBACK_BUFFEREDNOMIX: FMOD_SYSTEM_CALLBACK_TYPE = 0x00002000; -pub const FMOD_SYSTEM_CALLBACK_DEVICEREINITIALIZE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00004000; -pub const FMOD_SYSTEM_CALLBACK_OUTPUTUNDERRUN: FMOD_SYSTEM_CALLBACK_TYPE = 0x00008000; -pub const FMOD_SYSTEM_CALLBACK_RECORDPOSITIONCHANGED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00010000; +pub const FMOD_SYSTEM_CALLBACK_THREADDESTROYED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000100; +pub const FMOD_SYSTEM_CALLBACK_PREUPDATE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000200; +pub const FMOD_SYSTEM_CALLBACK_POSTUPDATE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000400; +pub const FMOD_SYSTEM_CALLBACK_RECORDLISTCHANGED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00000800; +pub const FMOD_SYSTEM_CALLBACK_BUFFEREDNOMIX: FMOD_SYSTEM_CALLBACK_TYPE = 0x00001000; +pub const FMOD_SYSTEM_CALLBACK_DEVICEREINITIALIZE: FMOD_SYSTEM_CALLBACK_TYPE = 0x00002000; +pub const FMOD_SYSTEM_CALLBACK_OUTPUTUNDERRUN: FMOD_SYSTEM_CALLBACK_TYPE = 0x00004000; +pub const FMOD_SYSTEM_CALLBACK_RECORDPOSITIONCHANGED: FMOD_SYSTEM_CALLBACK_TYPE = 0x00008000; pub const FMOD_SYSTEM_CALLBACK_ALL: FMOD_SYSTEM_CALLBACK_TYPE = 0xFFFFFFFF; pub type FMOD_MODE = c_uint; pub const FMOD_DEFAULT: FMOD_MODE = 0x00000000; @@ -1107,7 +1156,6 @@ pub const FMOD_CHANNELMASK_7POINT1: FMOD_CHANNELMASK = (FMOD_CHANNELMASK_FRONT_L | FMOD_CHANNELMASK_BACK_RIGHT); pub type FMOD_PORT_INDEX = c_ulonglong; pub const FMOD_PORT_INDEX_NONE: FMOD_PORT_INDEX = 0xFFFFFFFFFFFFFFFF; -pub const FMOD_PORT_INDEX_FLAG_VR_CONTROLLER: FMOD_PORT_INDEX = 0x1000000000000000; pub type FMOD_THREAD_PRIORITY = c_int; pub const FMOD_THREAD_PRIORITY_PLATFORM_MIN: FMOD_THREAD_PRIORITY = (-32 * 1024); pub const FMOD_THREAD_PRIORITY_PLATFORM_MAX: FMOD_THREAD_PRIORITY = (32 * 1024); @@ -1491,7 +1539,7 @@ pub struct FMOD_ADVANCEDSETTINGS { pub maxVorbisCodecs: c_int, pub maxAT9Codecs: c_int, pub maxFADPCMCodecs: c_int, - pub maxPCMCodecs: c_int, + pub maxOpusCodecs: c_int, pub ASIONumChannels: c_int, pub ASIOChannelList: *mut *mut c_char, pub ASIOSpeakerList: *mut FMOD_SPEAKER, @@ -1505,7 +1553,6 @@ pub struct FMOD_ADVANCEDSETTINGS { pub resamplerMethod: FMOD_DSP_RESAMPLER, pub randomSeed: c_uint, pub maxConvolutionThreads: c_int, - pub maxOpusCodecs: c_int, pub maxSpatialObjects: c_int, } impl Default for FMOD_ADVANCEDSETTINGS { @@ -1961,6 +2008,17 @@ impl Default for FMOD_DSP_PARAMETER_FFT { } #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE { + pub numchannels: c_int, + pub rms: [c_float; 32 as usize], +} +impl Default for FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE { + fn default() -> Self { + unsafe { std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct FMOD_DSP_DESCRIPTION { pub pluginsdkversion: c_uint, pub name: [c_char; 32 as usize], @@ -3485,6 +3543,10 @@ extern "C" { eventinstance: *mut FMOD_STUDIO_EVENTINSTANCE, description: *mut *mut FMOD_STUDIO_EVENTDESCRIPTION, ) -> FMOD_RESULT; + pub fn FMOD_Studio_EventInstance_GetSystem( + eventinstance: *mut FMOD_STUDIO_EVENTINSTANCE, + system: *mut *mut FMOD_STUDIO_SYSTEM, + ) -> FMOD_RESULT; pub fn FMOD_Studio_EventInstance_GetVolume( eventinstance: *mut FMOD_STUDIO_EVENTINSTANCE, volume: *mut c_float, @@ -4130,7 +4192,11 @@ extern "C" { mode: FMOD_SPEAKERMODE, channels: *mut c_int, ) -> FMOD_RESULT; - pub fn FMOD_System_GetVersion(system: *mut FMOD_SYSTEM, version: *mut c_uint) -> FMOD_RESULT; + pub fn FMOD_System_GetVersion( + system: *mut FMOD_SYSTEM, + version: *mut c_uint, + buildnumber: *mut c_uint, + ) -> FMOD_RESULT; pub fn FMOD_System_GetOutputHandle( system: *mut FMOD_SYSTEM, handle: *mut *mut c_void, @@ -4174,6 +4240,11 @@ extern "C" { type_: FMOD_DSP_TYPE, dsp: *mut *mut FMOD_DSP, ) -> FMOD_RESULT; + pub fn FMOD_System_CreateDSPConnection( + system: *mut FMOD_SYSTEM, + type_: FMOD_DSPCONNECTION_TYPE, + connection: *mut *mut FMOD_DSPCONNECTION, + ) -> FMOD_RESULT; pub fn FMOD_System_CreateChannelGroup( system: *mut FMOD_SYSTEM, name: *const c_char, diff --git a/libfmod/src/flags.rs b/libfmod/src/flags.rs index 13de8f9..8784e6d 100644 --- a/libfmod/src/flags.rs +++ b/libfmod/src/flags.rs @@ -82,6 +82,7 @@ bitflags! { const TYPE_FILE = ffi::FMOD_DEBUG_TYPE_FILE; const TYPE_CODEC = ffi::FMOD_DEBUG_TYPE_CODEC; const TYPE_TRACE = ffi::FMOD_DEBUG_TYPE_TRACE; + const TYPE_VIRTUAL = ffi::FMOD_DEBUG_TYPE_VIRTUAL; const DISPLAY_TIMESTAMPS = ffi::FMOD_DEBUG_DISPLAY_TIMESTAMPS; const DISPLAY_LINENUMBERS = ffi::FMOD_DEBUG_DISPLAY_LINENUMBERS; const DISPLAY_THREAD = ffi::FMOD_DEBUG_DISPLAY_THREAD; @@ -140,7 +141,6 @@ bitflags! { const PREMIX = ffi::FMOD_SYSTEM_CALLBACK_PREMIX; const POSTMIX = ffi::FMOD_SYSTEM_CALLBACK_POSTMIX; const ERROR = ffi::FMOD_SYSTEM_CALLBACK_ERROR; - const MIDMIX = ffi::FMOD_SYSTEM_CALLBACK_MIDMIX; const THREADDESTROYED = ffi::FMOD_SYSTEM_CALLBACK_THREADDESTROYED; const PREUPDATE = ffi::FMOD_SYSTEM_CALLBACK_PREUPDATE; const POSTUPDATE = ffi::FMOD_SYSTEM_CALLBACK_POSTUPDATE; @@ -205,9 +205,8 @@ bitflags! { const MASK_7POINT1 = ffi::FMOD_CHANNELMASK_7POINT1; } - pub struct PortIndex: ffi::FMOD_PORT_INDEX { - const NONE = ffi::FMOD_PORT_INDEX_NONE; - const FLAG_VR_CONTROLLER = ffi::FMOD_PORT_INDEX_FLAG_VR_CONTROLLER; + pub struct PortIndexNone: ffi::FMOD_PORT_INDEX { + const FMOD_PORT_INDEX_NONE = ffi::FMOD_PORT_INDEX_NONE; } pub struct ThreadPriority: ffi::FMOD_THREAD_PRIORITY { @@ -302,128 +301,128 @@ bitflags! { } -impl Into for StudioInit { - fn into(self) -> ffi::FMOD_STUDIO_INITFLAGS { - self.bits +impl From for ffi::FMOD_STUDIO_INITFLAGS { + fn from(value: StudioInit) -> ffi::FMOD_STUDIO_INITFLAGS { + value.bits } } -impl Into for Parameter { - fn into(self) -> ffi::FMOD_STUDIO_PARAMETER_FLAGS { - self.bits +impl From for ffi::FMOD_STUDIO_PARAMETER_FLAGS { + fn from(value: Parameter) -> ffi::FMOD_STUDIO_PARAMETER_FLAGS { + value.bits } } -impl Into for StudioSystemCallback { - fn into(self) -> ffi::FMOD_STUDIO_SYSTEM_CALLBACK_TYPE { - self.bits +impl From for ffi::FMOD_STUDIO_SYSTEM_CALLBACK_TYPE { + fn from(value: StudioSystemCallback) -> ffi::FMOD_STUDIO_SYSTEM_CALLBACK_TYPE { + value.bits } } -impl Into for EventCallback { - fn into(self) -> ffi::FMOD_STUDIO_EVENT_CALLBACK_TYPE { - self.bits +impl From for ffi::FMOD_STUDIO_EVENT_CALLBACK_TYPE { + fn from(value: EventCallback) -> ffi::FMOD_STUDIO_EVENT_CALLBACK_TYPE { + value.bits } } -impl Into for LoadBank { - fn into(self) -> ffi::FMOD_STUDIO_LOAD_BANK_FLAGS { - self.bits +impl From for ffi::FMOD_STUDIO_LOAD_BANK_FLAGS { + fn from(value: LoadBank) -> ffi::FMOD_STUDIO_LOAD_BANK_FLAGS { + value.bits } } -impl Into for CommandCapture { - fn into(self) -> ffi::FMOD_STUDIO_COMMANDCAPTURE_FLAGS { - self.bits +impl From for ffi::FMOD_STUDIO_COMMANDCAPTURE_FLAGS { + fn from(value: CommandCapture) -> ffi::FMOD_STUDIO_COMMANDCAPTURE_FLAGS { + value.bits } } -impl Into for CommandReplay { - fn into(self) -> ffi::FMOD_STUDIO_COMMANDREPLAY_FLAGS { - self.bits +impl From for ffi::FMOD_STUDIO_COMMANDREPLAY_FLAGS { + fn from(value: CommandReplay) -> ffi::FMOD_STUDIO_COMMANDREPLAY_FLAGS { + value.bits } } -impl Into for Debug { - fn into(self) -> ffi::FMOD_DEBUG_FLAGS { - self.bits +impl From for ffi::FMOD_DEBUG_FLAGS { + fn from(value: Debug) -> ffi::FMOD_DEBUG_FLAGS { + value.bits } } -impl Into for Memory { - fn into(self) -> ffi::FMOD_MEMORY_TYPE { - self.bits +impl From for ffi::FMOD_MEMORY_TYPE { + fn from(value: Memory) -> ffi::FMOD_MEMORY_TYPE { + value.bits } } -impl Into for Init { - fn into(self) -> ffi::FMOD_INITFLAGS { - self.bits +impl From for ffi::FMOD_INITFLAGS { + fn from(value: Init) -> ffi::FMOD_INITFLAGS { + value.bits } } -impl Into for DriverState { - fn into(self) -> ffi::FMOD_DRIVER_STATE { - self.bits +impl From for ffi::FMOD_DRIVER_STATE { + fn from(value: DriverState) -> ffi::FMOD_DRIVER_STATE { + value.bits } } -impl Into for TimeUnit { - fn into(self) -> ffi::FMOD_TIMEUNIT { - self.bits +impl From for ffi::FMOD_TIMEUNIT { + fn from(value: TimeUnit) -> ffi::FMOD_TIMEUNIT { + value.bits } } -impl Into for SystemCallback { - fn into(self) -> ffi::FMOD_SYSTEM_CALLBACK_TYPE { - self.bits +impl From for ffi::FMOD_SYSTEM_CALLBACK_TYPE { + fn from(value: SystemCallback) -> ffi::FMOD_SYSTEM_CALLBACK_TYPE { + value.bits } } -impl Into for Mode { - fn into(self) -> ffi::FMOD_MODE { - self.bits +impl From for ffi::FMOD_MODE { + fn from(value: Mode) -> ffi::FMOD_MODE { + value.bits } } -impl Into for ChannelMask { - fn into(self) -> ffi::FMOD_CHANNELMASK { - self.bits +impl From for ffi::FMOD_CHANNELMASK { + fn from(value: ChannelMask) -> ffi::FMOD_CHANNELMASK { + value.bits } } -impl Into for PortIndex { - fn into(self) -> ffi::FMOD_PORT_INDEX { - self.bits +impl From for ffi::FMOD_PORT_INDEX { + fn from(value: PortIndexNone) -> ffi::FMOD_PORT_INDEX { + value.bits } } -impl Into for ThreadPriority { - fn into(self) -> ffi::FMOD_THREAD_PRIORITY { - self.bits +impl From for ffi::FMOD_THREAD_PRIORITY { + fn from(value: ThreadPriority) -> ffi::FMOD_THREAD_PRIORITY { + value.bits } } -impl Into for ThreadStackSize { - fn into(self) -> ffi::FMOD_THREAD_STACK_SIZE { - self.bits +impl From for ffi::FMOD_THREAD_STACK_SIZE { + fn from(value: ThreadStackSize) -> ffi::FMOD_THREAD_STACK_SIZE { + value.bits } } -impl Into for ThreadAffinity { - fn into(self) -> ffi::FMOD_THREAD_AFFINITY { - self.bits +impl From for ffi::FMOD_THREAD_AFFINITY { + fn from(value: ThreadAffinity) -> ffi::FMOD_THREAD_AFFINITY { + value.bits } } -impl Into for CodecSeekMethod { - fn into(self) -> ffi::FMOD_CODEC_SEEK_METHOD { - self.bits +impl From for ffi::FMOD_CODEC_SEEK_METHOD { + fn from(value: CodecSeekMethod) -> ffi::FMOD_CODEC_SEEK_METHOD { + value.bits } } -impl Into for OutputMethodMix { - fn into(self) -> ffi::FMOD_OUTPUT_METHOD { - self.bits +impl From for ffi::FMOD_OUTPUT_METHOD { + fn from(value: OutputMethodMix) -> ffi::FMOD_OUTPUT_METHOD { + value.bits } } diff --git a/libfmod/src/lib.rs b/libfmod/src/lib.rs index 336b52f..714ae07 100644 --- a/libfmod/src/lib.rs +++ b/libfmod/src/lib.rs @@ -1,4 +1,5 @@ #![allow(unused_unsafe)] +#![allow(clippy::unnecessary_cast)] use std::ffi::{c_void, CStr, CString, IntoStringError, NulError}; use std::fmt::{Display, Formatter}; use std::mem::size_of; @@ -73,6 +74,13 @@ macro_rules! err_fmod { } }; } +macro_rules! move_string_to_c { + ($ value : expr) => { + CString::new($value) + .unwrap_or(CString::from(c"err!")) + .into_raw() + }; +} macro_rules! err_enum { ($ enumeration : expr , $ value : expr) => { Error::EnumBindgen { @@ -151,10 +159,8 @@ pub fn vec_as_mut_ptr(values: Vec, map: F) -> *mut O where F: FnMut(T) -> O, { - let mut values = values.into_iter().map(map).collect::>(); - let pointer = values.as_mut_ptr(); - std::mem::forget(values); - pointer + let values = values.into_iter().map(map).collect::>(); + Box::leak(values.into_boxed_slice()).as_mut_ptr() } const fn from_ref(value: &T) -> *const T { value @@ -1518,6 +1524,7 @@ pub enum DspConnectionType { Sidechain, Send, SendSidechain, + Preallocated, Max, } impl From for ffi::FMOD_DSPCONNECTION_TYPE { @@ -1527,6 +1534,7 @@ impl From for ffi::FMOD_DSPCONNECTION_TYPE { DspConnectionType::Sidechain => ffi::FMOD_DSPCONNECTION_TYPE_SIDECHAIN, DspConnectionType::Send => ffi::FMOD_DSPCONNECTION_TYPE_SEND, DspConnectionType::SendSidechain => ffi::FMOD_DSPCONNECTION_TYPE_SEND_SIDECHAIN, + DspConnectionType::Preallocated => ffi::FMOD_DSPCONNECTION_TYPE_PREALLOCATED, DspConnectionType::Max => ffi::FMOD_DSPCONNECTION_TYPE_MAX, } } @@ -1538,6 +1546,7 @@ impl DspConnectionType { ffi::FMOD_DSPCONNECTION_TYPE_SIDECHAIN => Ok(DspConnectionType::Sidechain), ffi::FMOD_DSPCONNECTION_TYPE_SEND => Ok(DspConnectionType::Send), ffi::FMOD_DSPCONNECTION_TYPE_SEND_SIDECHAIN => Ok(DspConnectionType::SendSidechain), + ffi::FMOD_DSPCONNECTION_TYPE_PREALLOCATED => Ok(DspConnectionType::Preallocated), ffi::FMOD_DSPCONNECTION_TYPE_MAX => Ok(DspConnectionType::Max), _ => Err(err_enum!("FMOD_DSPCONNECTION_TYPE", value)), } @@ -1644,6 +1653,8 @@ pub enum PortType { Personal, Vibration, Aux, + Passthrough, + VrVibration, Max, } impl From for ffi::FMOD_PORT_TYPE { @@ -1656,6 +1667,8 @@ impl From for ffi::FMOD_PORT_TYPE { PortType::Personal => ffi::FMOD_PORT_TYPE_PERSONAL, PortType::Vibration => ffi::FMOD_PORT_TYPE_VIBRATION, PortType::Aux => ffi::FMOD_PORT_TYPE_AUX, + PortType::Passthrough => ffi::FMOD_PORT_TYPE_PASSTHROUGH, + PortType::VrVibration => ffi::FMOD_PORT_TYPE_VR_VIBRATION, PortType::Max => ffi::FMOD_PORT_TYPE_MAX, } } @@ -1670,6 +1683,8 @@ impl PortType { ffi::FMOD_PORT_TYPE_PERSONAL => Ok(PortType::Personal), ffi::FMOD_PORT_TYPE_VIBRATION => Ok(PortType::Vibration), ffi::FMOD_PORT_TYPE_AUX => Ok(PortType::Aux), + ffi::FMOD_PORT_TYPE_PASSTHROUGH => Ok(PortType::Passthrough), + ffi::FMOD_PORT_TYPE_VR_VIBRATION => Ok(PortType::VrVibration), ffi::FMOD_PORT_TYPE_MAX => Ok(PortType::Max), _ => Err(err_enum!("FMOD_PORT_TYPE", value)), } @@ -1800,6 +1815,7 @@ pub enum DspParameterDataType { Fft, AttributesMulti3D, AttenuationRange, + DynamicResponse, } impl From for ffi::FMOD_DSP_PARAMETER_DATA_TYPE { fn from(value: DspParameterDataType) -> ffi::FMOD_DSP_PARAMETER_DATA_TYPE { @@ -1815,6 +1831,9 @@ impl From for ffi::FMOD_DSP_PARAMETER_DATA_TYPE { DspParameterDataType::AttenuationRange => { ffi::FMOD_DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE } + DspParameterDataType::DynamicResponse => { + ffi::FMOD_DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE + } } } } @@ -1834,6 +1853,9 @@ impl DspParameterDataType { ffi::FMOD_DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE => { Ok(DspParameterDataType::AttenuationRange) } + ffi::FMOD_DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE => { + Ok(DspParameterDataType::DynamicResponse) + } _ => Err(err_enum!("FMOD_DSP_PARAMETER_DATA_TYPE", value)), } } @@ -1855,15 +1877,12 @@ pub enum DspType { Parameq, Pitchshift, Chorus, - Vstplugin, - Winampplugin, Itecho, Compressor, Sfxreverb, LowpassSimple, Delay, Tremolo, - Ladspaplugin, Send, Return, HighpassSimple, @@ -1871,12 +1890,12 @@ pub enum DspType { ThreeEq, Fft, LoudnessMeter, - Envelopefollower, Convolutionreverb, Channelmix, Transceiver, Objectpan, MultibandEq, + MultibandDynamics, Max, } impl From for ffi::FMOD_DSP_TYPE { @@ -1897,15 +1916,12 @@ impl From for ffi::FMOD_DSP_TYPE { DspType::Parameq => ffi::FMOD_DSP_TYPE_PARAMEQ, DspType::Pitchshift => ffi::FMOD_DSP_TYPE_PITCHSHIFT, DspType::Chorus => ffi::FMOD_DSP_TYPE_CHORUS, - DspType::Vstplugin => ffi::FMOD_DSP_TYPE_VSTPLUGIN, - DspType::Winampplugin => ffi::FMOD_DSP_TYPE_WINAMPPLUGIN, DspType::Itecho => ffi::FMOD_DSP_TYPE_ITECHO, DspType::Compressor => ffi::FMOD_DSP_TYPE_COMPRESSOR, DspType::Sfxreverb => ffi::FMOD_DSP_TYPE_SFXREVERB, DspType::LowpassSimple => ffi::FMOD_DSP_TYPE_LOWPASS_SIMPLE, DspType::Delay => ffi::FMOD_DSP_TYPE_DELAY, DspType::Tremolo => ffi::FMOD_DSP_TYPE_TREMOLO, - DspType::Ladspaplugin => ffi::FMOD_DSP_TYPE_LADSPAPLUGIN, DspType::Send => ffi::FMOD_DSP_TYPE_SEND, DspType::Return => ffi::FMOD_DSP_TYPE_RETURN, DspType::HighpassSimple => ffi::FMOD_DSP_TYPE_HIGHPASS_SIMPLE, @@ -1913,12 +1929,12 @@ impl From for ffi::FMOD_DSP_TYPE { DspType::ThreeEq => ffi::FMOD_DSP_TYPE_THREE_EQ, DspType::Fft => ffi::FMOD_DSP_TYPE_FFT, DspType::LoudnessMeter => ffi::FMOD_DSP_TYPE_LOUDNESS_METER, - DspType::Envelopefollower => ffi::FMOD_DSP_TYPE_ENVELOPEFOLLOWER, DspType::Convolutionreverb => ffi::FMOD_DSP_TYPE_CONVOLUTIONREVERB, DspType::Channelmix => ffi::FMOD_DSP_TYPE_CHANNELMIX, DspType::Transceiver => ffi::FMOD_DSP_TYPE_TRANSCEIVER, DspType::Objectpan => ffi::FMOD_DSP_TYPE_OBJECTPAN, DspType::MultibandEq => ffi::FMOD_DSP_TYPE_MULTIBAND_EQ, + DspType::MultibandDynamics => ffi::FMOD_DSP_TYPE_MULTIBAND_DYNAMICS, DspType::Max => ffi::FMOD_DSP_TYPE_MAX, } } @@ -1941,15 +1957,12 @@ impl DspType { ffi::FMOD_DSP_TYPE_PARAMEQ => Ok(DspType::Parameq), ffi::FMOD_DSP_TYPE_PITCHSHIFT => Ok(DspType::Pitchshift), ffi::FMOD_DSP_TYPE_CHORUS => Ok(DspType::Chorus), - ffi::FMOD_DSP_TYPE_VSTPLUGIN => Ok(DspType::Vstplugin), - ffi::FMOD_DSP_TYPE_WINAMPPLUGIN => Ok(DspType::Winampplugin), ffi::FMOD_DSP_TYPE_ITECHO => Ok(DspType::Itecho), ffi::FMOD_DSP_TYPE_COMPRESSOR => Ok(DspType::Compressor), ffi::FMOD_DSP_TYPE_SFXREVERB => Ok(DspType::Sfxreverb), ffi::FMOD_DSP_TYPE_LOWPASS_SIMPLE => Ok(DspType::LowpassSimple), ffi::FMOD_DSP_TYPE_DELAY => Ok(DspType::Delay), ffi::FMOD_DSP_TYPE_TREMOLO => Ok(DspType::Tremolo), - ffi::FMOD_DSP_TYPE_LADSPAPLUGIN => Ok(DspType::Ladspaplugin), ffi::FMOD_DSP_TYPE_SEND => Ok(DspType::Send), ffi::FMOD_DSP_TYPE_RETURN => Ok(DspType::Return), ffi::FMOD_DSP_TYPE_HIGHPASS_SIMPLE => Ok(DspType::HighpassSimple), @@ -1957,12 +1970,12 @@ impl DspType { ffi::FMOD_DSP_TYPE_THREE_EQ => Ok(DspType::ThreeEq), ffi::FMOD_DSP_TYPE_FFT => Ok(DspType::Fft), ffi::FMOD_DSP_TYPE_LOUDNESS_METER => Ok(DspType::LoudnessMeter), - ffi::FMOD_DSP_TYPE_ENVELOPEFOLLOWER => Ok(DspType::Envelopefollower), ffi::FMOD_DSP_TYPE_CONVOLUTIONREVERB => Ok(DspType::Convolutionreverb), ffi::FMOD_DSP_TYPE_CHANNELMIX => Ok(DspType::Channelmix), ffi::FMOD_DSP_TYPE_TRANSCEIVER => Ok(DspType::Transceiver), ffi::FMOD_DSP_TYPE_OBJECTPAN => Ok(DspType::Objectpan), ffi::FMOD_DSP_TYPE_MULTIBAND_EQ => Ok(DspType::MultibandEq), + ffi::FMOD_DSP_TYPE_MULTIBAND_DYNAMICS => Ok(DspType::MultibandDynamics), ffi::FMOD_DSP_TYPE_MAX => Ok(DspType::Max), _ => Err(err_enum!("FMOD_DSP_TYPE", value)), } @@ -2062,6 +2075,7 @@ pub enum DspEcho { Feedback, DryLevel, WetLevel, + Delaychangemode, } impl From for ffi::FMOD_DSP_ECHO { fn from(value: DspEcho) -> ffi::FMOD_DSP_ECHO { @@ -2070,6 +2084,7 @@ impl From for ffi::FMOD_DSP_ECHO { DspEcho::Feedback => ffi::FMOD_DSP_ECHO_FEEDBACK, DspEcho::DryLevel => ffi::FMOD_DSP_ECHO_DRYLEVEL, DspEcho::WetLevel => ffi::FMOD_DSP_ECHO_WETLEVEL, + DspEcho::Delaychangemode => ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE, } } } @@ -2080,11 +2095,39 @@ impl DspEcho { ffi::FMOD_DSP_ECHO_FEEDBACK => Ok(DspEcho::Feedback), ffi::FMOD_DSP_ECHO_DRYLEVEL => Ok(DspEcho::DryLevel), ffi::FMOD_DSP_ECHO_WETLEVEL => Ok(DspEcho::WetLevel), + ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE => Ok(DspEcho::Delaychangemode), _ => Err(err_enum!("FMOD_DSP_ECHO", value)), } } } #[derive(Debug, Clone, Copy, PartialEq)] +pub enum DspEchoDelaychangemodeType { + Fade, + Lerp, + None, +} +impl From for ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE { + fn from(value: DspEchoDelaychangemodeType) -> ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE { + match value { + DspEchoDelaychangemodeType::Fade => ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_FADE, + DspEchoDelaychangemodeType::Lerp => ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_LERP, + DspEchoDelaychangemodeType::None => ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_NONE, + } + } +} +impl DspEchoDelaychangemodeType { + pub fn from( + value: ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE, + ) -> Result { + match value { + ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_FADE => Ok(DspEchoDelaychangemodeType::Fade), + ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_LERP => Ok(DspEchoDelaychangemodeType::Lerp), + ffi::FMOD_DSP_ECHO_DELAYCHANGEMODE_NONE => Ok(DspEchoDelaychangemodeType::None), + _ => Err(err_enum!("FMOD_DSP_ECHO_DELAYCHANGEMODE_TYPE", value)), + } + } +} +#[derive(Debug, Clone, Copy, PartialEq)] pub enum DspFader { Gain, OverallGain, @@ -2319,6 +2362,8 @@ pub enum DspMultibandEqFilterType { Bandpass, Notch, AllPass, + Lowpass6Db, + Highpass6Db, } impl From for ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE { fn from(value: DspMultibandEqFilterType) -> ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE { @@ -2342,6 +2387,8 @@ impl From for ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE { DspMultibandEqFilterType::Bandpass => ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_BANDPASS, DspMultibandEqFilterType::Notch => ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_NOTCH, DspMultibandEqFilterType::AllPass => ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_ALLPASS, + DspMultibandEqFilterType::Lowpass6Db => ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_6DB, + DspMultibandEqFilterType::Highpass6Db => ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_6DB, } } } @@ -2375,11 +2422,186 @@ impl DspMultibandEqFilterType { ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_BANDPASS => Ok(DspMultibandEqFilterType::Bandpass), ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_NOTCH => Ok(DspMultibandEqFilterType::Notch), ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_ALLPASS => Ok(DspMultibandEqFilterType::AllPass), + ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_6DB => { + Ok(DspMultibandEqFilterType::Lowpass6Db) + } + ffi::FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_6DB => { + Ok(DspMultibandEqFilterType::Highpass6Db) + } _ => Err(err_enum!("FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE", value)), } } } #[derive(Debug, Clone, Copy, PartialEq)] +pub enum DspMultibandDynamics { + LowerFrequency, + UpperFrequency, + Linked, + UseSidechain, + AMode, + AGain, + AThreshold, + ARatio, + AAttack, + ARelease, + AGainMakeup, + AResponseData, + BMode, + BGain, + BThreshold, + BRatio, + BAttack, + BRelease, + BGainMakeup, + BResponseData, + CMode, + CGain, + CThreshold, + CRatio, + CAttack, + CRelease, + CGainMakeup, + CResponseData, +} +impl From for ffi::FMOD_DSP_MULTIBAND_DYNAMICS { + fn from(value: DspMultibandDynamics) -> ffi::FMOD_DSP_MULTIBAND_DYNAMICS { + match value { + DspMultibandDynamics::LowerFrequency => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_LOWER_FREQUENCY + } + DspMultibandDynamics::UpperFrequency => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_UPPER_FREQUENCY + } + DspMultibandDynamics::Linked => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_LINKED, + DspMultibandDynamics::UseSidechain => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_USE_SIDECHAIN, + DspMultibandDynamics::AMode => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_MODE, + DspMultibandDynamics::AGain => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN, + DspMultibandDynamics::AThreshold => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_THRESHOLD, + DspMultibandDynamics::ARatio => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RATIO, + DspMultibandDynamics::AAttack => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_ATTACK, + DspMultibandDynamics::ARelease => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RELEASE, + DspMultibandDynamics::AGainMakeup => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN_MAKEUP, + DspMultibandDynamics::AResponseData => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RESPONSE_DATA, + DspMultibandDynamics::BMode => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_MODE, + DspMultibandDynamics::BGain => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN, + DspMultibandDynamics::BThreshold => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_THRESHOLD, + DspMultibandDynamics::BRatio => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RATIO, + DspMultibandDynamics::BAttack => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_ATTACK, + DspMultibandDynamics::BRelease => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RELEASE, + DspMultibandDynamics::BGainMakeup => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN_MAKEUP, + DspMultibandDynamics::BResponseData => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RESPONSE_DATA, + DspMultibandDynamics::CMode => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_MODE, + DspMultibandDynamics::CGain => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN, + DspMultibandDynamics::CThreshold => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_THRESHOLD, + DspMultibandDynamics::CRatio => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RATIO, + DspMultibandDynamics::CAttack => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_ATTACK, + DspMultibandDynamics::CRelease => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RELEASE, + DspMultibandDynamics::CGainMakeup => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN_MAKEUP, + DspMultibandDynamics::CResponseData => ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RESPONSE_DATA, + } + } +} +impl DspMultibandDynamics { + pub fn from(value: ffi::FMOD_DSP_MULTIBAND_DYNAMICS) -> Result { + match value { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_LOWER_FREQUENCY => { + Ok(DspMultibandDynamics::LowerFrequency) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_UPPER_FREQUENCY => { + Ok(DspMultibandDynamics::UpperFrequency) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_LINKED => Ok(DspMultibandDynamics::Linked), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_USE_SIDECHAIN => { + Ok(DspMultibandDynamics::UseSidechain) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_MODE => Ok(DspMultibandDynamics::AMode), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN => Ok(DspMultibandDynamics::AGain), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_THRESHOLD => Ok(DspMultibandDynamics::AThreshold), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RATIO => Ok(DspMultibandDynamics::ARatio), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_ATTACK => Ok(DspMultibandDynamics::AAttack), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RELEASE => Ok(DspMultibandDynamics::ARelease), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_GAIN_MAKEUP => Ok(DspMultibandDynamics::AGainMakeup), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_A_RESPONSE_DATA => { + Ok(DspMultibandDynamics::AResponseData) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_MODE => Ok(DspMultibandDynamics::BMode), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN => Ok(DspMultibandDynamics::BGain), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_THRESHOLD => Ok(DspMultibandDynamics::BThreshold), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RATIO => Ok(DspMultibandDynamics::BRatio), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_ATTACK => Ok(DspMultibandDynamics::BAttack), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RELEASE => Ok(DspMultibandDynamics::BRelease), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_GAIN_MAKEUP => Ok(DspMultibandDynamics::BGainMakeup), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_B_RESPONSE_DATA => { + Ok(DspMultibandDynamics::BResponseData) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_MODE => Ok(DspMultibandDynamics::CMode), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN => Ok(DspMultibandDynamics::CGain), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_THRESHOLD => Ok(DspMultibandDynamics::CThreshold), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RATIO => Ok(DspMultibandDynamics::CRatio), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_ATTACK => Ok(DspMultibandDynamics::CAttack), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RELEASE => Ok(DspMultibandDynamics::CRelease), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_GAIN_MAKEUP => Ok(DspMultibandDynamics::CGainMakeup), + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_C_RESPONSE_DATA => { + Ok(DspMultibandDynamics::CResponseData) + } + _ => Err(err_enum!("FMOD_DSP_MULTIBAND_DYNAMICS", value)), + } + } +} +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DspMultibandDynamicsModeType { + Disabled, + CompressUp, + CompressDown, + ExpandUp, + ExpandDown, +} +impl From for ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE { + fn from(value: DspMultibandDynamicsModeType) -> ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE { + match value { + DspMultibandDynamicsModeType::Disabled => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_DISABLED + } + DspMultibandDynamicsModeType::CompressUp => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_UP + } + DspMultibandDynamicsModeType::CompressDown => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_DOWN + } + DspMultibandDynamicsModeType::ExpandUp => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_UP + } + DspMultibandDynamicsModeType::ExpandDown => { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_DOWN + } + } + } +} +impl DspMultibandDynamicsModeType { + pub fn from( + value: ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE, + ) -> Result { + match value { + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_DISABLED => { + Ok(DspMultibandDynamicsModeType::Disabled) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_UP => { + Ok(DspMultibandDynamicsModeType::CompressUp) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_DOWN => { + Ok(DspMultibandDynamicsModeType::CompressDown) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_UP => { + Ok(DspMultibandDynamicsModeType::ExpandUp) + } + ffi::FMOD_DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_DOWN => { + Ok(DspMultibandDynamicsModeType::ExpandDown) + } + _ => Err(err_enum!("FMOD_DSP_MULTIBAND_DYNAMICS_MODE_TYPE", value)), + } + } +} +#[derive(Debug, Clone, Copy, PartialEq)] pub enum DspPitchShift { Pitch, FftSize, @@ -3007,7 +3229,7 @@ impl DspThreeEq { } } #[derive(Debug, Clone, Copy, PartialEq)] -pub enum DspFftWindow { +pub enum DspFftWindowType { Rect, Triangle, Hamming, @@ -3015,45 +3237,79 @@ pub enum DspFftWindow { BlackMan, BlackManHarris, } -impl From for ffi::FMOD_DSP_FFT_WINDOW { - fn from(value: DspFftWindow) -> ffi::FMOD_DSP_FFT_WINDOW { +impl From for ffi::FMOD_DSP_FFT_WINDOW_TYPE { + fn from(value: DspFftWindowType) -> ffi::FMOD_DSP_FFT_WINDOW_TYPE { match value { - DspFftWindow::Rect => ffi::FMOD_DSP_FFT_WINDOW_RECT, - DspFftWindow::Triangle => ffi::FMOD_DSP_FFT_WINDOW_TRIANGLE, - DspFftWindow::Hamming => ffi::FMOD_DSP_FFT_WINDOW_HAMMING, - DspFftWindow::Hanning => ffi::FMOD_DSP_FFT_WINDOW_HANNING, - DspFftWindow::BlackMan => ffi::FMOD_DSP_FFT_WINDOW_BLACKMAN, - DspFftWindow::BlackManHarris => ffi::FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS, + DspFftWindowType::Rect => ffi::FMOD_DSP_FFT_WINDOW_RECT, + DspFftWindowType::Triangle => ffi::FMOD_DSP_FFT_WINDOW_TRIANGLE, + DspFftWindowType::Hamming => ffi::FMOD_DSP_FFT_WINDOW_HAMMING, + DspFftWindowType::Hanning => ffi::FMOD_DSP_FFT_WINDOW_HANNING, + DspFftWindowType::BlackMan => ffi::FMOD_DSP_FFT_WINDOW_BLACKMAN, + DspFftWindowType::BlackManHarris => ffi::FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS, } } } -impl DspFftWindow { - pub fn from(value: ffi::FMOD_DSP_FFT_WINDOW) -> Result { +impl DspFftWindowType { + pub fn from(value: ffi::FMOD_DSP_FFT_WINDOW_TYPE) -> Result { match value { - ffi::FMOD_DSP_FFT_WINDOW_RECT => Ok(DspFftWindow::Rect), - ffi::FMOD_DSP_FFT_WINDOW_TRIANGLE => Ok(DspFftWindow::Triangle), - ffi::FMOD_DSP_FFT_WINDOW_HAMMING => Ok(DspFftWindow::Hamming), - ffi::FMOD_DSP_FFT_WINDOW_HANNING => Ok(DspFftWindow::Hanning), - ffi::FMOD_DSP_FFT_WINDOW_BLACKMAN => Ok(DspFftWindow::BlackMan), - ffi::FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS => Ok(DspFftWindow::BlackManHarris), - _ => Err(err_enum!("FMOD_DSP_FFT_WINDOW", value)), + ffi::FMOD_DSP_FFT_WINDOW_RECT => Ok(DspFftWindowType::Rect), + ffi::FMOD_DSP_FFT_WINDOW_TRIANGLE => Ok(DspFftWindowType::Triangle), + ffi::FMOD_DSP_FFT_WINDOW_HAMMING => Ok(DspFftWindowType::Hamming), + ffi::FMOD_DSP_FFT_WINDOW_HANNING => Ok(DspFftWindowType::Hanning), + ffi::FMOD_DSP_FFT_WINDOW_BLACKMAN => Ok(DspFftWindowType::BlackMan), + ffi::FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS => Ok(DspFftWindowType::BlackManHarris), + _ => Err(err_enum!("FMOD_DSP_FFT_WINDOW_TYPE", value)), + } + } +} +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DspFftDownmixType { + None, + Mono, +} +impl From for ffi::FMOD_DSP_FFT_DOWNMIX_TYPE { + fn from(value: DspFftDownmixType) -> ffi::FMOD_DSP_FFT_DOWNMIX_TYPE { + match value { + DspFftDownmixType::None => ffi::FMOD_DSP_FFT_DOWNMIX_NONE, + DspFftDownmixType::Mono => ffi::FMOD_DSP_FFT_DOWNMIX_MONO, + } + } +} +impl DspFftDownmixType { + pub fn from(value: ffi::FMOD_DSP_FFT_DOWNMIX_TYPE) -> Result { + match value { + ffi::FMOD_DSP_FFT_DOWNMIX_NONE => Ok(DspFftDownmixType::None), + ffi::FMOD_DSP_FFT_DOWNMIX_MONO => Ok(DspFftDownmixType::Mono), + _ => Err(err_enum!("FMOD_DSP_FFT_DOWNMIX_TYPE", value)), } } } #[derive(Debug, Clone, Copy, PartialEq)] pub enum DspFft { WindowSize, - WindowType, + Window, + BandStartFreq, + BandStopFreq, SpectrumData, - DominantFreq, + Rms, + SpectralCentroid, + ImmediateMode, + Downmix, + Channel, } impl From for ffi::FMOD_DSP_FFT { fn from(value: DspFft) -> ffi::FMOD_DSP_FFT { match value { DspFft::WindowSize => ffi::FMOD_DSP_FFT_WINDOWSIZE, - DspFft::WindowType => ffi::FMOD_DSP_FFT_WINDOWTYPE, + DspFft::Window => ffi::FMOD_DSP_FFT_WINDOW, + DspFft::BandStartFreq => ffi::FMOD_DSP_FFT_BAND_START_FREQ, + DspFft::BandStopFreq => ffi::FMOD_DSP_FFT_BAND_STOP_FREQ, DspFft::SpectrumData => ffi::FMOD_DSP_FFT_SPECTRUMDATA, - DspFft::DominantFreq => ffi::FMOD_DSP_FFT_DOMINANT_FREQ, + DspFft::Rms => ffi::FMOD_DSP_FFT_RMS, + DspFft::SpectralCentroid => ffi::FMOD_DSP_FFT_SPECTRAL_CENTROID, + DspFft::ImmediateMode => ffi::FMOD_DSP_FFT_IMMEDIATE_MODE, + DspFft::Downmix => ffi::FMOD_DSP_FFT_DOWNMIX, + DspFft::Channel => ffi::FMOD_DSP_FFT_CHANNEL, } } } @@ -3061,9 +3317,15 @@ impl DspFft { pub fn from(value: ffi::FMOD_DSP_FFT) -> Result { match value { ffi::FMOD_DSP_FFT_WINDOWSIZE => Ok(DspFft::WindowSize), - ffi::FMOD_DSP_FFT_WINDOWTYPE => Ok(DspFft::WindowType), + ffi::FMOD_DSP_FFT_WINDOW => Ok(DspFft::Window), + ffi::FMOD_DSP_FFT_BAND_START_FREQ => Ok(DspFft::BandStartFreq), + ffi::FMOD_DSP_FFT_BAND_STOP_FREQ => Ok(DspFft::BandStopFreq), ffi::FMOD_DSP_FFT_SPECTRUMDATA => Ok(DspFft::SpectrumData), - ffi::FMOD_DSP_FFT_DOMINANT_FREQ => Ok(DspFft::DominantFreq), + ffi::FMOD_DSP_FFT_RMS => Ok(DspFft::Rms), + ffi::FMOD_DSP_FFT_SPECTRAL_CENTROID => Ok(DspFft::SpectralCentroid), + ffi::FMOD_DSP_FFT_IMMEDIATE_MODE => Ok(DspFft::ImmediateMode), + ffi::FMOD_DSP_FFT_DOWNMIX => Ok(DspFft::Downmix), + ffi::FMOD_DSP_FFT_CHANNEL => Ok(DspFft::Channel), _ => Err(err_enum!("FMOD_DSP_FFT", value)), } } @@ -3137,34 +3399,6 @@ impl DspLoudnessMeterStateType { } } #[derive(Debug, Clone, Copy, PartialEq)] -pub enum DspEnvelopeFollower { - Attack, - Release, - Envelope, - UseSidechain, -} -impl From for ffi::FMOD_DSP_ENVELOPEFOLLOWER { - fn from(value: DspEnvelopeFollower) -> ffi::FMOD_DSP_ENVELOPEFOLLOWER { - match value { - DspEnvelopeFollower::Attack => ffi::FMOD_DSP_ENVELOPEFOLLOWER_ATTACK, - DspEnvelopeFollower::Release => ffi::FMOD_DSP_ENVELOPEFOLLOWER_RELEASE, - DspEnvelopeFollower::Envelope => ffi::FMOD_DSP_ENVELOPEFOLLOWER_ENVELOPE, - DspEnvelopeFollower::UseSidechain => ffi::FMOD_DSP_ENVELOPEFOLLOWER_USESIDECHAIN, - } - } -} -impl DspEnvelopeFollower { - pub fn from(value: ffi::FMOD_DSP_ENVELOPEFOLLOWER) -> Result { - match value { - ffi::FMOD_DSP_ENVELOPEFOLLOWER_ATTACK => Ok(DspEnvelopeFollower::Attack), - ffi::FMOD_DSP_ENVELOPEFOLLOWER_RELEASE => Ok(DspEnvelopeFollower::Release), - ffi::FMOD_DSP_ENVELOPEFOLLOWER_ENVELOPE => Ok(DspEnvelopeFollower::Envelope), - ffi::FMOD_DSP_ENVELOPEFOLLOWER_USESIDECHAIN => Ok(DspEnvelopeFollower::UseSidechain), - _ => Err(err_enum!("FMOD_DSP_ENVELOPEFOLLOWER", value)), - } - } -} -#[derive(Debug, Clone, Copy, PartialEq)] pub enum DspConvolutionReverb { ParamIr, ParamWet, @@ -3584,16 +3818,16 @@ impl TryFrom for BankInfo { } } } -impl Into for BankInfo { - fn into(self) -> ffi::FMOD_STUDIO_BANK_INFO { +impl From for ffi::FMOD_STUDIO_BANK_INFO { + fn from(value: BankInfo) -> ffi::FMOD_STUDIO_BANK_INFO { ffi::FMOD_STUDIO_BANK_INFO { - size: self.size, - userdata: self.userdata, - userdatalength: self.userdatalength, - opencallback: self.opencallback, - closecallback: self.closecallback, - readcallback: self.readcallback, - seekcallback: self.seekcallback, + size: value.size, + userdata: value.userdata, + userdatalength: value.userdatalength, + opencallback: value.opencallback, + closecallback: value.closecallback, + readcallback: value.readcallback, + seekcallback: value.seekcallback, } } } @@ -3613,11 +3847,11 @@ impl TryFrom for ParameterId { } } } -impl Into for ParameterId { - fn into(self) -> ffi::FMOD_STUDIO_PARAMETER_ID { +impl From for ffi::FMOD_STUDIO_PARAMETER_ID { + fn from(value: ParameterId) -> ffi::FMOD_STUDIO_PARAMETER_ID { ffi::FMOD_STUDIO_PARAMETER_ID { - data1: self.data_1, - data2: self.data_2, + data1: value.data_1, + data2: value.data_2, } } } @@ -3649,17 +3883,17 @@ impl TryFrom for ParameterDescription { } } } -impl Into for ParameterDescription { - fn into(self) -> ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION { +impl From for ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION { + fn from(value: ParameterDescription) -> ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION { ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION { - name: self.name.as_ptr().cast(), - id: self.id.into(), - minimum: self.minimum, - maximum: self.maximum, - defaultvalue: self.defaultvalue, - type_: self.type_.into(), - flags: self.flags, - guid: self.guid.into(), + name: move_string_to_c!(value.name), + id: value.id.into(), + minimum: value.minimum, + maximum: value.maximum, + defaultvalue: value.defaultvalue, + type_: value.type_.into(), + flags: value.flags, + guid: value.guid.into(), } } } @@ -3681,12 +3915,12 @@ impl TryFrom for UserProperty { } } } -impl Into for UserProperty { - fn into(self) -> ffi::FMOD_STUDIO_USER_PROPERTY { +impl From for ffi::FMOD_STUDIO_USER_PROPERTY { + fn from(value: UserProperty) -> ffi::FMOD_STUDIO_USER_PROPERTY { ffi::FMOD_STUDIO_USER_PROPERTY { - name: self.name.as_ptr().cast(), - type_: self.type_.into(), - union: self.union, + name: move_string_to_c!(value.name), + type_: value.type_.into(), + union: value.union, } } } @@ -3708,12 +3942,12 @@ impl TryFrom for ProgrammerSoundPr } } } -impl Into for ProgrammerSoundProperties { - fn into(self) -> ffi::FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES { +impl From for ffi::FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES { + fn from(value: ProgrammerSoundProperties) -> ffi::FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES { ffi::FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES { - name: self.name.as_ptr().cast(), - sound: self.sound.as_mut_ptr(), - subsoundIndex: self.subsound_index, + name: move_string_to_c!(value.name), + sound: value.sound.as_mut_ptr(), + subsoundIndex: value.subsound_index, } } } @@ -3733,11 +3967,11 @@ impl TryFrom for PluginInstanceProp } } } -impl Into for PluginInstanceProperties { - fn into(self) -> ffi::FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES { +impl From for ffi::FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES { + fn from(value: PluginInstanceProperties) -> ffi::FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES { ffi::FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES { - name: self.name.as_ptr().cast(), - dsp: self.dsp.as_mut_ptr(), + name: move_string_to_c!(value.name), + dsp: value.dsp.as_mut_ptr(), } } } @@ -3757,11 +3991,11 @@ impl TryFrom for TimelineMarkerProp } } } -impl Into for TimelineMarkerProperties { - fn into(self) -> ffi::FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES { +impl From for ffi::FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES { + fn from(value: TimelineMarkerProperties) -> ffi::FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES { ffi::FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES { - name: self.name.as_ptr().cast(), - position: self.position, + name: move_string_to_c!(value.name), + position: value.position, } } } @@ -3789,15 +4023,15 @@ impl TryFrom for TimelineBeatProperti } } } -impl Into for TimelineBeatProperties { - fn into(self) -> ffi::FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES { +impl From for ffi::FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES { + fn from(value: TimelineBeatProperties) -> ffi::FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES { ffi::FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES { - bar: self.bar, - beat: self.beat, - position: self.position, - tempo: self.tempo, - timesignatureupper: self.timesignatureupper, - timesignaturelower: self.timesignaturelower, + bar: value.bar, + beat: value.beat, + position: value.position, + tempo: value.tempo, + timesignatureupper: value.timesignatureupper, + timesignaturelower: value.timesignaturelower, } } } @@ -3819,11 +4053,13 @@ impl TryFrom for TimelineNeste } } } -impl Into for TimelineNestedBeatProperties { - fn into(self) -> ffi::FMOD_STUDIO_TIMELINE_NESTED_BEAT_PROPERTIES { +impl From for ffi::FMOD_STUDIO_TIMELINE_NESTED_BEAT_PROPERTIES { + fn from( + value: TimelineNestedBeatProperties, + ) -> ffi::FMOD_STUDIO_TIMELINE_NESTED_BEAT_PROPERTIES { ffi::FMOD_STUDIO_TIMELINE_NESTED_BEAT_PROPERTIES { - eventid: self.eventid.into(), - properties: self.properties.into(), + eventid: value.eventid.into(), + properties: value.properties.into(), } } } @@ -3851,16 +4087,16 @@ impl TryFrom for StudioAdvancedSettings { } } } -impl Into for StudioAdvancedSettings { - fn into(self) -> ffi::FMOD_STUDIO_ADVANCEDSETTINGS { +impl From for ffi::FMOD_STUDIO_ADVANCEDSETTINGS { + fn from(value: StudioAdvancedSettings) -> ffi::FMOD_STUDIO_ADVANCEDSETTINGS { ffi::FMOD_STUDIO_ADVANCEDSETTINGS { cbsize: size_of::() as i32, - commandqueuesize: self.commandqueuesize, - handleinitialsize: self.handleinitialsize, - studioupdateperiod: self.studioupdateperiod, - idlesampledatapoolsize: self.idlesampledatapoolsize, - streamingscheduledelay: self.streamingscheduledelay, - encryptionkey: self.encryptionkey.as_ptr().cast(), + commandqueuesize: value.commandqueuesize, + handleinitialsize: value.handleinitialsize, + studioupdateperiod: value.studioupdateperiod, + idlesampledatapoolsize: value.idlesampledatapoolsize, + streamingscheduledelay: value.streamingscheduledelay, + encryptionkey: move_string_to_c!(value.encryptionkey), } } } @@ -3878,10 +4114,10 @@ impl TryFrom for StudioCpuUsage { } } } -impl Into for StudioCpuUsage { - fn into(self) -> ffi::FMOD_STUDIO_CPU_USAGE { +impl From for ffi::FMOD_STUDIO_CPU_USAGE { + fn from(value: StudioCpuUsage) -> ffi::FMOD_STUDIO_CPU_USAGE { ffi::FMOD_STUDIO_CPU_USAGE { - update: self.update, + update: value.update, } } } @@ -3907,14 +4143,14 @@ impl TryFrom for BufferInfo { } } } -impl Into for BufferInfo { - fn into(self) -> ffi::FMOD_STUDIO_BUFFER_INFO { +impl From for ffi::FMOD_STUDIO_BUFFER_INFO { + fn from(value: BufferInfo) -> ffi::FMOD_STUDIO_BUFFER_INFO { ffi::FMOD_STUDIO_BUFFER_INFO { - currentusage: self.currentusage, - peakusage: self.peakusage, - capacity: self.capacity, - stallcount: self.stallcount, - stalltime: self.stalltime, + currentusage: value.currentusage, + peakusage: value.peakusage, + capacity: value.capacity, + stallcount: value.stallcount, + stalltime: value.stalltime, } } } @@ -3934,11 +4170,11 @@ impl TryFrom for BufferUsage { } } } -impl Into for BufferUsage { - fn into(self) -> ffi::FMOD_STUDIO_BUFFER_USAGE { +impl From for ffi::FMOD_STUDIO_BUFFER_USAGE { + fn from(value: BufferUsage) -> ffi::FMOD_STUDIO_BUFFER_USAGE { ffi::FMOD_STUDIO_BUFFER_USAGE { - studiocommandqueue: self.studiocommandqueue.into(), - studiohandle: self.studiohandle.into(), + studiocommandqueue: value.studiocommandqueue.into(), + studiohandle: value.studiohandle.into(), } } } @@ -3962,13 +4198,13 @@ impl TryFrom for SoundInfo { } } } -impl Into for SoundInfo { - fn into(self) -> ffi::FMOD_STUDIO_SOUND_INFO { +impl From for ffi::FMOD_STUDIO_SOUND_INFO { + fn from(value: SoundInfo) -> ffi::FMOD_STUDIO_SOUND_INFO { ffi::FMOD_STUDIO_SOUND_INFO { - name_or_data: self.name_or_data.as_ptr().cast(), - mode: self.mode, - exinfo: self.exinfo.into(), - subsoundindex: self.subsoundindex, + name_or_data: move_string_to_c!(value.name_or_data), + mode: value.mode, + exinfo: value.exinfo.into(), + subsoundindex: value.subsoundindex, } } } @@ -4000,17 +4236,17 @@ impl TryFrom for CommandInfo { } } } -impl Into for CommandInfo { - fn into(self) -> ffi::FMOD_STUDIO_COMMAND_INFO { +impl From for ffi::FMOD_STUDIO_COMMAND_INFO { + fn from(value: CommandInfo) -> ffi::FMOD_STUDIO_COMMAND_INFO { ffi::FMOD_STUDIO_COMMAND_INFO { - commandname: self.commandname.as_ptr().cast(), - parentcommandindex: self.parentcommandindex, - framenumber: self.framenumber, - frametime: self.frametime, - instancetype: self.instancetype.into(), - outputtype: self.outputtype.into(), - instancehandle: self.instancehandle, - outputhandle: self.outputhandle, + commandname: move_string_to_c!(value.commandname), + parentcommandindex: value.parentcommandindex, + framenumber: value.framenumber, + frametime: value.frametime, + instancetype: value.instancetype.into(), + outputtype: value.outputtype.into(), + instancehandle: value.instancehandle, + outputhandle: value.outputhandle, } } } @@ -4032,12 +4268,12 @@ impl TryFrom for MemoryUsage { } } } -impl Into for MemoryUsage { - fn into(self) -> ffi::FMOD_STUDIO_MEMORY_USAGE { +impl From for ffi::FMOD_STUDIO_MEMORY_USAGE { + fn from(value: MemoryUsage) -> ffi::FMOD_STUDIO_MEMORY_USAGE { ffi::FMOD_STUDIO_MEMORY_USAGE { - exclusive: self.exclusive, - inclusive: self.inclusive, - sampledata: self.sampledata, + exclusive: value.exclusive, + inclusive: value.inclusive, + sampledata: value.sampledata, } } } @@ -4069,17 +4305,17 @@ impl TryFrom for AsyncReadInfo { } } } -impl Into for AsyncReadInfo { - fn into(self) -> ffi::FMOD_ASYNCREADINFO { +impl From for ffi::FMOD_ASYNCREADINFO { + fn from(value: AsyncReadInfo) -> ffi::FMOD_ASYNCREADINFO { ffi::FMOD_ASYNCREADINFO { - handle: self.handle, - offset: self.offset, - sizebytes: self.sizebytes, - priority: self.priority, - userdata: self.userdata, - buffer: self.buffer, - bytesread: self.bytesread, - done: self.done, + handle: value.handle, + offset: value.offset, + sizebytes: value.sizebytes, + priority: value.priority, + userdata: value.userdata, + buffer: value.buffer, + bytesread: value.bytesread, + done: value.done, } } } @@ -4134,12 +4370,12 @@ impl From for (f32, f32, f32) { (value.x, value.y, value.z) } } -impl Into for Vector { - fn into(self) -> ffi::FMOD_VECTOR { +impl From for ffi::FMOD_VECTOR { + fn from(value: Vector) -> ffi::FMOD_VECTOR { ffi::FMOD_VECTOR { - x: self.x, - y: self.y, - z: self.z, + x: value.x, + y: value.y, + z: value.z, } } } @@ -4163,13 +4399,13 @@ impl TryFrom for Attributes3d { } } } -impl Into for Attributes3d { - fn into(self) -> ffi::FMOD_3D_ATTRIBUTES { +impl From for ffi::FMOD_3D_ATTRIBUTES { + fn from(value: Attributes3d) -> ffi::FMOD_3D_ATTRIBUTES { ffi::FMOD_3D_ATTRIBUTES { - position: self.position.into(), - velocity: self.velocity.into(), - forward: self.forward.into(), - up: self.up.into(), + position: value.position.into(), + velocity: value.velocity.into(), + forward: value.forward.into(), + up: value.up.into(), } } } @@ -4204,13 +4440,13 @@ impl Guid { } } } -impl Into for Guid { - fn into(self) -> ffi::FMOD_GUID { +impl From for ffi::FMOD_GUID { + fn from(value: Guid) -> ffi::FMOD_GUID { ffi::FMOD_GUID { - Data1: self.data_1, - Data2: self.data_2, - Data3: self.data_3, - Data4: self.data_4, + Data1: value.data_1, + Data2: value.data_2, + Data3: value.data_3, + Data4: value.data_4, } } } @@ -4230,11 +4466,11 @@ impl TryFrom for PluginList { } } } -impl Into for PluginList { - fn into(self) -> ffi::FMOD_PLUGINLIST { +impl From for ffi::FMOD_PLUGINLIST { + fn from(value: PluginList) -> ffi::FMOD_PLUGINLIST { ffi::FMOD_PLUGINLIST { - type_: self.type_.into(), - description: self.description, + type_: value.type_.into(), + description: value.description, } } } @@ -4246,7 +4482,7 @@ pub struct AdvancedSettings { pub max_vorbis_codecs: i32, pub max_at_9_codecs: i32, pub max_fadpcm_codecs: i32, - pub max_pcm_codecs: i32, + pub max_opus_codecs: i32, pub asio_num_channels: i32, pub asio_channel_list: Vec, pub asio_speaker_list: Vec, @@ -4260,7 +4496,6 @@ pub struct AdvancedSettings { pub resampler_method: DspResampler, pub random_seed: u32, pub max_convolution_threads: i32, - pub max_opus_codecs: i32, pub max_spatial_objects: i32, } impl TryFrom for AdvancedSettings { @@ -4274,7 +4509,7 @@ impl TryFrom for AdvancedSettings { max_vorbis_codecs: value.maxVorbisCodecs, max_at_9_codecs: value.maxAT9Codecs, max_fadpcm_codecs: value.maxFADPCMCodecs, - max_pcm_codecs: value.maxPCMCodecs, + max_opus_codecs: value.maxOpusCodecs, asio_num_channels: value.ASIONumChannels, asio_channel_list: to_vec!( value.ASIOChannelList, @@ -4296,49 +4531,36 @@ impl TryFrom for AdvancedSettings { resampler_method: DspResampler::from(value.resamplerMethod)?, random_seed: value.randomSeed, max_convolution_threads: value.maxConvolutionThreads, - max_opus_codecs: value.maxOpusCodecs, max_spatial_objects: value.maxSpatialObjects, }) } } } -impl Into for AdvancedSettings { - fn into(self) -> ffi::FMOD_ADVANCEDSETTINGS { +impl From for ffi::FMOD_ADVANCEDSETTINGS { + fn from(value: AdvancedSettings) -> ffi::FMOD_ADVANCEDSETTINGS { ffi::FMOD_ADVANCEDSETTINGS { cbSize: size_of::() as i32, - maxMPEGCodecs: self.max_mpeg_codecs, - maxADPCMCodecs: self.max_adpcm_codecs, - maxXMACodecs: self.max_xma_codecs, - maxVorbisCodecs: self.max_vorbis_codecs, - maxAT9Codecs: self.max_at_9_codecs, - maxFADPCMCodecs: self.max_fadpcm_codecs, - maxPCMCodecs: self.max_pcm_codecs, - ASIONumChannels: self.asio_num_channels, - ASIOChannelList: self - .asio_channel_list - .into_iter() - .map(|val| val.as_ptr()) - .collect::>() - .as_mut_ptr() - .cast(), - ASIOSpeakerList: self - .asio_speaker_list - .into_iter() - .map(|val| val.into()) - .collect::>() - .as_mut_ptr(), - vol0virtualvol: self.vol_0_virtualvol, - defaultDecodeBufferSize: self.default_decode_buffer_size, - profilePort: self.profile_port, - geometryMaxFadeTime: self.geometry_max_fade_time, - distanceFilterCenterFreq: self.distance_filter_center_freq, - reverb3Dinstance: self.reverb_3_d_instance, - DSPBufferPoolSize: self.dsp_buffer_pool_size, - resamplerMethod: self.resampler_method.into(), - randomSeed: self.random_seed, - maxConvolutionThreads: self.max_convolution_threads, - maxOpusCodecs: self.max_opus_codecs, - maxSpatialObjects: self.max_spatial_objects, + maxMPEGCodecs: value.max_mpeg_codecs, + maxADPCMCodecs: value.max_adpcm_codecs, + maxXMACodecs: value.max_xma_codecs, + maxVorbisCodecs: value.max_vorbis_codecs, + maxAT9Codecs: value.max_at_9_codecs, + maxFADPCMCodecs: value.max_fadpcm_codecs, + maxOpusCodecs: value.max_opus_codecs, + ASIONumChannels: value.asio_num_channels, + ASIOChannelList: vec_as_mut_ptr(value.asio_channel_list, |val| val.as_ptr()).cast(), + ASIOSpeakerList: vec_as_mut_ptr(value.asio_speaker_list, |val| val.into()), + vol0virtualvol: value.vol_0_virtualvol, + defaultDecodeBufferSize: value.default_decode_buffer_size, + profilePort: value.profile_port, + geometryMaxFadeTime: value.geometry_max_fade_time, + distanceFilterCenterFreq: value.distance_filter_center_freq, + reverb3Dinstance: value.reverb_3_d_instance, + DSPBufferPoolSize: value.dsp_buffer_pool_size, + resamplerMethod: value.resampler_method.into(), + randomSeed: value.random_seed, + maxConvolutionThreads: value.max_convolution_threads, + maxSpatialObjects: value.max_spatial_objects, } } } @@ -4366,15 +4588,15 @@ impl TryFrom for Tag { } } } -impl Into for Tag { - fn into(self) -> ffi::FMOD_TAG { +impl From for ffi::FMOD_TAG { + fn from(value: Tag) -> ffi::FMOD_TAG { ffi::FMOD_TAG { - type_: self.type_.into(), - datatype: self.datatype.into(), - name: self.name.as_ptr() as *mut _, - data: self.data, - datalen: self.datalen, - updated: self.updated, + type_: value.type_.into(), + datatype: value.datatype.into(), + name: move_string_to_c!(value.name) as *mut _, + data: value.data, + datalen: value.datalen, + updated: value.updated, } } } @@ -4469,48 +4691,56 @@ impl Default for CreateSoundexInfo { Self::try_from(ffi::FMOD_CREATESOUNDEXINFO::default()).unwrap() } } -impl Into for CreateSoundexInfo { - fn into(self) -> ffi::FMOD_CREATESOUNDEXINFO { +impl From for ffi::FMOD_CREATESOUNDEXINFO { + fn from(value: CreateSoundexInfo) -> ffi::FMOD_CREATESOUNDEXINFO { ffi::FMOD_CREATESOUNDEXINFO { cbsize: size_of::() as i32, - length: self.length, - fileoffset: self.fileoffset, - numchannels: self.numchannels, - defaultfrequency: self.defaultfrequency, - format: self.format.into(), - decodebuffersize: self.decodebuffersize, - initialsubsound: self.initialsubsound, - numsubsounds: self.numsubsounds, - inclusionlist: opt_ptr!(self.inclusionlist.clone(), |v| v.as_slice().as_ptr() + length: value.length, + fileoffset: value.fileoffset, + numchannels: value.numchannels, + defaultfrequency: value.defaultfrequency, + format: value.format.into(), + decodebuffersize: value.decodebuffersize, + initialsubsound: value.initialsubsound, + numsubsounds: value.numsubsounds, + inclusionlist: opt_ptr!(value.inclusionlist.clone(), |v| v.as_slice().as_ptr() as *mut _), - inclusionlistnum: self.inclusionlist.map(|v| v.len()).unwrap_or(0) as _, - pcmreadcallback: self.pcmreadcallback, - pcmsetposcallback: self.pcmsetposcallback, - nonblockcallback: self.nonblockcallback, - dlsname: opt_ptr!(self.dlsname.map(|v| CString::new(v).unwrap()), |v| v - .as_ptr()), - encryptionkey: opt_ptr!(self.encryptionkey.map(|v| CString::new(v).unwrap()), |v| v - .as_ptr()), - maxpolyphony: self.maxpolyphony, - userdata: self.userdata, - suggestedsoundtype: self.suggestedsoundtype.into(), - fileuseropen: self.fileuseropen, - fileuserclose: self.fileuserclose, - fileuserread: self.fileuserread, - fileuserseek: self.fileuserseek, - fileuserasyncread: self.fileuserasyncread, - fileuserasynccancel: self.fileuserasynccancel, - fileuserdata: self.fileuserdata, - filebuffersize: self.filebuffersize, - channelorder: self.channelorder.into(), - initialsoundgroup: opt_ptr!(self.initialsoundgroup, |v| v.as_mut_ptr()), - initialseekposition: self.initialseekposition, - initialseekpostype: self.initialseekpostype, - ignoresetfilesystem: self.ignoresetfilesystem, - audioqueuepolicy: self.audioqueuepolicy, - minmidigranularity: self.minmidigranularity, - nonblockthreadid: self.nonblockthreadid, - fsbguid: opt_ptr!(self.fsbguid, |v| &mut v.into() as *mut _), + inclusionlistnum: value.inclusionlist.map(|v| v.len()).unwrap_or(0) as _, + pcmreadcallback: value.pcmreadcallback, + pcmsetposcallback: value.pcmsetposcallback, + nonblockcallback: value.nonblockcallback, + dlsname: opt_ptr!( + value + .dlsname + .map(|v| Box::leak(CString::new(v).unwrap().into_boxed_c_str())), + |v| v.as_ptr() + ), + encryptionkey: opt_ptr!( + value + .encryptionkey + .map(|v| Box::leak(CString::new(v).unwrap().into_boxed_c_str())), + |v| v.as_ptr() + ), + maxpolyphony: value.maxpolyphony, + userdata: value.userdata, + suggestedsoundtype: value.suggestedsoundtype.into(), + fileuseropen: value.fileuseropen, + fileuserclose: value.fileuserclose, + fileuserread: value.fileuserread, + fileuserseek: value.fileuserseek, + fileuserasyncread: value.fileuserasyncread, + fileuserasynccancel: value.fileuserasynccancel, + fileuserdata: value.fileuserdata, + filebuffersize: value.filebuffersize, + channelorder: value.channelorder.into(), + initialsoundgroup: opt_ptr!(value.initialsoundgroup, |v| v.as_mut_ptr()), + initialseekposition: value.initialseekposition, + initialseekpostype: value.initialseekpostype, + ignoresetfilesystem: value.ignoresetfilesystem, + audioqueuepolicy: value.audioqueuepolicy, + minmidigranularity: value.minmidigranularity, + nonblockthreadid: value.nonblockthreadid, + fsbguid: opt_ptr!(value.fsbguid, |v| &mut v.into() as *mut _), } } } @@ -4648,21 +4878,21 @@ impl TryFrom for ReverbProperties { } } } -impl Into for ReverbProperties { - fn into(self) -> ffi::FMOD_REVERB_PROPERTIES { +impl From for ffi::FMOD_REVERB_PROPERTIES { + fn from(value: ReverbProperties) -> ffi::FMOD_REVERB_PROPERTIES { ffi::FMOD_REVERB_PROPERTIES { - DecayTime: self.decay_time, - EarlyDelay: self.early_delay, - LateDelay: self.late_delay, - HFReference: self.hf_reference, - HFDecayRatio: self.hf_decay_ratio, - Diffusion: self.diffusion, - Density: self.density, - LowShelfFrequency: self.low_shelf_frequency, - LowShelfGain: self.low_shelf_gain, - HighCut: self.high_cut, - EarlyLateMix: self.early_late_mix, - WetLevel: self.wet_level, + DecayTime: value.decay_time, + EarlyDelay: value.early_delay, + LateDelay: value.late_delay, + HFReference: value.hf_reference, + HFDecayRatio: value.hf_decay_ratio, + Diffusion: value.diffusion, + Density: value.density, + LowShelfFrequency: value.low_shelf_frequency, + LowShelfGain: value.low_shelf_gain, + HighCut: value.high_cut, + EarlyLateMix: value.early_late_mix, + WetLevel: value.wet_level, } } } @@ -4688,14 +4918,14 @@ impl TryFrom for ErrorCallbackInfo { } } } -impl Into for ErrorCallbackInfo { - fn into(self) -> ffi::FMOD_ERRORCALLBACK_INFO { +impl From for ffi::FMOD_ERRORCALLBACK_INFO { + fn from(value: ErrorCallbackInfo) -> ffi::FMOD_ERRORCALLBACK_INFO { ffi::FMOD_ERRORCALLBACK_INFO { - result: self.result.into(), - instancetype: self.instancetype.into(), - instance: self.instance, - functionname: self.functionname.as_ptr().cast(), - functionparams: self.functionparams.as_ptr().cast(), + result: value.result.into(), + instancetype: value.instancetype.into(), + instance: value.instance, + functionname: move_string_to_c!(value.functionname), + functionparams: move_string_to_c!(value.functionparams), } } } @@ -4723,15 +4953,15 @@ impl TryFrom for CpuUsage { } } } -impl Into for CpuUsage { - fn into(self) -> ffi::FMOD_CPU_USAGE { +impl From for ffi::FMOD_CPU_USAGE { + fn from(value: CpuUsage) -> ffi::FMOD_CPU_USAGE { ffi::FMOD_CPU_USAGE { - dsp: self.dsp, - stream: self.stream, - geometry: self.geometry, - update: self.update, - convolution1: self.convolution_1, - convolution2: self.convolution_2, + dsp: value.dsp, + stream: value.stream, + geometry: value.geometry, + update: value.update, + convolution1: value.convolution_1, + convolution2: value.convolution_2, } } } @@ -4753,12 +4983,12 @@ impl TryFrom for DspDataParameterInfo { } } } -impl Into for DspDataParameterInfo { - fn into(self) -> ffi::FMOD_DSP_DATA_PARAMETER_INFO { +impl From for ffi::FMOD_DSP_DATA_PARAMETER_INFO { + fn from(value: DspDataParameterInfo) -> ffi::FMOD_DSP_DATA_PARAMETER_INFO { ffi::FMOD_DSP_DATA_PARAMETER_INFO { - data: self.data, - length: self.length, - index: self.index, + data: value.data, + length: value.length, + index: value.index, } } } @@ -4800,22 +5030,22 @@ impl TryFrom for CodecDescription { } } } -impl Into for CodecDescription { - fn into(self) -> ffi::FMOD_CODEC_DESCRIPTION { +impl From for ffi::FMOD_CODEC_DESCRIPTION { + fn from(value: CodecDescription) -> ffi::FMOD_CODEC_DESCRIPTION { ffi::FMOD_CODEC_DESCRIPTION { - apiversion: self.apiversion, - name: self.name.as_ptr().cast(), - version: self.version, - defaultasstream: self.defaultasstream, - timeunits: self.timeunits, - open: self.open, - close: self.close, - read: self.read, - getlength: self.getlength, - setposition: self.setposition, - getposition: self.getposition, - soundcreate: self.soundcreate, - getwaveformat: self.getwaveformat, + apiversion: value.apiversion, + name: move_string_to_c!(value.name), + version: value.version, + defaultasstream: value.defaultasstream, + timeunits: value.timeunits, + open: value.open, + close: value.close, + read: value.read, + getlength: value.getlength, + setposition: value.setposition, + getposition: value.getposition, + soundcreate: value.soundcreate, + getwaveformat: value.getwaveformat, } } } @@ -4857,22 +5087,22 @@ impl TryFrom for CodecWaveformat { } } } -impl Into for CodecWaveformat { - fn into(self) -> ffi::FMOD_CODEC_WAVEFORMAT { +impl From for ffi::FMOD_CODEC_WAVEFORMAT { + fn from(value: CodecWaveformat) -> ffi::FMOD_CODEC_WAVEFORMAT { ffi::FMOD_CODEC_WAVEFORMAT { - name: self.name.as_ptr().cast(), - format: self.format.into(), - channels: self.channels, - frequency: self.frequency, - lengthbytes: self.lengthbytes, - lengthpcm: self.lengthpcm, - pcmblocksize: self.pcmblocksize, - loopstart: self.loopstart, - loopend: self.loopend, - mode: self.mode, - channelmask: self.channelmask, - channelorder: self.channelorder.into(), - peakvolume: self.peakvolume, + name: move_string_to_c!(value.name), + format: value.format.into(), + channels: value.channels, + frequency: value.frequency, + lengthbytes: value.lengthbytes, + lengthpcm: value.lengthpcm, + pcmblocksize: value.pcmblocksize, + loopstart: value.loopstart, + loopend: value.loopend, + mode: value.mode, + channelmask: value.channelmask, + channelorder: value.channelorder.into(), + peakvolume: value.peakvolume, } } } @@ -4904,17 +5134,17 @@ impl TryFrom for CodecStateFunctions { } } } -impl Into for CodecStateFunctions { - fn into(self) -> ffi::FMOD_CODEC_STATE_FUNCTIONS { +impl From for ffi::FMOD_CODEC_STATE_FUNCTIONS { + fn from(value: CodecStateFunctions) -> ffi::FMOD_CODEC_STATE_FUNCTIONS { ffi::FMOD_CODEC_STATE_FUNCTIONS { - metadata: self.metadata, - alloc: self.alloc, - free: self.free, - log: self.log, - read: self.read, - seek: self.seek, - tell: self.tell, - size: self.size, + metadata: value.metadata, + alloc: value.alloc, + free: value.free, + log: value.log, + read: value.read, + seek: value.seek, + tell: value.tell, + size: value.size, } } } @@ -4938,13 +5168,13 @@ impl TryFrom for CodecState { } } } -impl Into for CodecState { - fn into(self) -> ffi::FMOD_CODEC_STATE { +impl From for ffi::FMOD_CODEC_STATE { + fn from(value: CodecState) -> ffi::FMOD_CODEC_STATE { ffi::FMOD_CODEC_STATE { - plugindata: self.plugindata, - waveformat: &mut self.waveformat.into(), - functions: &mut self.functions.into(), - numsubsounds: self.numsubsounds, + plugindata: value.plugindata, + waveformat: &mut value.waveformat.into(), + functions: &mut value.functions.into(), + numsubsounds: value.numsubsounds, } } } @@ -5000,29 +5230,29 @@ impl TryFrom for OutputDescription { } } } -impl Into for OutputDescription { - fn into(self) -> ffi::FMOD_OUTPUT_DESCRIPTION { +impl From for ffi::FMOD_OUTPUT_DESCRIPTION { + fn from(value: OutputDescription) -> ffi::FMOD_OUTPUT_DESCRIPTION { ffi::FMOD_OUTPUT_DESCRIPTION { - apiversion: self.apiversion, - name: self.name.as_ptr().cast(), - version: self.version, - method: self.method, - getnumdrivers: self.getnumdrivers, - getdriverinfo: self.getdriverinfo, - init: self.init, - start: self.start, - stop: self.stop, - close: self.close, - update: self.update, - gethandle: self.gethandle, - mixer: self.mixer, - object3dgetinfo: self.object_3_dgetinfo, - object3dalloc: self.object_3_dalloc, - object3dfree: self.object_3_dfree, - object3dupdate: self.object_3_dupdate, - openport: self.openport, - closeport: self.closeport, - devicelistchanged: self.devicelistchanged, + apiversion: value.apiversion, + name: move_string_to_c!(value.name), + version: value.version, + method: value.method, + getnumdrivers: value.getnumdrivers, + getdriverinfo: value.getdriverinfo, + init: value.init, + start: value.start, + stop: value.stop, + close: value.close, + update: value.update, + gethandle: value.gethandle, + mixer: value.mixer, + object3dgetinfo: value.object_3_dgetinfo, + object3dalloc: value.object_3_dalloc, + object3dfree: value.object_3_dfree, + object3dupdate: value.object_3_dupdate, + openport: value.openport, + closeport: value.closeport, + devicelistchanged: value.devicelistchanged, } } } @@ -5052,16 +5282,16 @@ impl TryFrom for OutputState { } } } -impl Into for OutputState { - fn into(self) -> ffi::FMOD_OUTPUT_STATE { +impl From for ffi::FMOD_OUTPUT_STATE { + fn from(value: OutputState) -> ffi::FMOD_OUTPUT_STATE { ffi::FMOD_OUTPUT_STATE { - plugindata: self.plugindata, - readfrommixer: self.readfrommixer, - alloc: self.alloc, - free: self.free, - log: self.log, - copyport: self.copyport, - requestreset: self.requestreset, + plugindata: value.plugindata, + readfrommixer: value.readfrommixer, + alloc: value.alloc, + free: value.free, + log: value.log, + copyport: value.copyport, + requestreset: value.requestreset, } } } @@ -5089,15 +5319,15 @@ impl TryFrom for OutputObject3Dinfo { } } } -impl Into for OutputObject3Dinfo { - fn into(self) -> ffi::FMOD_OUTPUT_OBJECT3DINFO { +impl From for ffi::FMOD_OUTPUT_OBJECT3DINFO { + fn from(value: OutputObject3Dinfo) -> ffi::FMOD_OUTPUT_OBJECT3DINFO { ffi::FMOD_OUTPUT_OBJECT3DINFO { - buffer: self.buffer.as_ptr() as *mut _, - bufferlength: self.bufferlength, - position: self.position.into(), - gain: self.gain, - spread: self.spread, - priority: self.priority, + buffer: value.buffer.as_ptr() as *mut _, + bufferlength: value.bufferlength, + position: value.position.into(), + gain: value.gain, + spread: value.spread, + priority: value.priority, } } } @@ -5123,14 +5353,14 @@ impl TryFrom for DspBufferArray { } } } -impl Into for DspBufferArray { - fn into(self) -> ffi::FMOD_DSP_BUFFER_ARRAY { +impl From for ffi::FMOD_DSP_BUFFER_ARRAY { + fn from(value: DspBufferArray) -> ffi::FMOD_DSP_BUFFER_ARRAY { ffi::FMOD_DSP_BUFFER_ARRAY { - numbuffers: self.numbuffers, - buffernumchannels: self.buffernumchannels.as_ptr() as *mut _, - bufferchannelmask: self.bufferchannelmask.as_ptr() as *mut _, - buffers: self.buffers.as_ptr() as *mut _, - speakermode: self.speakermode.into(), + numbuffers: value.numbuffers, + buffernumchannels: value.buffernumchannels.as_ptr() as *mut _, + bufferchannelmask: value.bufferchannelmask.as_ptr() as *mut _, + buffers: value.buffers.as_ptr() as *mut _, + speakermode: value.speakermode.into(), } } } @@ -5150,11 +5380,11 @@ impl TryFrom for Complex { } } } -impl Into for Complex { - fn into(self) -> ffi::FMOD_COMPLEX { +impl From for ffi::FMOD_COMPLEX { + fn from(value: Complex) -> ffi::FMOD_COMPLEX { ffi::FMOD_COMPLEX { - real: self.real, - imag: self.imag, + real: value.real, + imag: value.imag, } } } @@ -5180,14 +5410,16 @@ impl TryFrom } } } -impl Into - for DspParameterFloatMappingPiecewiseLinear +impl From + for ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR { + fn from( + value: DspParameterFloatMappingPiecewiseLinear, + ) -> ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR { ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR { - numpoints: self.numpoints, - pointparamvalues: self.pointparamvalues.as_ptr() as *mut _, - pointpositions: self.pointpositions.as_ptr() as *mut _, + numpoints: value.numpoints, + pointparamvalues: value.pointparamvalues.as_ptr() as *mut _, + pointpositions: value.pointpositions.as_ptr() as *mut _, } } } @@ -5209,11 +5441,11 @@ impl TryFrom for DspParameterFloatMapping } } } -impl Into for DspParameterFloatMapping { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING { +impl From for ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING { + fn from(value: DspParameterFloatMapping) -> ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING { ffi::FMOD_DSP_PARAMETER_FLOAT_MAPPING { - type_: self.type_.into(), - piecewiselinearmapping: self.piecewiselinearmapping.into(), + type_: value.type_.into(), + piecewiselinearmapping: value.piecewiselinearmapping.into(), } } } @@ -5237,13 +5469,13 @@ impl TryFrom for DspParameterDescFloat { } } } -impl Into for DspParameterDescFloat { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_DESC_FLOAT { +impl From for ffi::FMOD_DSP_PARAMETER_DESC_FLOAT { + fn from(value: DspParameterDescFloat) -> ffi::FMOD_DSP_PARAMETER_DESC_FLOAT { ffi::FMOD_DSP_PARAMETER_DESC_FLOAT { - min: self.min, - max: self.max, - defaultval: self.defaultval, - mapping: self.mapping.into(), + min: value.min, + max: value.max, + defaultval: value.defaultval, + mapping: value.mapping.into(), } } } @@ -5269,14 +5501,14 @@ impl TryFrom for DspParameterDescInt { } } } -impl Into for DspParameterDescInt { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_DESC_INT { +impl From for ffi::FMOD_DSP_PARAMETER_DESC_INT { + fn from(value: DspParameterDescInt) -> ffi::FMOD_DSP_PARAMETER_DESC_INT { ffi::FMOD_DSP_PARAMETER_DESC_INT { - min: self.min, - max: self.max, - defaultval: self.defaultval, - goestoinf: self.goestoinf, - valuenames: self.valuenames.as_ptr() as *mut _, + min: value.min, + max: value.max, + defaultval: value.defaultval, + goestoinf: value.goestoinf, + valuenames: value.valuenames.as_ptr() as *mut _, } } } @@ -5296,11 +5528,11 @@ impl TryFrom for DspParameterDescBool { } } } -impl Into for DspParameterDescBool { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_DESC_BOOL { +impl From for ffi::FMOD_DSP_PARAMETER_DESC_BOOL { + fn from(value: DspParameterDescBool) -> ffi::FMOD_DSP_PARAMETER_DESC_BOOL { ffi::FMOD_DSP_PARAMETER_DESC_BOOL { - defaultval: self.defaultval, - valuenames: self.valuenames.as_ptr() as *mut _, + defaultval: value.defaultval, + valuenames: value.valuenames.as_ptr() as *mut _, } } } @@ -5318,10 +5550,10 @@ impl TryFrom for DspParameterDescData { } } } -impl Into for DspParameterDescData { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_DESC_DATA { +impl From for ffi::FMOD_DSP_PARAMETER_DESC_DATA { + fn from(value: DspParameterDescData) -> ffi::FMOD_DSP_PARAMETER_DESC_DATA { ffi::FMOD_DSP_PARAMETER_DESC_DATA { - datatype: self.datatype, + datatype: value.datatype, } } } @@ -5347,14 +5579,14 @@ impl TryFrom for DspParameterDesc { } } } -impl Into for DspParameterDesc { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_DESC { +impl From for ffi::FMOD_DSP_PARAMETER_DESC { + fn from(value: DspParameterDesc) -> ffi::FMOD_DSP_PARAMETER_DESC { ffi::FMOD_DSP_PARAMETER_DESC { - type_: self.type_.into(), - name: self.name, - label: self.label, - description: self.description.as_ptr().cast(), - union: self.union, + type_: value.type_.into(), + name: value.name, + label: value.label, + description: move_string_to_c!(value.description), + union: value.union, } } } @@ -5374,11 +5606,11 @@ impl TryFrom for DspParameterOverallgain { } } } -impl Into for DspParameterOverallgain { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_OVERALLGAIN { +impl From for ffi::FMOD_DSP_PARAMETER_OVERALLGAIN { + fn from(value: DspParameterOverallgain) -> ffi::FMOD_DSP_PARAMETER_OVERALLGAIN { ffi::FMOD_DSP_PARAMETER_OVERALLGAIN { - linear_gain: self.linear_gain, - linear_gain_additive: self.linear_gain_additive, + linear_gain: value.linear_gain, + linear_gain_additive: value.linear_gain_additive, } } } @@ -5398,11 +5630,11 @@ impl TryFrom for DspParameterAttributes3d } } } -impl Into for DspParameterAttributes3d { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES { +impl From for ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES { + fn from(value: DspParameterAttributes3d) -> ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES { ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES { - relative: self.relative.into(), - absolute: self.absolute.into(), + relative: value.relative.into(), + absolute: value.absolute.into(), } } } @@ -5432,13 +5664,13 @@ impl TryFrom for DspParameterAttribu } } } -impl Into for DspParameterAttributes3dMulti { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI { +impl From for ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI { + fn from(value: DspParameterAttributes3dMulti) -> ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI { ffi::FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI { - numlisteners: self.numlisteners, - relative: self.relative.map(Attributes3d::into), - weight: self.weight, - absolute: self.absolute.into(), + numlisteners: value.numlisteners, + relative: value.relative.map(Attributes3d::into), + weight: value.weight, + absolute: value.absolute.into(), } } } @@ -5458,11 +5690,11 @@ impl TryFrom for DspParameterAttenuat } } } -impl Into for DspParameterAttenuationRange { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_ATTENUATION_RANGE { +impl From for ffi::FMOD_DSP_PARAMETER_ATTENUATION_RANGE { + fn from(value: DspParameterAttenuationRange) -> ffi::FMOD_DSP_PARAMETER_ATTENUATION_RANGE { ffi::FMOD_DSP_PARAMETER_ATTENUATION_RANGE { - min: self.min, - max: self.max, + min: value.min, + max: value.max, } } } @@ -5480,10 +5712,10 @@ impl TryFrom for DspParameterSidechain { } } } -impl Into for DspParameterSidechain { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_SIDECHAIN { +impl From for ffi::FMOD_DSP_PARAMETER_SIDECHAIN { + fn from(value: DspParameterSidechain) -> ffi::FMOD_DSP_PARAMETER_SIDECHAIN { ffi::FMOD_DSP_PARAMETER_SIDECHAIN { - sidechainenable: self.sidechainenable, + sidechainenable: value.sidechainenable, } } } @@ -5518,15 +5750,39 @@ impl TryFrom for DspParameterFft { } } } -impl Into for DspParameterFft { - fn into(self) -> ffi::FMOD_DSP_PARAMETER_FFT { +impl From for ffi::FMOD_DSP_PARAMETER_FFT { + fn from(value: DspParameterFft) -> ffi::FMOD_DSP_PARAMETER_FFT { ffi::FMOD_DSP_PARAMETER_FFT { - length: self.length, - numchannels: self.spectrum.len() as i32, + length: value.length, + numchannels: value.spectrum.len() as i32, spectrum: [null_mut(); 32], } } } +#[derive(Debug, Clone)] +pub struct DspParameterDynamicResponse { + pub numchannels: i32, + pub rms: [f32; 32 as usize], +} +impl TryFrom for DspParameterDynamicResponse { + type Error = Error; + fn try_from(value: ffi::FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE) -> Result { + unsafe { + Ok(DspParameterDynamicResponse { + numchannels: value.numchannels, + rms: value.rms, + }) + } + } +} +impl From for ffi::FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE { + fn from(value: DspParameterDynamicResponse) -> ffi::FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE { + ffi::FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE { + numchannels: value.numchannels, + rms: value.rms, + } + } +} #[derive(Clone)] pub struct DspDescription { pub pluginsdkversion: u32, @@ -5593,35 +5849,37 @@ impl TryFrom for DspDescription { } } } -impl Into for DspDescription { - fn into(self) -> ffi::FMOD_DSP_DESCRIPTION { +impl From for ffi::FMOD_DSP_DESCRIPTION { + fn from(value: DspDescription) -> ffi::FMOD_DSP_DESCRIPTION { ffi::FMOD_DSP_DESCRIPTION { - pluginsdkversion: self.pluginsdkversion, - name: self.name, - version: self.version, - numinputbuffers: self.numinputbuffers, - numoutputbuffers: self.numoutputbuffers, - create: self.create, - release: self.release, - reset: self.reset, - read: self.read, - process: self.process, - setposition: self.setposition, - numparameters: self.paramdesc.len() as i32, - paramdesc: &mut vec_as_mut_ptr(self.paramdesc, |param| param.into()), - setparameterfloat: self.setparameterfloat, - setparameterint: self.setparameterint, - setparameterbool: self.setparameterbool, - setparameterdata: self.setparameterdata, - getparameterfloat: self.getparameterfloat, - getparameterint: self.getparameterint, - getparameterbool: self.getparameterbool, - getparameterdata: self.getparameterdata, - shouldiprocess: self.shouldiprocess, - userdata: self.userdata, - sys_register: self.sys_register, - sys_deregister: self.sys_deregister, - sys_mix: self.sys_mix, + pluginsdkversion: value.pluginsdkversion, + name: value.name, + version: value.version, + numinputbuffers: value.numinputbuffers, + numoutputbuffers: value.numoutputbuffers, + create: value.create, + release: value.release, + reset: value.reset, + read: value.read, + process: value.process, + setposition: value.setposition, + numparameters: value.paramdesc.len() as i32, + paramdesc: vec_as_mut_ptr(value.paramdesc, |param| { + Box::leak(Box::new(param.into())) as *mut _ + }), + setparameterfloat: value.setparameterfloat, + setparameterint: value.setparameterint, + setparameterbool: value.setparameterbool, + setparameterdata: value.setparameterdata, + getparameterfloat: value.getparameterfloat, + getparameterint: value.getparameterint, + getparameterbool: value.getparameterbool, + getparameterdata: value.getparameterdata, + shouldiprocess: value.shouldiprocess, + userdata: value.userdata, + sys_register: value.sys_register, + sys_deregister: value.sys_deregister, + sys_mix: value.sys_mix, } } } @@ -5641,11 +5899,11 @@ impl TryFrom for DspStateDftFunctions { } } } -impl Into for DspStateDftFunctions { - fn into(self) -> ffi::FMOD_DSP_STATE_DFT_FUNCTIONS { +impl From for ffi::FMOD_DSP_STATE_DFT_FUNCTIONS { + fn from(value: DspStateDftFunctions) -> ffi::FMOD_DSP_STATE_DFT_FUNCTIONS { ffi::FMOD_DSP_STATE_DFT_FUNCTIONS { - fftreal: self.fftreal, - inversefftreal: self.inversefftreal, + fftreal: value.fftreal, + inversefftreal: value.inversefftreal, } } } @@ -5673,15 +5931,15 @@ impl TryFrom for DspStatePanFunctions { } } } -impl Into for DspStatePanFunctions { - fn into(self) -> ffi::FMOD_DSP_STATE_PAN_FUNCTIONS { +impl From for ffi::FMOD_DSP_STATE_PAN_FUNCTIONS { + fn from(value: DspStatePanFunctions) -> ffi::FMOD_DSP_STATE_PAN_FUNCTIONS { ffi::FMOD_DSP_STATE_PAN_FUNCTIONS { - summonomatrix: self.summonomatrix, - sumstereomatrix: self.sumstereomatrix, - sumsurroundmatrix: self.sumsurroundmatrix, - summonotosurroundmatrix: self.summonotosurroundmatrix, - sumstereotosurroundmatrix: self.sumstereotosurroundmatrix, - getrolloffgain: self.getrolloffgain, + summonomatrix: value.summonomatrix, + sumstereomatrix: value.sumstereomatrix, + sumsurroundmatrix: value.sumsurroundmatrix, + summonotosurroundmatrix: value.summonotosurroundmatrix, + sumstereotosurroundmatrix: value.sumstereotosurroundmatrix, + getrolloffgain: value.getrolloffgain, } } } @@ -5721,21 +5979,21 @@ impl TryFrom for DspStateFunctions { } } } -impl Into for DspStateFunctions { - fn into(self) -> ffi::FMOD_DSP_STATE_FUNCTIONS { +impl From for ffi::FMOD_DSP_STATE_FUNCTIONS { + fn from(value: DspStateFunctions) -> ffi::FMOD_DSP_STATE_FUNCTIONS { ffi::FMOD_DSP_STATE_FUNCTIONS { - alloc: self.alloc, - realloc: self.realloc, - free: self.free, - getsamplerate: self.getsamplerate, - getblocksize: self.getblocksize, - dft: &mut self.dft.into(), - pan: &mut self.pan.into(), - getspeakermode: self.getspeakermode, - getclock: self.getclock, - getlistenerattributes: self.getlistenerattributes, - log: self.log, - getuserdata: self.getuserdata, + alloc: value.alloc, + realloc: value.realloc, + free: value.free, + getsamplerate: value.getsamplerate, + getblocksize: value.getblocksize, + dft: &mut value.dft.into(), + pan: &mut value.pan.into(), + getspeakermode: value.getspeakermode, + getclock: value.getclock, + getlistenerattributes: value.getlistenerattributes, + log: value.log, + getuserdata: value.getuserdata, } } } @@ -5767,17 +6025,17 @@ impl TryFrom for DspState { } } } -impl Into for DspState { - fn into(self) -> ffi::FMOD_DSP_STATE { +impl From for ffi::FMOD_DSP_STATE { + fn from(value: DspState) -> ffi::FMOD_DSP_STATE { ffi::FMOD_DSP_STATE { - instance: self.instance, - plugindata: self.plugindata, - channelmask: self.channelmask, - source_speakermode: self.source_speakermode.into(), - sidechaindata: self.sidechaindata.as_ptr() as *mut _, - sidechainchannels: self.sidechainchannels, - functions: &mut self.functions.into(), - systemobject: self.systemobject, + instance: value.instance, + plugindata: value.plugindata, + channelmask: value.channelmask, + source_speakermode: value.source_speakermode.into(), + sidechaindata: value.sidechaindata.as_ptr() as *mut _, + sidechainchannels: value.sidechainchannels, + functions: &mut value.functions.into(), + systemobject: value.systemobject, } } } @@ -5801,13 +6059,13 @@ impl TryFrom for DspMeteringInfo { } } } -impl Into for DspMeteringInfo { - fn into(self) -> ffi::FMOD_DSP_METERING_INFO { +impl From for ffi::FMOD_DSP_METERING_INFO { + fn from(value: DspMeteringInfo) -> ffi::FMOD_DSP_METERING_INFO { ffi::FMOD_DSP_METERING_INFO { - numsamples: self.numsamples, - peaklevel: self.peaklevel, - rmslevel: self.rmslevel, - numchannels: self.numchannels, + numsamples: value.numsamples, + peaklevel: value.peaklevel, + rmslevel: value.rmslevel, + numchannels: value.numchannels, } } } @@ -5839,17 +6097,17 @@ impl TryFrom for DspLoudnessMeterInfoTyp } } } -impl Into for DspLoudnessMeterInfoType { - fn into(self) -> ffi::FMOD_DSP_LOUDNESS_METER_INFO_TYPE { +impl From for ffi::FMOD_DSP_LOUDNESS_METER_INFO_TYPE { + fn from(value: DspLoudnessMeterInfoType) -> ffi::FMOD_DSP_LOUDNESS_METER_INFO_TYPE { ffi::FMOD_DSP_LOUDNESS_METER_INFO_TYPE { - momentaryloudness: self.momentaryloudness, - shorttermloudness: self.shorttermloudness, - integratedloudness: self.integratedloudness, - loudness10thpercentile: self.loudness_10_thpercentile, - loudness95thpercentile: self.loudness_95_thpercentile, - loudnesshistogram: self.loudnesshistogram, - maxtruepeak: self.maxtruepeak, - maxmomentaryloudness: self.maxmomentaryloudness, + momentaryloudness: value.momentaryloudness, + shorttermloudness: value.shorttermloudness, + integratedloudness: value.integratedloudness, + loudness10thpercentile: value.loudness_10_thpercentile, + loudness95thpercentile: value.loudness_95_thpercentile, + loudnesshistogram: value.loudnesshistogram, + maxtruepeak: value.maxtruepeak, + maxmomentaryloudness: value.maxmomentaryloudness, } } } @@ -5867,10 +6125,10 @@ impl TryFrom for DspLoudnessMeterWe } } } -impl Into for DspLoudnessMeterWeightingType { - fn into(self) -> ffi::FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE { +impl From for ffi::FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE { + fn from(value: DspLoudnessMeterWeightingType) -> ffi::FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE { ffi::FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE { - channelweight: self.channelweight, + channelweight: value.channelweight, } } } @@ -8739,10 +8997,11 @@ impl Sound { } pub fn get_tag(&self, name: &str, index: Option) -> Result { unsafe { + let c_name = CString::new(name)?; let mut tag = ffi::FMOD_TAG::default(); match ffi::FMOD_Sound_GetTag( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), index.unwrap_or(0), &mut tag, ) { @@ -8860,13 +9119,13 @@ impl Sound { name: Option, ) -> Result { unsafe { + let c_name = name.map(|s| CString::new(s)).transpose()?; let mut point = null_mut(); match ffi::FMOD_Sound_AddSyncPoint( self.pointer, offset, offsettype.into(), - name.map(|value| CString::new(value).map(|value| value.as_ptr())) - .unwrap_or(Ok(null_mut()))?, + c_name.as_ref().map_or(null_mut(), |s| s.as_ptr()), &mut point, ) { ffi::FMOD_OK => Ok(SyncPoint::from(point)), @@ -9676,10 +9935,8 @@ impl CommandReplay { } pub fn set_bank_path(&self, bank_path: &str) -> Result<(), Error> { unsafe { - match ffi::FMOD_Studio_CommandReplay_SetBankPath( - self.pointer, - CString::new(bank_path)?.as_ptr(), - ) { + let c_bank_path = CString::new(bank_path)?; + match ffi::FMOD_Studio_CommandReplay_SetBankPath(self.pointer, c_bank_path.as_ptr()) { ffi::FMOD_OK => Ok(()), error => Err(err_fmod!("FMOD_Studio_CommandReplay_SetBankPath", error)), } @@ -9924,10 +10181,11 @@ impl EventDescription { name: &str, ) -> Result { unsafe { + let c_name = CString::new(name)?; let mut parameter = ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION::default(); match ffi::FMOD_Studio_EventDescription_GetParameterDescriptionByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), &mut parameter, ) { ffi::FMOD_OK => Ok(ParameterDescription::try_from(parameter)?), @@ -9994,11 +10252,12 @@ impl EventDescription { size: i32, ) -> Result<(String, i32), Error> { unsafe { + let c_name = CString::new(name)?; let label = CString::from_vec_unchecked(b"".to_vec()).into_raw(); let mut retrieved = i32::default(); match ffi::FMOD_Studio_EventDescription_GetParameterLabelByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), labelindex, label, size, @@ -10077,10 +10336,11 @@ impl EventDescription { } pub fn get_user_property(&self, name: &str) -> Result { unsafe { + let c_name = CString::new(name)?; let mut property = ffi::FMOD_STUDIO_USER_PROPERTY::default(); match ffi::FMOD_Studio_EventDescription_GetUserProperty( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), &mut property, ) { ffi::FMOD_OK => Ok(UserProperty::try_from(property)?), @@ -10345,6 +10605,15 @@ impl EventInstance { } } } + pub fn get_system(&self) -> Result { + unsafe { + let mut system = null_mut(); + match ffi::FMOD_Studio_EventInstance_GetSystem(self.pointer, &mut system) { + ffi::FMOD_OK => Ok(Studio::from(system)), + error => Err(err_fmod!("FMOD_Studio_EventInstance_GetSystem", error)), + } + } + } pub fn get_volume(&self) -> Result<(f32, f32), Error> { unsafe { let mut volume = f32::default(); @@ -10583,11 +10852,12 @@ impl EventInstance { } pub fn get_parameter_by_name(&self, name: &str) -> Result<(f32, f32), Error> { unsafe { + let c_name = CString::new(name)?; let mut value = f32::default(); let mut finalvalue = f32::default(); match ffi::FMOD_Studio_EventInstance_GetParameterByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), &mut value, &mut finalvalue, ) { @@ -10606,9 +10876,10 @@ impl EventInstance { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_name = CString::new(name)?; match ffi::FMOD_Studio_EventInstance_SetParameterByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), value, from_bool!(ignoreseekspeed), ) { @@ -10627,10 +10898,12 @@ impl EventInstance { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_name = CString::new(name)?; + let c_label = CString::new(label)?; match ffi::FMOD_Studio_EventInstance_SetParameterByNameWithLabel( self.pointer, - CString::new(name)?.as_ptr(), - CString::new(label)?.as_ptr(), + c_name.as_ptr(), + c_label.as_ptr(), from_bool!(ignoreseekspeed), ) { ffi::FMOD_OK => Ok(()), @@ -10687,10 +10960,11 @@ impl EventInstance { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_label = CString::new(label)?; match ffi::FMOD_Studio_EventInstance_SetParameterByIDWithLabel( self.pointer, id.into(), - CString::new(label)?.as_ptr(), + c_label.as_ptr(), from_bool!(ignoreseekspeed), ) { ffi::FMOD_OK => Ok(()), @@ -10880,12 +11154,10 @@ impl Studio { } pub fn get_event(&self, path_or_id: &str) -> Result { unsafe { + let c_path_or_id = CString::new(path_or_id)?; let mut event = null_mut(); - match ffi::FMOD_Studio_System_GetEvent( - self.pointer, - CString::new(path_or_id)?.as_ptr(), - &mut event, - ) { + match ffi::FMOD_Studio_System_GetEvent(self.pointer, c_path_or_id.as_ptr(), &mut event) + { ffi::FMOD_OK => Ok(EventDescription::from(event)), error => Err(err_fmod!("FMOD_Studio_System_GetEvent", error)), } @@ -10893,12 +11165,9 @@ impl Studio { } pub fn get_bus(&self, path_or_id: &str) -> Result { unsafe { + let c_path_or_id = CString::new(path_or_id)?; let mut bus = null_mut(); - match ffi::FMOD_Studio_System_GetBus( - self.pointer, - CString::new(path_or_id)?.as_ptr(), - &mut bus, - ) { + match ffi::FMOD_Studio_System_GetBus(self.pointer, c_path_or_id.as_ptr(), &mut bus) { ffi::FMOD_OK => Ok(Bus::from(bus)), error => Err(err_fmod!("FMOD_Studio_System_GetBus", error)), } @@ -10906,12 +11175,9 @@ impl Studio { } pub fn get_vca(&self, path_or_id: &str) -> Result { unsafe { + let c_path_or_id = CString::new(path_or_id)?; let mut vca = null_mut(); - match ffi::FMOD_Studio_System_GetVCA( - self.pointer, - CString::new(path_or_id)?.as_ptr(), - &mut vca, - ) { + match ffi::FMOD_Studio_System_GetVCA(self.pointer, c_path_or_id.as_ptr(), &mut vca) { ffi::FMOD_OK => Ok(Vca::from(vca)), error => Err(err_fmod!("FMOD_Studio_System_GetVCA", error)), } @@ -10919,12 +11185,9 @@ impl Studio { } pub fn get_bank(&self, path_or_id: &str) -> Result { unsafe { + let c_path_or_id = CString::new(path_or_id)?; let mut bank = null_mut(); - match ffi::FMOD_Studio_System_GetBank( - self.pointer, - CString::new(path_or_id)?.as_ptr(), - &mut bank, - ) { + match ffi::FMOD_Studio_System_GetBank(self.pointer, c_path_or_id.as_ptr(), &mut bank) { ffi::FMOD_OK => Ok(Bank::from(bank)), error => Err(err_fmod!("FMOD_Studio_System_GetBank", error)), } @@ -10968,12 +11231,9 @@ impl Studio { } pub fn get_sound_info(&self, key: &str) -> Result { unsafe { + let c_key = CString::new(key)?; let mut info = ffi::FMOD_STUDIO_SOUND_INFO::default(); - match ffi::FMOD_Studio_System_GetSoundInfo( - self.pointer, - CString::new(key)?.as_ptr(), - &mut info, - ) { + match ffi::FMOD_Studio_System_GetSoundInfo(self.pointer, c_key.as_ptr(), &mut info) { ffi::FMOD_OK => Ok(SoundInfo::try_from(info)?), error => Err(err_fmod!("FMOD_Studio_System_GetSoundInfo", error)), } @@ -10984,10 +11244,11 @@ impl Studio { name: &str, ) -> Result { unsafe { + let c_name = CString::new(name)?; let mut parameter = ffi::FMOD_STUDIO_PARAMETER_DESCRIPTION::default(); match ffi::FMOD_Studio_System_GetParameterDescriptionByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), &mut parameter, ) { ffi::FMOD_OK => Ok(ParameterDescription::try_from(parameter)?), @@ -11024,11 +11285,12 @@ impl Studio { size: i32, ) -> Result<(String, i32), Error> { unsafe { + let c_name = CString::new(name)?; let label = CString::from_vec_unchecked(b"".to_vec()).into_raw(); let mut retrieved = i32::default(); match ffi::FMOD_Studio_System_GetParameterLabelByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), labelindex, label, size, @@ -11114,10 +11376,11 @@ impl Studio { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_label = CString::new(label)?; match ffi::FMOD_Studio_System_SetParameterByIDWithLabel( self.pointer, id.into(), - CString::new(label)?.as_ptr(), + c_label.as_ptr(), from_bool!(ignoreseekspeed), ) { ffi::FMOD_OK => Ok(()), @@ -11150,11 +11413,12 @@ impl Studio { } pub fn get_parameter_by_name(&self, name: &str) -> Result<(f32, f32), Error> { unsafe { + let c_name = CString::new(name)?; let mut value = f32::default(); let mut finalvalue = f32::default(); match ffi::FMOD_Studio_System_GetParameterByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), &mut value, &mut finalvalue, ) { @@ -11170,9 +11434,10 @@ impl Studio { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_name = CString::new(name)?; match ffi::FMOD_Studio_System_SetParameterByName( self.pointer, - CString::new(name)?.as_ptr(), + c_name.as_ptr(), value, from_bool!(ignoreseekspeed), ) { @@ -11188,10 +11453,12 @@ impl Studio { ignoreseekspeed: bool, ) -> Result<(), Error> { unsafe { + let c_name = CString::new(name)?; + let c_label = CString::new(label)?; match ffi::FMOD_Studio_System_SetParameterByNameWithLabel( self.pointer, - CString::new(name)?.as_ptr(), - CString::new(label)?.as_ptr(), + c_name.as_ptr(), + c_label.as_ptr(), from_bool!(ignoreseekspeed), ) { ffi::FMOD_OK => Ok(()), @@ -11204,12 +11471,9 @@ impl Studio { } pub fn lookup_id(&self, path: &str) -> Result { unsafe { + let c_path = CString::new(path)?; let mut id = ffi::FMOD_GUID::default(); - match ffi::FMOD_Studio_System_LookupID( - self.pointer, - CString::new(path)?.as_ptr(), - &mut id, - ) { + match ffi::FMOD_Studio_System_LookupID(self.pointer, c_path.as_ptr(), &mut id) { ffi::FMOD_OK => Ok(Guid::try_from(id)?), error => Err(err_fmod!("FMOD_Studio_System_LookupID", error)), } @@ -11325,10 +11589,11 @@ impl Studio { flags: impl Into, ) -> Result { unsafe { + let c_filename = CString::new(filename)?; let mut bank = null_mut(); match ffi::FMOD_Studio_System_LoadBankFile( self.pointer, - CString::new(filename)?.as_ptr(), + c_filename.as_ptr(), flags.into(), &mut bank, ) { @@ -11385,10 +11650,8 @@ impl Studio { } pub fn unregister_plugin(&self, name: &str) -> Result<(), Error> { unsafe { - match ffi::FMOD_Studio_System_UnregisterPlugin( - self.pointer, - CString::new(name)?.as_ptr(), - ) { + let c_name = CString::new(name)?; + match ffi::FMOD_Studio_System_UnregisterPlugin(self.pointer, c_name.as_ptr()) { ffi::FMOD_OK => Ok(()), error => Err(err_fmod!("FMOD_Studio_System_UnregisterPlugin", error)), } @@ -11424,9 +11687,10 @@ impl Studio { flags: impl Into, ) -> Result<(), Error> { unsafe { + let c_filename = CString::new(filename)?; match ffi::FMOD_Studio_System_StartCommandCapture( self.pointer, - CString::new(filename)?.as_ptr(), + c_filename.as_ptr(), flags.into(), ) { ffi::FMOD_OK => Ok(()), @@ -11448,10 +11712,11 @@ impl Studio { flags: impl Into, ) -> Result { unsafe { + let c_filename = CString::new(filename)?; let mut replay = null_mut(); match ffi::FMOD_Studio_System_LoadCommandReplay( self.pointer, - CString::new(filename)?.as_ptr(), + c_filename.as_ptr(), flags.into(), &mut replay, ) { @@ -11938,7 +12203,8 @@ impl System { } pub fn set_plugin_path(&self, path: &str) -> Result<(), Error> { unsafe { - match ffi::FMOD_System_SetPluginPath(self.pointer, CString::new(path)?.as_ptr()) { + let c_path = CString::new(path)?; + match ffi::FMOD_System_SetPluginPath(self.pointer, c_path.as_ptr()) { ffi::FMOD_OK => Ok(()), error => Err(err_fmod!("FMOD_System_SetPluginPath", error)), } @@ -11946,10 +12212,11 @@ impl System { } pub fn load_plugin(&self, filename: &str, priority: Option) -> Result { unsafe { + let c_filename = CString::new(filename)?; let mut handle = u32::default(); match ffi::FMOD_System_LoadPlugin( self.pointer, - CString::new(filename)?.as_ptr(), + c_filename.as_ptr(), &mut handle, priority.unwrap_or(0), ) { @@ -12377,11 +12644,12 @@ impl System { } } } - pub fn get_version(&self) -> Result { + pub fn get_version(&self) -> Result<(u32, u32), Error> { unsafe { let mut version = u32::default(); - match ffi::FMOD_System_GetVersion(self.pointer, &mut version) { - ffi::FMOD_OK => Ok(version), + let mut buildnumber = 0u32; + match ffi::FMOD_System_GetVersion(self.pointer, &mut version, &mut buildnumber) { + ffi::FMOD_OK => Ok((version, buildnumber)), error => Err(err_fmod!("FMOD_System_GetVersion", error)), } } @@ -12536,13 +12804,23 @@ impl System { } } } + pub fn create_dsp_connection(&self, type_: DspConnectionType) -> Result { + unsafe { + let mut connection = null_mut(); + match ffi::FMOD_System_CreateDSPConnection(self.pointer, type_.into(), &mut connection) + { + ffi::FMOD_OK => Ok(DspConnection::from(connection)), + error => Err(err_fmod!("FMOD_System_CreateDSPConnection", error)), + } + } + } pub fn create_channel_group(&self, name: Option) -> Result { unsafe { + let c_name = name.map(|s| CString::new(s)).transpose()?; let mut channelgroup = null_mut(); match ffi::FMOD_System_CreateChannelGroup( self.pointer, - name.map(|value| CString::new(value).map(|value| value.as_ptr())) - .unwrap_or(Ok(null_mut()))?, + c_name.as_ref().map_or(null_mut(), |s| s.as_ptr()), &mut channelgroup, ) { ffi::FMOD_OK => Ok(ChannelGroup::from(channelgroup)), @@ -12552,12 +12830,10 @@ impl System { } pub fn create_sound_group(&self, name: &str) -> Result { unsafe { + let c_name = CString::new(name)?; let mut soundgroup = null_mut(); - match ffi::FMOD_System_CreateSoundGroup( - self.pointer, - CString::new(name)?.as_ptr(), - &mut soundgroup, - ) { + match ffi::FMOD_System_CreateSoundGroup(self.pointer, c_name.as_ptr(), &mut soundgroup) + { ffi::FMOD_OK => Ok(SoundGroup::from(soundgroup)), error => Err(err_fmod!("FMOD_System_CreateSoundGroup", error)), } @@ -12872,7 +13148,8 @@ impl System { } pub fn set_network_proxy(&self, proxy: &str) -> Result<(), Error> { unsafe { - match ffi::FMOD_System_SetNetworkProxy(self.pointer, CString::new(proxy)?.as_ptr()) { + let c_proxy = CString::new(proxy)?; + match ffi::FMOD_System_SetNetworkProxy(self.pointer, c_proxy.as_ptr()) { ffi::FMOD_OK => Ok(()), error => Err(err_fmod!("FMOD_System_SetNetworkProxy", error)), } diff --git a/libfmod/tests/init_test.rs b/libfmod/tests/init_test.rs new file mode 100644 index 0000000..b315933 --- /dev/null +++ b/libfmod/tests/init_test.rs @@ -0,0 +1,25 @@ +// Phase 3.3: Test System Initialization for FMOD 2.03.09 + +use libfmod::{Init, System}; + +#[test] +fn test_system_init() { + let system = System::create().unwrap(); + let result = system.init(512, Init::NORMAL, None); + + assert!(result.is_ok(), "Init failed: {:?}", result); + println!("✓ System initialized with 512 channels"); + + system.release().ok(); +} + +#[test] +fn test_minimal_init() { + let system = System::create().unwrap(); + let result = system.init(32, Init::NORMAL, None); // Minimal channels + + assert!(result.is_ok(), "Minimal init failed: {:?}", result); + println!("✓ Minimal system works"); + + system.release().ok(); +} diff --git a/libfmod/tests/manual/getting_started.rs b/libfmod/tests/manual/getting_started.rs index 75e2a54..a9e004a 100644 --- a/libfmod/tests/manual/getting_started.rs +++ b/libfmod/tests/manual/getting_started.rs @@ -6,7 +6,7 @@ use libfmod::ffi::{ FMOD_SYSTEM_CALLBACK_PREUPDATE, }; use libfmod::{ - ffi, AdvancedSettings, CreateSoundexInfo, DspResampler, Error, Mode, OpenState, Sound, Studio, + ffi, AdvancedSettings, CreateSoundexInfo, DspResampler, Error, Mode, OpenState, Studio, StudioAdvancedSettings, System, }; @@ -26,7 +26,7 @@ fn test_core_system_advanced_settings() -> Result<(), Error> { max_vorbis_codecs: 32, max_at_9_codecs: 32, max_fadpcm_codecs: 32, - max_pcm_codecs: 0, + max_opus_codecs: 32, asio_num_channels: 0, asio_channel_list: vec![], asio_speaker_list: vec![], @@ -40,7 +40,7 @@ fn test_core_system_advanced_settings() -> Result<(), Error> { resampler_method: DspResampler::Spline, random_seed: 0, max_convolution_threads: 3, - max_opus_codecs: 32, + max_spatial_objects: 0, }; system.set_advanced_settings(settings)?; let settings = system.get_advanced_settings()?; diff --git a/libfmod/tests/system_test.rs b/libfmod/tests/system_test.rs new file mode 100644 index 0000000..d4f6a0a --- /dev/null +++ b/libfmod/tests/system_test.rs @@ -0,0 +1,18 @@ +// Phase 3.1: Test System Creation for FMOD 2.03.09 + +use libfmod::System; + +#[test] +fn test_system_create() { + let system = System::create(); + assert!(system.is_ok(), "System creation failed: {:?}", system); + println!("✓ System created successfully"); +} + +#[test] +fn test_system_create_and_release() { + let system = System::create().unwrap(); + let result = system.release(); + assert!(result.is_ok(), "System release failed: {:?}", result); + println!("✓ System lifecycle works"); +} diff --git a/libfmod/tests/version_test.rs b/libfmod/tests/version_test.rs new file mode 100644 index 0000000..fb7398c --- /dev/null +++ b/libfmod/tests/version_test.rs @@ -0,0 +1,27 @@ +// Phase 3.2: Test Version API for FMOD 2.03.09 + +use libfmod::System; + +#[test] +fn test_get_version_new_api() { + let system = System::create().unwrap(); + let result = system.get_version(); + + assert!(result.is_ok(), "get_version failed: {:?}", result); + + let (version, build) = result.unwrap(); + println!("FMOD version: 0x{:08x}, build: {}", version, build); + + // Verify we got 2.03.x + let major = (version >> 16) & 0xFF; + let minor = (version >> 8) & 0xFF; + let patch = version & 0xFF; + + assert_eq!(major, 2, "Expected major version 2, got {}", major); + assert_eq!(minor, 3, "Expected minor version 3, got {}", minor); + + println!( + "✓ Version API works: {}.{}.{} (build {})", + major, minor, patch, build + ); +} diff --git a/setup_fmod_2.03.09.sh b/setup_fmod_2.03.09.sh new file mode 100755 index 0000000..1abfd2b --- /dev/null +++ b/setup_fmod_2.03.09.sh @@ -0,0 +1,115 @@ +#!/bin/bash + +# FMOD 2.03.09 Setup Script +# This script helps set up the FMOD SDK for the libfmod migration + +echo "=== FMOD 2.03.09 Setup Script ===" +echo + +# Check if we're in the right directory +if [ ! -f "libfmod-gen/Cargo.toml" ]; then + echo "Error: Please run this script from the libfmod root directory" + exit 1 +fi + +# Create fmod directory if it doesn't exist +mkdir -p libfmod-gen/fmod + +echo "IMPORTANT: FMOD SDK requires manual download from https://www.fmod.com" +echo "Please follow these steps:" +echo +echo "1. Go to https://www.fmod.com/download" +echo "2. Register/login to your FMOD account" +echo "3. Download 'FMOD Engine' version 2.03.09 for Linux" +echo " File: fmodstudioapi20309linux.tar.gz" +echo "4. Place the downloaded file in: $(pwd)/libfmod-gen/fmod/" +echo +echo "Press Enter when you've placed the file there..." +read + +# Check if the file exists +FMOD_ARCHIVE="libfmod-gen/fmod/fmodstudioapi20309linux.tar.gz" +if [ ! -f "$FMOD_ARCHIVE" ]; then + echo "Error: File not found: $FMOD_ARCHIVE" + echo "Please download and place the file there first." + exit 1 +fi + +echo "Found FMOD archive. Extracting..." +cd libfmod-gen/fmod +tar -xzf fmodstudioapi20309linux.tar.gz +mv fmodstudioapi20309linux 20309 +cd ../.. + +echo +echo "Verifying installation..." +echo + +# Phase 1 TEST 1.1: Verify FMOD Installation +FMOD_SDK_PATH="$(pwd)/libfmod-gen/fmod/20309" +export FMOD_SDK_PATH + +echo "📝 TEST 1.1: Verify FMOD Installation" +echo "----------------------------------------" + +# Check headers exist +echo -n "Checking core header... " +if [ -f "$FMOD_SDK_PATH/api/core/inc/fmod.h" ]; then + echo "✓" +else + echo "✗ Missing" + exit 1 +fi + +echo -n "Checking studio header... " +if [ -f "$FMOD_SDK_PATH/api/studio/inc/fmod_studio.h" ]; then + echo "✓" +else + echo "✗ Missing" + exit 1 +fi + +# Verify version in header +echo -n "Checking FMOD version... " +VERSION=$(grep "#define FMOD_VERSION" "$FMOD_SDK_PATH/api/core/inc/fmod.h" | awk '{print $3}') +if [ "$VERSION" = "0x00020309" ]; then + echo "✓ Version: $VERSION (2.03.09)" +else + echo "✗ Unexpected version: $VERSION" + echo " Expected: 0x00020309" + exit 1 +fi + +# Check libraries +echo -n "Checking libraries... " +if [ -f "$FMOD_SDK_PATH/api/core/lib/x86_64/libfmod.so" ] && \ + [ -f "$FMOD_SDK_PATH/api/core/lib/x86_64/libfmodL.so" ]; then + echo "✓" +else + echo "✗ Missing libraries" + exit 1 +fi + +# Test library loading +echo -n "Testing library dependencies... " +LDD_OUTPUT=$(ldd "$FMOD_SDK_PATH/api/core/lib/x86_64/libfmod.so" 2>&1) +if echo "$LDD_OUTPUT" | grep -q "not found"; then + echo "✗ Missing dependencies:" + echo "$LDD_OUTPUT" | grep "not found" + exit 1 +else + echo "✓" +fi + +echo +echo "=========================================" +echo "✅ FMOD 2.03.09 SDK setup complete!" +echo "=========================================" +echo +echo "SDK Path: $FMOD_SDK_PATH" +echo +echo "To use in your shell session:" +echo " export FMOD_SDK_PATH=\"$FMOD_SDK_PATH\"" +echo " export LD_LIBRARY_PATH=\"\$FMOD_SDK_PATH/api/core/lib/x86_64:\$LD_LIBRARY_PATH\"" +echo +echo "Next step: Run Phase 2 - Fix libfmod-gen breaking changes" \ No newline at end of file