init method

Future<void> init({
  1. FutureOr<RxChat?> getChat(
    1. ChatId
    )?,
})

Initializes the media client resources.

No-op if already initialized.

Implementation

Future<void> init({FutureOr<RxChat?> Function(ChatId)? getChat}) async {
  Log.debug('init()', '$runtimeType');

  if (_background) {
    _background = false;

    _devicesSubscription = MediaUtils.onDeviceChange.listen((e) async {
      Log.debug('onDeviceChange(${e.map((e) => e.label())})', '$runtimeType');

      await _devicesGuard.protect(() async {
        if (devices.isEmpty) {
          devices.value = await MediaUtils.enumerateDevices();
        }

        final List<DeviceDetails> previous = List.from(
          devices,
          growable: false,
        );

        devices.value = e;

        final List<DeviceDetails> removed = [];

        for (DeviceDetails d in previous) {
          if (devices.none((p) => p.deviceId() == d.deviceId())) {
            removed.add(d);
          }
        }

        final bool audioChanged = !previous
            .audio()
            .map((e) => e.deviceId())
            .sameAs(devices.audio().map((e) => e.deviceId()));

        final bool outputChanged = !previous
            .output()
            .map((e) => e.deviceId())
            .sameAs(devices.output().map((e) => e.deviceId()));

        final bool videoChanged = !previous
            .video()
            .map((e) => e.deviceId())
            .sameAs(devices.video().map((e) => e.deviceId()));

        if (audioChanged) {
          _pickAudioDevice();
        }

        if (outputChanged) {
          _pickOutputDevice();
        }

        if (videoChanged) {
          _pickVideoDevice(previous, removed);
        }
      });
    });

    _displaysSubscription = MediaUtils.onDisplayChange.listen((e) async {
      final List<MediaDisplayDetails> previous = List.from(
        displays,
        growable: false,
      );

      displays.value = e;

      final List<MediaDisplayDetails> removed = [];

      for (MediaDisplayDetails d in previous) {
        if (displays.none((p) => p.deviceId() == d.deviceId())) {
          removed.add(d);
        }
      }

      _pickScreenDevice(removed);
    });

    // Puts the members of the provided [chat] to the [members] through
    // [_addDialing].
    Future<void> addDialingsFrom(RxChat? chat) async {
      if (chat == null) {
        return;
      }

      final int membersCount = chat.chat.value.membersCount;
      final bool shouldAddDialed =
          (outgoing && conversationStartedAt == null) ||
          chat.chat.value.isDialog;

      // Dialed [User]s should be added, if [membersCount] is less than a page
      // of [Chat.members].
      if (membersCount <= chat.members.perPage && shouldAddDialed) {
        if (chat.members.length < membersCount) {
          await chat.members.around();
        }

        // If [connected], then the dialed [User] will be added in [connect],
        // when handling [ChatMembersDialedAll].
        if (!connected) {
          for (UserId e in chat.members.items.keys.where(
            (e) => e != me.id.userId,
          )) {
            _addDialing(e);
          }
        }
      }
    }

    // Retrieve the [RxChat] this [OngoingCall] is happening in to add its
    // members to the [members] in redialing mode as fast as possible.
    final FutureOr<RxChat?>? chatOrFuture = getChat?.call(chatId.value);
    if (chatOrFuture is RxChat?) {
      addDialingsFrom(chatOrFuture);
    } else {
      chatOrFuture.then(addDialingsFrom);
    }

    await _initRoom();
    await _setInitialMediaSettings();
    await _initLocalMedia();
  }
}