forked from MirrorHub/synapse
Use event age to recognise which calls are current and which aren't and hence support answering calls that were placed before we loaded the page.
This commit is contained in:
parent
c099b36af3
commit
dd2b933a0d
4 changed files with 79 additions and 16 deletions
|
@ -130,6 +130,10 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even
|
|||
angular.element('#ringAudio')[0].pause();
|
||||
angular.element('#ringbackAudio')[0].pause();
|
||||
angular.element('#busyAudio')[0].play();
|
||||
} else if (newVal == 'ended' && oldVal == 'invite_sent' && $rootScope.currentCall.hangupParty == 'local' && $rootScope.currentCall.hangupReason == 'invite_timeout') {
|
||||
angular.element('#ringAudio')[0].pause();
|
||||
angular.element('#ringbackAudio')[0].pause();
|
||||
angular.element('#busyAudio')[0].play();
|
||||
} else if (oldVal == 'invite_sent') {
|
||||
angular.element('#ringbackAudio')[0].pause();
|
||||
} else if (oldVal == 'ringing') {
|
||||
|
|
|
@ -53,6 +53,8 @@ angular.module('MatrixCall', [])
|
|||
this.candidateSendTries = 0;
|
||||
}
|
||||
|
||||
MatrixCall.CALL_TIMEOUT = 60000;
|
||||
|
||||
MatrixCall.prototype.createPeerConnection = function() {
|
||||
var stunServer = 'stun:stun.l.google.com:19302';
|
||||
var pc;
|
||||
|
@ -86,6 +88,14 @@ angular.module('MatrixCall', [])
|
|||
this.direction = 'inbound';
|
||||
};
|
||||
|
||||
// perverse as it may seem, sometimes we want to instantiate a call with a hangup message
|
||||
// (because when getting the state of the room on load, events come in reverse order and
|
||||
// we want to remember that a call has been hung up)
|
||||
MatrixCall.prototype.initWithHangup = function(msg) {
|
||||
this.msg = msg;
|
||||
this.state = 'ended';
|
||||
};
|
||||
|
||||
MatrixCall.prototype.answer = function() {
|
||||
console.log("Answering call "+this.call_id);
|
||||
var self = this;
|
||||
|
@ -188,14 +198,12 @@ angular.module('MatrixCall', [])
|
|||
console.log("Ignoring remote ICE candidate because call has ended");
|
||||
return;
|
||||
}
|
||||
var candidateObject = new RTCIceCandidate({
|
||||
sdpMLineIndex: cand.label,
|
||||
candidate: cand.candidate
|
||||
});
|
||||
this.peerConn.addIceCandidate(candidateObject, function() {}, function(e) {});
|
||||
this.peerConn.addIceCandidate(new RTCIceCandidate(cand), function() {}, function(e) {});
|
||||
};
|
||||
|
||||
MatrixCall.prototype.receivedAnswer = function(msg) {
|
||||
if (this.state == 'ended') return;
|
||||
|
||||
this.peerConn.setRemoteDescription(new RTCSessionDescription(msg.answer), this.onSetRemoteDescriptionSuccess, this.onSetRemoteDescriptionError);
|
||||
this.state = 'connecting';
|
||||
};
|
||||
|
@ -213,11 +221,17 @@ angular.module('MatrixCall', [])
|
|||
var content = {
|
||||
version: 0,
|
||||
call_id: this.call_id,
|
||||
offer: description
|
||||
offer: description,
|
||||
lifetime: MatrixCall.CALL_TIMEOUT
|
||||
};
|
||||
this.sendEventWithRetry('m.call.invite', content);
|
||||
|
||||
var self = this;
|
||||
$timeout(function() {
|
||||
self.hangupReason = 'invite_timeout';
|
||||
self.hangup();
|
||||
}, MatrixCall.CALL_TIMEOUT);
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
self.state = 'invite_sent';
|
||||
});
|
||||
|
|
|
@ -24,22 +24,52 @@ angular.module('matrixPhoneService', [])
|
|||
matrixPhoneService.INCOMING_CALL_EVENT = "INCOMING_CALL_EVENT";
|
||||
matrixPhoneService.REPLACED_CALL_EVENT = "REPLACED_CALL_EVENT";
|
||||
matrixPhoneService.allCalls = {};
|
||||
// a place to save candidates that come in for calls we haven't got invites for yet (when paginating backwards)
|
||||
matrixPhoneService.candidatesByCall = {};
|
||||
|
||||
matrixPhoneService.callPlaced = function(call) {
|
||||
matrixPhoneService.allCalls[call.call_id] = call;
|
||||
};
|
||||
|
||||
$rootScope.$on(eventHandlerService.CALL_EVENT, function(ngEvent, event, isLive) {
|
||||
if (!isLive) return; // until matrix supports expiring messages
|
||||
if (event.user_id == matrixService.config().user_id) return;
|
||||
|
||||
var msg = event.content;
|
||||
|
||||
if (event.type == 'm.call.invite') {
|
||||
if (event.age == undefined || msg.lifetime == undefined) {
|
||||
// if the event doesn't have either an age (the HS is too old) or a lifetime
|
||||
// (the sending client was too old when it sent it) then fall back to old behaviour
|
||||
if (!isLive) return; // until matrix supports expiring messages
|
||||
}
|
||||
|
||||
if (event.age > msg.lifetime) {
|
||||
console.log("Ignoring expired call event of type "+event.type);
|
||||
return;
|
||||
}
|
||||
|
||||
var call = undefined;
|
||||
if (!isLive) {
|
||||
// if this event wasn't live then this call may already be over
|
||||
call = matrixPhoneService.allCalls[msg.call_id];
|
||||
if (call && call.state == 'ended') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var MatrixCall = $injector.get('MatrixCall');
|
||||
var call = new MatrixCall(event.room_id);
|
||||
call.call_id = msg.call_id;
|
||||
call.initWithInvite(msg);
|
||||
matrixPhoneService.allCalls[call.call_id] = call;
|
||||
|
||||
// if we stashed candidate events for that call ID, play them back now
|
||||
if (!isLive && matrixPhoneService.candidatesByCall[call.call_id] != undefined) {
|
||||
for (var i = 0; i < matrixPhoneService.candidatesByCall[call.call_id].length; ++i) {
|
||||
call.gotRemoteIceCandidate(matrixPhoneService.candidatesByCall[call.call_id][i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Were we trying to call that user (room)?
|
||||
var existingCall;
|
||||
var callIds = Object.keys(matrixPhoneService.allCalls);
|
||||
|
@ -79,21 +109,35 @@ angular.module('matrixPhoneService', [])
|
|||
call.receivedAnswer(msg);
|
||||
} else if (event.type == 'm.call.candidates') {
|
||||
var call = matrixPhoneService.allCalls[msg.call_id];
|
||||
if (!call) {
|
||||
if (!call && isLive) {
|
||||
console.log("Got candidates for unknown call ID "+msg.call_id);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < msg.candidates.length; ++i) {
|
||||
call.gotRemoteIceCandidate(msg.candidates[i]);
|
||||
} else if (!call) {
|
||||
if (matrixPhoneService.candidatesByCall[msg.call_id] == undefined) {
|
||||
matrixPhoneService.candidatesByCall[msg.call_id] = [];
|
||||
}
|
||||
matrixPhoneService.candidatesByCall[msg.call_id] = matrixPhoneService.candidatesByCall[msg.call_id].concat(msg.candidates);
|
||||
} else {
|
||||
for (var i = 0; i < msg.candidates.length; ++i) {
|
||||
call.gotRemoteIceCandidate(msg.candidates[i]);
|
||||
}
|
||||
}
|
||||
} else if (event.type == 'm.call.hangup') {
|
||||
var call = matrixPhoneService.allCalls[msg.call_id];
|
||||
if (!call) {
|
||||
if (!call && isLive) {
|
||||
console.log("Got hangup for unknown call ID "+msg.call_id);
|
||||
return;
|
||||
} else if (!call) {
|
||||
// if not live, store the fact that the call has ended because we're probably getting events backwards so
|
||||
// the hangup will come before the invite
|
||||
var MatrixCall = $injector.get('MatrixCall');
|
||||
var call = new MatrixCall(event.room_id);
|
||||
call.call_id = msg.call_id;
|
||||
call.initWithHangup(msg);
|
||||
matrixPhoneService.allCalls[msg.call_id] = call;
|
||||
} else {
|
||||
call.onHangupReceived();
|
||||
delete(matrixPhoneService.allCalls[msg.call_id]);
|
||||
}
|
||||
call.onHangupReceived();
|
||||
delete(matrixPhoneService.allCalls[msg.call_id]);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@
|
|||
<span ng-show="currentCall.state == 'connecting'">Call Connecting...</span>
|
||||
<span ng-show="currentCall.state == 'connected'">Call Connected</span>
|
||||
<span ng-show="currentCall.state == 'ended' && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'remote'">Call Rejected</span>
|
||||
<span ng-show="currentCall.state == 'ended' && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'local'">Call Canceled</span>
|
||||
<span ng-show="currentCall.state == 'ended' && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'local' && currentCall.hangupReason == undefined">Call Canceled</span>
|
||||
<span ng-show="currentCall.state == 'ended' && !currentCall.didConnect && currentCall.direction == 'outbound' && currentCall.hangupParty == 'local' && currentCall.hangupReason == 'invite_timeout'">User Not Responding</span>
|
||||
<span ng-show="currentCall.state == 'ended' && currentCall.didConnect && currentCall.direction == 'outbound'">Call Ended</span>
|
||||
<span ng-show="currentCall.state == 'ended' && !currentCall.didConnect && currentCall.direction == 'inbound'">Call Canceled</span>
|
||||
<span ng-show="currentCall.state == 'ended' && currentCall.didConnect && currentCall.direction == 'inbound'">Call Ended</span>
|
||||
|
|
Loading…
Reference in a new issue