From 7ffd97b5dc91212d0824fe5af2591727774e7cc3 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 16 Jul 2015 11:05:09 +0100 Subject: [PATCH] Implement call FSM. All works. --- skins/base/views/molecules/RoomHeader.js | 14 ++---- src/CallHandler.js | 55 ++++++++++++++++++------ src/controllers/molecules/RoomHeader.js | 39 ++++------------- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/skins/base/views/molecules/RoomHeader.js b/skins/base/views/molecules/RoomHeader.js index e64aee53..1708bd1c 100644 --- a/skins/base/views/molecules/RoomHeader.js +++ b/skins/base/views/molecules/RoomHeader.js @@ -32,8 +32,8 @@ module.exports = React.createClass({ var callButtons; if (this.state) { - switch (this.state.callState) { - case "INBOUND": + switch (this.state.call_state) { + case "ringing": callButtons = (
@@ -45,14 +45,8 @@ module.exports = React.createClass({
); break; - case "OUTBOUND": - callButtons = ( -
- BYEBYE -
- ); - break; - case "IN_CALL": + case "ringback": + case "connected": callButtons = (
BYEBYE diff --git a/src/CallHandler.js b/src/CallHandler.js index d6367a6b..029b8917 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -22,7 +22,8 @@ limitations under the License. * This handler dispatches when voip calls are added/updated/removed from this list: * { * action: 'call_state' - * room_id: + * room_id: , + * status: ringing|ringback|connected|ended|busy|stop_ringback|stop_ringing * } * * To know if the call was added/removed, this handler exposes a getter to @@ -33,8 +34,6 @@ limitations under the License. * { * action: 'place_call', * type: 'voice|video', - * remote_element: DOMVideoElement, // only if type: video - * local_element: DOMVideoElement, // only if type: video * room_id: * } * @@ -67,19 +66,51 @@ function _setCallListeners(call) { console.error("Call error: %s", err); console.error(err.stack); call.hangup(); - _setCallState(undefined, call.roomId); + _setCallState(undefined, call.roomId, "ended"); }); call.on("hangup", function() { - _setCallState(undefined, call.roomId); + _setCallState(undefined, call.roomId, "ended"); + }); + // map web rtc states to dummy UI state + // ringing|ringback|connected|ended|busy|stop_ringback|stop_ringing + call.on("state", function(newState, oldState) { + if (newState === "ringing") { + _setCallState(call, call.roomId, "ringing"); + } + else if (newState === "invite_sent") { + _setCallState(call, call.roomId, "ringback"); + } + else if (newState === "ended" && oldState === "connected") { + _setCallState(call, call.roomId, "ended"); + } + else if (newState === "ended" && oldState === "invite_sent" && + (call.hangupParty === "remote" || + (call.hangupParty === "local" && call.hangupReason === "invite_timeout") + )) { + _setCallState(call, call.roomId, "busy"); + } + else if (oldState === "invite_sent") { + _setCallState(call, call.roomId, "stop_ringback"); + } + else if (oldState === "ringing") { + _setCallState(call, call.roomId, "stop_ringing"); + } + else if (newState === "connected") { + _setCallState(call, call.roomId, "connected"); + } }); } -function _setCallState(call, roomId) { - console.log("_setState >>> %s >>> %s ", call, roomId); +function _setCallState(call, roomId, status) { + console.log("_setState >>> %s >>> %s >> %s", call, roomId, status); calls[roomId] = call; + if (call) { + call.call_state = status; + } dis.dispatch({ action: 'call_state', - room_id: roomId + room_id: roomId, + status: status }); } @@ -94,7 +125,7 @@ dis.register(function(payload) { MatrixClientPeg.get(), payload.room_id ); _setCallListeners(call); - _setCallState(call, call.roomId); + _setCallState(call, call.roomId, "ringback"); if (payload.type === 'voice') { call.placeVoiceCall(); } @@ -116,21 +147,21 @@ dis.register(function(payload) { } var call = payload.call; _setCallListeners(call); - _setCallState(call, call.roomId); + _setCallState(call, call.roomId, "ringing"); break; case 'hangup': if (!calls[payload.room_id]) { return; // no call to hangup } calls[payload.room_id].hangup(); - _setCallState(null, payload.room_id); + _setCallState(null, payload.room_id, "ended"); break; case 'answer': if (!calls[payload.room_id]) { return; // no call to answer } calls[payload.room_id].answer(); - _setCallState(calls[payload.room_id], payload.room_id); + _setCallState(calls[payload.room_id], payload.room_id, "connected"); break; } }); diff --git a/src/controllers/molecules/RoomHeader.js b/src/controllers/molecules/RoomHeader.js index b66d1ff9..766f9b40 100644 --- a/src/controllers/molecules/RoomHeader.js +++ b/src/controllers/molecules/RoomHeader.js @@ -25,40 +25,16 @@ var dis = require("../../dispatcher"); var CallHandler = require("../../CallHandler"); module.exports = { - _setCallState: function(call) { - if (!call) { - this.setState({ - callState: "NO_CALL" - }); - return; - } - var callState = 'NO_CALL'; - if (call.state !== 'ended') { - if (call.state === 'connected') { - callState = "IN_CALL"; - } - else if (call.direction === 'outbound') { - callState = "OUTBOUND"; - } - else if (call.direction === 'inbound') { - callState = "INBOUND"; - } - else { - console.error("Cannot determine call state."); - } - } - this.setState({ - callState: callState - }); - }, componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); - var call; if (this.props.room) { - call = CallHandler.getCall(this.props.room.roomId); + var call = CallHandler.getCall(this.props.room.roomId); + var callState = call ? call.call_state : "ended"; + this.setState({ + call_state: callState + }); } - this._setCallState(call); }, componentWillUnmount: function() { @@ -75,7 +51,10 @@ module.exports = { return; } var call = CallHandler.getCall(payload.room_id); - this._setCallState(call); + var callState = call ? call.call_state : "ended"; + this.setState({ + call_state: callState + }); }, onVideoClick: function() {