---
title: Contribute
description: Learn how to contribute to flutter_soloud
showPageImage: true
---

## Contribute

To use native code, bindings from Dart to C/C++ are generated from the header file `src/bindings.h` using [package:ffigen](https://pub.dev/packages/ffigen). `src/bindings.h` is the single source of truth for the native ABI.

To regenerate Dart bindings:
1. Declare your new native C/C++ functions with `FFI_PLUGIN_EXPORT` in `src/bindings.h` and implement them in `src/bindings.cpp`.
2. Run in terminal:
   ```bash
   dart run ffigen --config ffigen.yaml
   ```
   *(On macOS if system headers are missing: `CPATH="$(xcrun --show-sdk-path)/usr/include" dart run ffigen --config ffigen.yaml`)*
3. The bindings will be automatically placed into `lib/src/bindings/flutter_soloud_ffigen.dart`.
4. Wrap and expose the generated functions in `lib/src/bindings/bindings_player_ffi.dart` and `lib/src/soloud.dart`.

#### Project structure

This plugin uses the following structure:

* `lib`: Contains the Dart API code and bindings.
* `src`: Contains the native C/C++ source code, filters, audio buffers, and SoLoud engine.
* `src/bindings.h`: The single source of truth and ffigen entry point for the native C ABI.
* `src/soloud`: Contains the SoLoud sources of the fork.
* `hook`: Contains the [Dart build hooks](https://dart.dev/tools/hooks) (`hook/build.dart`, `hook/sources.dart`, `hook/xiph.dart`) that compile native code automatically for Android, iOS, macOS, Windows, and Linux into Code Assets.
* `web`: Contains the scripts and assets for compiling and initializing the WebAssembly build on the Web platform.
* `xiph`: Contains build scripts and configuration for `ogg`, `opus`, `vorbis`, and `flac`. Official precompiled binaries are hosted in the [flutter_soloud_prebuilds](https://github.com/alnitak/flutter_soloud_prebuilds) repository.

The `flutter_soloud` plugin utilizes a [forked](https://github.com/alnitak/soloud) repository of [SoLoud](https://github.com/jarikomppa/soloud), where the [miniaudio](https://github.com/mackron/miniaudio) audio backend is used by default.

#### Debugging

I have provided the necessary settings in the **.vscode** directory for debugging native C++ code on Linux, macOS, and Windows. To debug on Android, please use *Android Studio* and open the project located in the ***example/android*** directory. On iOS, please use Xcode.

##### Logging

When debugging the package using the `example/` app, you might want to change the logging level to something more granular. For example, in `main()`:

```dart
// Capture even the finest log messages.
Logger.root.level = Level.ALL;
```


#### Audio Backends
- **Apple (macOS/iOS)**: Uses `miniaudio` with CoreAudio / AVFAudio.
- **Linux**: On Linux, `flutter_soloud` uses `miniaudio` with support for ALSA, PulseAudio, and JACK backends. By default, it prioritizes ALSA, then PulseAudio, then JACK (`LinuxAudioBackend.auto_`). You can choose or switch the backend at runtime via `SoLoud.instance.setLinuxAudioBackend(LinuxAudioBackend backend)` or by passing `linuxAudioBackend` to `SoLoud.instance.init()`.
- **Windows**: Uses `miniaudio` with WASAPI.
- **Android**: The default audio backend is `miniaudio`, which will automatically select the appropriate audio backend based on your Android version:
  - AAudio with Android 11.0 and newer.
  - OpenSL|ES for older Android versions.

#### Web

In the `web` directory, there is a `compile_wasm.sh` script that generates the `.js` and `.wasm` files for the native C code located in the `src` dir. Run it after installing *emscripten*. There is also a `compile_worker_and_init_module.sh` to compile the web worker needed by native code to communicate with Dart and the `init_soloud.dart` which initializes the WASM module. The default emscripten Module name is `Module_soloud` instead of the default `Module` to prevent some other WASM plugins from conflicting.

The generated files are already provided, but if it is needed to modify C/C++ code or the `web/worker.dart` code, the scripts must be run to reflect the changes.

The `compile_wasm.sh` script uses the `-O3` code optimization flag. To see a better errors logs, use `-O0 -g -s ASSERTIONS=1` in `compile_wasm.sh`.

---

The `AudioIsolate` [has been removed](https://github.com/alnitak/flutter_soloud/pull/89) and all the logic has been implemented natively. Events like `voice ended` are sent from C back to Dart. However, since it is not possible to call Dart from a native thread (the audio thread), a new web worker is created using the WASM `EM_ASM` directive. This allows sending the `voice ended` event back to Dart via the worker.

Here a sketch to show the step used:
![sketch](https://github.com/alnitak/flutter_soloud_docs/raw/main/img/wasmWorker.png)

**#1.** This function is called while initializing the player with `FlutterSoLoudWeb.setDartEventCallbacks()`.
It creates a Web Worker in the [WASM Module](https://emscripten.org/docs/api_reference/module.html) using the compiled `web/worker.dart`. After calling this, the WASM Module will have a new variable called `Module_soloud.wasmWorker` which will be used in Dart to receive messages.
By doing this it will be easy to use the Worker to send messages from within the CPP code.

**#2.** This function, like #1, uses [EM_ASM](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-javascript-from-native) to inline JS. This JS code uses the `Module_soloud.wasmWorker` created in #1 to send a message.

**#3.** This is the JS used and created in #1. Every messages sent by #2 are managed here and sent to #4.

**#4.** Here when the event message has been received, a new event is added to a Stream. This Stream is listened by the SoLoud API.

**#5.** Here we listen to the event messages coming from the `WorkerController` stream. Currently, only the "voice ended" event is supported. The Stream is listened in `SoLoud._initializeNativeCallbacks()`.

