diff options
-rw-r--r-- | webclient/app-controller.js | 22 | ||||
-rwxr-xr-x | webclient/app.css | 32 | ||||
-rw-r--r-- | webclient/components/matrix/matrix-call.js | 22 | ||||
-rw-r--r-- | webclient/index.html | 13 |
4 files changed, 70 insertions, 19 deletions
diff --git a/webclient/app-controller.js b/webclient/app-controller.js index f63bb32f4f..7f48148aaa 100644 --- a/webclient/app-controller.js +++ b/webclient/app-controller.js @@ -93,7 +93,13 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even }; $rootScope.$watch('currentCall', function(newVal, oldVal) { - if (!$rootScope.currentCall) return; + if (!$rootScope.currentCall) { + // This causes the still frame to be flushed out of the video elements, + // avoiding a flash of the last frame of the previous call when starting the next + angular.element('#localVideo')[0].load(); + angular.element('#remoteVideo')[0].load(); + return; + } var roomMembers = angular.copy($rootScope.events.rooms[$rootScope.currentCall.room_id].members); delete roomMembers[matrixService.config().user_id]; @@ -140,7 +146,19 @@ angular.module('MatrixWebClientController', ['matrixService', 'mPresence', 'even } else if (oldVal == 'ringing') { angular.element('#ringAudio')[0].pause(); } else if (newVal == 'connected') { - $scope.videoMode = 'large'; + $timeout(function() { + //if ($scope.currentCall.type == 'video') $scope.videoMode = 'large'; + }, 5000); + } + + if ($rootScope.currentCall && $rootScope.currentCall.type == 'video' && $rootScope.currentCall.state != 'connected') { + $scope.videoMode = 'mini'; + } + }); + $rootScope.$watch('currentCall.type', function(newVal, oldVal) { + // need to listen for this too as the type of the call won't be know when it's created + if ($rootScope.currentCall && $rootScope.currentCall.type == 'video' && $rootScope.currentCall.state != 'connected') { + $scope.videoMode = 'mini'; } }); diff --git a/webclient/app.css b/webclient/app.css index 69e608287e..7b6051e0b9 100755 --- a/webclient/app.css +++ b/webclient/app.css @@ -97,30 +97,44 @@ a:active { color: #000; } left: 0px; z-index: 1; background-color: rgba(0,0,0,0.0); + pointer-events: none; transition: background-color linear 300ms; } #videoBackground.large { background-color: rgba(0,0,0,0.85); + pointer-events: auto; } -#localVideo { - position: absolute; +#videoContainer { + max-width: 1280px; + margin: auto; top: 32px; - left: 160px; +} + +#videoContainer.large { +} + +#localVideo.mini { + position: relative; + left: 120px; width: 128px; height: 72px; - z-index: 2; +} + +#localVideo.ended { + -webkit-filter: grayscale(1); } #remoteVideo { - position: absolute; - top: 32px; - left: 300px; + transition: all linear 300ms; +} + +#remoteVideo.mini { + position: relative; + left: 120px; width: 128px; height: 72px; - z-index: 2; - transition: all linear 300ms; } #remoteVideo.large { diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js index 636259297e..5ba782bac8 100644 --- a/webclient/components/matrix/matrix-call.js +++ b/webclient/components/matrix/matrix-call.js @@ -65,7 +65,7 @@ angular.module('MatrixCall', []) var stunServer = 'stun:stun.l.google.com:19302'; var pc; if (window.mozRTCPeerConnection) { - pc = window.mozRTCPeerConnection({'url': stunServer}); + pc = new window.mozRTCPeerConnection({'url': stunServer}); } else { pc = new window.RTCPeerConnection({"iceServers":[{"urls":"stun:stun.l.google.com:19302"}]}); } @@ -118,6 +118,17 @@ angular.module('MatrixCall', []) this.peerConn.setRemoteDescription(new RTCSessionDescription(this.msg.offer), this.onSetRemoteDescriptionSuccess, this.onSetRemoteDescriptionError); this.state = 'ringing'; this.direction = 'inbound'; + + if (window.mozRTCPeerConnection) { + // firefox's RTCPeerConnection doesn't add streams until it starts getting media on them + // so we need to figure out whether a video channel has been offered by ourselves. + if (this.msg.offer.sdp.indexOf('m=video') > -1) { + this.type = 'video'; + } else { + this.type = 'voice'; + } + } + var self = this; $timeout(function() { if (self.state == 'ringing') { @@ -167,7 +178,10 @@ angular.module('MatrixCall', []) MatrixCall.prototype.hangup = function(suppressEvent) { console.log("Ending call "+this.call_id); - this.remoteVideoElement.pause(); + // pausing now keeps the last frame (ish) of the video call in the video element + // rather than it just turning black straight away + if (this.remoteVideoElement) this.remoteVideoElement.pause(); + if (this.localVideoElement) this.localVideoElement.pause(); this.stopAllMedia(); if (this.peerConn) this.peerConn.close(); @@ -318,7 +332,7 @@ angular.module('MatrixCall', []) }; MatrixCall.prototype.getUserMediaFailed = function() { - this.onError("Couldn't start capturing audio! Is your microphone set up?"); + this.onError("Couldn't start capturing! Is your microphone set up?"); this.hangup(); }; @@ -411,6 +425,8 @@ angular.module('MatrixCall', []) MatrixCall.prototype.onHangupReceived = function() { console.log("Hangup received"); + if (this.remoteVideoElement) this.remoteVideoElement.pause(); + if (this.localVideoElement) this.localVideoElement.pause(); this.state = 'ended'; this.hangupParty = 'remote'; this.stopAllMedia(); diff --git a/webclient/index.html b/webclient/index.html index 05801a93bc..78a68753d4 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -45,7 +45,12 @@ </head> <body> - <div id="videoBackground" ng-class="videoMode" ng-show="videoMode == 'large' || videoMode == 'fullscreen'"></div> + <div id="videoBackground" ng-class="videoMode"> + <div id="videoContainer" ng-class="videoMode"> + <video id="localVideo" ng-class="[videoMode, currentCall.state]" ng-show="currentCall && currentCall.type == 'video' && (currentCall.state == 'connected' || currentCall.state == 'connecting' || currentCall.state == 'invite_sent' || currentCall.state == 'ended')"></video> + <video id="remoteVideo" ng-class="[videoMode, currentCall.state]" ng-show="currentCall && currentCall.type == 'video' && (currentCall.state == 'connected' || currentCall.state == 'ended')"></video> + </div> + </div> <div id="header"> <!-- Do not show buttons on the login page --> @@ -59,8 +64,8 @@ <br /> <span id="callState"> <span ng-show="currentCall.state == 'invite_sent'">Calling...</span> - <span ng-show="currentCall.state == 'ringing' && currentCall.type == 'video'">Incoming Video Call</span> - <span ng-show="currentCall.state == 'ringing' && currentCall.type == 'voice'">Incoming Voice Call</span> + <span ng-show="currentCall.state == 'ringing' && currentCall && currentCall.type == 'video'">Incoming Video Call</span> + <span ng-show="currentCall.state == 'ringing' && currentCall && currentCall.type == 'voice'">Incoming Voice Call</span> <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> @@ -94,8 +99,6 @@ <source src="media/busy.mp3" type="audio/mpeg" /> </audio> </div> - <video id="localVideo" ng-class="videoMode" ng-show="currentCall && currentCall.type == 'video' && (currentCall.state == 'connected' || currentCall.state == 'connecting' || currentCall.state == 'invite_sent')"></video> - <video id="remoteVideo" ng-class="[videoMode, currentCall.state]" ng-show="currentCall && currentCall.type == 'video' && currentCall.state == 'connected' || currentCall.state == 'ended'"></video> <a href id="headerUserId" ng-click='goToUserPage(user_id)'>{{ user_id }}</a> |