diff --git a/js/app.js b/js/app.js index 1e5188f0826..6b1bbafce15 100644 --- a/js/app.js +++ b/js/app.js @@ -627,13 +627,17 @@ delete this._reconnectCallToken; - // Disable video when joining a call in a room with more than 5 - // participants. - var participants = this.activeRoom.get('participants'); - if (participants && Object.keys(participants).length > 5) { + if (this.activeRoom.get('type') === this.ROOM_TYPE_ONE_TO_ONE) { + this._mediaControlsView.setAudioEnabled(true); this.setVideoEnabled(false); + + return; } + this._mediaControlsView.setAudioEnabled(false); + this.setVideoEnabled(false); + + var participants = this.activeRoom.get('participants'); var numberOfParticipantsAndGuests = (participants? Object.keys(participants).length: 0) + this.activeRoom.get('numGuests'); if (this.signaling.isNoMcuWarningEnabled() && numberOfParticipantsAndGuests >= 5) { @@ -706,6 +710,16 @@ localMediaChannel.trigger('waitingForPermissions'); } + var participants = this.activeRoom.get('participants'); + var numberOfParticipantsAndGuests = (participants? Object.keys(participants).length: 0) + + this.activeRoom.get('numGuests'); + if (numberOfParticipantsAndGuests >= 5) { + this.signaling.setSendVideoIfAvailable(false); + this.setVideoEnabled(false); + } else { + this.signaling.setSendVideoIfAvailable(true); + } + OCA.SpreedMe.webrtc.startMedia(this.token); }, startLocalMedia: function(configuration) { diff --git a/js/connection.js b/js/connection.js index 87eb1731dcf..c1bc914c330 100644 --- a/js/connection.js +++ b/js/connection.js @@ -119,7 +119,7 @@ if (configuration.audio) { flags |= OCA.SpreedMe.app.FLAG_WITH_AUDIO; } - if (configuration.video) { + if (configuration.video && self.app.signaling.getSendVideoIfAvailable()) { flags |= OCA.SpreedMe.app.FLAG_WITH_VIDEO; } } diff --git a/js/embedded.js b/js/embedded.js index 9ec6f69682e..7ecdf0c3e2d 100644 --- a/js/embedded.js +++ b/js/embedded.js @@ -147,13 +147,17 @@ delete this._reconnectCallToken; - // Disable video when joining a call in a room with more than 5 - // participants. - var participants = this.activeRoom.get('participants'); - if (participants && Object.keys(participants).length > 5) { + if (this.activeRoom.get('type') === this.ROOM_TYPE_ONE_TO_ONE) { + this._mediaControlsView.setAudioEnabled(true); this.setVideoEnabled(false); + + return; } + this._mediaControlsView.setAudioEnabled(false); + this.setVideoEnabled(false); + + var participants = this.activeRoom.get('participants'); var numberOfParticipantsAndGuests = (participants? Object.keys(participants).length: 0) + this.activeRoom.get('numGuests'); if (this.signaling.isNoMcuWarningEnabled() && numberOfParticipantsAndGuests >= 5) { @@ -188,6 +192,16 @@ localMediaChannel.trigger('waitingForPermissions'); } + var participants = this.activeRoom.get('participants'); + var numberOfParticipantsAndGuests = (participants? Object.keys(participants).length: 0) + + this.activeRoom.get('numGuests'); + if (numberOfParticipantsAndGuests >= 5) { + this.signaling.setSendVideoIfAvailable(false); + this.setVideoEnabled(false); + } else { + this.signaling.setSendVideoIfAvailable(true); + } + OCA.SpreedMe.webrtc.startMedia(this.token); }, startLocalMedia: function(configuration) { diff --git a/js/signaling.js b/js/signaling.js index 87ccccbdd08..f21204621f8 100644 --- a/js/signaling.js +++ b/js/signaling.js @@ -76,6 +76,7 @@ this.pendingChatRequests = []; this._lastChatMessagesFetch = null; this.chatBatchSize = 100; + this._sendVideoIfAvailable = true; } OCA.Talk.Signaling.Base = Base; @@ -134,6 +135,10 @@ return this.sessionId; }; + OCA.Talk.Signaling.Base.prototype.getCurrentCallFlags = function() { + return this.currentCallFlags; + }; + OCA.Talk.Signaling.Base.prototype.disconnect = function() { this.sessionId = ''; this.currentCallToken = null; @@ -299,6 +304,14 @@ }); }; + OCA.Talk.Signaling.Base.prototype.getSendVideoIfAvailable = function() { + return this._sendVideoIfAvailable; + }; + + OCA.Talk.Signaling.Base.prototype.setSendVideoIfAvailable = function(sendVideoIfAvailable) { + this._sendVideoIfAvailable = sendVideoIfAvailable; + }; + OCA.Talk.Signaling.Base.prototype._joinCallSuccess = function(/* token */) { // Override in subclasses if necessary. }; @@ -515,8 +528,19 @@ } }; - OCA.Talk.Signaling.Internal.prototype.forceReconnect = function(/* newSession */) { - console.error("Forced reconnects are not supported with the internal signaling."); + OCA.Talk.Signaling.Internal.prototype.forceReconnect = function(newSession, flags) { + if (newSession) { + console.log('Forced reconnects with a new session are not supported in the internal signaling; same session as before will be used'); + } + + if (flags !== undefined) { + this.currentCallFlags = flags; + } + + // FIXME Naive reconnection routine; as the same session is kept peers + // must be explicitly ended before the reconnection is forced. + this.leaveCall(this.currentCallToken, true); + this.joinCall(this.currentCallToken); }; OCA.Talk.Signaling.Internal.prototype._sendMessageWithCallback = function(ev) { @@ -830,7 +854,11 @@ OCA.Talk.Signaling.Base.prototype.disconnect.apply(this, arguments); }; - OCA.Talk.Signaling.Standalone.prototype.forceReconnect = function(newSession) { + OCA.Talk.Signaling.Standalone.prototype.forceReconnect = function(newSession, flags) { + if (flags !== undefined) { + this.currentCallFlags = flags; + } + if (!this.connected) { if (!newSession) { // Not connected, will do reconnect anyway. diff --git a/js/simplewebrtc/bundled.js b/js/simplewebrtc/bundled.js index 20f5f589dba..b42b4292d21 100644 --- a/js/simplewebrtc/bundled.js +++ b/js/simplewebrtc/bundled.js @@ -629,6 +629,7 @@ function Peer(options) { this.sharemyscreen = options.sharemyscreen || false; this.browserPrefix = options.prefix; this.stream = options.stream; + this.sendVideoIfAvailable = options.sendVideoIfAvailable === undefined ? true : options.sendVideoIfAvailable; this.enableDataChannels = options.enableDataChannels === undefined ? this.parent.config.enableDataChannels : options.enableDataChannels; this.receiveMedia = options.receiveMedia || this.parent.config.receiveMedia; this.channels = {}; @@ -673,7 +674,11 @@ function Peer(options) { } } else { this.parent.localStreams.forEach(function (stream) { - self.pc.addStream(stream); + stream.getTracks().forEach(function (track) { + if (track.kind !== 'video' || self.sendVideoIfAvailable) { + self.pc.addTrack(track, stream); + } + }); }); } // proxy events to parent @@ -1079,7 +1084,8 @@ function SimpleWebRTC(opts) { type: message.roomType, enableDataChannels: self.config.enableDataChannels && message.roomType !== 'screen', sharemyscreen: message.roomType === 'screen' && !message.broadcaster, - broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null + broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null, + sendVideoIfAvailable: self.connection.getSendVideoIfAvailable() }); self.emit('createdPeer', peer); } diff --git a/js/simplewebrtc/peer.js b/js/simplewebrtc/peer.js index f0b61fd92de..7640f571f01 100644 --- a/js/simplewebrtc/peer.js +++ b/js/simplewebrtc/peer.js @@ -25,6 +25,7 @@ function Peer(options) { this.sharemyscreen = options.sharemyscreen || false; this.browserPrefix = options.prefix; this.stream = options.stream; + this.sendVideoIfAvailable = options.sendVideoIfAvailable === undefined ? true : options.sendVideoIfAvailable; this.enableDataChannels = options.enableDataChannels === undefined ? this.parent.config.enableDataChannels : options.enableDataChannels; this.receiveMedia = options.receiveMedia || this.parent.config.receiveMedia; this.channels = {}; @@ -68,7 +69,11 @@ function Peer(options) { } } else { this.parent.localStreams.forEach(function (stream) { - self.pc.addStream(stream); + stream.getTracks().forEach(function (track) { + if (track.kind !== 'video' || self.sendVideoIfAvailable) { + self.pc.addTrack(track, stream); + } + }); }); } diff --git a/js/simplewebrtc/simplewebrtc.js b/js/simplewebrtc/simplewebrtc.js index 6e4924fb405..f5705d98e17 100644 --- a/js/simplewebrtc/simplewebrtc.js +++ b/js/simplewebrtc/simplewebrtc.js @@ -108,7 +108,8 @@ function SimpleWebRTC(opts) { type: message.roomType, enableDataChannels: self.config.enableDataChannels && message.roomType !== 'screen', sharemyscreen: message.roomType === 'screen' && !message.broadcaster, - broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null + broadcaster: message.roomType === 'screen' && !message.broadcaster ? self.connection.getSessionid() : null, + sendVideoIfAvailable: self.connection.getSendVideoIfAvailable() }); self.emit('createdPeer', peer); } diff --git a/js/views/mediacontrolsview.js b/js/views/mediacontrolsview.js index 16a37acf9b7..cbf9a140292 100644 --- a/js/views/mediacontrolsview.js +++ b/js/views/mediacontrolsview.js @@ -183,7 +183,7 @@ } else { this._webrtc.pauseVideo(); - this.getUI('videoButton').attr('data-original-title', t('spreed', 'Enable video (v)')) + this.getUI('videoButton').attr('data-original-title', this._getEnableVideoButtonTitle()) .addClass('local-video-disabled video-disabled icon-video-off') .removeClass('icon-video'); this.getUI('audioButton').addClass('local-video-disabled'); @@ -195,6 +195,14 @@ return true; }, + _getEnableVideoButtonTitle: function() { + if (!this._app.signaling || this._app.signaling.getSendVideoIfAvailable()) { + return t('spreed', 'Enable video (v)'); + } + + return t('spreed', 'Enable video (v) - Your connection will be briefly interrupted when enabling the video for the first time'); + }, + /** * Sets the video as available or not available. * diff --git a/js/webrtc.js b/js/webrtc.js index 89d0ffb15b0..9677bbfab56 100644 --- a/js/webrtc.js +++ b/js/webrtc.js @@ -130,7 +130,8 @@ var spreedPeerConnectionTable = []; receiveMedia: { offerToReceiveAudio: 0, offerToReceiveVideo: 0 - } + }, + sendVideoIfAvailable: signaling.getSendVideoIfAvailable() }); webrtc.emit('createdPeer', ownPeer); ownPeer.start(); @@ -184,7 +185,8 @@ var spreedPeerConnectionTable = []; receiveMedia: { offerToReceiveAudio: 1, offerToReceiveVideo: 1 - } + }, + sendVideoIfAvailable: signaling.getSendVideoIfAvailable() }); webrtc.emit('createdPeer', peer); peer.start(); @@ -934,16 +936,7 @@ var spreedPeerConnectionTable = []; app.disableScreensharingButton(); }); - OCA.SpreedMe.webrtc.webrtc.on('iceFailed', function (/* peer */) { - var signaling = OCA.SpreedMe.app.signaling; - if (!signaling.hasFeature("mcu")) { - // ICE restarts will be handled by "iceConnectionStateChange" - // above. - return; - } - - // For now assume the connection to the MCU is interrupted on ICE - // failures and force a reconnection of all streams. + var forceReconnect = function(signaling, flags) { if (ownPeer) { OCA.SpreedMe.webrtc.removePeers(ownPeer.id); OCA.SpreedMe.speakers.remove(ownPeer.id, true); @@ -952,13 +945,45 @@ var spreedPeerConnectionTable = []; ownPeer.end(); ownPeer = null; } + usersChanged(signaling, [], previousUsersInRoom); usersInCallMapping = {}; previousUsersInRoom = []; + // Reconnects with a new session id will trigger "usersChanged" // with the users in the room and that will re-establish the // peerconnection streams. - signaling.forceReconnect(true); + // If flags are undefined the current call flags are used. + signaling.forceReconnect(true, flags); + }; + + OCA.SpreedMe.webrtc.webrtc.on('videoOn', function () { + var signaling = OCA.SpreedMe.app.signaling; + if (signaling.getSendVideoIfAvailable()) { + return; + } + + // When enabling the local video if the video is not being sent a + // reconnection is forced to start sending it. + signaling.setSendVideoIfAvailable(true); + + var flags = signaling.getCurrentCallFlags(); + flags |= OCA.SpreedMe.app.FLAG_WITH_VIDEO; + + forceReconnect(signaling, flags); + }); + + OCA.SpreedMe.webrtc.webrtc.on('iceFailed', function (/* peer */) { + var signaling = OCA.SpreedMe.app.signaling; + if (!signaling.hasFeature("mcu")) { + // ICE restarts will be handled by "iceConnectionStateChange" + // above. + return; + } + + // For now assume the connection to the MCU is interrupted on ICE + // failures and force a reconnection of all streams. + forceReconnect(signaling); }); OCA.SpreedMe.webrtc.on('localMediaStarted', function (configuration) {