Browse Source

Allow receiver to receive connections without a stream, by injecting a dummy stream.

pull/206/head
Simon Eisenmann 10 years ago committed by Simon Eisenmann
parent
commit
a44cedc52d
  1. 114
      static/js/directives/audiovideo.js
  2. 5
      static/js/mediastream/peercall.js

114
static/js/directives/audiovideo.js

@ -38,8 +38,11 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
}; };
// Dummy stream. // Dummy stream.
var dummy = { var DummyStream = function() {};
id: "defaultDummyStream" DummyStream.prototype.id = "defaultDummyStream";
DummyStream.prototype.stop = function() {};
DummyStream.is = function(stream) {
return stream && stream.stop === DummyStream.prototype.stop;
}; };
$scope.container = $element[0]; $scope.container = $element[0];
@ -72,19 +75,28 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
} }
var callscope; var callscope;
var subscope;
if (calls.hasOwnProperty(currentcall.id)) { if (calls.hasOwnProperty(currentcall.id)) {
//console.log("xxx has call", id, currentcall.id); //console.log("xxx has call", id, currentcall.id);
callscope = calls[currentcall.id]; if (DummyStream.is(stream)) {
if (stream === dummy) {
return; return;
} }
callscope = calls[currentcall.id];
if (callscope.dummy) { if (callscope.dummy) {
// Current call has a dummy target. Use it directly. // Current call is marked as dummy. Use it directly.
callscope.dummy.$apply(function() { var dummyId = getStreamId(callscope.dummy, currentcall);
console.log("Replacing dummy with stream", id); subscope = streams[dummyId];
callscope.dummy.attachStream(stream); if (subscope) {
}); subscope.dummy = null;
callscope.dummy = null; delete streams[dummyId];
streams[id] = subscope;
safeApply(subscope, function(scope) {
console.log("Replacing dummy with stream", id);
scope.attachStream(stream);
});
} else {
console.warn("Scope marked as dummy but target stream not found", dummyId);
}
return; return;
} }
} else { } else {
@ -97,7 +109,6 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
} }
// Create scope for this stream. // Create scope for this stream.
var subscope;
subscope = callscope.$new(); subscope = callscope.$new();
callscope.streams++; callscope.streams++;
var peerid = subscope.peerid = currentcall.id; var peerid = subscope.peerid = currentcall.id;
@ -125,8 +136,8 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
console.log("Created stream scope", id); console.log("Created stream scope", id);
// If stream is a dummy, mark us in callscope. // If stream is a dummy, mark us in callscope.
if (stream === dummy) { if (DummyStream.is(stream)) {
callscope.dummy = subscope; callscope.dummy = stream;
} }
// Add created scope. // Add created scope.
@ -138,40 +149,49 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
clonedElement.data("peerid", scope.peerid); clonedElement.data("peerid", scope.peerid);
scope.element = clonedElement; scope.element = clonedElement;
scope.attachStream = function(stream) { scope.attachStream = function(stream) {
if (stream === dummy) { if (DummyStream.is(stream)) {
scope.withvideo = false;
scope.onlyaudio = true;
_.defer(function() {
scope.$emit("active", currentcall);
$scope.redraw();
});
return; return;
} else {
var video = clonedElement.find("video")[0];
$window.attachMediaStream(video, stream);
// Waiter callbacks also count as connected, as browser support (FireFox 25) is not setting state changes properly.
videoWaiter.wait(video, stream, function(withvideo) {
if (scope.destroyed) {
console.log("Abort wait for video on destroyed scope.");
return;
}
if (withvideo) {
scope.$apply(function($scope) {
$scope.withvideo = true;
$scope.onlyaudio = false;
});
} else {
console.info("Incoming stream has no video tracks.");
scope.$apply(function($scope) {
$scope.withvideo = false;
$scope.onlyaudio = true;
});
}
scope.$emit("active", currentcall);
$scope.redraw();
}, function() {
if (scope.destroyed) {
console.log("No longer wait for video on destroyed scope.");
return;
}
console.warn("We did not receive video data for remote stream", currentcall, stream, video);
scope.$emit("active", currentcall);
$scope.redraw();
});
scope.dummy = null;
} }
var video = clonedElement.find("video")[0];
$window.attachMediaStream(video, stream);
// Waiter callbacks also count as connected, as browser support (FireFox 25) is not setting state changes properly.
videoWaiter.wait(video, stream, function(withvideo) {
if (scope.destroyed) {
console.log("Abort wait for video on destroyed scope.");
return;
}
if (withvideo) {
scope.$apply(function($scope) {
$scope.withvideo = true;
});
} else {
console.info("Incoming stream has no video tracks.");
scope.$apply(function($scope) {
$scope.onlyaudio = true;
});
}
scope.$emit("active", currentcall);
$scope.redraw();
}, function() {
if (scope.destroyed) {
console.log("No longer wait for video on destroyed scope.");
return;
}
console.warn("We did not receive video data for remote stream", currentcall, stream, video);
scope.$emit("active", currentcall);
$scope.redraw();
});
scope.unattached = false; scope.unattached = false;
scope.dummy = false;
}; };
scope.doChat = function() { scope.doChat = function() {
$scope.$emit("startchat", currentcall.id, { $scope.$emit("startchat", currentcall.id, {
@ -323,6 +343,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
$window.reattachMediaStream($scope.miniVideo, $scope.localVideo); $window.reattachMediaStream($scope.miniVideo, $scope.localVideo);
$scope.haveStreams = true; $scope.haveStreams = true;
} }
if (stream === null) {
// Inject dummy stream.
stream = new DummyStream();
}
$scope.addRemoteStream(stream, currentcall); $scope.addRemoteStream(stream, currentcall);
}); });
@ -346,7 +370,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
case "connected": case "connected":
case "completed": case "completed":
case "failed": case "failed":
$scope.addRemoteStream(dummy, currentcall); $scope.addRemoteStream(new DummyStream(), currentcall);
break; break;
} }

5
static/js/mediastream/peercall.js

@ -142,13 +142,18 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
// reason we always trigger onRemoteStream added for all streams which are available // reason we always trigger onRemoteStream added for all streams which are available
// after the remote SDP was set successfully. // after the remote SDP was set successfully.
_.defer(_.bind(function() { _.defer(_.bind(function() {
var streams = 0;
_.each(peerconnection.getRemoteStreams(), _.bind(function(stream) { _.each(peerconnection.getRemoteStreams(), _.bind(function(stream) {
if (!this.streams.hasOwnProperty(stream.id) && (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. // 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); console.log("Adding stream after remote SDP success.", stream);
this.onRemoteStreamAdded(stream); this.onRemoteStreamAdded(stream);
streams++;
} }
}, this)); }, this));
if (streams === 0 && this.sdpConstraints.mandatory && (this.sdpConstraints.mandatory.OfferToReceiveAudio || this.sdpConstraints.mandatory.OfferToReceiveVideo)) {
this.e.triggerHandler("remoteStreamAdded", [null, this]);
}
}, this)); }, this));
}, this), _.bind(function(err) { }, this), _.bind(function(err) {
console.error("Set remote session description failed", err); console.error("Set remote session description failed", err);

Loading…
Cancel
Save