start method

Future<CallHandleImpl> start({
  1. String? toUser,
  2. String? toGroup,
  3. List<String>? usernames,
  4. required CallMedia media,
  5. Map<String, String>? ext,
})

Implementation

Future<CallHandleImpl> start({String? toUser, String? toGroup, List<String>? usernames, required CallMedia media, Map<String, String>? ext}) async {
  core.requireSignedIn();
  if (config()?['rtc_enabled'] == false) {
    throw DRException(code: 'permission_denied', details: {'reason': 'rtc_disabled'}, source: ErrorSource.local, message: 'rtc_disabled');
  }
  final data = <String, Object?>{'client_call_id': core.platform.random.uuid(), 'media': media.name, 'media_providers': providerKinds};
  if (toUser != null) {
    if (toGroup != null) throw validationError('invalid_value', 'to_group');
    if (toUser.isEmpty) throw validationError('required', 'to_user');
    data['to_user'] = toUser.toLowerCase();
  } else {
    if (toGroup == null || toGroup.isEmpty) throw validationError('required', 'to_group');
    data['to_group'] = toGroup;
    if (usernames != null) {
      final max = asInt(config()?['max_group_call_participants']);
      if (max != null && max > 0 && usernames.length > max - 1) throw validationError('too_many_invitees', 'usernames', {'max': max - 1});
      data['usernames'] = [for (final u in usernames) u.toLowerCase()];
    }
  }
  if (ext != null) data['ext'] = Map<String, String>.of(ext);
  // 发起不自动重试限流;长连接上的网络错误、超时用同一个 client_call_id 改用客户端 API 重试一次
  final result = await signal('rtc.start', '/client/v1/calls', data);
  final call = asMap(result['call']);
  if (call == null) throw localError('internal', message: 'rtc.start 的响应中没有 call');
  final handle = _upsert(call, self: asMap(call['self']) ?? selfOf(call, me, true));
  // 对方忙:返回的通话已经结束,不连接媒体
  final mediaJson = asMap(result['media']);
  if (call['status'] != 'ended' && mediaJson != null) fireAndForget(handle.attachMedia(mediaJson, asInt(result['heartbeat_interval_seconds'])));
  return handle;
}