Merge branch 'nico/awaited-voip' into 'main'
fix: Await unawaited stuff in voip code See merge request famedly/company/frontend/famedlysdk!1082
This commit is contained in:
commit
5dd53a66d9
|
|
@ -84,9 +84,9 @@ class WrappedMediaStream {
|
||||||
renderer.srcObject = null;
|
renderer.srcObject = null;
|
||||||
if (isLocal() && !isGroupCall && stream != null) {
|
if (isLocal() && !isGroupCall && stream != null) {
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
stream!.getTracks().forEach((element) {
|
for (final element in stream!.getTracks()) {
|
||||||
element.stop();
|
await element.stop();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
await stream?.dispose();
|
await stream?.dispose();
|
||||||
stream = null;
|
stream = null;
|
||||||
|
|
@ -395,7 +395,7 @@ class CallSession {
|
||||||
setCallState(CallState.kCreateOffer);
|
setCallState(CallState.kCreateOffer);
|
||||||
final stream = await _getUserMedia(type);
|
final stream = await _getUserMedia(type);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
addLocalStream(stream, SDPStreamMetadataPurpose.Usermedia);
|
await addLocalStream(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ class CallSession {
|
||||||
if (!isGroupCall) {
|
if (!isGroupCall) {
|
||||||
final stream = await _getUserMedia(type);
|
final stream = await _getUserMedia(type);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
addLocalStream(stream, SDPStreamMetadataPurpose.Usermedia);
|
await addLocalStream(stream, SDPStreamMetadataPurpose.Usermedia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,12 +473,12 @@ class CallSession {
|
||||||
|
|
||||||
waitForLocalAVStream = false;
|
waitForLocalAVStream = false;
|
||||||
|
|
||||||
callFeeds.forEach((element) async {
|
for (final element in callFeeds) {
|
||||||
addLocalStream(
|
await addLocalStream(
|
||||||
await voip.delegate.cloneStream(element.stream!), element.purpose);
|
await voip.delegate.cloneStream(element.stream!), element.purpose);
|
||||||
});
|
}
|
||||||
|
|
||||||
answer();
|
await answer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> placeCallWithStreams(List<WrappedMediaStream> callFeeds,
|
Future<void> placeCallWithStreams(List<WrappedMediaStream> callFeeds,
|
||||||
|
|
@ -490,27 +490,27 @@ class CallSession {
|
||||||
// create the peer connection now so it can be gathering candidates while we get user
|
// create the peer connection now so it can be gathering candidates while we get user
|
||||||
// media (assuming a candidate pool size is configured)
|
// media (assuming a candidate pool size is configured)
|
||||||
await _preparePeerConnection();
|
await _preparePeerConnection();
|
||||||
gotCallFeedsForInvite(callFeeds, requestScreenshareFeed);
|
await gotCallFeedsForInvite(callFeeds, requestScreenshareFeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gotCallFeedsForInvite(List<WrappedMediaStream> callFeeds,
|
Future<void> gotCallFeedsForInvite(List<WrappedMediaStream> callFeeds,
|
||||||
[bool requestScreenshareFeed = false]) {
|
[bool requestScreenshareFeed = false]) async {
|
||||||
if (successor != null) {
|
if (successor != null) {
|
||||||
successor!.gotCallFeedsForAnswer(callFeeds);
|
await successor!.gotCallFeedsForAnswer(callFeeds);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state == CallState.kEnded) {
|
if (state == CallState.kEnded) {
|
||||||
cleanUp();
|
await cleanUp();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callFeeds.forEach((element) async {
|
for (final element in callFeeds) {
|
||||||
addLocalStream(
|
await addLocalStream(
|
||||||
await voip.delegate.cloneStream(element.stream!), element.purpose);
|
await voip.delegate.cloneStream(element.stream!), element.purpose);
|
||||||
});
|
}
|
||||||
|
|
||||||
if (requestScreenshareFeed) {
|
if (requestScreenshareFeed) {
|
||||||
pc!.addTransceiver(
|
await pc!.addTransceiver(
|
||||||
kind: RTCRtpMediaType.RTCRtpMediaTypeVideo,
|
kind: RTCRtpMediaType.RTCRtpMediaTypeVideo,
|
||||||
init:
|
init:
|
||||||
RTCRtpTransceiverInit(direction: TransceiverDirection.RecvOnly));
|
RTCRtpTransceiverInit(direction: TransceiverDirection.RecvOnly));
|
||||||
|
|
@ -526,7 +526,7 @@ class CallSession {
|
||||||
setCallState(CallState.kEnded);
|
setCallState(CallState.kEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAnswerReceived(
|
Future<void> onAnswerReceived(
|
||||||
RTCSessionDescription answer, SDPStreamMetadata? metadata) async {
|
RTCSessionDescription answer, SDPStreamMetadata? metadata) async {
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
_updateRemoteSDPStreamMetadata(metadata);
|
_updateRemoteSDPStreamMetadata(metadata);
|
||||||
|
|
@ -535,7 +535,9 @@ class CallSession {
|
||||||
if (direction == CallDirection.kOutgoing) {
|
if (direction == CallDirection.kOutgoing) {
|
||||||
setCallState(CallState.kConnecting);
|
setCallState(CallState.kConnecting);
|
||||||
await pc!.setRemoteDescription(answer);
|
await pc!.setRemoteDescription(answer);
|
||||||
remoteCandidates.forEach((candidate) => pc!.addCandidate(candidate));
|
for (final candidate in remoteCandidates) {
|
||||||
|
await pc!.addCandidate(candidate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send select_answer event.
|
/// Send select_answer event.
|
||||||
|
|
@ -543,7 +545,7 @@ class CallSession {
|
||||||
opts.room, callId, lifetimeMs, localPartyId, remotePartyId!);
|
opts.room, callId, lifetimeMs, localPartyId, remotePartyId!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onNegotiateReceived(
|
Future<void> onNegotiateReceived(
|
||||||
SDPStreamMetadata? metadata, RTCSessionDescription description) async {
|
SDPStreamMetadata? metadata, RTCSessionDescription description) async {
|
||||||
final polite = direction == CallDirection.kIncoming;
|
final polite = direction == CallDirection.kIncoming;
|
||||||
|
|
||||||
|
|
@ -611,13 +613,13 @@ class CallSession {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSDPStreamMetadataReceived(SDPStreamMetadata metadata) async {
|
Future<void> onSDPStreamMetadataReceived(SDPStreamMetadata metadata) async {
|
||||||
_updateRemoteSDPStreamMetadata(metadata);
|
_updateRemoteSDPStreamMetadata(metadata);
|
||||||
fireCallEvent(CallEvent.kFeedsChanged);
|
fireCallEvent(CallEvent.kFeedsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCandidatesReceived(List<dynamic> candidates) {
|
Future<void> onCandidatesReceived(List<dynamic> candidates) async {
|
||||||
candidates.forEach((json) async {
|
for (final json in candidates) {
|
||||||
final candidate = RTCIceCandidate(
|
final candidate = RTCIceCandidate(
|
||||||
json['candidate'],
|
json['candidate'],
|
||||||
json['sdpMid'] ?? '',
|
json['sdpMid'] ?? '',
|
||||||
|
|
@ -633,16 +635,16 @@ class CallSession {
|
||||||
} else {
|
} else {
|
||||||
remoteCandidates.add(candidate);
|
remoteCandidates.add(candidate);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (pc != null &&
|
if (pc != null &&
|
||||||
pc!.iceConnectionState ==
|
pc!.iceConnectionState ==
|
||||||
RTCIceConnectionState.RTCIceConnectionStateDisconnected) {
|
RTCIceConnectionState.RTCIceConnectionStateDisconnected) {
|
||||||
restartIce();
|
await restartIce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAssertedIdentityReceived(AssertedIdentity identity) async {
|
void onAssertedIdentityReceived(AssertedIdentity identity) {
|
||||||
remoteAssertedIdentity = identity;
|
remoteAssertedIdentity = identity;
|
||||||
fireCallEvent(CallEvent.kAssertedIdentityChanged);
|
fireCallEvent(CallEvent.kAssertedIdentityChanged);
|
||||||
}
|
}
|
||||||
|
|
@ -674,7 +676,7 @@ class CallSession {
|
||||||
setScreensharingEnabled(false);
|
setScreensharingEnabled(false);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
addLocalStream(stream, SDPStreamMetadataPurpose.Screenshare);
|
await addLocalStream(stream, SDPStreamMetadataPurpose.Screenshare);
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
fireCallEvent(CallEvent.kError);
|
fireCallEvent(CallEvent.kError);
|
||||||
|
|
@ -696,7 +698,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLocalStream(MediaStream stream, String purpose,
|
Future<void> addLocalStream(MediaStream stream, String purpose,
|
||||||
{bool addToPeerConnection = true}) async {
|
{bool addToPeerConnection = true}) async {
|
||||||
final existingStream =
|
final existingStream =
|
||||||
getLocalStreams.where((element) => element.purpose == purpose);
|
getLocalStreams.where((element) => element.purpose == purpose);
|
||||||
|
|
@ -722,14 +724,14 @@ class CallSession {
|
||||||
if (addToPeerConnection) {
|
if (addToPeerConnection) {
|
||||||
if (purpose == SDPStreamMetadataPurpose.Screenshare) {
|
if (purpose == SDPStreamMetadataPurpose.Screenshare) {
|
||||||
screensharingSenders.clear();
|
screensharingSenders.clear();
|
||||||
stream.getTracks().forEach((track) async {
|
for (final track in stream.getTracks()) {
|
||||||
screensharingSenders.add(await pc!.addTrack(track, stream));
|
screensharingSenders.add(await pc!.addTrack(track, stream));
|
||||||
});
|
}
|
||||||
} else if (purpose == SDPStreamMetadataPurpose.Usermedia) {
|
} else if (purpose == SDPStreamMetadataPurpose.Usermedia) {
|
||||||
usermediaSenders.clear();
|
usermediaSenders.clear();
|
||||||
stream.getTracks().forEach((track) async {
|
for (final track in stream.getTracks()) {
|
||||||
usermediaSenders.add(await pc!.addTrack(track, stream));
|
usermediaSenders.add(await pc!.addTrack(track, stream));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,7 +746,7 @@ class CallSession {
|
||||||
fireCallEvent(CallEvent.kFeedsChanged);
|
fireCallEvent(CallEvent.kFeedsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addRemoteStream(MediaStream stream) async {
|
Future<void> _addRemoteStream(MediaStream stream) async {
|
||||||
//final userId = remoteUser.id;
|
//final userId = remoteUser.id;
|
||||||
final metadata = remoteSDPStreamMetadata!.sdpStreamMetadatas[stream.id];
|
final metadata = remoteSDPStreamMetadata!.sdpStreamMetadatas[stream.id];
|
||||||
if (metadata == null) {
|
if (metadata == null) {
|
||||||
|
|
@ -783,17 +785,17 @@ class CallSession {
|
||||||
Logs().i('Pushed remote stream (id="${stream.id}", purpose=$purpose)');
|
Logs().i('Pushed remote stream (id="${stream.id}", purpose=$purpose)');
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteAllStreams() {
|
Future<void> deleteAllStreams() async {
|
||||||
streams.forEach((stream) async {
|
for (final stream in streams) {
|
||||||
if (stream.isLocal() || groupCallId == null) {
|
if (stream.isLocal() || groupCallId == null) {
|
||||||
await stream.dispose();
|
await stream.dispose();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
streams.clear();
|
streams.clear();
|
||||||
fireCallEvent(CallEvent.kFeedsChanged);
|
fireCallEvent(CallEvent.kFeedsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteFeedByStream(MediaStream stream) {
|
Future<void> deleteFeedByStream(MediaStream stream) async {
|
||||||
final index =
|
final index =
|
||||||
streams.indexWhere((element) => element.stream!.id == stream.id);
|
streams.indexWhere((element) => element.stream!.id == stream.id);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
|
|
@ -802,23 +804,23 @@ class CallSession {
|
||||||
}
|
}
|
||||||
final wstream = streams.elementAt(index);
|
final wstream = streams.elementAt(index);
|
||||||
onStreamRemoved.add(wstream);
|
onStreamRemoved.add(wstream);
|
||||||
deleteStream(wstream);
|
await deleteStream(wstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteStream(WrappedMediaStream stream) {
|
Future<void> deleteStream(WrappedMediaStream stream) async {
|
||||||
stream.dispose();
|
await stream.dispose();
|
||||||
streams.removeAt(streams.indexOf(stream));
|
streams.removeAt(streams.indexOf(stream));
|
||||||
fireCallEvent(CallEvent.kFeedsChanged);
|
fireCallEvent(CallEvent.kFeedsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeLocalStream(WrappedMediaStream callFeed) {
|
Future<void> removeLocalStream(WrappedMediaStream callFeed) async {
|
||||||
final senderArray = callFeed.purpose == SDPStreamMetadataPurpose.Usermedia
|
final senderArray = callFeed.purpose == SDPStreamMetadataPurpose.Usermedia
|
||||||
? usermediaSenders
|
? usermediaSenders
|
||||||
: screensharingSenders;
|
: screensharingSenders;
|
||||||
|
|
||||||
senderArray.forEach((element) async {
|
for (final element in senderArray) {
|
||||||
await pc!.removeTrack(element);
|
await pc!.removeTrack(element);
|
||||||
});
|
}
|
||||||
|
|
||||||
if (callFeed.purpose == SDPStreamMetadataPurpose.Screenshare) {
|
if (callFeed.purpose == SDPStreamMetadataPurpose.Screenshare) {
|
||||||
stopMediaStream(callFeed.stream);
|
stopMediaStream(callFeed.stream);
|
||||||
|
|
@ -827,7 +829,7 @@ class CallSession {
|
||||||
// Empty the array
|
// Empty the array
|
||||||
senderArray.removeRange(0, senderArray.length);
|
senderArray.removeRange(0, senderArray.length);
|
||||||
onStreamRemoved.add(callFeed);
|
onStreamRemoved.add(callFeed);
|
||||||
deleteStream(callFeed);
|
await deleteStream(callFeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallState(CallState newState) {
|
void setCallState(CallState newState) {
|
||||||
|
|
@ -850,7 +852,7 @@ class CallSession {
|
||||||
|
|
||||||
bool get isMicrophoneMuted => localUserMediaStream?.isAudioMuted() ?? false;
|
bool get isMicrophoneMuted => localUserMediaStream?.isAudioMuted() ?? false;
|
||||||
|
|
||||||
void setRemoteOnHold(bool onHold) async {
|
Future<void> setRemoteOnHold(bool onHold) async {
|
||||||
if (isRemoteOnHold == onHold) return;
|
if (isRemoteOnHold == onHold) return;
|
||||||
remoteOnHold = onHold;
|
remoteOnHold = onHold;
|
||||||
final transceivers = await pc!.getTransceivers();
|
final transceivers = await pc!.getTransceivers();
|
||||||
|
|
@ -859,7 +861,7 @@ class CallSession {
|
||||||
? TransceiverDirection.SendOnly
|
? TransceiverDirection.SendOnly
|
||||||
: TransceiverDirection.SendRecv);
|
: TransceiverDirection.SendRecv);
|
||||||
}
|
}
|
||||||
_updateMuteStatus();
|
await _updateMuteStatus();
|
||||||
fireCallEvent(CallEvent.kRemoteHoldUnhold);
|
fireCallEvent(CallEvent.kRemoteHoldUnhold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -884,7 +886,7 @@ class CallSession {
|
||||||
return callOnHold;
|
return callOnHold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void answer() async {
|
Future<void> answer() async {
|
||||||
if (inviteOrAnswerSent) {
|
if (inviteOrAnswerSent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -895,7 +897,9 @@ class CallSession {
|
||||||
setCallState(CallState.kCreateAnswer);
|
setCallState(CallState.kCreateAnswer);
|
||||||
|
|
||||||
final answer = await pc!.createAnswer({});
|
final answer = await pc!.createAnswer({});
|
||||||
remoteCandidates.forEach((candidate) => pc!.addCandidate(candidate));
|
for (final candidate in remoteCandidates) {
|
||||||
|
await pc!.addCandidate(candidate);
|
||||||
|
}
|
||||||
|
|
||||||
final callCapabilities = CallCapabilities()
|
final callCapabilities = CallCapabilities()
|
||||||
..dtmf = false
|
..dtmf = false
|
||||||
|
|
@ -924,7 +928,7 @@ class CallSession {
|
||||||
/// This used to be done by calling hangup, but is a separate method and protocol
|
/// This used to be done by calling hangup, but is a separate method and protocol
|
||||||
/// event as of MSC2746.
|
/// event as of MSC2746.
|
||||||
///
|
///
|
||||||
void reject() {
|
Future<void> reject() async {
|
||||||
// stop play ringtone
|
// stop play ringtone
|
||||||
voip.delegate.stopRingtone();
|
voip.delegate.stopRingtone();
|
||||||
|
|
||||||
|
|
@ -933,15 +937,15 @@ class CallSession {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Logs().d('[VOIP] Rejecting call: $callId');
|
Logs().d('[VOIP] Rejecting call: $callId');
|
||||||
terminate(CallParty.kLocal, CallErrorCode.UserHangup, true);
|
await terminate(CallParty.kLocal, CallErrorCode.UserHangup, true);
|
||||||
sendCallReject(room, callId, lifetimeMs, localPartyId);
|
await sendCallReject(room, callId, lifetimeMs, localPartyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hangup([String? reason, bool suppressEvent = true]) async {
|
Future<void> hangup([String? reason, bool suppressEvent = true]) async {
|
||||||
// stop play ringtone
|
// stop play ringtone
|
||||||
voip.delegate.stopRingtone();
|
voip.delegate.stopRingtone();
|
||||||
|
|
||||||
terminate(
|
await terminate(
|
||||||
CallParty.kLocal, reason ?? CallErrorCode.UserHangup, !suppressEvent);
|
CallParty.kLocal, reason ?? CallErrorCode.UserHangup, !suppressEvent);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -953,7 +957,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendDTMF(String tones) async {
|
Future<void> sendDTMF(String tones) async {
|
||||||
final senders = await pc!.getSenders();
|
final senders = await pc!.getSenders();
|
||||||
for (final sender in senders) {
|
for (final sender in senders) {
|
||||||
if (sender.track != null && sender.track!.kind == 'audio') {
|
if (sender.track != null && sender.track!.kind == 'audio') {
|
||||||
|
|
@ -964,7 +968,8 @@ class CallSession {
|
||||||
Logs().e('Unable to find a track to send DTMF on');
|
Logs().e('Unable to find a track to send DTMF on');
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminate(CallParty party, String reason, bool shouldEmit) async {
|
Future<void> terminate(
|
||||||
|
CallParty party, String reason, bool shouldEmit) async {
|
||||||
if (state == CallState.kEnded) {
|
if (state == CallState.kEnded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -981,7 +986,7 @@ class CallSession {
|
||||||
setCallState(CallState.kEnded);
|
setCallState(CallState.kEnded);
|
||||||
voip.currentCID = null;
|
voip.currentCID = null;
|
||||||
voip.calls.remove(callId);
|
voip.calls.remove(callId);
|
||||||
cleanUp();
|
await cleanUp();
|
||||||
|
|
||||||
onCallHangup.add(this);
|
onCallHangup.add(this);
|
||||||
|
|
||||||
|
|
@ -991,7 +996,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRejectReceived(String? reason) {
|
Future<void> onRejectReceived(String? reason) async {
|
||||||
Logs().v('[VOIP] Reject received for call ID ' + callId);
|
Logs().v('[VOIP] Reject received for call ID ' + callId);
|
||||||
// No need to check party_id for reject because if we'd received either
|
// No need to check party_id for reject because if we'd received either
|
||||||
// an answer or reject, we wouldn't be in state InviteSent
|
// an answer or reject, we wouldn't be in state InviteSent
|
||||||
|
|
@ -1001,7 +1006,8 @@ class CallSession {
|
||||||
CallState.kRinging == state;
|
CallState.kRinging == state;
|
||||||
|
|
||||||
if (shouldTerminate) {
|
if (shouldTerminate) {
|
||||||
terminate(CallParty.kRemote, reason ?? CallErrorCode.UserHangup, true);
|
await terminate(
|
||||||
|
CallParty.kRemote, reason ?? CallErrorCode.UserHangup, true);
|
||||||
} else {
|
} else {
|
||||||
Logs().e('Call is in state: ${state.toString()}: ignoring reject');
|
Logs().e('Call is in state: ${state.toString()}: ignoring reject');
|
||||||
}
|
}
|
||||||
|
|
@ -1018,7 +1024,8 @@ class CallSession {
|
||||||
await pc!.setLocalDescription(offer);
|
await pc!.setLocalDescription(offer);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logs().d('Error setting local description! ${err.toString()}');
|
Logs().d('Error setting local description! ${err.toString()}');
|
||||||
terminate(CallParty.kLocal, CallErrorCode.SetLocalDescription, true);
|
await terminate(
|
||||||
|
CallParty.kLocal, CallErrorCode.SetLocalDescription, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1051,7 +1058,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onNegotiationNeeded() async {
|
Future<void> onNegotiationNeeded() async {
|
||||||
Logs().i('Negotiation is needed!');
|
Logs().i('Negotiation is needed!');
|
||||||
makingOffer = true;
|
makingOffer = true;
|
||||||
try {
|
try {
|
||||||
|
|
@ -1112,10 +1119,10 @@ class CallSession {
|
||||||
terminate(CallParty.kRemote, CallErrorCode.AnsweredElsewhere, true);
|
terminate(CallParty.kRemote, CallErrorCode.AnsweredElsewhere, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanUp() async {
|
Future<void> cleanUp() async {
|
||||||
streams.forEach((stream) {
|
for (final stream in streams) {
|
||||||
stream.dispose();
|
await stream.dispose();
|
||||||
});
|
}
|
||||||
streams.clear();
|
streams.clear();
|
||||||
if (pc != null) {
|
if (pc != null) {
|
||||||
await pc!.close();
|
await pc!.close();
|
||||||
|
|
@ -1123,7 +1130,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateMuteStatus() async {
|
Future<void> _updateMuteStatus() async {
|
||||||
final micShouldBeMuted = (localUserMediaStream != null &&
|
final micShouldBeMuted = (localUserMediaStream != null &&
|
||||||
localUserMediaStream!.isAudioMuted()) ||
|
localUserMediaStream!.isAudioMuted()) ||
|
||||||
remoteOnHold;
|
remoteOnHold;
|
||||||
|
|
@ -1141,9 +1148,9 @@ class CallSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setTracksEnabled(List<MediaStreamTrack> tracks, bool enabled) {
|
void _setTracksEnabled(List<MediaStreamTrack> tracks, bool enabled) {
|
||||||
tracks.forEach((track) async {
|
for (final track in tracks) {
|
||||||
track.enabled = enabled;
|
track.enabled = enabled;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDPStreamMetadata _getLocalSDPStreamMetadata() {
|
SDPStreamMetadata _getLocalSDPStreamMetadata() {
|
||||||
|
|
@ -1159,7 +1166,7 @@ class CallSession {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
void restartIce() async {
|
Future<void> restartIce() async {
|
||||||
Logs().v('[VOIP] iceRestart.');
|
Logs().v('[VOIP] iceRestart.');
|
||||||
// Needs restart ice on session.pc and renegotiation.
|
// Needs restart ice on session.pc and renegotiation.
|
||||||
iceGatheringFinished = false;
|
iceGatheringFinished = false;
|
||||||
|
|
@ -1229,7 +1236,7 @@ class CallSession {
|
||||||
pc?.createDataChannel(label, dataChannelDict);
|
pc?.createDataChannel(label, dataChannelDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tryRemoveStopedStreams() {
|
Future<void> tryRemoveStopedStreams() async {
|
||||||
final removedStreams = <String, WrappedMediaStream>{};
|
final removedStreams = <String, WrappedMediaStream>{};
|
||||||
streams.forEach((stream) {
|
streams.forEach((stream) {
|
||||||
if (stream.stopped) {
|
if (stream.stopped) {
|
||||||
|
|
@ -1238,9 +1245,9 @@ class CallSession {
|
||||||
});
|
});
|
||||||
streams
|
streams
|
||||||
.removeWhere((stream) => removedStreams.containsKey(stream.stream!.id));
|
.removeWhere((stream) => removedStreams.containsKey(stream.stream!.id));
|
||||||
removedStreams.forEach((id, element) {
|
for (final element in removedStreams.entries) {
|
||||||
_removeStream(element.stream!);
|
await _removeStream(element.value.stream!);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _removeStream(MediaStream stream) async {
|
Future<void> _removeStream(MediaStream stream) async {
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ class VoIP {
|
||||||
delegate.playRingtone();
|
delegate.playRingtone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallAnswer(
|
Future<void> onCallAnswer(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
Logs().v('[VOIP] onCallAnswer => ${content.toString()}');
|
Logs().v('[VOIP] onCallAnswer => ${content.toString()}');
|
||||||
final String callId = content['call_id'];
|
final String callId = content['call_id'];
|
||||||
|
|
@ -252,13 +252,13 @@ class VoIP {
|
||||||
if (content[sdpStreamMetadataKey] != null) {
|
if (content[sdpStreamMetadataKey] != null) {
|
||||||
metadata = SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]);
|
metadata = SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]);
|
||||||
}
|
}
|
||||||
call.onAnswerReceived(answer, metadata);
|
await call.onAnswerReceived(answer, metadata);
|
||||||
} else {
|
} else {
|
||||||
Logs().v('[VOIP] onCallAnswer: Session [$callId] not found!');
|
Logs().v('[VOIP] onCallAnswer: Session [$callId] not found!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallCandidates(
|
Future<void> onCallCandidates(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -273,13 +273,13 @@ class VoIP {
|
||||||
'Ignoring call candidates for room $roomId claiming to be for call in room ${call.room.id}');
|
'Ignoring call candidates for room $roomId claiming to be for call in room ${call.room.id}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
call.onCandidatesReceived(content['candidates']);
|
await call.onCandidatesReceived(content['candidates']);
|
||||||
} else {
|
} else {
|
||||||
Logs().v('[VOIP] onCallCandidates: Session [$callId] not found!');
|
Logs().v('[VOIP] onCallCandidates: Session [$callId] not found!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallHangup(String roomId, String _ /*senderId unused*/,
|
Future<void> onCallHangup(String roomId, String _ /*senderId unused*/,
|
||||||
Map<String, dynamic> content) async {
|
Map<String, dynamic> content) async {
|
||||||
// stop play ringtone, if this is an incoming call
|
// stop play ringtone, if this is an incoming call
|
||||||
if (!delegate.isBackgroud) {
|
if (!delegate.isBackgroud) {
|
||||||
|
|
@ -295,7 +295,7 @@ class VoIP {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// hangup in any case, either if the other party hung up or we did on another device
|
// hangup in any case, either if the other party hung up or we did on another device
|
||||||
call.terminate(CallParty.kRemote,
|
await call.terminate(CallParty.kRemote,
|
||||||
content['reason'] ?? CallErrorCode.UserHangup, true);
|
content['reason'] ?? CallErrorCode.UserHangup, true);
|
||||||
} else {
|
} else {
|
||||||
Logs().v('[VOIP] onCallHangup: Session [$callId] not found!');
|
Logs().v('[VOIP] onCallHangup: Session [$callId] not found!');
|
||||||
|
|
@ -303,7 +303,7 @@ class VoIP {
|
||||||
currentCID = null;
|
currentCID = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallReject(
|
Future<void> onCallReject(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -319,13 +319,13 @@ class VoIP {
|
||||||
'Ignoring call reject for room $roomId claiming to be for call in room ${call.room.id}');
|
'Ignoring call reject for room $roomId claiming to be for call in room ${call.room.id}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
call.onRejectReceived(content['reason']);
|
await call.onRejectReceived(content['reason']);
|
||||||
} else {
|
} else {
|
||||||
Logs().v('[VOIP] onCallHangup: Session [$callId] not found!');
|
Logs().v('[VOIP] onCallHangup: Session [$callId] not found!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallReplaces(
|
Future<void> onCallReplaces(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -344,7 +344,7 @@ class VoIP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallSelectAnswer(
|
Future<void> onCallSelectAnswer(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -365,7 +365,7 @@ class VoIP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSDPStreamMetadataChangedReceived(
|
Future<void> onSDPStreamMetadataChangedReceived(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -385,12 +385,12 @@ class VoIP {
|
||||||
Logs().d('SDP Stream metadata is null');
|
Logs().d('SDP Stream metadata is null');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
call.onSDPStreamMetadataReceived(
|
await call.onSDPStreamMetadataReceived(
|
||||||
SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]));
|
SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onAssertedIdentityReceived(
|
Future<void> onAssertedIdentityReceived(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -415,7 +415,7 @@ class VoIP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCallNegotiate(
|
Future<void> onCallNegotiate(
|
||||||
String roomId, String senderId, Map<String, dynamic> content) async {
|
String roomId, String senderId, Map<String, dynamic> content) async {
|
||||||
if (senderId == client.userID) {
|
if (senderId == client.userID) {
|
||||||
// Ignore messages to yourself.
|
// Ignore messages to yourself.
|
||||||
|
|
@ -437,7 +437,7 @@ class VoIP {
|
||||||
if (content[sdpStreamMetadataKey] != null) {
|
if (content[sdpStreamMetadataKey] != null) {
|
||||||
metadata = SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]);
|
metadata = SDPStreamMetadata.fromJson(content[sdpStreamMetadataKey]);
|
||||||
}
|
}
|
||||||
call.onNegotiateReceived(metadata,
|
await call.onNegotiateReceived(metadata,
|
||||||
RTCSessionDescription(description['sdp'], description['type']));
|
RTCSessionDescription(description['sdp'], description['type']));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logs().e('Failed to complete negotiation ${err.toString()}');
|
Logs().e('Failed to complete negotiation ${err.toString()}');
|
||||||
|
|
@ -564,7 +564,7 @@ class VoIP {
|
||||||
return groupCalls[groupCallId];
|
return groupCalls[groupCallId];
|
||||||
}
|
}
|
||||||
|
|
||||||
void startGroupCalls() async {
|
Future<void> startGroupCalls() async {
|
||||||
final rooms = client.rooms;
|
final rooms = client.rooms;
|
||||||
rooms.forEach((element) {
|
rooms.forEach((element) {
|
||||||
createGroupCallForRoom(element);
|
createGroupCallForRoom(element);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue