Custom FMOD objects
| Using playback and capture modes and devices |

### Custom FMOD objects

#### Using custom FMOD system objects

Instead of using the standard Client Lib functions `ts3client_openPlaybackDevice`, `ts3client_openCaptureDevice` and `ts3client_activateCaptureDevice` it is possible to supply a `FMOD::System` object of your own that is then used by the TeamSpeak 3 SDK. This allows you to integrate your existing FMOD solution for your application with the FMOD solution used by TeamSpeak 3, or even if you don't use FMOD in your application you can use this functionality if you want more control over the way the `FMOD::System` objects are used.

By managing the `FMOD::System` objects yourself and by using the later described `onFMODChannelCreatedEvent` callback you will be able to use advanced FMOD functionality that the TeamSpeak 3 client SDK does not use and does not expose to be used through the `clientlib.h` API, for example custom DSP effects or modelling the 3D world.

| Note
Using custom FMOD objects is entirely optional.

The function to open a playback device using a custom `FMOD::System` object is an alternative to `ts3client_openPlaybackDevice`:

`unsigned int ts3client_openCustomPlaybackDevice(` | serverConnectionHandlerID, |
| fmodSystem`)`; |

`anyID serverConnectionHandlerID`;
`void* fmodSystem`;

The function to open a capture device using a custom `FMOD::System` object is an alternative to `ts3client_openCaptureDevice`:

`unsigned int ts3client_openCustomCaptureDevice(` | serverConnectionHandlerID, |
| fmodSystem, |
| fmodDriverID`)`; |

`anyID serverConnectionHandlerID`;
`void* fmodSystem`;
`int fmodDriverID`;

The function to activate the capture device using a custom `FMOD::System` object is an alternative to `ts3client_activateCaptureDevice`:

`unsigned int ts3client_activateCustomCaptureDevice(` | serverConnectionHandlerID, |
| fmodSystem, |
| fmodDriverID`)`; |

`anyID serverConnectionHandlerID`;
`void* fmodSystem`;
`int fmodDriverID`;

Parameters

- `serverConnectionHandlerID`

  Connection handler of the server on which you want to initialize or activate the device.

- `fmodSystem`

  A `FMOD::System` object created and customized by your code, as shown in the following examples.

  If you use the FMOD C API, you can pass a `FMOD_SYSTEM*` object instead of `FMOD::System*`, as the two are interchangable.

- `fmodDriverID`

  Enumerated FMOD driver ID, see the FMOD documentation for details.

All functions return `ERROR_ok` on success, otherwise an error code as defined in `public_errors.h`.

| Note
The TeamSpeak 3 SDK uses `void*` pointers to avoid the dependency on FMOD, as custom FMOD objects is an optional feature.

Simple example how to create a `FMOD::System` object for opening a capture device:

    FMOD::System* pFMODSystem = NULL;
    FMOD_RESULT result;

    result = FMOD::System_Create(&pFMODSystem);
    if(result != FMOD_OK) {
        cout << "System_Create: " << FMOD_ErrorString(result) << endl;
        return;
    }

    result= pFMODSystem->setOutput(static_cast<FMOD_OUTPUTTYPE>(modeID));
    if(result != FMOD_OK) {
        cout << "setOutput failed (modeID: " << modeID << "): " << FMOD_ErrorString(result) << endl;
        return;
    }

    result = pFMODSystem->init(32, FMOD_INIT_NORMAL, NULL);
    if(result != FMOD_OK) {
        cout << "init: " << FMOD_ErrorString(result) << endl;
        return;
    }

Simple example how to create a `FMOD::System` object for opening a playback device:

    FMOD::System* system = NULL;
    FMOD_RESULT result;

    result = FMOD::System_Create(&system);
    if(result != FMOD_OK) {
        cout << "System_Create: " << FMOD_ErrorString(result) << endl;
        return false;
    }

    result= system->setOutput(static_cast<FMOD_OUTPUTTYPE>(modeID));
    if(result != FMOD_OK) {
        cout << "setOutput failed (modeID: " << modeID << "): " << FMOD_ErrorString(result) << endl;
        return false;
    }

    result= system->setDriver(driverID);
    if(result != FMOD_OK) {
        cout << "setDriver: " << FMOD_ErrorString(result) << endl;
        return false;
    }

    result = system->init(1000, FMOD_INIT_NORMAL, NULL);
    if(result != FMOD_OK) {
        cout << "init: " << FMOD_ErrorString(result) << endl;
        return false;
    }

