part of '../neon_spreed.dart'; abstract class SpreedCallParticipant { SpreedCallParticipant( this.userID, this.sessionID, this.renderer, this.stream, ); final String userID; final String sessionID; RTCVideoRenderer? renderer; MediaStream? stream; void dispose() { stream?.getTracks().forEach((final track) => unawaited(track.stop())); unawaited(stream?.dispose()); renderer?.srcObject = null; unawaited(renderer?.dispose()); } } class SpreedLocalCallParticipant extends SpreedCallParticipant { SpreedLocalCallParticipant( super.userID, super.sessionID, super.renderer, super.stream, ); } class SpreedRemoteCallParticipant extends SpreedCallParticipant { SpreedRemoteCallParticipant( super.userID, super.sessionID, super.renderer, super.stream, this._connection, this._senders, { this.audioEnabled = false, this.videoEnabled = false, }); RTCPeerConnection? _connection; List? _senders; final List _candidates = []; bool audioEnabled; bool videoEnabled; RTCPeerConnection? get connection => _connection; List? get senders => _senders; Future _clearSenders() async { if (_senders != null && _connection != null) { for (final sender in _senders!) { await _connection!.removeTrack(sender); } } if (_senders != null) { for (final sender in _senders!) { try { await sender.dispose(); } catch (_) { // TODO: Somehow peerConnection is null when calling this on disposing the participant } } _senders = null; } } Future acceptNewConnection(final RTCPeerConnection? connection) async { await _clearSenders(); await _connection?.close(); _connection = connection; if (_connection != null) { for (final candidate in _candidates) { debugPrint('Loading candidate'); await _connection!.addCandidate(candidate); } _candidates.clear(); } } Future acceptNewLocalStream(final MediaStream? stream) async { await _clearSenders(); if (_connection != null && stream != null) { _senders = []; for (final track in stream.getTracks()) { _senders!.add(await _connection!.addTrack(track, stream)); } } } Future addCandidate(final RTCIceCandidate candidate) async { if (connection != null) { await connection!.addCandidate(candidate); } else { _candidates.add(candidate); debugPrint('Storing candidate for later use'); } } @override void dispose() { unawaited(_clearSenders()); unawaited(_connection?.close()); super.dispose(); } }