connect method

Future<void> connect(
  1. LinuxCastDevice device, {
  2. String receiverApplicationId = 'CC1AD845',
})

Opens TLS and launches the selected receiver, waiting for its response.

Implementation

Future<void> connect(
  LinuxCastDevice device, {
  String receiverApplicationId = 'CC1AD845',
}) async {
  if (_disposed) throw StateError('Client is disposed');
  await disconnect();
  _failed = false;
  try {
    _socket = await SecureSocket.connect(
      device.host,
      device.port,
      onBadCertificate: (_) => true,
      timeout: _deadline,
    );
    final decoder = CastFrameDecoder();
    _subscription = _socket!.listen(
      (chunk) {
        try {
          for (final frame in decoder.add(chunk)) {
            _handle(frame);
          }
        } catch (error, stack) {
          _fail(error, stack);
        }
      },
      onError: (Object error, StackTrace stack) => _fail(error, stack),
      onDone: () => _fail(
        const SocketException('Cast connection closed'),
        StackTrace.current,
      ),
    );
    _send(_connection, {'type': 'CONNECT'}, destination: 'receiver-0');
    _heartbeatTimer = Timer.periodic(const Duration(seconds: 5), (_) {
      _send(_heartbeat, {'type': 'PING'}, destination: 'receiver-0');
    });
    final response = await _request(
      _receiver,
      {'type': 'LAUNCH', 'appId': receiverApplicationId},
      destination: 'receiver-0',
      timeout: _launchDeadline,
    );
    final status = response['status'] as Map<String, dynamic>?;
    final apps = status?['applications'] as List<dynamic>? ?? [];
    final app = apps
        .cast<Map<String, dynamic>>()
        .where((item) => item['appId'] == receiverApplicationId)
        .firstOrNull;
    if (app == null || app['transportId'] is! String) {
      throw StateError('Receiver application did not launch');
    }
    _transport = app['transportId'] as String;
    _session = app['sessionId'] as String?;
    _send(_connection, {'type': 'CONNECT'});
    for (var attempt = 1; ; attempt++) {
      try {
        await _request(_media, {
          'type': 'GET_STATUS',
        }, timeout: _getStatusDeadline);
        break;
      } on TimeoutException {
        if (attempt == _getStatusAttempts) rethrow;
      }
    }
    _pollTimer = Timer.periodic(const Duration(seconds: 2), (_) {
      if (isConnected) {
        _send(_media, {'type': 'GET_STATUS', 'requestId': ++_nextRequest});
      }
    });
  } catch (_) {
    await disconnect();
    rethrow;
  }
}