diff --git a/skins/base/views/molecules/voip/CallHandler.js b/skins/base/views/molecules/voip/CallHandler.js index 8fd8282f..41023dd6 100644 --- a/skins/base/views/molecules/voip/CallHandler.js +++ b/skins/base/views/molecules/voip/CallHandler.js @@ -28,7 +28,25 @@ var VideoView = ComponentBroker.get('molecules/voip/VideoView'); module.exports = React.createClass({ displayName: 'CallHandler', mixins: [CallHandlerController], + + getVideoView: function() { + return this.refs.video; + }, + render: function(){ + if (this.state && this.state.call) { + if (this.state.call.type === "video") { + return ( + + ); + } + else if (this.state.call.type === "voice") { + // in the future. + return ( +
+ ); + } + } return (
); diff --git a/src/controllers/molecules/voip/CallHandler.js b/src/controllers/molecules/voip/CallHandler.js index f5e09338..0bb4685b 100644 --- a/src/controllers/molecules/voip/CallHandler.js +++ b/src/controllers/molecules/voip/CallHandler.js @@ -15,13 +15,25 @@ limitations under the License. */ 'use strict'; - +var MatrixClientPeg = require("../../../MatrixClientPeg"); +var Matrix = require("matrix-js-sdk"); var dis = require("../../../dispatcher"); +/* + * State vars: + * this.state.call = MatrixCall|null + * + * Props: + * this.props.room = Room (JS SDK) - can be null (for singleton views) + */ + module.exports = { componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); + this.setState({ + call: null + }); }, componentWillUnmount: function() { @@ -37,12 +49,75 @@ module.exports = { switch (payload.action) { case 'place_call': + if (this.state.call) { + return; // don't allow >1 call to be placed. + } console.log("Place %s call in %s", payload.type, payload.room_id); + var call = Matrix.createNewMatrixCall( + MatrixClientPeg.get(), payload.room_id + ); + this._setCallListeners(call); + this.setState({ + call: call + }); + if (payload.type === 'voice') { + call.placeVoiceCall(); + } + else if (payload.type === 'video') { + var videoView = this.getVideoView(); + call.placeVideoCall( + videoView.getRemoteVideoElement(), + videoView.getLocalVideoElement() + ); + } + else { + console.error("Unknown call type: %s", payload.type); + } break; case 'incoming_call': + if (this.state.call) { + payload.call.hangup("busy"); + return; // don't allow >1 call to be received. + } + this._setCallListeners(call); + this.setState({ + call: call + }); console.log("Incoming call: %s", payload.call); break; + case 'hangup': + if (!this.state.call) { + return; // no call to hangup + } + this.state.call.hangup(); + this.setState({ + call: null + }); + break; + case 'answer': + if (!this.state.call) { + return; // no call to answer + } + this.state.call.answer(); + break; } + }, + + _setCallListeners: function(call) { + var self = this; + call.on("error", function(err) { + console.error("Call error: %s", err); + console.error(err.stack); + call.hangup(); + self.setState({ + call: null + }); + }); + call.on("hangup", function() { + self.setState({ + call: null + }); + }) } };