Browse Source

Merge branch 'release-0.24'

pull/256/head v0.24.9
Simon Eisenmann 10 years ago
parent
commit
0da63dd9df
  1. 2
      .javascript_ignore
  2. 1
      .travis.yml
  3. 52
      Makefile.am
  4. 3
      README.md
  5. 1
      html/head.html
  6. 1
      html/sandboxes/odfcanvas_sandbox.html
  7. 1
      html/sandboxes/pdfcanvas_sandbox.html
  8. 2
      package.json
  9. 3
      src/hooks/pre-commit.hook
  10. 1
      static/js/base.js
  11. 18
      static/js/directives/buddylist.js
  12. 27
      static/js/directives/buddypicturecapture.js
  13. 24
      static/js/directives/buddypictureupload.js
  14. 32
      static/js/directives/chat.js
  15. 22
      static/js/directives/youtubevideo.js
  16. 165
      static/js/libs/webrtc.adapter.js
  17. 4
      static/js/main.js
  18. 15
      static/js/mediastream/peercall.js
  19. 8
      static/js/mediastream/peerscreenshare.js
  20. 8
      static/js/mediastream/peerxfer.js
  21. 4
      static/js/mediastream/tokens.js
  22. 3
      static/js/mediastream/utils.js
  23. 17
      static/js/mediastream/webrtc.js
  24. 2
      static/js/services/alertify.js
  25. 16
      static/js/services/animationframe.js
  26. 2
      static/js/services/desktopnotify.js
  27. 13
      static/js/services/filedownload.js
  28. 4
      static/js/services/geolocation.js
  29. 34
      static/js/services/mediadevices.js
  30. 29
      static/js/services/mediasources.js
  31. 5
      static/js/services/mediastream.js
  32. 20
      static/js/services/rooms.js
  33. 2
      static/partials/chat.html

2
.javascript_ignore

