|
@@ -413,7 +413,7 @@ JitsiConference.prototype.muteParticipant = function (id) {
|
413
|
413
|
this.room.muteParticipant(participant.getJid(), true);
|
414
|
414
|
};
|
415
|
415
|
|
416
|
|
-JitsiConference.prototype.onMemberJoined = function (jid, email, nick) {
|
|
416
|
+JitsiConference.prototype.onMemberJoined = function (jid, nick) {
|
417
|
417
|
var id = Strophe.getResourceFromJid(jid);
|
418
|
418
|
if (id === 'focus' || this.myUserId() === id) {
|
419
|
419
|
return;
|
|
@@ -1071,6 +1071,23 @@ var JitsiTrackErrors = require("./JitsiTrackErrors");
|
1071
|
1071
|
var Logger = require("jitsi-meet-logger");
|
1072
|
1072
|
var RTC = require("./modules/RTC/RTC");
|
1073
|
1073
|
var Statistics = require("./modules/statistics/statistics");
|
|
1074
|
+var Resolutions = require("./service/RTC/Resolutions");
|
|
1075
|
+
|
|
1076
|
+function getLowerResolution(resolution) {
|
|
1077
|
+ if(!Resolutions[resolution])
|
|
1078
|
+ return null;
|
|
1079
|
+ var order = Resolutions[resolution].order;
|
|
1080
|
+ var res = null;
|
|
1081
|
+ var resName = null;
|
|
1082
|
+ for(var i in Resolutions) {
|
|
1083
|
+ var tmp = Resolutions[i];
|
|
1084
|
+ if (!res || (res.order < tmp.order && tmp.order < order)) {
|
|
1085
|
+ resName = i;
|
|
1086
|
+ res = tmp;
|
|
1087
|
+ }
|
|
1088
|
+ }
|
|
1089
|
+ return resName;
|
|
1090
|
+}
|
1074
|
1091
|
|
1075
|
1092
|
/**
|
1076
|
1093
|
* Namespace for the interface of Jitsi Meet Library.
|
|
@@ -1135,6 +1152,16 @@ var LibJitsiMeet = {
|
1135
|
1152
|
}
|
1136
|
1153
|
}
|
1137
|
1154
|
return tracks;
|
|
1155
|
+ }).catch(function (error) {
|
|
1156
|
+ if(error === JitsiTrackErrors.UNSUPPORTED_RESOLUTION) {
|
|
1157
|
+ var oldResolution = options.resolution || '360';
|
|
1158
|
+ var newResolution = getLowerResolution(oldResolution);
|
|
1159
|
+ if(newResolution === null)
|
|
1160
|
+ return Promise.reject(error);
|
|
1161
|
+ options.resolution = newResolution;
|
|
1162
|
+ return LibJitsiMeet.createLocalTracks(options);
|
|
1163
|
+ }
|
|
1164
|
+ return Promise.reject(error);
|
1138
|
1165
|
});
|
1139
|
1166
|
},
|
1140
|
1167
|
/**
|
|
@@ -1163,7 +1190,7 @@ window.Promise = window.Promise || require("es6-promise").Promise;
|
1163
|
1190
|
|
1164
|
1191
|
module.exports = LibJitsiMeet;
|
1165
|
1192
|
|
1166
|
|
-},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"es6-promise":46,"jitsi-meet-logger":48}],8:[function(require,module,exports){
|
|
1193
|
+},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"./service/RTC/Resolutions":81,"es6-promise":46,"jitsi-meet-logger":48}],8:[function(require,module,exports){
|
1167
|
1194
|
/* global Strophe */
|
1168
|
1195
|
|
1169
|
1196
|
/**
|
|
@@ -1326,10 +1353,10 @@ module.exports = {
|
1326
|
1353
|
/**
|
1327
|
1354
|
* Returns JitsiTrackErrors based on the error object passed by GUM
|
1328
|
1355
|
* @param error the error
|
1329
|
|
- * @param {Object} options the options object given to GUM.
|
|
1356
|
+ * @param {Array} devices Array with the requested devices
|
1330
|
1357
|
*/
|
1331
|
|
- parseError: function (error, options) {
|
1332
|
|
- options = options || {};
|
|
1358
|
+ parseError: function (error, devices) {
|
|
1359
|
+ devices = devices || [];
|
1333
|
1360
|
if (typeof error == "object" && error.constraintName && error.name
|
1334
|
1361
|
&& (error.name == "ConstraintNotSatisfiedError" ||
|
1335
|
1362
|
error.name == "OverconstrainedError") &&
|
|
@@ -1337,7 +1364,7 @@ module.exports = {
|
1337
|
1364
|
error.constraintName == "maxWidth" ||
|
1338
|
1365
|
error.constraintName == "minHeight" ||
|
1339
|
1366
|
error.constraintName == "maxHeight") &&
|
1340
|
|
- options.devices.indexOf("video") !== -1) {
|
|
1367
|
+ devices.indexOf("video") !== -1) {
|
1341
|
1368
|
return this.UNSUPPORTED_RESOLUTION;
|
1342
|
1369
|
} else {
|
1343
|
1370
|
return this.GENERAL;
|
|
@@ -1604,7 +1631,7 @@ module.exports = DataChannels;
|
1604
|
1631
|
var JitsiTrack = require("./JitsiTrack");
|
1605
|
1632
|
var RTCBrowserType = require("./RTCBrowserType");
|
1606
|
1633
|
var JitsiTrackEvents = require('../../JitsiTrackEvents');
|
1607
|
|
-var RTC = require("./RTCUtils");
|
|
1634
|
+var RTCUtils = require("./RTCUtils");
|
1608
|
1635
|
|
1609
|
1636
|
/**
|
1610
|
1637
|
* Represents a single media track (either audio or video).
|
|
@@ -1661,7 +1688,7 @@ JitsiLocalTrack.prototype._setMute = function (mute) {
|
1661
|
1688
|
if (mute) {
|
1662
|
1689
|
this.dontFireRemoveEvent = true;
|
1663
|
1690
|
this.rtc.room.removeStream(this.stream, function () {});
|
1664
|
|
- RTC.stopMediaStream(this.stream);
|
|
1691
|
+ RTCUtils.stopMediaStream(this.stream);
|
1665
|
1692
|
if(isAudio)
|
1666
|
1693
|
this.rtc.room.setAudioMute(mute);
|
1667
|
1694
|
else
|
|
@@ -1671,7 +1698,7 @@ JitsiLocalTrack.prototype._setMute = function (mute) {
|
1671
|
1698
|
//FIXME: Maybe here we should set the SRC for the containers to something
|
1672
|
1699
|
} else {
|
1673
|
1700
|
var self = this;
|
1674
|
|
- RTC.obtainAudioAndVideoPermissions({
|
|
1701
|
+ RTCUtils.obtainAudioAndVideoPermissions({
|
1675
|
1702
|
devices: (isAudio ? ["audio"] : ["video"]),
|
1676
|
1703
|
resolution: self.resolution})
|
1677
|
1704
|
.then(function (streams) {
|
|
@@ -1690,7 +1717,8 @@ JitsiLocalTrack.prototype._setMute = function (mute) {
|
1690
|
1717
|
|
1691
|
1718
|
for(var i = 0; i < self.containers.length; i++)
|
1692
|
1719
|
{
|
1693
|
|
- RTC.attachMediaStream(self.containers[i], self.stream);
|
|
1720
|
+ RTCUtils.attachMediaStream(
|
|
1721
|
+ self.containers[i], self.stream);
|
1694
|
1722
|
}
|
1695
|
1723
|
|
1696
|
1724
|
self.rtc.room.addStream(stream.stream,
|
|
@@ -1716,7 +1744,7 @@ JitsiLocalTrack.prototype.stop = function () {
|
1716
|
1744
|
return;
|
1717
|
1745
|
if(this.rtc)
|
1718
|
1746
|
this.rtc.room.removeStream(this.stream, function () {});
|
1719
|
|
- RTC.stopMediaStream(this.stream);
|
|
1747
|
+ RTCUtils.stopMediaStream(this.stream);
|
1720
|
1748
|
this.detach();
|
1721
|
1749
|
}
|
1722
|
1750
|
|
|
@@ -2857,6 +2885,8 @@ function obtainDevices(options) {
|
2857
|
2885
|
}
|
2858
|
2886
|
|
2859
|
2887
|
var device = options.devices.splice(0, 1);
|
|
2888
|
+ var devices = [];
|
|
2889
|
+ devices.push(device);
|
2860
|
2890
|
options.deviceGUM[device](function (stream) {
|
2861
|
2891
|
options.streams = options.streams || {};
|
2862
|
2892
|
options.streams[device] = stream;
|
|
@@ -2865,7 +2895,7 @@ function obtainDevices(options) {
|
2865
|
2895
|
function (error) {
|
2866
|
2896
|
logger.error(
|
2867
|
2897
|
"failed to obtain " + device + " stream - stop", error);
|
2868
|
|
- options.errorCallback(JitsiTrackErrors.parseError(error));
|
|
2898
|
+ options.errorCallback(JitsiTrackErrors.parseError(error, devices));
|
2869
|
2899
|
});
|
2870
|
2900
|
}
|
2871
|
2901
|
|
|
@@ -2997,7 +3027,15 @@ var RTCUtils = {
|
2997
|
3027
|
this.enumerateDevices = enumerateDevicesThroughMediaStreamTrack;
|
2998
|
3028
|
}
|
2999
|
3029
|
this.attachMediaStream = function (element, stream) {
|
3000
|
|
- element.attr('src', webkitURL.createObjectURL(stream));
|
|
3030
|
+
|
|
3031
|
+ // saves the created url for the stream, so we can reuse it
|
|
3032
|
+ // and not keep creating urls
|
|
3033
|
+ if (!stream.jitsiObjectURL) {
|
|
3034
|
+ stream.jitsiObjectURL
|
|
3035
|
+ = webkitURL.createObjectURL(stream);
|
|
3036
|
+ }
|
|
3037
|
+
|
|
3038
|
+ element.attr('src', stream.jitsiObjectURL);
|
3001
|
3039
|
};
|
3002
|
3040
|
this.getStreamID = function (stream) {
|
3003
|
3041
|
// streams from FF endpoints have the characters '{' and '}'
|
|
@@ -3176,11 +3214,16 @@ var RTCUtils = {
|
3176
|
3214
|
var GUM = function (device, s, e) {
|
3177
|
3215
|
this.getUserMediaWithConstraints(device, s, e, options);
|
3178
|
3216
|
};
|
|
3217
|
+
|
3179
|
3218
|
var deviceGUM = {
|
3180
|
3219
|
"audio": GUM.bind(self, ["audio"]),
|
3181
|
|
- "video": GUM.bind(self, ["video"]),
|
3182
|
|
- "desktop": screenObtainer.obtainStream.bind(screenObtainer)
|
|
3220
|
+ "video": GUM.bind(self, ["video"])
|
3183
|
3221
|
};
|
|
3222
|
+
|
|
3223
|
+ if(screenObtainer.isSupported()){
|
|
3224
|
+ deviceGUM["desktop"] = screenObtainer.obtainStream.bind(
|
|
3225
|
+ screenObtainer);
|
|
3226
|
+ }
|
3184
|
3227
|
// With FF/IE we can't split the stream into audio and video because FF
|
3185
|
3228
|
// doesn't support media stream constructors. So, we need to get the
|
3186
|
3229
|
// audio stream separately from the video stream using two distinct GUM
|
|
@@ -3213,14 +3256,16 @@ var RTCUtils = {
|
3213
|
3256
|
desktopStream: desktopStream});
|
3214
|
3257
|
}, function (error) {
|
3215
|
3258
|
reject(
|
3216
|
|
- JitsiTrackErrors.parseError(error));
|
|
3259
|
+ JitsiTrackErrors.parseError(error,
|
|
3260
|
+ options.devices));
|
3217
|
3261
|
});
|
3218
|
3262
|
} else {
|
3219
|
3263
|
successCallback({audioVideo: stream});
|
3220
|
3264
|
}
|
3221
|
3265
|
},
|
3222
|
3266
|
function (error) {
|
3223
|
|
- reject(JitsiTrackErrors.parseError(error));
|
|
3267
|
+ reject(JitsiTrackErrors.parseError(error,
|
|
3268
|
+ options.devices));
|
3224
|
3269
|
},
|
3225
|
3270
|
options);
|
3226
|
3271
|
} else if (hasDesktop) {
|
|
@@ -3229,7 +3274,8 @@ var RTCUtils = {
|
3229
|
3274
|
successCallback({desktopStream: stream});
|
3230
|
3275
|
}, function (error) {
|
3231
|
3276
|
reject(
|
3232
|
|
- JitsiTrackErrors.parseError(error));
|
|
3277
|
+ JitsiTrackErrors.parseError(error,
|
|
3278
|
+ ["desktop"]));
|
3233
|
3279
|
});
|
3234
|
3280
|
}
|
3235
|
3281
|
}
|
|
@@ -3285,6 +3331,11 @@ var RTCUtils = {
|
3285
|
3331
|
if (mediaStream.stop) {
|
3286
|
3332
|
mediaStream.stop();
|
3287
|
3333
|
}
|
|
3334
|
+
|
|
3335
|
+ // if we have done createObjectURL, lets clean it
|
|
3336
|
+ if (mediaStream.jitsiObjectURL) {
|
|
3337
|
+ webkitURL.revokeObjectURL(mediaStream.jitsiObjectURL);
|
|
3338
|
+ }
|
3288
|
3339
|
},
|
3289
|
3340
|
/**
|
3290
|
3341
|
* Returns whether the desktop sharing is enabled or not.
|
|
@@ -6295,6 +6346,8 @@ ChatRoom.prototype.onPresence = function (pres) {
|
6295
|
6346
|
parser.packet2JSON(pres, nodes);
|
6296
|
6347
|
this.lastPresences[from] = nodes;
|
6297
|
6348
|
var jibri = null;
|
|
6349
|
+ // process nodes to extract data needed for MUC_JOINED and MUC_MEMBER_JOINED
|
|
6350
|
+ // events
|
6298
|
6351
|
for(var i = 0; i < nodes.length; i++)
|
6299
|
6352
|
{
|
6300
|
6353
|
var node = nodes[i];
|
|
@@ -6302,53 +6355,24 @@ ChatRoom.prototype.onPresence = function (pres) {
|
6302
|
6355
|
{
|
6303
|
6356
|
case "nick":
|
6304
|
6357
|
member.nick = node.value;
|
6305
|
|
- if(!member.isFocus) {
|
6306
|
|
- var displayName = !this.xmpp.options.displayJids
|
6307
|
|
- ? member.nick : Strophe.getResourceFromJid(from);
|
6308
|
|
-
|
6309
|
|
- if (displayName && displayName.length > 0) {
|
6310
|
|
- this.eventEmitter.emit(XMPPEvents.DISPLAY_NAME_CHANGED, from, displayName);
|
6311
|
|
- }
|
6312
|
|
- }
|
6313
|
6358
|
break;
|
6314
|
6359
|
case "userId":
|
6315
|
6360
|
member.id = node.value;
|
6316
|
6361
|
break;
|
6317
|
|
- case "bridgeIsDown":
|
6318
|
|
- if(!this.bridgeIsDown) {
|
6319
|
|
- this.bridgeIsDown = true;
|
6320
|
|
- this.eventEmitter.emit(XMPPEvents.BRIDGE_DOWN);
|
6321
|
|
- }
|
6322
|
|
- break;
|
6323
|
|
- case "jibri-recording-status":
|
6324
|
|
- var jibri = node;
|
6325
|
|
- break;
|
6326
|
|
- case "call-control":
|
6327
|
|
- var att = node.attributes;
|
6328
|
|
- if(!att)
|
6329
|
|
- break;
|
6330
|
|
- this.phoneNumber = att.phone || null;
|
6331
|
|
- this.phonePin = att.pin || null;
|
6332
|
|
- this.eventEmitter.emit(XMPPEvents.PHONE_NUMBER_CHANGED);
|
6333
|
|
- break;
|
6334
|
|
- default :
|
6335
|
|
- this.processNode(node, from);
|
6336
|
6362
|
}
|
6337
|
|
-
|
6338
|
6363
|
}
|
6339
|
6364
|
|
6340
|
6365
|
if (from == this.myroomjid) {
|
6341
|
|
- if (member.affiliation == 'owner')
|
6342
|
|
-
|
6343
|
|
- if (this.role !== member.role) {
|
|
6366
|
+ if (member.affiliation == 'owner'
|
|
6367
|
+ && this.role !== member.role) {
|
6344
|
6368
|
this.role = member.role;
|
6345
|
|
-
|
6346
|
|
- this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED, this.role);
|
6347
|
|
- }
|
|
6369
|
+ this.eventEmitter.emit(
|
|
6370
|
+ XMPPEvents.LOCAL_ROLE_CHANGED, this.role);
|
|
6371
|
+ }
|
6348
|
6372
|
if (!this.joined) {
|
6349
|
6373
|
this.joined = true;
|
6350
|
6374
|
console.log("(TIME) MUC joined:\t", window.performance.now());
|
6351
|
|
- this.eventEmitter.emit(XMPPEvents.MUC_JOINED, from, member);
|
|
6375
|
+ this.eventEmitter.emit(XMPPEvents.MUC_JOINED);
|
6352
|
6376
|
}
|
6353
|
6377
|
} else if (this.members[from] === undefined) {
|
6354
|
6378
|
// new participant
|
|
@@ -6366,14 +6390,16 @@ ChatRoom.prototype.onPresence = function (pres) {
|
6366
|
6390
|
logger.info("Ignore focus: " + from + ", real JID: " + member.jid);
|
6367
|
6391
|
}
|
6368
|
6392
|
else {
|
6369
|
|
- this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_JOINED, from, member.id, member.nick);
|
|
6393
|
+ this.eventEmitter.emit(
|
|
6394
|
+ XMPPEvents.MUC_MEMBER_JOINED, from, member.nick);
|
6370
|
6395
|
}
|
6371
|
6396
|
} else {
|
6372
|
6397
|
// Presence update for existing participant
|
6373
|
6398
|
// Watch role change:
|
6374
|
6399
|
if (this.members[from].role != member.role) {
|
6375
|
6400
|
this.members[from].role = member.role;
|
6376
|
|
- this.eventEmitter.emit(XMPPEvents.MUC_ROLE_CHANGED, from, member.role);
|
|
6401
|
+ this.eventEmitter.emit(
|
|
6402
|
+ XMPPEvents.MUC_ROLE_CHANGED, from, member.role);
|
6377
|
6403
|
}
|
6378
|
6404
|
|
6379
|
6405
|
// store the new display name
|
|
@@ -6381,7 +6407,45 @@ ChatRoom.prototype.onPresence = function (pres) {
|
6381
|
6407
|
this.members[from].displayName = member.displayName;
|
6382
|
6408
|
}
|
6383
|
6409
|
|
|
6410
|
+ // after we had fired member or room joined events, lets fire events
|
|
6411
|
+ // for the rest info we got in presence
|
|
6412
|
+ for(var i = 0; i < nodes.length; i++)
|
|
6413
|
+ {
|
|
6414
|
+ var node = nodes[i];
|
|
6415
|
+ switch(node.tagName)
|
|
6416
|
+ {
|
|
6417
|
+ case "nick":
|
|
6418
|
+ if(!member.isFocus) {
|
|
6419
|
+ var displayName = !this.xmpp.options.displayJids
|
|
6420
|
+ ? member.nick : Strophe.getResourceFromJid(from);
|
6384
|
6421
|
|
|
6422
|
+ if (displayName && displayName.length > 0) {
|
|
6423
|
+ this.eventEmitter.emit(
|
|
6424
|
+ XMPPEvents.DISPLAY_NAME_CHANGED, from, displayName);
|
|
6425
|
+ }
|
|
6426
|
+ }
|
|
6427
|
+ break;
|
|
6428
|
+ case "bridgeIsDown":
|
|
6429
|
+ if(!this.bridgeIsDown) {
|
|
6430
|
+ this.bridgeIsDown = true;
|
|
6431
|
+ this.eventEmitter.emit(XMPPEvents.BRIDGE_DOWN);
|
|
6432
|
+ }
|
|
6433
|
+ break;
|
|
6434
|
+ case "jibri-recording-status":
|
|
6435
|
+ var jibri = node;
|
|
6436
|
+ break;
|
|
6437
|
+ case "call-control":
|
|
6438
|
+ var att = node.attributes;
|
|
6439
|
+ if(!att)
|
|
6440
|
+ break;
|
|
6441
|
+ this.phoneNumber = att.phone || null;
|
|
6442
|
+ this.phonePin = att.pin || null;
|
|
6443
|
+ this.eventEmitter.emit(XMPPEvents.PHONE_NUMBER_CHANGED);
|
|
6444
|
+ break;
|
|
6445
|
+ default :
|
|
6446
|
+ this.processNode(node, from);
|
|
6447
|
+ }
|
|
6448
|
+ }
|
6385
|
6449
|
|
6386
|
6450
|
if(!member.isFocus)
|
6387
|
6451
|
this.eventEmitter.emit(XMPPEvents.USER_ID_CHANGED, from, member.id);
|