See FMOD Ex Frequently Asked Questions for the recommended way to initialize the output device and the FMOD API documentation for further details.

When the TeamSpeak 3 SDK is using a passed-in `FMOD::System` object, it will not call `close()` or `release()` on the `FMOD::System` object when finished with it, but rather notify the SDK user via a callback that the SDK has finished using the object. You can either call `release()` on the `FMOD::System` object or - if you are still using it in your own application - do nothing.

When closing a capture device, which has been previously opened using `ts3client_openCustomCaptureDevice`, the following callback allows to clean-up the custom `FMOD::System` object if desired:

`void onCustomCaptureDeviceCloseEvent(` | serverConnectionHandlerID, |
| fmodSystem`)`; |

`anyID serverConnectionHandlerID`;
`void* fmodSystem`;

When closing a playback device, which has been previously opened using `ts3client_openCustomPlaybackDevice`, the following callback allows to clean-up the custom `FMOD::System` object if desired:

`void onCustomPlaybackDeviceCloseEvent(` | serverConnectionHandlerID, |
| fmodSystem`)`; |

`anyID serverConnectionHandlerID`;
`void* fmodSystem`;

| Note
Note that you still use the standard ts3client_closePlaybackDevice and ts3client_closeCaptureDevice function to close devices opened using `ts3client_openCustomCaptureDevice` and `ts3client_openCustomPlaybackDevice`.

#### Customizing FMOD channel objects

FMOD channels are created by the Client Lib whenever a user starts talking. By implementing the following callback, additional settings can be applied to the `FMOD::Channel` object.

| Note
The `onFMODChannelCreatedEvent` callback is always called, no matter if devices were opened with the standard or custom functions. This allows to apply additional settings to FMOD Channels even if the custom FMOD System objects mechanism is not used. If you do not need this callback, just set the function pointer to `NULL` in the ClientUIFunctions parameter for `ts3client_initClientLib`.

The order of operations when a client starts talking is:

- FMOD channel is created in a paused state.

- Client Lib sets standard options on the `FMOD::Channel` object, like 3D sound settings as set with `ts3client_fmod_Channelset3DAttributes`.

- `onFMODChannelCreatedEvent` is called and allows you to apply additional settings on the `FMOD::Channel` object, or to even overwrite the default settings that were made in the previous step.

- The FMOD channel is unpaused and the client starts talking.

`void onFMODChannelCreatedEvent(` | serverConnectionHandlerID, |
| clientID, |
| fmodChannel`)`; |

`anyID serverConnectionHandlerID`;
`anyID clientID`;
`void* fmodChannel`;

Parameters

- `serverConnectionHandlerID`

  Connection handler of the server on which the FMOD channel is created.

- `clientID`

  ID of the client who starts talking.

- `fmodChannel`

  A `FMOD::Channel` object on which additional settings can be applied.

  If you use the FMOD C API, cast the `void* fmodChannel` object to `FMOD_CHANNEL*` instead of `FMOD::Channel*`, as the two are interchangable.

The callback should return quickly to avoid delaying unpausing the FMOD channel.

#### Querying the current FMOD System objects

The currently used FMOD System playback and capture objects - may it be a standard or custom object - can be queried from the clientlib if you want to use them for own FMOD operations like for example playing wave files.

Request the current playback device with:

`unsigned int ts3client_getCurrentPlaybackDevice(` | serverConnectionHandlerID, |
| fmodSystemResult`)`; |

`anyID serverConnectionHandlerID`;
`void** fmodSystemResult`;

Request the current capture device with:

`unsigned int ts3client_getCurrentCaptureDevice(` | serverConnectionHandlerID, |
| fmodSystemResult`)`; |

`anyID serverConnectionHandlerID`;
`void** fmodSystemResult`;

Parameters

- `serverConnectionHandlerID`

  ID of the server connection handler on which the FMOD system devices should be queried.

- `serverConnectionHandlerID`

  Address of a variable that receives the requested FMOD System object.

Returns `ERROR_ok` on success, otherwise an error code as defined in `public_errors.h`. If the function fails, `fmodSystemResult` is undefined.

Activating the capture device |  | Sound codecs