|
|
|
@ -22,7 +22,7 @@
@@ -22,7 +22,7 @@
|
|
|
|
|
"use strict"; |
|
|
|
|
define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/audiovideopeer.html', 'bigscreen', 'webrtc.adapter'], function($, _, template, templatePeer, BigScreen) { |
|
|
|
|
|
|
|
|
|
return ["$window", "$compile", "$filter", "mediaStream", "safeApply", "desktopNotify", "buddyData", "videoWaiter", "videoLayout", "animationFrame", function($window, $compile, $filter, mediaStream, safeApply, desktopNotify, buddyData, videoWaiter, videoLayout, animationFrame) { |
|
|
|
|
return ["$window", "$compile", "$filter", "mediaStream", "safeApply", "desktopNotify", "buddyData", "videoWaiter", "videoLayout", "animationFrame", "$timeout", "dummyStream", function($window, $compile, $filter, mediaStream, safeApply, desktopNotify, buddyData, videoWaiter, videoLayout, animationFrame, $timeout, DummyStream) { |
|
|
|
|
|
|
|
|
|
var peerTemplate = $compile(templatePeer); |
|
|
|
|
|
|
|
|
@ -33,19 +33,15 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -33,19 +33,15 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
|
|
|
|
|
var getStreamId = function(stream, currentcall) { |
|
|
|
|
var id = currentcall.id + "-" + stream.id; |
|
|
|
|
console.log("Created stream ID", id); |
|
|
|
|
//console.log("Created stream ID", id);
|
|
|
|
|
return id; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Dummy stream.
|
|
|
|
|
var dummy = { |
|
|
|
|
id: "defaultDummyStream" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
$scope.container = $element[0]; |
|
|
|
|
$scope.layoutparent = $element.parent(); |
|
|
|
|
|
|
|
|
|
$scope.remoteVideos = $element.find(".remoteVideos")[0]; |
|
|
|
|
$scope.localVideos = $element.find(".localVideos")[0]; |
|
|
|
|
$scope.localVideo = $element.find(".localVideo")[0]; |
|
|
|
|
$scope.miniVideo = $element.find(".miniVideo")[0]; |
|
|
|
|
$scope.mini = $element.find(".miniContainer")[0]; |
|
|
|
@ -63,33 +59,50 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -63,33 +59,50 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
$scope.addRemoteStream = function(stream, currentcall) { |
|
|
|
|
|
|
|
|
|
var id = getStreamId(stream, currentcall); |
|
|
|
|
console.log("New stream", id); |
|
|
|
|
|
|
|
|
|
if (streams.hasOwnProperty(id)) { |
|
|
|
|
console.warn("Cowardly refusing to add stream id twice", id, currentcall); |
|
|
|
|
console.warn("Cowardly refusing to add stream id twice", id); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var callscope; |
|
|
|
|
var subscope; |
|
|
|
|
|
|
|
|
|
// Dummy replacement support.
|
|
|
|
|
if (calls.hasOwnProperty(currentcall.id)) { |
|
|
|
|
subscope = calls[currentcall.id]; |
|
|
|
|
if (stream === dummy) { |
|
|
|
|
//console.log("xxx has call", id, currentcall.id);
|
|
|
|
|
if (DummyStream.is(stream)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (subscope.dummy) { |
|
|
|
|
subscope.$apply(function() { |
|
|
|
|
subscope.attachStream(stream); |
|
|
|
|
}); |
|
|
|
|
callscope = calls[currentcall.id]; |
|
|
|
|
if (callscope.dummy) { |
|
|
|
|
// Current call is marked as dummy. Use it directly.
|
|
|
|
|
var dummyId = getStreamId(callscope.dummy, currentcall); |
|
|
|
|
subscope = streams[dummyId]; |
|
|
|
|
if (subscope) { |
|
|
|
|
subscope.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; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
//console.log("xxx create call scope", currentcall.id, id);
|
|
|
|
|
// Create scope.
|
|
|
|
|
subscope = $scope.$new(); |
|
|
|
|
calls[currentcall.id] = subscope; |
|
|
|
|
callscope = $scope.$new(); |
|
|
|
|
calls[currentcall.id] = callscope; |
|
|
|
|
callscope.streams = 0; |
|
|
|
|
console.log("Created call scope", id); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//console.log("Add remote stream to scope", stream.id, stream, currentcall);
|
|
|
|
|
// Create scope for this stream.
|
|
|
|
|
subscope = callscope.$new(); |
|
|
|
|
callscope.streams++; |
|
|
|
|
var peerid = subscope.peerid = currentcall.id; |
|
|
|
|
buddyData.push(peerid); |
|
|
|
|
subscope.unattached = true; |
|
|
|
@ -100,57 +113,76 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -100,57 +113,76 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
console.log("Stream scope is now active", id, peerid); |
|
|
|
|
}); |
|
|
|
|
subscope.$on("$destroy", function() { |
|
|
|
|
if (subscope.destroyed) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
console.log("Destroyed scope for stream", id, peerid); |
|
|
|
|
subscope.destroyed = true; |
|
|
|
|
callscope.streams--; |
|
|
|
|
if (callscope.streams < 1) { |
|
|
|
|
callscope.$destroy(); |
|
|
|
|
delete calls[peerid]; |
|
|
|
|
console.log("Destroyed scope for call", peerid, id); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
console.log("Created stream scope", id, peerid); |
|
|
|
|
console.log("Created stream scope", id); |
|
|
|
|
|
|
|
|
|
// Add created scope.
|
|
|
|
|
if (stream === dummy) { |
|
|
|
|
subscope.dummy = true; |
|
|
|
|
// If stream is a dummy, mark us in callscope.
|
|
|
|
|
if (DummyStream.is(stream)) { |
|
|
|
|
callscope.dummy = stream; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add created scope.
|
|
|
|
|
streams[id] = subscope; |
|
|
|
|
|
|
|
|
|
// Render template.
|
|
|
|
|
peerTemplate(subscope, function(clonedElement, scope) { |
|
|
|
|
$($scope.remoteVideos).append(clonedElement); |
|
|
|
|
clonedElement.data("peerid", scope.peerid); |
|
|
|
|
scope.element = clonedElement; |
|
|
|
|
scope.attachStream = function(stream) { |
|
|
|
|
if (stream === dummy) { |
|
|
|
|
if (DummyStream.is(stream)) { |
|
|
|
|
scope.withvideo = false; |
|
|
|
|
scope.onlyaudio = true; |
|
|
|
|
$timeout(function() { |
|
|
|
|
scope.$emit("active", currentcall); |
|
|
|
|
$scope.redraw(); |
|
|
|
|
}); |
|
|
|
|
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.dummy = false; |
|
|
|
|
}; |
|
|
|
|
scope.doChat = function() { |
|
|
|
|
$scope.$emit("startchat", currentcall.id, { |
|
|
|
@ -159,27 +191,23 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -159,27 +191,23 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
scope.attachStream(stream); |
|
|
|
|
$($scope.remoteVideos).append(clonedElement); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
$scope.removeRemoteStream = function(stream, currentcall) { |
|
|
|
|
|
|
|
|
|
//console.log("remove stream", stream, stream.id, currentcall);
|
|
|
|
|
var id = getStreamId(stream, currentcall); |
|
|
|
|
console.log("Stream removed", id); |
|
|
|
|
|
|
|
|
|
var subscope = streams[id]; |
|
|
|
|
if (subscope) { |
|
|
|
|
buddyData.pop(currentcall.id); |
|
|
|
|
delete streams[id]; |
|
|
|
|
//console.log("remove scope", subscope);
|
|
|
|
|
if (subscope.element) { |
|
|
|
|
subscope.element.remove(); |
|
|
|
|
} |
|
|
|
|
var callscope = calls[currentcall.id]; |
|
|
|
|
if (subscope === callscope) { |
|
|
|
|
delete calls[currentcall.id]; |
|
|
|
|
} |
|
|
|
|
subscope.$destroy(); |
|
|
|
|
$scope.redraw(); |
|
|
|
|
} |
|
|
|
@ -202,6 +230,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -202,6 +230,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
$element.addClass("active"); |
|
|
|
|
//console.log("active 3");
|
|
|
|
|
_.delay(function() { |
|
|
|
|
$scope.localVideos.style.opacity = 0; |
|
|
|
|
$scope.localVideo.style.opacity = 0; |
|
|
|
|
$scope.localVideo.src = ""; |
|
|
|
|
}, 500); |
|
|
|
@ -228,6 +257,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -228,6 +257,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
|
|
|
|
|
mediaStream.webrtc.e.on("usermedia", function(event, usermedia) { |
|
|
|
|
|
|
|
|
|
if (!usermedia || !usermedia.started) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//console.log("XXXX XXXXXXXXXXXXXXXXXXXXX usermedia event", usermedia);
|
|
|
|
|
if ($scope.haveStreams) { |
|
|
|
|
|
|
|
|
@ -244,6 +277,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -244,6 +277,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if ($scope.localVideo.videoWidth > 0) { |
|
|
|
|
console.log("Local video size: ", $scope.localVideo.videoWidth, $scope.localVideo.videoHeight); |
|
|
|
|
$scope.localVideo.style.opacity = 1; |
|
|
|
|
$scope.redraw(); |
|
|
|
|
} else { |
|
|
|
@ -279,6 +313,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -279,6 +313,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
$($scope.remoteVideos).children(".remoteVideo").remove(); |
|
|
|
|
}, 1500); |
|
|
|
|
$($scope.mini).removeClass("visible"); |
|
|
|
|
$scope.localVideos.style.opacity = 1; |
|
|
|
|
$scope.localVideo.style.opacity = 0; |
|
|
|
|
$scope.remoteVideos.style.opacity = 0; |
|
|
|
|
$element.removeClass('active'); |
|
|
|
@ -300,6 +335,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -300,6 +335,10 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
$window.reattachMediaStream($scope.miniVideo, $scope.localVideo); |
|
|
|
|
$scope.haveStreams = true; |
|
|
|
|
} |
|
|
|
|
if (stream === null) { |
|
|
|
|
// Inject dummy stream.
|
|
|
|
|
stream = new DummyStream(); |
|
|
|
|
} |
|
|
|
|
$scope.addRemoteStream(stream, currentcall); |
|
|
|
|
|
|
|
|
|
}); |
|
|
|
@ -323,7 +362,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -323,7 +362,7 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
case "connected": |
|
|
|
|
case "completed": |
|
|
|
|
case "failed": |
|
|
|
|
$scope.addRemoteStream(dummy, currentcall); |
|
|
|
|
$scope.addRemoteStream(new DummyStream(), currentcall); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -378,7 +417,14 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
@@ -378,7 +417,14 @@ define(['jquery', 'underscore', 'text!partials/audiovideo.html', 'text!partials/
|
|
|
|
|
width: scope.layoutparent.width(), |
|
|
|
|
height: scope.layoutparent.height() |
|
|
|
|
} |
|
|
|
|
var again = videoLayout.update(getRendererName(), size, scope, controller); |
|
|
|
|
var name; |
|
|
|
|
if (size.width < 1 || size.height < 1) { |
|
|
|
|
// Use invisible renderer when no size available.
|
|
|
|
|
name = "invisible"; |
|
|
|
|
} else { |
|
|
|
|
name = getRendererName(); |
|
|
|
|
} |
|
|
|
|
var again = videoLayout.update(name, size, scope, controller); |
|
|
|
|
if (again) { |
|
|
|
|
// Layout needs a redraw.
|
|
|
|
|
needsRedraw = true; |
|
|
|
|