Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
09dc708
feat: migrate libfmod to FMOD 2.03.09
utgarda Sep 25, 2025
e5b1983
test: add comprehensive FMOD Studio feature tests
utgarda Sep 25, 2025
3f4acc6
feat: add interactive test harness and FMOD setup manual #1
utgarda Sep 25, 2025
78dbdfb
chore: add macOS runner script for FMOD examples and update .gitignore
Maweill Sep 26, 2025
8e237f2
fix: interactive harness UI and event handling
utgarda Sep 27, 2025
340f00a
fix: resolve memory safety dangling pointer warnings in AdvancedSetti…
utgarda Oct 2, 2025
863405c
fix: use Box::leak to prevent dangling pointers in FFI code
utgarda Oct 29, 2025
14be873
fix: correct get_version return type to (u32, u32) and add max_spatia…
utgarda Oct 29, 2025
e41fc1c
chore: ignore .cargo directory
utgarda Oct 29, 2025
3acd861
fix: resolve CString dangling pointer UB in generator for all string …
utgarda Oct 31, 2025
7bf6362
refactor: address PR #23 review feedback - remove bash scripts, demos…
utgarda Nov 1, 2025
3952a8d
docs: update README to reference separate libfmod-demos repository ht…
utgarda Nov 1, 2025
1eb639a
chore: run cargo fmt on generator and examples
utgarda Nov 1, 2025
3aba9b5
fix: remove unused imports in test files
utgarda Nov 1, 2025
d18c144
docs: add test.sh helper script and update README with FMOD SDK setup…
utgarda Nov 3, 2025
94bf3e1
fix: handle variadic macros with ##__VA_ARGS__ in parser grammar, rem…
utgarda Nov 6, 2025
a217341
chore: remove demo examples and helper scripts moved to libfmod-demos…
utgarda Nov 6, 2025
4a46702
docs: update CHANGELOG for FMOD 2.03.09 and clarify patching system #23
utgarda Nov 6, 2025
2461993
docs: add pest grammar macro handling context for FMOD 2.03.09 #23
utgarda Nov 7, 2025
c2d38f7
fix: use From over Into per clippy::from_over_into #23
utgarda Nov 7, 2025
28e34e6
chore: suppress clippy::unnecessary_cast in generated FFI code #23
utgarda Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.idea
.DS_Store
FMOD\ Programmers\ API/
.fmod203/
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
125 changes: 125 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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`
52 changes: 48 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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.
Expand Down
120 changes: 120 additions & 0 deletions RUN_FMOD_2.03.md
Original file line number Diff line number Diff line change
@@ -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
```
Loading