diff --git a/static/js/directives/audiovideo.js b/static/js/directives/audiovideo.js index dbca88b3..1504f37c 100644 --- a/static/js/directives/audiovideo.js +++ b/static/js/directives/audiovideo.js @@ -27,6 +27,11 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { var streams = {}; + var getStreamId = function(stream, currentcall) { + var id = currentcall.id + "-" + stream.id; + console.log("Created stream ID", id); + return id; + }; $scope.container = $element.get(0); $scope.layoutparent = $element.parent(); @@ -48,8 +53,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ $scope.addRemoteStream = function(stream, currentcall) { - if (streams.hasOwnProperty(stream.id)) { - console.warn("Cowardly refusing to add stream id twice", stream.id, currentcall); + var id = getStreamId(stream, currentcall); + + if (streams.hasOwnProperty(id)) { + console.warn("Cowardly refusing to add stream id twice", id, currentcall); return; } @@ -62,16 +69,16 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ subscope.onlyaudio = false; subscope.destroyed = false; subscope.$on("active", function() { - console.log("Stream scope is now active", stream.id, peerid); + console.log("Stream scope is now active", id, peerid); }); subscope.$on("$destroy", function() { - console.log("Destroyed scope for stream", stream.id, peerid); + console.log("Destroyed scope for stream", id, peerid); subscope.destroyed = true; }); - console.log("Created stream scope", stream.id, peerid); + console.log("Created stream scope", id, peerid); // Add created scope. - streams[stream.id] = subscope; + streams[id] = subscope; // Render template. peerTemplate(subscope, function(clonedElement, scope) { @@ -120,10 +127,12 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/ $scope.removeRemoteStream = function(stream, currentcall) { //console.log("remove stream", stream, stream.id, currentcall); - var subscope = streams[stream.id]; + var id = getStreamId(stream, currentcall); + + var subscope = streams[id]; if (subscope) { buddyData.pop(currentcall.id); - delete streams[stream.id]; + delete streams[id]; //console.log("remove scope", subscope); if (subscope.element) { subscope.element.remove(); diff --git a/static/js/mediastream/peercall.js b/static/js/mediastream/peercall.js index d2ee4e3e..d7f14b38 100644 --- a/static/js/mediastream/peercall.js +++ b/static/js/mediastream/peercall.js @@ -138,7 +138,7 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection // after the remote SDP was set successfully. _.defer(_.bind(function() { _.each(peerconnection.getRemoteStreams(), _.bind(function(stream) { - if (!this.streams.hasOwnProperty(stream) && (stream.getAudioTracks().length > 0 || stream.getVideoTracks().length > 0)) { + if (!this.streams.hasOwnProperty(stream.id) && (stream.getAudioTracks().length > 0 || stream.getVideoTracks().length > 0)) { // NOTE(longsleep): Add stream here when it has at least one audio or video track, to avoid FF >= 33 to add it multiple times. console.log("Adding stream after remote SDP success.", stream); this.onRemoteStreamAdded(stream); diff --git a/static/js/mediastream/peerconnection.js b/static/js/mediastream/peerconnection.js index 3a7abd4b..971b83ec 100644 --- a/static/js/mediastream/peerconnection.js +++ b/static/js/mediastream/peerconnection.js @@ -70,13 +70,22 @@ define(['jquery', 'underscore', 'webrtc.adapter'], function($, _) { // for example https://bugzilla.mozilla.org/show_bug.cgi?id=998546. pc.onaddstream = _.bind(this.onRemoteStreamAdded, this); pc.onremovestream = _.bind(this.onRemoteStreamRemoved, this); - // NOTE(longsleep): onnegotiationneeded is not supported by Firefox - // https://bugzilla.mozilla.org/show_bug.cgi?id=840728 - pc.onnegotiationneeded = _.bind(this.onNegotiationNeeded, this); + if (webrtcDetectedBrowser === "firefox") { + // NOTE(longsleep): onnegotiationneeded is not supported by Firefox. We trigger it + // manually when a stream is added or removed. + // https://bugzilla.mozilla.org/show_bug.cgi?id=840728 + this.negotiationNeeded = _.bind(function() { + if (this.currentcall.initiate) { + // Trigger onNegotiationNeeded once for Firefox. + console.log("Negotiation needed."); + this.onNegotiationNeeded({target: this.pc}); + } + }, this); + } else { + pc.onnegotiationneeded = _.bind(this.onNegotiationNeeded, this); + } pc.ondatachannel = _.bind(this.onDatachannel, this); pc.onsignalingstatechange = function(event) { - // XXX(longsleep): Remove this or handle it in a real function. - // XXX(longsleep): Firefox 25 does send event as a string (like stable). console.debug("Signaling state changed", pc.signalingState); }; // NOTE(longsleep): @@ -113,6 +122,10 @@ define(['jquery', 'underscore', 'webrtc.adapter'], function($, _) { }; + PeerConnection.prototype.negotiationNeeded = function() { + // Per default this does nothing as the browser is expected to handle this. + }; + PeerConnection.prototype.createDatachannel = function(label, init) { if (!label) { @@ -226,12 +239,8 @@ define(['jquery', 'underscore', 'webrtc.adapter'], function($, _) { PeerConnection.prototype.onNegotiationNeeded = function(event) { - // XXX(longsleep): Renegotiation seems to break video streams on Chrome 31. - // XXX(longsleep): Renegotiation can happen from both sides, meaning this - // could switch offer/answer side - oh crap. var peerconnection = event.target; if (peerconnection === this.pc) { - //console.log("Negotiation needed.", peerconnection.remoteDescription, peerconnection.iceConnectionState, peerconnection.signalingState, this); this.currentcall.onNegotiationNeeded(); } @@ -271,12 +280,14 @@ define(['jquery', 'underscore', 'webrtc.adapter'], function($, _) { PeerConnection.prototype.addStream = function() { + _.defer(this.negotiationNeeded); return this.pc.addStream.apply(this.pc, arguments); }; PeerConnection.prototype.removeStream = function() { + _.defer(this.negotiationNeeded); return this.pc.removeStream.apply(this.pc, arguments); };