General

To help you avoid common pitfalls during integration, it is recommended that you read about handling changes, exceptions, and the initial state.

Disconnects

When setting up Easy Call Control, you must know how to handle disconnection cases. For example, when a user physically unplugs the device.

To listen for disconnect events, ensure you setup a subscription. The code depends on your chosen initialization of the Easy Call Control module.

Option A) Initialized with Single Call

// This sample is pseudo-code. You have to initialize Easy Call Control with Single Call before you subscribe.
singleCallControl.OnDisconnect.Subscribe(
    _ =>
    {
        // this callback is triggered if the device disconnects
    });

Option B) Inititalized with Multiple Call

// This sample is pseudo-code. You have to initialize Easy Call Control with Multiple Call before you subscribe.
multiCallControl.OnDisconnect.Subscribe(
    _ =>
    {
        // this callback is triggered if the device disconnects
    });

When a device is disconnected, the IMultiCallControl or ISingleCallControl instances become invalid and can no longer be used.

To continue using Easy Call Control on a new device, you must create a new instance of either IMultiCallControl or ISingleCallControl.

De-initialize with Teardown

You can use the Teardown method whenever you want to deactivate a IMultiCallControl or ISingleCallControl instance.

The method removes internal event subscriptions to avoid memory leaks and, if taken, clear the internal call lock. The most common use case is when you are handling a change of device.

If you create a single-page web application or work on a similar project with a persistent state, you must call Teardown whenever the IMultiCallControl or ISingleCallControl instance is no longer needed.

For example, when changing views in the UI.

Failure to do so can cause undesirable behavior and memory leaks.

Initial state

If a device is disconnected -- or the user decides to change devices in the middle of a call, you must recover the device state when instantiating a new one.

You can set an initial state from the easyCallControlFactory.CreateMultiCallControl and easyCallControlFactory.CreateSingleCallControl methods, which take an optional second argument containing the initial state. The following is an example for IMultiCallControl.

if (easyCallControlFactory.SupportsEasyCallControl(device))
{
    MultiInitialState initialState = new MultiInitialState
    (
        ongoingCalls: 2,
        isMuted: true,
        isOnHold: false
    );
    IMultiCallControl multiCallControl = await easyCallControlFactory.CreateMultiCallControl(device, initialState);

    // The device will have two ongoing calls and be muted at startup
}

And for ISingleCallControl.

if (easyCallControlFactory.SupportsEasyCallControl(device))
{
    SingleInitialState initialState = new SingleInitialState
    (
        callActive: true,
        isMuted: true
    );
    ISingleCallControl singleCallControl = await easyCallControlFactory.CreateSingleCallControl(device, initialState);

    // The device will be in a call and be muted at startup
}

Changing Devices

If the user wants to select another device, you must first Teardown the old IMultiCallControl or ISingleCallControl instance before creating a new one.

The following is a pseudo-code example of how that might look:

MultiInitialState yourAppState = new MultiInitialState
{
    OngoingCalls = 2,
    IsMuted = true,
    IsOnHold = false
};

IDevice newDevice; // The device selected by the user in your GUI

// Teardown old instance
// This will clear internal call locking and event subscriptions to avoid leaks
oldMultiCallControl.Teardown();

// Set initial state for the new device
MultiInitialState initialState = new MultiInitialState
{
    OngoingCalls = yourAppState.OngoingCalls,
    IsMuted = yourAppState.IsMuted,
    IsOnHold = yourAppState.IsOnHold
};

// Create new instance
IMultiCallControl newMultiCallControl = await easyCallControlFactory.CreateMultiCallControl(
    newDevice,
    initialState
);

// Now, you can continue your program using newMultiCallControl

Exceptions

In certain scenarios, the module can throw an exception. For example, if a Jabra device is being used for a call by another application running on the computer, an exception will be thrown if your application tries to make a call from the same device.

Most of the exceptions are not strictly avoidable and can happen due to the current state of the device.

For this reason, it is recommended that you have a strategy for handling potential exceptions from every method in the ISingleCallControl or IMultiCallControl class that has potential exceptions listed.