toggleSpeaker method

Future<void> toggleSpeaker()

Toggles between the speakerphone, earpiece and headphones output.

Implementation

Future<void> toggleSpeaker() async {
  if (PlatformUtils.isMobile) {
    keepUi();
  }

  final List<DeviceDetails> outputs = _currentCall.value.devices
      .output()
      .where((e) => e.id() != 'default' && e.deviceId() != 'default')
      .toList();

  // If there are more than 2 outputs (earpiece and speakerphone), then show
  // the audio output picker for iOS and Android.
  if (!PlatformUtils.isWeb) {
    if (outputs.length > 2) {
      if (PlatformUtils.isIOS) {
        await _audioRouter.showAudioRoutePicker(router.context!);
        return;
      }

      if (PlatformUtils.isAndroid) {
        await OutputRouteView.show(
          router.context!,
          initial: _currentCall.value.outputDevice.value,
          onSelected: (d) async {
            await _currentCall.value.setOutputDevice(d);
          },
        );

        return;
      }
    }
  }

  if (outputs.length > 1) {
    int index = outputs.indexWhere(
      (e) => e == _currentCall.value.outputDevice.value,
    );

    if (PlatformUtils.isMobile) {
      final int previous = index;

      index = outputs.indexWhere(
        (e) => e.speaker == AudioUtils.speaker.value,
      );

      if (index == -1) {
        index = previous;
      }
    }

    if (index == -1) {
      index = 0;
    }

    ++index;
    if (index >= outputs.length) {
      index = 0;
    }

    // iOS doesn't allow to use ear-piece, when there're any Bluetooth
    // devices connected.
    if (PlatformUtils.isIOS) {
      if (outputs.any((e) => e.speaker == AudioSpeakerKind.headphones)) {
        if (outputs[index].speaker == AudioSpeakerKind.earpiece) {
          ++index;
          if (index >= outputs.length) {
            index = 0;
          }
        }
      }
    }

    await _currentCall.value.setOutputDevice(outputs[index], force: true);
  }
}