@ -1 +1 @@ @@ -1 +1 @@
static/js/libs/**.js
static/js/libs/

1
.travis.yml

@ -7,6 +7,7 @@ go: @@ -7,6 +7,7 @@ go:
- 1.2
- 1.3
- 1.4
- 1.5
- tip
env:

52
Makefile.am

@ -124,32 +124,32 @@ release: OUTPUT = $(DIST_BIN) @@ -124,32 +124,32 @@ release: OUTPUT = $(DIST_BIN)
release: $(DIST_BIN) binary releaseassets
install:
@echo "Installing binaries to: $(BIN)"
@echo "Installing static resources to: $(SHARE)"
$(INSTALL) -d $(BIN)
$(INSTALL) -d $(SHARE)/www/html
$(INSTALL) -d $(SHARE)/www/html/sandboxes
$(INSTALL) -d $(SHARE)/www/static
$(INSTALL) -d $(SHARE)/www/static/img
$(INSTALL) -d $(SHARE)/www/static/sounds
$(INSTALL) -d $(SHARE)/www/static/fonts
$(INSTALL) -d $(SHARE)/www/static/translation
$(INSTALL) -d $(SHARE)/www/static/css
$(INSTALL) -d $(SHARE)/www/static/js/libs/pdf
$(INSTALL) -d $(SHARE)/www/static/js/sandboxes
$(INSTALL) bin/$(EXENAME) $(BIN)
$(INSTALL) html/*.html $(SHARE)/www/html
$(INSTALL) html/sandboxes/*.html $(SHARE)/www/html/sandboxes
$(INSTALL) static/img/* $(SHARE)/www/static/img
$(INSTALL) static/sounds/* $(SHARE)/www/static/sounds
$(INSTALL) static/fonts/* $(SHARE)/www/static/fonts
$(INSTALL) static/translation/* $(SHARE)/www/static/translation
$(INSTALL) static/css/* $(SHARE)/www/static/css
$(INSTALL) -D static/js/libs/require/require.js $(SHARE)/www/static/js/libs/require/require.js
$(INSTALL) $(OUTPUT_JS)/*.js $(SHARE)/www/static/js
$(INSTALL) $(OUTPUT_JS)/libs/pdf/*.js $(SHARE)/www/static/js/libs/pdf
$(INSTALL) -D static/js/libs/webodf.js $(SHARE)/www/static/js/libs/webodf.js
$(INSTALL) $(OUTPUT_JS)/sandboxes/*.js $(SHARE)/www/static/js/sandboxes
@echo "Installing binaries to: $(DESTDIR)$(BIN)"
@echo "Installing static resources to: $(DESTDIR)$(SHARE)"
$(INSTALL) -d $(DESTDIR)$(BIN)
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/html
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/html/sandboxes
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/img
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/sounds
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/fonts
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/translation
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/css
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/js/libs/pdf
$(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/js/sandboxes
$(INSTALL) bin/$(EXENAME) $(DESTDIR)$(BIN)
$(INSTALL) html/*.html $(DESTDIR)$(SHARE)/www/html
$(INSTALL) html/sandboxes/*.html $(DESTDIR)$(SHARE)/www/html/sandboxes
$(INSTALL) static/img/* $(DESTDIR)$(SHARE)/www/static/img
$(INSTALL) static/sounds/* $(DESTDIR)$(SHARE)/www/static/sounds
$(INSTALL) static/fonts/* $(DESTDIR)$(SHARE)/www/static/fonts
$(INSTALL) static/translation/* $(DESTDIR)$(SHARE)/www/static/translation
$(INSTALL) static/css/* $(DESTDIR)$(SHARE)/www/static/css
$(INSTALL) -D static/js/libs/require/require.js $(DESTDIR)$(SHARE)/www/static/js/libs/require/require.js
$(INSTALL) $(OUTPUT_JS)/*.js $(DESTDIR)$(SHARE)/www/static/js
$(INSTALL) $(OUTPUT_JS)/libs/pdf/*.js $(DESTDIR)$(SHARE)/www/static/js/libs/pdf
$(INSTALL) -D static/js/libs/webodf.js $(DESTDIR)$(SHARE)/www/static/js/libs/webodf.js
$(INSTALL) $(OUTPUT_JS)/sandboxes/*.js $(DESTDIR)$(SHARE)/www/static/js/sandboxes
clean:
$(GO) clean -i -r app/... 2>/dev/null || true

3
README.md

@ -102,6 +102,9 @@ Styles can be found in src/styles. Translations are found in src/i18n. @@ -102,6 +102,9 @@ Styles can be found in src/styles. Translations are found in src/i18n.
Each folder has its own Makefile to build the corresponding files. Check the
Makefile.am templates for available make targets.
Javascript console logging is automatically _disabled_ and can be enabled by
adding the query parameter `debug` to your url `https://my_url?debug`.
## Running server for development

1
html/head.html

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="referrer" content="no-referrer">
<base href="<%.Cfg.B%>">
<%if.Csp%><link rel="stylesheet" type="text/css" href="<%.Cfg.S%>/css/csp.min.css"><%end%>
<link rel="stylesheet" type="text/css" href="<%.Cfg.S%>/css/bootstrap.min.css">

1
html/sandboxes/odfcanvas_sandbox.html

@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
user-select:none;
-webkit-user-select:none;
-moz-user-select:none;
background:white;
}
</style>
</head>

1
html/sandboxes/pdfcanvas_sandbox.html

@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
margin:0 auto;
position:relative;
display:none;
background:white;
}
</style>
</head>

2
package.json

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
{
"private": true,
"dependencies": {
"autoprefixer": ">= 3.1.0",
"autoprefixer": ">= 3.1.0 <= 5.2.1",
"po2json": ">= 0.4.1",
"jshint": ">= 2.5.5"
}

3
src/hooks/pre-commit.hook

@ -27,7 +27,6 @@ echo "========================================================================== @@ -27,7 +27,6 @@ echo "==========================================================================
fi
done
for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "\.js$"` ; do
case "$file" in
*/libs/*)
@ -39,7 +38,7 @@ for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep " @@ -39,7 +38,7 @@ for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "
*)
echo "Checking ${file}"
nf=`git checkout-index --temp ${file} | cut -f 1`
jshint --config .jshint "${nf}"
PATH="node_modules/.bin:${PATH}" jshint --config .jshint "${nf}"
r=$?
rm "${nf}"
if [ $r != 0 ] ; then

1
static/js/base.js

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
*
*/
"use strict";
define([ // Helper module to put non dependency base libraries together.
'modernizr',
'moment',

18
static/js/directives/buddylist.js

@ -29,10 +29,19 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -29,10 +29,19 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
var buddylist = $scope.buddylist = buddyList.buddylist($element, $scope, {});
var onJoined = _.bind(buddylist.onJoined, buddylist);
var onLeft = _.bind(buddylist.onLeft, buddylist);
var onStatus = _.bind(buddylist.onStatus, buddylist);
var onContactAdded = _.bind(buddylist.onContactAdded, buddylist);
var onContactRemoved = _.bind(buddylist.onContactRemoved, buddylist);
var onContactUpdated = _.bind(buddylist.onContactUpdated, buddylist);
var inRoom = false;
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
var inRoom = false;
var updateBuddyListVisibility = function() {
if (inRoom && !$scope.peer) {
$scope.layout.buddylist = true;
@ -87,13 +96,6 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -87,13 +96,6 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
};
var buddylist = $scope.buddylist = buddyList.buddylist($element, $scope, {});
var onJoined = _.bind(buddylist.onJoined, buddylist);
var onLeft = _.bind(buddylist.onLeft, buddylist);
var onStatus = _.bind(buddylist.onStatus, buddylist);
var onContactAdded = _.bind(buddylist.onContactAdded, buddylist);
var onContactRemoved = _.bind(buddylist.onContactRemoved, buddylist);
var onContactUpdated = _.bind(buddylist.onContactUpdated, buddylist);
api.e.on("received.userleftorjoined", function(event, dataType, data) {
if (dataType === "Left") {
onLeft(data);

27
static/js/directives/buddypicturecapture.js

@ -27,6 +27,17 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -27,6 +27,17 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
var controller = ['$scope', 'safeApply', '$timeout', '$q', "mediaDevices", "userMedia", function($scope, safeApply, $timeout, $q, mediaDevices, userMedia) {
var localStream = null;
var delayToTakePicture = 3000;
var countDownFrom = 3;
var takePictureCountDown;
var writeVideoToCanvas;
var writePreviewPic;
var makePicture;
var videoStop;
var videoStart;
// Buddy picutre capture size.
$scope.captureSize = {
width: 128,
@ -41,12 +52,8 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -41,12 +52,8 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
$scope.canvasPic = null;
$scope.canvasPrev = null;
var localStream = null;
var delayToTakePicture = 3000;
var countDownFrom = 3;
// Counts down from start to 1
var takePictureCountDown = function(start, delayTotal) {
takePictureCountDown = function(start, delayTotal) {
$scope.countingDown = true;
$scope.countdown = {};
$scope.countdown.num = start;
@ -63,7 +70,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -63,7 +70,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}
};
var writeVideoToCanvas = function(canvas) {
writeVideoToCanvas = function(canvas) {
var videoWidth = $scope.video.videoWidth;
var videoHeight = $scope.video.videoHeight;
@ -89,12 +96,12 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -89,12 +96,12 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
};
var writePreviewPic = function() {
writePreviewPic = function() {
writeVideoToCanvas($scope.canvasPrev);
$scope.preview = $scope.canvasPrev.toDataURL("image/jpeg");
};
var makePicture = function(stream, cntFrom, delayTotal) {
makePicture = function(stream, cntFrom, delayTotal) {
takePictureCountDown(cntFrom, delayTotal);
$timeout(function() {
$scope.flash.addClass("flash");
@ -107,7 +114,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -107,7 +114,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}, delayTotal);
};
var videoStop = function(stream, video) {
videoStop = function(stream, video) {
if (stream) {
video.pause();
userMedia.stopUserMediaStream(stream);
@ -115,7 +122,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct @@ -115,7 +122,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}
};
var videoStart = function() {
videoStart = function() {
$scope.waitingForPermission = true;
var videoConstraints = true;
var videoAllowed = $q.defer();

24
static/js/directives/buddypictureupload.js

@ -39,8 +39,16 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -39,8 +39,16 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
var previewWidth = 205;
var previewHeight = 205;
$scope.maxUploadMb = 8;
var maxUploadBytes = $scope.maxUploadMb * 1024 * 1024;
var maxUploadBytes = 8388608; // 8MB
var completedUpload;
var setUploadImageDimension;
var getAutoFitDimensions;
var getScaledDimensions;
var writePictureToCanvas;
var clearPicture;
$scope.maxUploadMb = maxUploadBytes / 1024 / 1024;
$scope.showUploadPicture = false;
$scope.previewUpload = false;
$scope.imgData = null;
@ -54,11 +62,11 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -54,11 +62,11 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
$scope.aspectRatio = 1;
var completedUpload = function() {
completedUpload = function() {
$scope.upload.status = 100;
};
var setUploadImageDimension = function(data) {
setUploadImageDimension = function(data) {
$scope.prevImage.onload = function() {
// clear old dimensions
this.style.cssText = null;
@ -76,7 +84,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -76,7 +84,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
// Auto fit by smallest dimension
var getAutoFitDimensions = function(from, to) {
getAutoFitDimensions = function(from, to) {
if (!from.width && !from.height && !to.width && !to.height) {
return null;
}
@ -94,7 +102,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -94,7 +102,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
// (image, canvas) -> object
var getScaledDimensions = function(from, to) {
getScaledDimensions = function(from, to) {
if (!from.style.width && !from.style.height && !to.width && !to.height) {
return null;
}
@ -120,7 +128,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -120,7 +128,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
return {width: width, height: height, x: x, y: y};
};
var writePictureToCanvas = function(canvas) {
writePictureToCanvas = function(canvas) {
var img = $scope.prevImage;
var dim = getScaledDimensions(img, canvas);
var context = canvas.getContext("2d");
@ -129,7 +137,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi @@ -129,7 +137,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
//console.log('writeUploadToCanvas', dim);
};
var clearPicture = function() {
clearPicture = function() {
$(".file-input-name").empty();
$scope.imgData = null;
$scope.prevImage.src = "";

32
static/js/directives/chat.js

@ -44,6 +44,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -44,6 +44,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
$scope.currentRoom = null;
$scope.currentRoomActive = false;
$scope.maxMessageSize = maxMessageSize;
$scope.autoFocusDisabled = false;
$scope.getVisibleRooms = function() {
var res = [];
@ -415,11 +416,6 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -415,11 +416,6 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
pane.append(clonedElement);
$scope.element = clonedElement;
$scope.visible = true;
if (options.autofocus) {
_.defer(function() {
$scope.$broadcast("focus");
});
}
var sendFiles = function(files) {
_.each(files, function(f) {
@ -461,18 +457,16 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -461,18 +457,16 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
subscope.enabled = true;
}
}
if (options.autofocus && subscope.visible) {
subscope.$broadcast("focus");
}
}
if (!options.noactivate) {
scope.activateRoom(subscope.id, true);
scope.activateRoom(subscope.id, true, !!options.autofocus);
}
if (options.restore && !options.noenable) {
if (!scope.layout.chat) {
scope.autoFocusDisabled = true;
scope.layout.chat = true;
}
}
@ -524,7 +518,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -524,7 +518,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
scope.layout.chatMaximized = !scope.layout.chatMaximized;
};
scope.activateRoom = function(id, active) {
scope.activateRoom = function(id, active, autofocus) {
var subscope = controller.rooms[id];
if (!subscope) {
return;
@ -555,6 +549,13 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -555,6 +549,13 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
if (flip) {
pane.toggleClass("flip");
}
if (active && autofocus && !scope.autoFocusDisabled) {
_.defer(function() {
if (scope.layout.chat) {
subscope.$broadcast("focus");
}
});
}
};
scope.deactivateRoom = function() {
@ -566,13 +567,22 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro @@ -566,13 +567,22 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
pane.removeClass("flip");
}
scope.layout.chatMaximized = false;
if (chat) {
if (!scope.autoFocusDisabled) {
if (scope.currentRoom && scope.currentRoom.active) {
scope.activateRoom(scope.currentRoom.id, true, true);
}
} else {
scope.autoFocusDisabled = false;
}
}
});
scope.$on("room.updated", function(event, room) {
var subscope = scope.showGroupRoom(null, {
restore: true,
noenable: true,
noactivate: true
noactivate: !!scope.currentRoomActive
});
if (scope.currentRoomName != room.Name) {
var msg = $("<span>").text(translation._("You are now in room %s ...", room.Name));

22
static/js/directives/youtubevideo.js

@ -106,6 +106,16 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo @@ -106,6 +106,16 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
var initialState = null;
var sandboxApi = null;
var peers = {};
var youtubevideos = [];
var youtubevideoCount = 0;
var currentToken = null;
var tokenHandler = null;
var mediaStreamSendYouTubeVideo;
var connector;
var updater;
var createSandboxApi = function(force, template) {
if (sandboxApi && force) {
sandboxApi.destroy();
@ -475,13 +485,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo @@ -475,13 +485,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
}
});
var peers = {};
var youtubevideos = [];
var youtubevideoCount = 0;
var currentToken = null;
var tokenHandler = null;
var mediaStreamSendYouTubeVideo = function(peercall, token, params) {
mediaStreamSendYouTubeVideo = function(peercall, token, params) {
mediaStream.api.apply("sendYouTubeVideo", {
send: function(type, data) {
if (!peercall.peerconnection.datachannelReady) {
@ -495,7 +499,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo @@ -495,7 +499,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
})(peercall.id, token, params);
};
var connector = function(token, peercall) {
connector = function(token, peercall) {
if (peers.hasOwnProperty(peercall.id)) {
// Already got a connection.
return;
@ -522,7 +526,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo @@ -522,7 +526,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
};
// Updater function to bring in new calls.
var updater = function(event, state, currentcall) {
updater = function(event, state, currentcall) {
switch (state) {
case "completed":
case "connected":

165
static/js/libs/webrtc.adapter.js

@ -30,6 +30,8 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT @@ -30,6 +30,8 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
@ -39,24 +41,79 @@ var webrtcMinimumVersion = null; @@ -39,24 +41,79 @@ var webrtcMinimumVersion = null;
var webrtcUtils = {
log: function() {
// suppress console.log output when being included as a module.
if (!(typeof module !== 'undefined' ||
typeof require === 'function') && (typeof define === 'function')) {
console.log.apply(console, arguments);
if (typeof module !== 'undefined' ||
typeof require === 'function' && typeof define === 'function') {
return;
}
console.log.apply(console, arguments);
},
extractVersion: function(uastring, expr, pos) {
var match = uastring.match(expr);
return match && match.length >= pos && parseInt(match[pos], 10);
}
};
/*
function trace(text) {
// This function is used for logging.
if (text[text.length - 1] === '\n') {
text = text.substring(0, text.length - 1);
}
if (window.performance) {
var now = (window.performance.now() / 1000).toFixed(3);
webrtcUtils.log(now + ': ' + text);
} else {
webrtcUtils.log(text);
}
}
*/
if (typeof window === 'object') {
if (window.HTMLMediaElement &&
!('srcObject' in window.HTMLMediaElement.prototype)) {
// Shim the srcObject property, once, when HTMLMediaElement is found.
Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
get: function() {
// If prefixed srcObject property exists, return it.
// Otherwise use the shimmed property, _srcObject
return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;
},
set: function(stream) {
if ('mozSrcObject' in this) {
this.mozSrcObject = stream;
} else {
// Use _srcObject as a private property for this shim
this._srcObject = stream;
// TODO: revokeObjectUrl(this.src) when !stream to release resources?
this.src = URL.createObjectURL(stream);
}
}
});
}
// Proxy existing globals
getUserMedia = window.navigator && window.navigator.getUserMedia;
}
// Attach a media stream to an element.
attachMediaStream = function(element, stream) {
element.srcObject = stream;
};
reattachMediaStream = function(to, from) {
to.srcObject = from.srcObject;
};
if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('This does not appear to be a browser');
webrtcDetectedBrowser = 'not a browser';
} else if (navigator.mozGetUserMedia) {
} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {
webrtcUtils.log('This appears to be Firefox');
webrtcDetectedBrowser = 'firefox';
// the detected firefox version.
webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
/Firefox\/([0-9]+)\./, 1);
// the minimum firefox version still supported by adapter.
webrtcMinimumVersion = 31;
@ -88,14 +145,18 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -88,14 +145,18 @@ if (typeof window === 'undefined' || !window.navigator) {
pcConfig.iceServers = newIceServers;
}
}
return new mozRTCPeerConnection(pcConfig, pcConstraints);
return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
};
// The RTCSessionDescription object.
window.RTCSessionDescription = mozRTCSessionDescription;
if (!window.RTCSessionDescription) {
window.RTCSessionDescription = mozRTCSessionDescription;
}
// The RTCIceCandidate object.
window.RTCIceCandidate = mozRTCIceCandidate;
if (!window.RTCIceCandidate) {
window.RTCIceCandidate = mozRTCIceCandidate;
}
// getUserMedia constraints shim.
getUserMedia = function(constraints, onSuccess, onError) {
@ -168,8 +229,8 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -168,8 +229,8 @@ if (typeof window === 'undefined' || !window.navigator) {
navigator.mediaDevices.enumerateDevices || function() {
return new Promise(function(resolve) {
var infos = [
{kind: 'audioinput', deviceId: 'default', label:'', groupId:''},
{kind: 'videoinput', deviceId: 'default', label:'', groupId:''}
{kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
{kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
];
resolve(infos);
});
@ -180,7 +241,7 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -180,7 +241,7 @@ if (typeof window === 'undefined' || !window.navigator) {
var orgEnumerateDevices =
navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
navigator.mediaDevices.enumerateDevices = function() {
return orgEnumerateDevices().catch(function(e) {
return orgEnumerateDevices().then(undefined, function(e) {
if (e.name === 'NotFoundError') {
return [];
}
@ -188,30 +249,27 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -188,30 +249,27 @@ if (typeof window === 'undefined' || !window.navigator) {
});
};
}
// Attach a media stream to an element.
attachMediaStream = function(element, stream) {
element.mozSrcObject = stream;
};
reattachMediaStream = function(to, from) {
to.mozSrcObject = from.mozSrcObject;
};
} else if (navigator.webkitGetUserMedia) {
} else if (navigator.webkitGetUserMedia && window.webkitRTCPeerConnection) {
webrtcUtils.log('This appears to be Chrome');
webrtcDetectedBrowser = 'chrome';
// the detected chrome version.
webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
/Chrom(e|ium)\/([0-9]+)\./, 2);
// the minimum chrome version still supported by adapter.
webrtcMinimumVersion = 38;
// The RTCPeerConnection object.
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
// Translate iceTransportPolicy to iceTransports,
// see https://code.google.com/p/webrtc/issues/detail?id=4869
if (pcConfig && pcConfig.iceTransportPolicy) {
pcConfig.iceTransports = pcConfig.iceTransportPolicy;
}
var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
var origGetStats = pc.getStats.bind(pc);
pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
var self = this;
@ -251,7 +309,14 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -251,7 +309,14 @@ if (typeof window === 'undefined' || !window.navigator) {
// promise-support
return new Promise(function(resolve, reject) {
origGetStats.apply(self, [resolve, reject]);
if (args.length === 1 && selector === null) {
origGetStats.apply(self, [
function(response) {
resolve.apply(null, [fixChromeStats(response)]);
}, reject]);
} else {
origGetStats.apply(self, [resolve, reject]);
}
});
};
@ -417,7 +482,7 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -417,7 +482,7 @@ if (typeof window === 'undefined' || !window.navigator) {
// Attach a media stream to an element.
attachMediaStream = function(element, stream) {
if (typeof element.srcObject !== 'undefined') {
if (webrtcDetectedVersion >= 43) {
element.srcObject = stream;
} else if (typeof element.src !== 'undefined') {
element.src = URL.createObjectURL(stream);
@ -425,9 +490,12 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -425,9 +490,12 @@ if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('Error attaching stream to element.');
}
};
reattachMediaStream = function(to, from) {
to.src = from.src;
if (webrtcDetectedVersion >= 43) {
to.srcObject = from.srcObject;
} else {
to.src = from.src;
}
};
} else if (navigator.mediaDevices && navigator.userAgent.match(
@ -435,20 +503,11 @@ if (typeof window === 'undefined' || !window.navigator) { @@ -435,20 +503,11 @@ if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('This appears to be Edge');
webrtcDetectedBrowser = 'edge';
webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
/Edge\/(\d+).(\d+)$/, 2);
// the minimum version still supported by adapter.
webrtcMinimumVersion = 12;
getUserMedia = navigator.getUserMedia;
attachMediaStream = function(element, stream) {
element.srcObject = stream;
};
reattachMediaStream = function(to, from) {
to.srcObject = from.srcObject;
};
} else {
webrtcUtils.log('Browser does not appear to be WebRTC-capable');
}
@ -461,26 +520,35 @@ function requestUserMedia(constraints) { @@ -461,26 +520,35 @@ function requestUserMedia(constraints) {
}
var webrtcTesting = {};
Object.defineProperty(webrtcTesting, 'version', {
set: function(version) {
webrtcDetectedVersion = version;
}
});
try {
Object.defineProperty(webrtcTesting, 'version', {
set: function(version) {
webrtcDetectedVersion = version;
}
});
} catch (e) {}
if (typeof module !== 'undefined') {
var RTCPeerConnection;
var RTCIceCandidate;
var RTCSessionDescription;
if (typeof window !== 'undefined') {
RTCPeerConnection = window.RTCPeerConnection;
RTCIceCandidate = window.RTCIceCandidate;
RTCSessionDescription = window.RTCSessionDescription;
}
module.exports = {
RTCPeerConnection: RTCPeerConnection,
RTCIceCandidate: RTCIceCandidate,
RTCSessionDescription: RTCSessionDescription,
getUserMedia: getUserMedia,
attachMediaStream: attachMediaStream,
reattachMediaStream: reattachMediaStream,
webrtcDetectedBrowser: webrtcDetectedBrowser,
webrtcDetectedVersion: webrtcDetectedVersion,
webrtcMinimumVersion: webrtcMinimumVersion,
webrtcTesting: webrtcTesting
webrtcTesting: webrtcTesting,
webrtcUtils: webrtcUtils
//requestUserMedia: not exposed on purpose.
//trace: not exposed on purpose.
};
@ -489,13 +557,16 @@ if (typeof module !== 'undefined') { @@ -489,13 +557,16 @@ if (typeof module !== 'undefined') {
define([], function() {
return {
RTCPeerConnection: window.RTCPeerConnection,
RTCIceCandidate: window.RTCIceCandidate,
RTCSessionDescription: window.RTCSessionDescription,
getUserMedia: getUserMedia,
attachMediaStream: attachMediaStream,
reattachMediaStream: reattachMediaStream,
webrtcDetectedBrowser: webrtcDetectedBrowser,
webrtcDetectedVersion: webrtcDetectedVersion,
webrtcMinimumVersion: webrtcMinimumVersion,
webrtcTesting: webrtcTesting
webrtcTesting: webrtcTesting,
webrtcUtils: webrtcUtils
//requestUserMedia: not exposed on purpose.
//trace: not exposed on purpose.
};

4
static/js/main.js

@ -181,8 +181,8 @@ if (Object.create) { @@ -181,8 +181,8 @@ if (Object.create) {
custom: {
families: ["FontAwesome"],
testStrings: {
"FontAwesome": '\uf004\uf005'
}
"FontAwesome": '\uf004\uf005'
}
},
active: function() {
console.log("Web fonts loaded.");

15
static/js/mediastream/peercall.js

@ -34,9 +34,8 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection @@ -34,9 +34,8 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
this.mediaConstraints = $.extend(true, {}, this.webrtc.settings.mediaConstraints);
this.pcConfig = $.extend(true, {}, this.webrtc.settings.pcConfig);
this.pcConstraints = $.extend(true, {}, this.webrtc.settings.pcConstraints);
this.sdpConstraints = $.extend(true, {}, this.webrtc.settings.sdpConstraints);
this.offerConstraints = $.extend(true, {}, this.webrtc.settings.offerConstraints);
this.sdpParams = $.extend(true, {}, this.webrtc.settings.sdpParams);
this.offerOptions = $.extend(true, {}, this.webrtc.settings.offerOptions);
this.peerconnection = null;
this.datachannels = {};
@ -69,17 +68,17 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection @@ -69,17 +68,17 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
PeerCall.prototype.createOffer = function(cb) {
var constraints = utils.mergeConstraints(this.offerConstraints, this.sdpConstraints);
console.log('Creating offer with constraints: \n' +
' \'' + JSON.stringify(constraints, null, '\t') + '\'.', this.negotiationNeeded);
this.peerconnection.createOffer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), constraints);
var options = this.offerOptions;
console.log('Creating offer with options: \n' +
' \'' + JSON.stringify(options, null, '\t') + '\'.', this.negotiationNeeded);
this.peerconnection.createOffer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), options);
};
PeerCall.prototype.createAnswer = function(cb) {
console.log("Creating answer.", this.negotiationNeeded);
this.peerconnection.createAnswer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), this.peerconnection.sdpConstraints);
this.peerconnection.createAnswer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this));
};
@ -151,7 +150,7 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection @@ -151,7 +150,7 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
streams++;
}
}, this));
if (streams === 0 && this.sdpConstraints.mandatory && (this.sdpConstraints.mandatory.OfferToReceiveAudio || this.sdpConstraints.mandatory.OfferToReceiveVideo)) {
if (streams === 0 && (this.offerOptions.offerToReceiveAudio || this.offerOptions.offerToReceiveVideo)) {
// We assume that we will eventually receive a stream, so we trigger the event to let the UI prepare for it.
this.e.triggerHandler("remoteStreamAdded", [null, this]);
}

8
static/js/mediastream/peerscreenshare.js

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], function($, _, PeerCall, tokens) {
var screenshareIds = 0;
var PeerScreenshare;
// Register ourselves for tokens.
tokens.registerHandler("screenshare", function(webrtc, id, token, from) {
@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f @@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
});
// PeerScreenshare inherits from PeerCall.
var PeerScreenshare = function(webrtc, id, token, to) {
PeerScreenshare = function(webrtc, id, token, to) {
if (id === null) {
id = screenshareIds++;
@ -50,9 +51,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f @@ -50,9 +51,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
audio: false,
video: false
}
this.sdpConstraints.mandatory.OfferToReceiveAudio = false;
this.sdpConstraints.mandatory.OfferToReceiveVideo = true;
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
@ -60,6 +58,8 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f @@ -60,6 +58,8 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
mandatory: {},
optional: []
};
this.offerOptions.offerToReceiveAudio = false;
this.offerOptions.offerToReceiveVideo = true;
// Inject token into sessiondescription and ice candidate data.
this.e.on("sessiondescription icecandidate", _.bind(function(event, data) {

8
static/js/mediastream/peerxfer.js

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'webrtc.adapter'], function($, _, PeerCall, tokens) {
var xfersIds = 0;
var PeerXfer;
// Register ourselves for tokens.
tokens.registerHandler("xfer", function(webrtc, id, token, from) {
@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w @@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
});
// PeerXfer inherits from PeerCall.
var PeerXfer = function(webrtc, id, token, to) {
PeerXfer = function(webrtc, id, token, to) {
if (id === null) {
id = xfersIds++;
@ -48,10 +49,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w @@ -48,10 +49,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
audio: false,
video: false
};
this.sdpConstraints = {
mandatory: {},
optional: []
};
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
@ -59,6 +56,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w @@ -59,6 +56,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
mandatory: {},
optional: []
};
this.offerOptions = {};
// Inject token into sessiondescription and ice candidate data.
this.e.on("sessiondescription icecandidate", _.bind(function(event, data) {

4
static/js/mediastream/tokens.js

@ -22,6 +22,8 @@ @@ -22,6 +22,8 @@
"use strict";
define(['jquery', 'underscore'], function($, _) {
var tokens;
var Token = function(handlerKey) {
this.e = $({});
this.count = 0;
@ -179,7 +181,7 @@ define(['jquery', 'underscore'], function($, _) { @@ -179,7 +181,7 @@ define(['jquery', 'underscore'], function($, _) {
};
var tokens = new Tokens();
tokens = new Tokens();
return tokens;
});

3
static/js/mediastream/utils.js

@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
"use strict";
define([], function() {
/*jshint strict: true, latedef: false */
function trace(text) {
// noop
@ -232,7 +233,7 @@ define([], function() { @@ -232,7 +233,7 @@ define([], function() {
// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'.
function maybePreferCodec(sdp, type, dir, codec) {
var str = type + ' ' + dir + ' codec';
if (codec === '') {
if (!codec) {
trace('No preference on ' + str + '.');
return sdp;
}

17
static/js/mediastream/webrtc.js

@ -80,18 +80,6 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -80,18 +80,6 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
mandatory: {},
optional: []
},
// Set up audio and video regardless of what devices are present.
sdpConstraints: {
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
},
optional: []
},
offerConstraints: {
mandatory: {},
optional: []
},
screensharing: {
mediaConstraints: {
audio: false,
@ -115,6 +103,11 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u @@ -115,6 +103,11 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
//videoRecvBitrate: ,
//videoRecvCodec
},
// Set up audio and video regardless of what devices are present.
offerOptions: {
offerToReceiveAudio: true,
offerToReceiveVideo: true
},
renegotiation: true
};

2
static/js/services/alertify.js

@ -108,7 +108,7 @@ define(["angular"], function(angular) { @@ -108,7 +108,7 @@ define(["angular"], function(angular) {
if (!conf ||
conf && !conf.type ||
conf && !conf.baseType) {
throw Error("Custom template not configured correctly.");
throw new Error("Custom template not configured correctly.");
}
var templateUrl = '/dialogs/' + conf.type + '.html';
if (conf.template) {

16
static/js/services/animationframe.js

@ -28,20 +28,26 @@ define(["underscore", "rAF"], function(_) { @@ -28,20 +28,26 @@ define(["underscore", "rAF"], function(_) {
var requestAnimationFrame = $window.requestAnimationFrame;
var registry = [];
var caller = function(f) {
var caller;
var runner;
var timer;
var worker;
var animationFrame;
caller = function(f) {
f();
};
var runner = function(c) {
runner = function(c) {
registry.forEach(caller);
requestAnimationFrame(worker)
}
var timer = $window.setTimeout;
var worker = function() {
timer = $window.setTimeout;
worker = function() {
timer(runner, 100);
};
// Public api.
var animationFrame = {
animationFrame = {
register: function(f) {
registry.push(f);
}

2
static/js/services/desktopnotify.js

@ -74,7 +74,7 @@ define(['jquery', 'underscore', 'desktop-notify', 'webrtc.adapter'], function($, @@ -74,7 +74,7 @@ define(['jquery', 'underscore', 'desktop-notify', 'webrtc.adapter'], function($,
// on Android, where Notifications raise an exception.
// See https://code.google.com/p/chromium/issues/detail?id=481856
try {
/*jshint nonew: false */
/*jshint strict: true, nonew: false */
new $window.Notification('');
} catch(e) {
if (e.name == 'TypeError') {

13
static/js/services/filedownload.js

@ -26,8 +26,9 @@ define(["jquery", "underscore"], function($, _) { @@ -26,8 +26,9 @@ define(["jquery", "underscore"], function($, _) {
var downloads = 0;
var Session = function(id, token, scope) {
var Session = function(fileDownload, id, token, scope) {
this.fileDownload = fileDownload;
this.id = id;
this.token = token;
this.scope = scope;
@ -175,7 +176,7 @@ define(["jquery", "underscore"], function($, _) { @@ -175,7 +176,7 @@ define(["jquery", "underscore"], function($, _) {
session.done(this);
return;
}
fileDownload.sendRequest(xfer, this.chunk++);
session.fileDownload.sendRequest(xfer, this.chunk++);
}, job);
//console.log("Starting new job", job, this.fragments, xfer.id);
xfer.e.on("sessionData", _.bind(this.handleData, this, job));
@ -287,7 +288,7 @@ define(["jquery", "underscore"], function($, _) { @@ -287,7 +288,7 @@ define(["jquery", "underscore"], function($, _) {
FileDownload.prototype.createSession = function(scope, token) {
var id = Session.makeId(token, this.downloads++);
var session = this.sessions[id] = new Session(id, token, scope);
var session = this.sessions[id] = new Session(this, id, token, scope);
//console.log("Created new file download session", id, session);
return session;
};
@ -330,11 +331,7 @@ define(["jquery", "underscore"], function($, _) { @@ -330,11 +331,7 @@ define(["jquery", "underscore"], function($, _) {
};
// Create signleton.
var fileDownload = new FileDownload();
return fileDownload;
return new FileDownload();
}];

4
static/js/services/geolocation.js

@ -29,8 +29,8 @@ define(['underscore', 'modernizr'], function(_, Modernizr) { @@ -29,8 +29,8 @@ define(['underscore', 'modernizr'], function(_, Modernizr) {
var defaults = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
timeout: 5000,
maximumAge: 0
};
return {

34
static/js/services/mediadevices.js

@ -19,44 +19,12 @@ @@ -19,44 +19,12 @@
*
*/
/* global Promise */
"use strict";
define(['webrtc.adapter'], function() {
// mediaDevices
return ["$window", function($window) {
var mediaDevices = $window.navigator.mediaDevices || {};
var getUserMedia = (function() {
// Implement a Promise based wrapper around getUserMedia.
if (mediaDevices.getUserMedia) {
// mediaDevices calls return Promise native.
return mediaDevices.getUserMedia.bind(mediaDevices);
} else {
return function getUserMedia(constraints) {
return new Promise(function(resolve, reject) {
var onSuccess = function(stream) {
resolve(stream)
};
var onError = function(error) {
reject(error);
};
try {
$window.getUserMedia(constraints, onSuccess, onError);
} catch(err) {
onError(err);
}
});
}
}
})();
// Public api.
return {
shim: mediaDevices.getUserMedia ? false : true,
getUserMedia: getUserMedia
}
return $window.navigator.mediaDevices;
}];
});

29
static/js/services/mediasources.js

@ -20,13 +20,14 @@ @@ -20,13 +20,14 @@
*/
"use strict";
define(['jquery', 'underscore'], function($, _) {
define(['jquery', 'underscore', 'webrtc.adapter'], function($, _, adapter) {
return ["$window", function($window) {
return ["$window", "mediaDevices", function($window, mediaDevices) {
var MediaSources = function() {
this.supported = $window.MediaStreamTrack && $window.MediaStreamTrack.getSources
// For now enable media sources only in Chrome until other browsers have some use for it.
this.supported = $window.navigator.mediaDevices.enumerateDevices && adapter.webrtcDetectedBrowser === "chrome";
this.audio = [];
this.video = [];
@ -57,25 +58,29 @@ define(['jquery', 'underscore'], function($, _) { @@ -57,25 +58,29 @@ define(['jquery', 'underscore'], function($, _) {
MediaSources.prototype._refresh = function(cb) {
$window.MediaStreamTrack.getSources(_.bind(function(sources) {
mediaDevices.enumerateDevices().then(_.bind(function(devices) {
var audio = this.audio = [];
var video = this.video = [];
_.each(sources, function(source) {
_.each(devices, function(device) {
var o = {
id: source.id,
facing: source.facing
};
if (source.kind === "audio") {
o.label = source.label ? source.label : "Microphone " + (audio.length + 1);
id: device.deviceId,
}
if (device.kind === "audioinput") {
o.label = device.label ? device.label : "Microphone " + (audio.length + 1);
audio.push(o);
} else if (source.kind === "video") {
o.label = source.label ? source.label : "Camera " + (video.length + 1);
} else if (device.kind === "videoinput") {
o.label = device.label ? device.label : "Camera " + (video.length + 1);
video.push(o);
}
});
if (cb) {
cb(audio, video);
}
}, this), _.bind(function(error) {
console.error("failed to get media devices: " + error);
if (cb) {
cb([], []);
}
}, this));
};

5
static/js/services/mediastream.js

@ -252,8 +252,9 @@ define([ @@ -252,8 +252,9 @@ define([
}, 1000);
if (context.Cfg.Tokens) {
var prompt, check;
var storedCode = localStorage.getItem("mediastream-access-code");
var prompt = function() {
prompt = function() {
alertify.dialog.prompt(translation._("Access code required"), function(code) {
if (!code) {
prompt();
@ -264,7 +265,7 @@ define([ @@ -264,7 +265,7 @@ define([
}, prompt);
};
var url = restURL.api("tokens");
var check = function(code) {
check = function(code) {
$http({
method: "POST",
url: url,

20
static/js/services/rooms.js

@ -37,7 +37,14 @@ define([ @@ -37,7 +37,14 @@ define([
var canJoinRooms = !mediaStream.config.AuthorizeRoomJoin;
var canCreateRooms = canJoinRooms ? !mediaStream.config.AuthorizeRoomCreation : false;
var joinFailed = function(error) {
var rooms;
var joinFailed;
var joinRequestedRoom;
var setCurrentRoom;
var updateRoom;
var applyRoomUpdate;
joinFailed = function(error) {
setCurrentRoom(null);
switch(error.Code) {
@ -70,7 +77,7 @@ define([ @@ -70,7 +77,7 @@ define([
}
};
var joinRequestedRoom = function() {
joinRequestedRoom = function() {
if (!connector.connected || appData.authorizing()) {
// Do nothing while not connected or authorizing.
return;
@ -95,7 +102,7 @@ define([ @@ -95,7 +102,7 @@ define([
}
};
var setCurrentRoom = function(room) {
setCurrentRoom = function(room) {
if (room === currentRoom) {
return;
}
@ -112,13 +119,13 @@ define([ @@ -112,13 +119,13 @@ define([
}
};
var updateRoom = function(room) {
updateRoom = function(room) {
var response = $q.defer();
api.requestRoomUpdate(room, response.resolve, response.reject);
return response.promise.then(applyRoomUpdate);
};
var applyRoomUpdate = function(room) {
applyRoomUpdate = function(room) {
if (room.Credentials) {
roompin.update(currentRoom.Name, room.Credentials.PIN);
delete room.Credentials;
@ -169,7 +176,8 @@ define([ @@ -169,7 +176,8 @@ define([
}
});
var rooms = {
// Public API.
rooms = {
inDefaultRoom: function() {
return (currentRoom !== null ? currentRoom.Name : requestedRoomName) === "";
},

2
static/partials/chat.html

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<div class="chatheader"><div class="chatstatusicon" ng-click="activateRoom(currentRoom.id, true)"><i class="fa fa-angle-right"></i> <i class="fa fa fa-comments-o"></i></div><div class="chatheadertitle"><span>{{_("Chat sessions")}}</span></div> <div class="ctrl"><i ng-show="layout.chatMaximized" ng-click="toggleMax()" class="fa fa-compress"></i></div></div>
<div class="chatbody">
<div class="list-group nicescroll">
<a ng-repeat="room in getVisibleRooms()" ng-click="activateRoom(room.id, true)" class="list-group-item" ng-class="{newmessage: room.pending, disabled: !room.enabled}">
<a ng-repeat="room in getVisibleRooms()" ng-click="activateRoom(room.id, true, true)" class="list-group-item" ng-class="{newmessage: room.pending, disabled: !room.enabled}">
<span class="badge" ng-show="room.pending">{{room.pending}}</span>
<span ng-if="room.id !== ''">{{room.id|displayName}}</span>
<span ng-if="room.id === ''">{{_("Room chat")}} {{currentRoomName}}</span>

Loading…
Cancel
Save