summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Baker <dbkr@matrix.org>2014-09-18 15:51:30 +0100
committerDavid Baker <dbkr@matrix.org>2014-09-18 15:51:30 +0100
commit3bd8cbc62fd8ac47acd56ec50360259f6098c66b (patch)
treea0db10c55eb9db72564d3cf8f91678d04ca62c81
parentWIP video chat layout (diff)
downloadsynapse-3bd8cbc62fd8ac47acd56ec50360259f6098c66b.tar.xz
Prettier and stabler video with basic support for viewing mode. For now, transition into 'large' mode is disabled.
-rw-r--r--webclient/app-controller.js22
-rwxr-xr-xwebclient/app.css32
-rw-r--r--webclient/components/matrix/matrix-call.js22
-rw-r--r--webclient/index.html13
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>
             &nbsp;