Merge branch 'voip/fix-bugs-for-group-call' into 'main'
Fix bugs in 1v1 and group calls. See merge request famedly/company/frontend/famedlysdk!1132
This commit is contained in:
commit
64f2a4b3c6
|
|
@ -82,13 +82,16 @@ class WrappedMediaStream {
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
renderer.srcObject = null;
|
renderer.srcObject = null;
|
||||||
if (isLocal() && stream != null && isWeb) {
|
if (isLocal()) {
|
||||||
for (final element in stream!.getTracks()) {
|
if (isWeb) {
|
||||||
await element.stop();
|
await stopMediaStream(stream);
|
||||||
|
} else {
|
||||||
|
if (!isGroupCall) {
|
||||||
|
await stopMediaStream(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await stream?.dispose();
|
|
||||||
stream = null;
|
|
||||||
}
|
}
|
||||||
|
stream = null;
|
||||||
await renderer.dispose();
|
await renderer.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -827,7 +830,7 @@ class CallSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callFeed.purpose == SDPStreamMetadataPurpose.Screenshare) {
|
if (callFeed.purpose == SDPStreamMetadataPurpose.Screenshare) {
|
||||||
stopMediaStream(callFeed.stream);
|
await stopMediaStream(callFeed.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty the array
|
// Empty the array
|
||||||
|
|
@ -932,20 +935,19 @@ 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.
|
||||||
///
|
///
|
||||||
Future<void> reject() async {
|
Future<void> reject({String? reason, bool shouldEmit = true}) async {
|
||||||
// stop play ringtone
|
// stop play ringtone
|
||||||
voip.delegate.stopRingtone();
|
voip.delegate.stopRingtone();
|
||||||
|
if (state != CallState.kRinging && state != CallState.kFledgling) {
|
||||||
if (state != CallState.kRinging) {
|
Logs().e('[VOIP] Call must be in \'ringing|fledgling\' state to reject!');
|
||||||
Logs().e('[VOIP] Call must be in \'ringing\' state to reject!');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Logs().d('[VOIP] Rejecting call: $callId');
|
Logs().d('[VOIP] Rejecting call: $callId');
|
||||||
await terminate(CallParty.kLocal, CallErrorCode.UserHangup, true);
|
await terminate(CallParty.kLocal, CallErrorCode.UserHangup, shouldEmit);
|
||||||
await sendCallReject(room, callId, lifetimeMs, localPartyId);
|
await sendCallReject(room, callId, lifetimeMs, localPartyId, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> hangup([String? reason, bool suppressEvent = true]) async {
|
Future<void> hangup([String? reason, bool suppressEvent = false]) async {
|
||||||
// stop play ringtone
|
// stop play ringtone
|
||||||
voip.delegate.stopRingtone();
|
voip.delegate.stopRingtone();
|
||||||
|
|
||||||
|
|
@ -987,15 +989,15 @@ class CallSession {
|
||||||
hangupParty = party;
|
hangupParty = party;
|
||||||
hangupReason = reason;
|
hangupReason = reason;
|
||||||
|
|
||||||
setCallState(CallState.kEnded);
|
if (shouldEmit) {
|
||||||
|
setCallState(CallState.kEnded);
|
||||||
|
}
|
||||||
voip.currentCID = null;
|
voip.currentCID = null;
|
||||||
voip.calls.remove(callId);
|
voip.calls.remove(callId);
|
||||||
await cleanUp();
|
await cleanUp();
|
||||||
|
|
||||||
onCallHangup.add(this);
|
|
||||||
|
|
||||||
voip.delegate.handleCallEnded(this);
|
|
||||||
if (shouldEmit) {
|
if (shouldEmit) {
|
||||||
|
onCallHangup.add(this);
|
||||||
|
voip.delegate.handleCallEnded(this);
|
||||||
fireCallEvent(CallEvent.kHangup);
|
fireCallEvent(CallEvent.kHangup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1432,7 +1434,7 @@ class CallSession {
|
||||||
/// [version] is the version of the VoIP specification this message adheres to. This specification is version 1.
|
/// [version] is the version of the VoIP specification this message adheres to. This specification is version 1.
|
||||||
/// [party_id] The party ID for call, Can be set to client.deviceId.
|
/// [party_id] The party ID for call, Can be set to client.deviceId.
|
||||||
Future<String?> sendCallReject(
|
Future<String?> sendCallReject(
|
||||||
Room room, String callId, int lifetime, String party_id,
|
Room room, String callId, int lifetime, String party_id, String? reason,
|
||||||
{String version = voipProtoVersion, String? txid}) async {
|
{String version = voipProtoVersion, String? txid}) async {
|
||||||
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
||||||
|
|
||||||
|
|
@ -1440,6 +1442,7 @@ class CallSession {
|
||||||
'call_id': callId,
|
'call_id': callId,
|
||||||
'party_id': party_id,
|
'party_id': party_id,
|
||||||
if (groupCallId != null) 'conf_id': groupCallId,
|
if (groupCallId != null) 'conf_id': groupCallId,
|
||||||
|
if (reason != null) 'reason': reason,
|
||||||
'version': version,
|
'version': version,
|
||||||
'lifetime': lifetime,
|
'lifetime': lifetime,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -594,9 +594,10 @@ class GroupCall {
|
||||||
|
|
||||||
onGroupCallEvent.add(GroupCallEvent.LocalScreenshareStateChanged);
|
onGroupCallEvent.add(GroupCallEvent.LocalScreenshareStateChanged);
|
||||||
|
|
||||||
calls.forEach((call) {
|
calls.forEach((call) async {
|
||||||
call.addLocalStream(
|
await call.addLocalStream(
|
||||||
localScreenshareStream!.stream!, localScreenshareStream!.purpose);
|
await voip.delegate.cloneStream(localScreenshareStream!.stream!),
|
||||||
|
localScreenshareStream!.purpose);
|
||||||
});
|
});
|
||||||
|
|
||||||
await sendMemberStateEvent();
|
await sendMemberStateEvent();
|
||||||
|
|
@ -613,7 +614,7 @@ class GroupCall {
|
||||||
calls.forEach((call) {
|
calls.forEach((call) {
|
||||||
call.removeLocalStream(call.localScreenSharingStream!);
|
call.removeLocalStream(call.localScreenSharingStream!);
|
||||||
});
|
});
|
||||||
stopMediaStream(localScreenshareStream!.stream);
|
await stopMediaStream(localScreenshareStream?.stream);
|
||||||
removeScreenshareStream(localScreenshareStream!);
|
removeScreenshareStream(localScreenshareStream!);
|
||||||
localScreenshareStream = null;
|
localScreenshareStream = null;
|
||||||
localDesktopCapturerSourceId = null;
|
localDesktopCapturerSourceId = null;
|
||||||
|
|
@ -1092,12 +1093,10 @@ class GroupCall {
|
||||||
|
|
||||||
onStreamRemoved.add(stream);
|
onStreamRemoved.add(stream);
|
||||||
|
|
||||||
stream.stream!.getTracks().forEach((element) {
|
if (stream.isLocal()) {
|
||||||
element.stop();
|
stream.disposeRenderer();
|
||||||
});
|
stopMediaStream(stream.stream);
|
||||||
|
}
|
||||||
stream.stream!.dispose();
|
|
||||||
stream.disposeRenderer();
|
|
||||||
|
|
||||||
onGroupCallEvent.add(GroupCallEvent.UserMediaStreamsChanged);
|
onGroupCallEvent.add(GroupCallEvent.UserMediaStreamsChanged);
|
||||||
|
|
||||||
|
|
@ -1187,14 +1186,11 @@ class GroupCall {
|
||||||
|
|
||||||
onStreamRemoved.add(stream);
|
onStreamRemoved.add(stream);
|
||||||
|
|
||||||
if (voip.delegate.isWeb) {
|
if (stream.isLocal()) {
|
||||||
stream.stream!.getTracks().forEach((element) {
|
stream.disposeRenderer();
|
||||||
element.stop();
|
stopMediaStream(stream.stream);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.dispose();
|
|
||||||
|
|
||||||
onGroupCallEvent.add(GroupCallEvent.ScreenshareStreamsChanged);
|
onGroupCallEvent.add(GroupCallEvent.ScreenshareStreamsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import 'package:random_string/random_string.dart';
|
import 'package:random_string/random_string.dart';
|
||||||
import 'package:webrtc_interface/webrtc_interface.dart';
|
import 'package:webrtc_interface/webrtc_interface.dart';
|
||||||
|
|
||||||
void stopMediaStream(MediaStream? stream) async {
|
Future<void> stopMediaStream(MediaStream? stream) async {
|
||||||
stream?.getTracks().forEach((element) async {
|
stream?.getTracks().forEach((element) async {
|
||||||
await element.stop();
|
await element.stop();
|
||||||
});
|
});
|
||||||
|
await stream?.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTracksEnabled(List<MediaStreamTrack> tracks, bool enabled) {
|
void setTracksEnabled(List<MediaStreamTrack> tracks, bool enabled) {
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@ abstract class WebRTCDelegate {
|
||||||
void stopRingtone();
|
void stopRingtone();
|
||||||
void handleNewCall(CallSession session);
|
void handleNewCall(CallSession session);
|
||||||
void handleCallEnded(CallSession session);
|
void handleCallEnded(CallSession session);
|
||||||
|
void handleMissedCall(CallSession session);
|
||||||
void handleNewGroupCall(GroupCall groupCall);
|
void handleNewGroupCall(GroupCall groupCall);
|
||||||
void handleGroupCallEnded(GroupCall groupCall);
|
void handleGroupCallEnded(GroupCall groupCall);
|
||||||
|
|
||||||
bool get isBackgroud;
|
bool get isBackgroud;
|
||||||
bool get isWeb;
|
bool get isWeb;
|
||||||
|
bool get canHandleNewCall => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoIP {
|
class VoIP {
|
||||||
|
|
@ -200,10 +200,20 @@ class VoIP {
|
||||||
newCall.opponentDeviceId = deviceId;
|
newCall.opponentDeviceId = deviceId;
|
||||||
newCall.opponentSessionId = content['sender_session_id'];
|
newCall.opponentSessionId = content['sender_session_id'];
|
||||||
|
|
||||||
|
if (!delegate.canHandleNewCall &&
|
||||||
|
(confId == null || confId != currentGroupCID)) {
|
||||||
|
Logs().v(
|
||||||
|
'[VOIP] onCallInvite: Unable to handle new calls, maybe user is busy.');
|
||||||
|
await newCall.reject(reason: 'busy', shouldEmit: false);
|
||||||
|
delegate.handleMissedCall(newCall);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final offer = RTCSessionDescription(
|
final offer = RTCSessionDescription(
|
||||||
content['offer']['sdp'],
|
content['offer']['sdp'],
|
||||||
content['offer']['type'],
|
content['offer']['type'],
|
||||||
);
|
);
|
||||||
|
|
||||||
await newCall.initWithInvite(
|
await newCall.initWithInvite(
|
||||||
callType, offer, sdpStreamMetadata, lifetime, confId != null);
|
callType, offer, sdpStreamMetadata, lifetime, confId != null);
|
||||||
|
|
||||||
|
|
@ -223,7 +233,9 @@ class VoIP {
|
||||||
///TODO: notify the callkeep that the call is incoming.
|
///TODO: notify the callkeep that the call is incoming.
|
||||||
}
|
}
|
||||||
// Play ringtone
|
// Play ringtone
|
||||||
delegate.playRingtone();
|
if (confId == null) {
|
||||||
|
delegate.playRingtone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onCallAnswer(
|
Future<void> onCallAnswer(
|
||||||
|
|
|
||||||
|
|
@ -967,7 +967,8 @@ void main() {
|
||||||
await call.sendCallCandidates(room, '1234', '4567', [], txid: '1234');
|
await call.sendCallCandidates(room, '1234', '4567', [], txid: '1234');
|
||||||
await call.sendSelectCallAnswer(room, '1234', 1234, '4567', '6789',
|
await call.sendSelectCallAnswer(room, '1234', 1234, '4567', '6789',
|
||||||
txid: '1234');
|
txid: '1234');
|
||||||
await call.sendCallReject(room, '1234', 1234, '4567', txid: '1234');
|
await call.sendCallReject(room, '1234', 1234, '4567', 'busy',
|
||||||
|
txid: '1234');
|
||||||
await call.sendCallNegotiate(room, '1234', 1234, '4567', 'sdp',
|
await call.sendCallNegotiate(room, '1234', 1234, '4567', 'sdp',
|
||||||
txid: '1234');
|
txid: '1234');
|
||||||
await call.sendHangupCall(room, '1234', '4567', 'user_hangup',
|
await call.sendHangupCall(room, '1234', '4567', 'user_hangup',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue