From e80b8cfea3d4294c395005b258244e28dcbaaa8a Mon Sep 17 00:00:00 2001 From: isymchych Date: Thu, 14 Jan 2016 14:52:09 +0200 Subject: [PATCH] handle AVAILABLE_DEVICES_CHANGED event --- conference.js | 12 +- libs/lib-jitsi-meet.js | 319 ++++++++++++++++++-------- modules/UI/UI.js | 4 + modules/UI/videolayout/LargeVideo.js | 4 +- modules/UI/videolayout/VideoLayout.js | 18 +- 5 files changed, 239 insertions(+), 118 deletions(-) diff --git a/conference.js b/conference.js index 92793ac7b..1677116d3 100644 --- a/conference.js +++ b/conference.js @@ -126,10 +126,6 @@ class ConferenceConnector { AuthHandler.requireAuth(APP.conference.roomName); break; - case ConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE: - APP.UI.notifyBridgeDown(); - break; - case ConferenceErrors.RESERVATION_ERROR: { let [code, msg] = params; @@ -167,7 +163,7 @@ class ConferenceConnector { break; default: - this._handleConferenceFailed(err, msg); + this._handleConferenceFailed(err, ...params); } } _unsubscribe() { @@ -645,6 +641,12 @@ export default { ); }); + room.on( + ConferenceEvents.AVAILABLE_DEVICES_CHANGED, function (id, devices) { + APP.UI.updateDevicesAvailability(id, devices); + } + ); + // call hangup APP.UI.addListener(UIEvents.HANGUP, () => { APP.UI.requestFeedback().then(() => { diff --git a/libs/lib-jitsi-meet.js b/libs/lib-jitsi-meet.js index 4f6bc1a81..e0ad052f3 100644 --- a/libs/lib-jitsi-meet.js +++ b/libs/lib-jitsi-meet.js @@ -7,6 +7,7 @@ var RTC = require("./modules/RTC/RTC"); var XMPPEvents = require("./service/xmpp/XMPPEvents"); var AuthenticationEvents = require("./service/authentication/AuthenticationEvents"); var RTCEvents = require("./service/RTC/RTCEvents"); +var DSEvents = require("./service/desktopsharing/DesktopSharingEventTypes"); var EventEmitter = require("events"); var JitsiConferenceEvents = require("./JitsiConferenceEvents"); var JitsiConferenceErrors = require("./JitsiConferenceErrors"); @@ -59,6 +60,10 @@ function JitsiConference(options) { this.startAudioMuted = false; this.startVideoMuted = false; this.startMutedPolicy = {audio: false, video: false}; + this.availableDevices = { + audio: undefined, + video: undefined + }; } /** @@ -803,6 +808,24 @@ function setupListeners(conference) { conference.room.addListener(XMPPEvents.BRIDGE_DOWN, function () { conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE); }); + conference.room.addListener(XMPPEvents.RESERVATION_ERROR, function (code, msg) { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.RESERVATION_ERROR, code, msg); + }); + conference.room.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.GRACEFUL_SHUTDOWN); + }); + conference.room.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function () { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.JINGLE_FATAL_ERROR); + }); + conference.room.addListener(XMPPEvents.MUC_DESTROYED, function (reason) { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONFERENCE_DESTROYED, reason); + }); + conference.room.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, function (err, msg) { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CHAT_ERROR, err, msg); + }); + conference.room.addListener(XMPPEvents.FOCUS_DISCONNECTED, function (focus, retrySec) { + conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.FOCUS_DISCONNECTED, focus, retrySec); + }); // FIXME // conference.room.addListener(XMPPEvents.MUC_JOINED, function () { // conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT); @@ -854,6 +877,20 @@ function setupListeners(conference) { conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED, id, txt, ts); }); + conference.room.addListener(XMPPEvents.PRESENCE_STATUS, function (jid, status) { + var id = Strophe.getResourceFromJid(jid); + var participant = conference.getParticipantById(id); + if (!participant || participant._status === status) { + return; + } + participant._status = status; + conference.eventEmitter.emit(JitsiConferenceEvents.USER_STATUS_CHANGED, id, status); + }); + + conference.rtc.addListener(DSEvents.FIREFOX_EXTENSION_NEEDED, function (url) { + conference.eventEmitter.emit(JitsiConferenceEvents.FIREFOX_EXTENSION_NEEDED, url); + }); + conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) { if(conference.lastDominantSpeaker !== id && conference.room) { conference.lastDominantSpeaker = id; @@ -931,6 +968,50 @@ function setupListeners(conference) { } }); + conference.rtc.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) { + conference.room.updateDeviceAvailability(devices); + }); + conference.room.addPresenceListener("devices", function (data, from) { + var isAudioAvailable = false; + var isVideoAvailable = false; + data.children.forEach(function (config) { + if (config.tagName === 'audio') { + isAudioAvailable = config.value === 'true'; + } + if (config.tagName === 'video') { + isVideoAvailable = config.value === 'true'; + } + }); + + var availableDevices; + if (conference.myUserId() === from) { + availableDevices = conference.availableDevices; + } else { + var participant = conference.getParticipantById(from); + if (!participant) { + return; + } + + availableDevices = participant._availableDevices; + } + + var updated = false; + + if (availableDevices.audio !== isAudioAvailable) { + updated = true; + availableDevices.audio = isAudioAvailable; + } + + if (availableDevices.video !== isVideoAvailable) { + updated = true; + availableDevices.video = isVideoAvailable; + } + + if (updated) { + conference.eventEmitter.emit(JitsiConferenceEvents.AVAILABLE_DEVICES_CHANGED, from, availableDevices); + } + }); + if(conference.statistics) { //FIXME: Maybe remove event should not be associated with the conference. conference.statistics.addAudioLevelListener(function (ssrc, level) { @@ -945,10 +1026,6 @@ function setupListeners(conference) { function () { conference.statistics.dispose(); }); - // FIXME: Maybe we should move this. - // RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) { - // conference.room.updateDeviceAvailability(devices); - // }); conference.room.addListener(XMPPEvents.PEERCONNECTION_READY, function (session) { @@ -1001,7 +1078,7 @@ function setupListeners(conference) { module.exports = JitsiConference; }).call(this,"/JitsiConference.js") -},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/DTMF/JitsiDTMFManager":11,"./modules/RTC/RTC":16,"./modules/settings/Settings":21,"./modules/statistics/statistics":25,"./service/RTC/RTCEvents":132,"./service/authentication/AuthenticationEvents":134,"./service/xmpp/XMPPEvents":138,"events":45,"jitsi-meet-logger":49}],2:[function(require,module,exports){ +},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/DTMF/JitsiDTMFManager":11,"./modules/RTC/RTC":16,"./modules/settings/Settings":21,"./modules/statistics/statistics":25,"./service/RTC/RTCEvents":136,"./service/authentication/AuthenticationEvents":138,"./service/desktopsharing/DesktopSharingEventTypes":139,"./service/xmpp/XMPPEvents":142,"events":45,"jitsi-meet-logger":49}],2:[function(require,module,exports){ /** * Enumeration with the errors for the conference. * @type {{string: string}} @@ -1031,7 +1108,31 @@ var JitsiConferenceErrors = { /** * Indicates that there is no available videobridge. */ - VIDEOBRIDGE_NOT_AVAILABLE: "conference.videobridgeNotAvailable" + VIDEOBRIDGE_NOT_AVAILABLE: "conference.videobridgeNotAvailable", + /** + * Indicates that reservation system returned error. + */ + RESERVATION_ERROR: "conference.reservationError", + /** + * Indicates that graceful shutdown happened. + */ + GRACEFUL_SHUTDOWN: "conference.gracefulShutdown", + /** + * Indicates that jingle fatal error happened. + */ + JINGLE_FATAL_ERROR: "conference.jingleFatalError", + /** + * Indicates that conference has been destroyed. + */ + CONFERENCE_DESTROYED: "conference.destroyed", + /** + * Indicates that chat error occured. + */ + CHAT_ERROR: "conference.chatError", + /** + * Indicates that focus error happened. + */ + FOCUS_DISCONNECTED: "conference.focusDisconnected" /** * Many more errors TBD here. */ @@ -1069,6 +1170,10 @@ var JitsiConferenceEvents = { * User role changed. */ USER_ROLE_CHANGED: "conference.roleChanged", + /** + * User status changed. + */ + USER_STATUS_CHANGED: "conference.statusChanged", /** * New text message was received. */ @@ -1145,7 +1250,16 @@ var JitsiConferenceEvents = { /** * Indicates that phone number changed. */ - PHONE_NUMBER_CHANGED: "conference.phoneNumberChanged" + PHONE_NUMBER_CHANGED: "conference.phoneNumberChanged", + /** + * Indicates that to proceed with screen sharing + * browser extension must be installed first. + */ + FIREFOX_EXTENSION_NEEDED: "conference.firefoxExtensionRequired", + /** + * Indicates that available devices changed. + */ + AVAILABLE_DEVICES_CHANGED: "conference.availableDevicesChanged" }; module.exports = JitsiConferenceEvents; @@ -1419,7 +1533,7 @@ window.Promise = window.Promise || require("es6-promise").Promise; module.exports = LibJitsiMeet; -},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":16,"./modules/statistics/statistics":25,"./service/RTC/Resolutions":133,"es6-promise":47,"jitsi-meet-logger":49}],8:[function(require,module,exports){ +},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":16,"./modules/statistics/statistics":25,"./service/RTC/Resolutions":137,"es6-promise":47,"jitsi-meet-logger":49}],8:[function(require,module,exports){ /* global Strophe */ /** @@ -1433,6 +1547,11 @@ function JitsiParticipant(jid, conference, displayName){ this._supportsDTMF = false; this._tracks = []; this._role = 'none'; + this._status = null; + this._availableDevices = { + audio: undefined, + video: undefined + }; } /** @@ -1470,6 +1589,13 @@ JitsiParticipant.prototype.getDisplayName = function() { return this._displayName; }; +/** + * @returns {String} The status of the participant. + */ +JitsiParticipant.prototype.getStatus = function () { + return this._status; +}; + /** * @returns {Boolean} Whether this participant is a moderator or not. */ @@ -1865,9 +1991,8 @@ DataChannels.prototype._some = function (callback, thisArg) { module.exports = DataChannels; - }).call(this,"/modules/RTC/DataChannels.js") -},{"../../service/RTC/RTCEvents":132,"jitsi-meet-logger":49}],13:[function(require,module,exports){ +},{"../../service/RTC/RTCEvents":136,"jitsi-meet-logger":49}],13:[function(require,module,exports){ var JitsiTrack = require("./JitsiTrack"); var RTCBrowserType = require("./RTCBrowserType"); var JitsiTrackEvents = require('../../JitsiTrackEvents'); @@ -2393,8 +2518,6 @@ var JitsiTrack = require("./JitsiTrack"); var JitsiLocalTrack = require("./JitsiLocalTrack.js"); var DataChannels = require("./DataChannels"); var JitsiRemoteTrack = require("./JitsiRemoteTrack.js"); -var DesktopSharingEventTypes - = require("../../service/desktopsharing/DesktopSharingEventTypes"); var MediaStreamType = require("../../service/RTC/MediaStreamTypes"); var RTCEvents = require("../../service/RTC/RTCEvents.js"); @@ -2644,7 +2767,7 @@ RTC.prototype.setAudioLevel = function (jid, audioLevel) { } module.exports = RTC; -},{"../../service/RTC/MediaStreamTypes":131,"../../service/RTC/RTCEvents.js":132,"../../service/desktopsharing/DesktopSharingEventTypes":135,"./DataChannels":12,"./JitsiLocalTrack.js":13,"./JitsiRemoteTrack.js":14,"./JitsiTrack":15,"./RTCBrowserType":17,"./RTCUtils.js":18,"events":45}],17:[function(require,module,exports){ +},{"../../service/RTC/MediaStreamTypes":135,"../../service/RTC/RTCEvents.js":136,"./DataChannels":12,"./JitsiLocalTrack.js":13,"./JitsiRemoteTrack.js":14,"./JitsiTrack":15,"./RTCBrowserType":17,"./RTCUtils.js":18,"events":45}],17:[function(require,module,exports){ var currentBrowser; @@ -3637,7 +3760,7 @@ var RTCUtils = { module.exports = RTCUtils; }).call(this,"/modules/RTC/RTCUtils.js") -},{"../../JitsiTrackErrors":9,"../../service/RTC/RTCEvents":132,"../../service/RTC/Resolutions":133,"../xmpp/SDPUtil":33,"./RTCBrowserType":17,"./ScreenObtainer":19,"./adapter.screenshare":20,"events":45,"jitsi-meet-logger":49}],19:[function(require,module,exports){ +},{"../../JitsiTrackErrors":9,"../../service/RTC/RTCEvents":136,"../../service/RTC/Resolutions":137,"../xmpp/SDPUtil":33,"./RTCBrowserType":17,"./ScreenObtainer":19,"./adapter.screenshare":20,"events":45,"jitsi-meet-logger":49}],19:[function(require,module,exports){ (function (__filename){ /* global chrome, $, alert */ /* jshint -W003 */ @@ -4053,7 +4176,7 @@ function initFirefoxExtensionDetection(options) { module.exports = ScreenObtainer; }).call(this,"/modules/RTC/ScreenObtainer.js") -},{"../../JitsiTrackErrors":9,"../../service/desktopsharing/DesktopSharingEventTypes":135,"./RTCBrowserType":17,"./adapter.screenshare":20,"jitsi-meet-logger":49}],20:[function(require,module,exports){ +},{"../../JitsiTrackErrors":9,"../../service/desktopsharing/DesktopSharingEventTypes":139,"./RTCBrowserType":17,"./adapter.screenshare":20,"jitsi-meet-logger":49}],20:[function(require,module,exports){ (function (__filename){ /*! adapterjs - v0.12.3 - 2015-11-16 */ var console = require("jitsi-meet-logger").getLogger(__filename); @@ -5587,7 +5710,7 @@ CallStats.sendAddIceCandidateFailed = _try_catch(function (e, pc, cs) { module.exports = CallStats; }).call(this,"/modules/statistics/CallStats.js") -},{"jitsi-meet-logger":49,"jssha":50,"socket.io-client":81}],23:[function(require,module,exports){ +},{"jitsi-meet-logger":49,"jssha":50,"socket.io-client":85}],23:[function(require,module,exports){ /* global config */ /** * Provides statistics for the local stream. @@ -6444,7 +6567,7 @@ StatsCollector.prototype.processAudioLevelReport = function () { }; }).call(this,"/modules/statistics/RTPStatsCollector.js") -},{"../../service/statistics/Events":136,"../RTC/RTCBrowserType":17,"jitsi-meet-logger":49}],25:[function(require,module,exports){ +},{"../../service/statistics/Events":140,"../RTC/RTCBrowserType":17,"jitsi-meet-logger":49}],25:[function(require,module,exports){ /* global require, APP */ var LocalStats = require("./LocalStatsCollector.js"); var RTPStats = require("./RTPStatsCollector.js"); @@ -6728,7 +6851,7 @@ Statistics.LOCAL_JID = require("../../service/statistics/constants").LOCAL_JID; module.exports = Statistics; -},{"../../service/statistics/Events":136,"../../service/statistics/constants":137,"./CallStats":22,"./LocalStatsCollector.js":23,"./RTPStatsCollector.js":24,"events":45}],26:[function(require,module,exports){ +},{"../../service/statistics/Events":140,"../../service/statistics/constants":141,"./CallStats":22,"./LocalStatsCollector.js":23,"./RTPStatsCollector.js":24,"events":45}],26:[function(require,module,exports){ /** /** * @const @@ -7558,12 +7681,9 @@ ChatRoom.prototype.onPresence = function (pres) { } } - if(!member.isFocus) - this.eventEmitter.emit(XMPPEvents.USER_ID_CHANGED, from, member.id); - // Trigger status message update if (member.status) { - this.eventEmitter.emit(XMPPEvents.PRESENCE_STATUS, from, member); + this.eventEmitter.emit(XMPPEvents.PRESENCE_STATUS, from, member.status); } if(jibri) @@ -8048,7 +8168,7 @@ ChatRoom.prototype.onMute = function (iq) { module.exports = ChatRoom; }).call(this,"/modules/xmpp/ChatRoom.js") -},{"../../service/xmpp/XMPPEvents":138,"./moderator":35,"./recording":36,"events":45,"jitsi-meet-logger":49}],29:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"./moderator":35,"./recording":36,"events":45,"jitsi-meet-logger":49}],29:[function(require,module,exports){ (function (__filename){ /* * JingleSession provides an API to manage a single Jingle session. We will @@ -9847,7 +9967,7 @@ JingleSessionPC.prototype.getIceConnectionState = function () { module.exports = JingleSessionPC; }).call(this,"/modules/xmpp/JingleSessionPC.js") -},{"../../service/xmpp/XMPPEvents":138,"../RTC/RTC":16,"../RTC/RTCBrowserType":17,"./JingleSession":29,"./SDP":31,"./SDPDiffer":32,"./SDPUtil":33,"./TraceablePeerConnection":34,"async":44,"jitsi-meet-logger":49,"sdp-transform":78}],31:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"../RTC/RTC":16,"../RTC/RTCBrowserType":17,"./JingleSession":29,"./SDP":31,"./SDPDiffer":32,"./SDPUtil":33,"./TraceablePeerConnection":34,"async":44,"jitsi-meet-logger":49,"sdp-transform":82}],31:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -11542,7 +11662,7 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) { module.exports = TraceablePeerConnection; }).call(this,"/modules/xmpp/TraceablePeerConnection.js") -},{"../../service/xmpp/XMPPEvents":138,"../RTC/RTC":16,"../RTC/RTCBrowserType.js":17,"../util/RandomUtil":26,"jitsi-meet-logger":49,"sdp-interop":68,"sdp-simulcast":75,"sdp-transform":78}],35:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"../RTC/RTC":16,"../RTC/RTCBrowserType.js":17,"../util/RandomUtil":26,"jitsi-meet-logger":49,"sdp-interop":68,"sdp-simulcast":75,"sdp-transform":82}],35:[function(require,module,exports){ (function (__filename){ /* global $, $iq, Promise, Strophe */ @@ -11998,7 +12118,7 @@ Moderator.prototype.logout = function (callback) { module.exports = Moderator; }).call(this,"/modules/xmpp/moderator.js") -},{"../../service/authentication/AuthenticationEvents":134,"../../service/xmpp/XMPPEvents":138,"jitsi-meet-logger":49}],36:[function(require,module,exports){ +},{"../../service/authentication/AuthenticationEvents":138,"../../service/xmpp/XMPPEvents":142,"jitsi-meet-logger":49}],36:[function(require,module,exports){ (function (__filename){ /* global $, $iq, config, connection, focusMucJid, messageHandler, Toolbar, Util, Promise */ @@ -12225,7 +12345,7 @@ Recording.prototype.getURL = function () { module.exports = Recording; }).call(this,"/modules/xmpp/recording.js") -},{"../../service/xmpp/XMPPEvents":138,"jitsi-meet-logger":49}],37:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"jitsi-meet-logger":49}],37:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ /* a simple MUC connection plugin @@ -12635,7 +12755,7 @@ module.exports = function(XMPP, eventEmitter) { }).call(this,"/modules/xmpp/strophe.jingle.js") -},{"../../service/xmpp/XMPPEvents":138,"../RTC/RTCBrowserType":17,"./JingleSessionPC":30,"jitsi-meet-logger":49}],39:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"../RTC/RTCBrowserType":17,"./JingleSessionPC":30,"jitsi-meet-logger":49}],39:[function(require,module,exports){ /* global Strophe */ module.exports = function () { @@ -12783,7 +12903,7 @@ module.exports = function (XMPP, eventEmitter) { }; }).call(this,"/modules/xmpp/strophe.ping.js") -},{"../../service/xmpp/XMPPEvents":138,"jitsi-meet-logger":49}],41:[function(require,module,exports){ +},{"../../service/xmpp/XMPPEvents":142,"jitsi-meet-logger":49}],41:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ var logger = require("jitsi-meet-logger").getLogger(__filename); @@ -13006,9 +13126,6 @@ function initStrophePlugins(XMPP) // broadcastLocalVideoType, // StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED // ); -// RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) { -// XMPP.addToPresence("devices", devices); -// }); //} function XMPP(options) { @@ -13261,7 +13378,7 @@ XMPP.prototype.disconnect = function () { module.exports = XMPP; }).call(this,"/modules/xmpp/xmpp.js") -},{"../../JitsiConnectionErrors":5,"../../JitsiConnectionEvents":6,"../../service/RTC/RTCEvents":132,"../../service/xmpp/XMPPEvents":138,"../RTC/RTC":16,"./strophe.emuc":37,"./strophe.jingle":38,"./strophe.logger":39,"./strophe.ping":40,"./strophe.rayo":41,"./strophe.util":42,"events":45,"jitsi-meet-logger":49,"pako":51}],44:[function(require,module,exports){ +},{"../../JitsiConnectionErrors":5,"../../JitsiConnectionEvents":6,"../../service/RTC/RTCEvents":136,"../../service/xmpp/XMPPEvents":142,"../RTC/RTC":16,"./strophe.emuc":37,"./strophe.jingle":38,"./strophe.logger":39,"./strophe.ping":40,"./strophe.rayo":41,"./strophe.util":42,"events":45,"jitsi-meet-logger":49,"pako":51}],44:[function(require,module,exports){ (function (process){ /*! * async @@ -24326,10 +24443,18 @@ arguments[4][73][0].apply(exports,arguments) },{"./grammar":77,"dup":73}],80:[function(require,module,exports){ arguments[4][74][0].apply(exports,arguments) },{"./grammar":77,"dup":74}],81:[function(require,module,exports){ +arguments[4][71][0].apply(exports,arguments) +},{"dup":71}],82:[function(require,module,exports){ +arguments[4][72][0].apply(exports,arguments) +},{"./parser":83,"./writer":84,"dup":72}],83:[function(require,module,exports){ +arguments[4][73][0].apply(exports,arguments) +},{"./grammar":81,"dup":73}],84:[function(require,module,exports){ +arguments[4][74][0].apply(exports,arguments) +},{"./grammar":81,"dup":74}],85:[function(require,module,exports){ module.exports = require('./lib/'); -},{"./lib/":82}],82:[function(require,module,exports){ +},{"./lib/":86}],86:[function(require,module,exports){ /** * Module dependencies. @@ -24418,7 +24543,7 @@ exports.connect = lookup; exports.Manager = require('./manager'); exports.Socket = require('./socket'); -},{"./manager":83,"./socket":85,"./url":86,"debug":90,"socket.io-parser":126}],83:[function(require,module,exports){ +},{"./manager":87,"./socket":89,"./url":90,"debug":94,"socket.io-parser":130}],87:[function(require,module,exports){ /** * Module dependencies. @@ -24923,7 +25048,7 @@ Manager.prototype.onreconnect = function(){ this.emitAll('reconnect', attempt); }; -},{"./on":84,"./socket":85,"./url":86,"backo2":87,"component-bind":88,"component-emitter":89,"debug":90,"engine.io-client":91,"indexof":122,"object-component":123,"socket.io-parser":126}],84:[function(require,module,exports){ +},{"./on":88,"./socket":89,"./url":90,"backo2":91,"component-bind":92,"component-emitter":93,"debug":94,"engine.io-client":95,"indexof":126,"object-component":127,"socket.io-parser":130}],88:[function(require,module,exports){ /** * Module exports. @@ -24949,7 +25074,7 @@ function on(obj, ev, fn) { }; } -},{}],85:[function(require,module,exports){ +},{}],89:[function(require,module,exports){ /** * Module dependencies. @@ -25336,7 +25461,7 @@ Socket.prototype.disconnect = function(){ return this; }; -},{"./on":84,"component-bind":88,"component-emitter":89,"debug":90,"has-binary":120,"socket.io-parser":126,"to-array":130}],86:[function(require,module,exports){ +},{"./on":88,"component-bind":92,"component-emitter":93,"debug":94,"has-binary":124,"socket.io-parser":130,"to-array":134}],90:[function(require,module,exports){ (function (global){ /** @@ -25413,7 +25538,7 @@ function url(uri, loc){ } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"debug":90,"parseuri":124}],87:[function(require,module,exports){ +},{"debug":94,"parseuri":128}],91:[function(require,module,exports){ /** * Expose `Backoff`. @@ -25500,7 +25625,7 @@ Backoff.prototype.setJitter = function(jitter){ }; -},{}],88:[function(require,module,exports){ +},{}],92:[function(require,module,exports){ /** * Slice reference. */ @@ -25525,7 +25650,7 @@ module.exports = function(obj, fn){ } }; -},{}],89:[function(require,module,exports){ +},{}],93:[function(require,module,exports){ /** * Expose `Emitter`. @@ -25691,7 +25816,7 @@ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; -},{}],90:[function(require,module,exports){ +},{}],94:[function(require,module,exports){ /** * Expose `debug()` as the module. @@ -25830,11 +25955,11 @@ try { if (window.localStorage) debug.enable(localStorage.debug); } catch(e){} -},{}],91:[function(require,module,exports){ +},{}],95:[function(require,module,exports){ module.exports = require('./lib/'); -},{"./lib/":92}],92:[function(require,module,exports){ +},{"./lib/":96}],96:[function(require,module,exports){ module.exports = require('./socket'); @@ -25846,7 +25971,7 @@ module.exports = require('./socket'); */ module.exports.parser = require('engine.io-parser'); -},{"./socket":93,"engine.io-parser":105}],93:[function(require,module,exports){ +},{"./socket":97,"engine.io-parser":109}],97:[function(require,module,exports){ (function (global){ /** * Module dependencies. @@ -26555,7 +26680,7 @@ Socket.prototype.filterUpgrades = function (upgrades) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./transport":94,"./transports":95,"component-emitter":89,"debug":102,"engine.io-parser":105,"indexof":122,"parsejson":116,"parseqs":117,"parseuri":118}],94:[function(require,module,exports){ +},{"./transport":98,"./transports":99,"component-emitter":93,"debug":106,"engine.io-parser":109,"indexof":126,"parsejson":120,"parseqs":121,"parseuri":122}],98:[function(require,module,exports){ /** * Module dependencies. */ @@ -26716,7 +26841,7 @@ Transport.prototype.onClose = function () { this.emit('close'); }; -},{"component-emitter":89,"engine.io-parser":105}],95:[function(require,module,exports){ +},{"component-emitter":93,"engine.io-parser":109}],99:[function(require,module,exports){ (function (global){ /** * Module dependencies @@ -26773,7 +26898,7 @@ function polling(opts){ } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling-jsonp":96,"./polling-xhr":97,"./websocket":99,"xmlhttprequest":100}],96:[function(require,module,exports){ +},{"./polling-jsonp":100,"./polling-xhr":101,"./websocket":103,"xmlhttprequest":104}],100:[function(require,module,exports){ (function (global){ /** @@ -27010,7 +27135,7 @@ JSONPPolling.prototype.doWrite = function (data, fn) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":98,"component-inherit":101}],97:[function(require,module,exports){ +},{"./polling":102,"component-inherit":105}],101:[function(require,module,exports){ (function (global){ /** * Module requirements. @@ -27398,7 +27523,7 @@ function unloadHandler() { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":98,"component-emitter":89,"component-inherit":101,"debug":102,"xmlhttprequest":100}],98:[function(require,module,exports){ +},{"./polling":102,"component-emitter":93,"component-inherit":105,"debug":106,"xmlhttprequest":104}],102:[function(require,module,exports){ /** * Module dependencies. */ @@ -27645,7 +27770,7 @@ Polling.prototype.uri = function(){ return schema + '://' + this.hostname + port + this.path + query; }; -},{"../transport":94,"component-inherit":101,"debug":102,"engine.io-parser":105,"parseqs":117,"xmlhttprequest":100}],99:[function(require,module,exports){ +},{"../transport":98,"component-inherit":105,"debug":106,"engine.io-parser":109,"parseqs":121,"xmlhttprequest":104}],103:[function(require,module,exports){ /** * Module dependencies. */ @@ -27885,7 +28010,7 @@ WS.prototype.check = function(){ return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name); }; -},{"../transport":94,"component-inherit":101,"debug":102,"engine.io-parser":105,"parseqs":117,"ws":119}],100:[function(require,module,exports){ +},{"../transport":98,"component-inherit":105,"debug":106,"engine.io-parser":109,"parseqs":121,"ws":123}],104:[function(require,module,exports){ // browser shim for xmlhttprequest module var hasCORS = require('has-cors'); @@ -27923,7 +28048,7 @@ module.exports = function(opts) { } } -},{"has-cors":114}],101:[function(require,module,exports){ +},{"has-cors":118}],105:[function(require,module,exports){ module.exports = function(a, b){ var fn = function(){}; @@ -27931,7 +28056,7 @@ module.exports = function(a, b){ a.prototype = new fn; a.prototype.constructor = a; }; -},{}],102:[function(require,module,exports){ +},{}],106:[function(require,module,exports){ /** * This is the web browser implementation of `debug()`. @@ -28080,7 +28205,7 @@ function load() { exports.enable(load()); -},{"./debug":103}],103:[function(require,module,exports){ +},{"./debug":107}],107:[function(require,module,exports){ /** * This is the common logic for both the Node.js and web browser @@ -28279,7 +28404,7 @@ function coerce(val) { return val; } -},{"ms":104}],104:[function(require,module,exports){ +},{"ms":108}],108:[function(require,module,exports){ /** * Helpers. */ @@ -28392,7 +28517,7 @@ function plural(ms, n, name) { return Math.ceil(ms / n) + ' ' + name + 's'; } -},{}],105:[function(require,module,exports){ +},{}],109:[function(require,module,exports){ (function (global){ /** * Module dependencies. @@ -28990,7 +29115,7 @@ exports.decodePayloadAsBinary = function (data, binaryType, callback) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./keys":106,"after":107,"arraybuffer.slice":108,"base64-arraybuffer":109,"blob":110,"has-binary":111,"utf8":113}],106:[function(require,module,exports){ +},{"./keys":110,"after":111,"arraybuffer.slice":112,"base64-arraybuffer":113,"blob":114,"has-binary":115,"utf8":117}],110:[function(require,module,exports){ /** * Gets the keys for an object. @@ -29011,7 +29136,7 @@ module.exports = Object.keys || function keys (obj){ return arr; }; -},{}],107:[function(require,module,exports){ +},{}],111:[function(require,module,exports){ module.exports = after function after(count, callback, err_cb) { @@ -29041,7 +29166,7 @@ function after(count, callback, err_cb) { function noop() {} -},{}],108:[function(require,module,exports){ +},{}],112:[function(require,module,exports){ /** * An abstraction for slicing an arraybuffer even when * ArrayBuffer.prototype.slice is not supported @@ -29072,7 +29197,7 @@ module.exports = function(arraybuffer, start, end) { return result.buffer; }; -},{}],109:[function(require,module,exports){ +},{}],113:[function(require,module,exports){ /* * base64-arraybuffer * https://github.com/niklasvh/base64-arraybuffer @@ -29133,7 +29258,7 @@ module.exports = function(arraybuffer, start, end) { }; })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); -},{}],110:[function(require,module,exports){ +},{}],114:[function(require,module,exports){ (function (global){ /** * Create a blob builder even when vendor prefixes exist @@ -29186,7 +29311,7 @@ module.exports = (function() { })(); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],111:[function(require,module,exports){ +},{}],115:[function(require,module,exports){ (function (global){ /* @@ -29248,12 +29373,12 @@ function hasBinary(data) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":112}],112:[function(require,module,exports){ +},{"isarray":116}],116:[function(require,module,exports){ module.exports = Array.isArray || function (arr) { return Object.prototype.toString.call(arr) == '[object Array]'; }; -},{}],113:[function(require,module,exports){ +},{}],117:[function(require,module,exports){ (function (global){ /*! http://mths.be/utf8js v2.0.0 by @mathias */ ;(function(root) { @@ -29496,7 +29621,7 @@ module.exports = Array.isArray || function (arr) { }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],114:[function(require,module,exports){ +},{}],118:[function(require,module,exports){ /** * Module dependencies. @@ -29521,7 +29646,7 @@ try { module.exports = false; } -},{"global":115}],115:[function(require,module,exports){ +},{"global":119}],119:[function(require,module,exports){ /** * Returns `this`. Execute this without a "context" (i.e. without it being @@ -29531,7 +29656,7 @@ try { module.exports = (function () { return this; })(); -},{}],116:[function(require,module,exports){ +},{}],120:[function(require,module,exports){ (function (global){ /** * JSON parse. @@ -29566,7 +29691,7 @@ module.exports = function parsejson(data) { } }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],117:[function(require,module,exports){ +},{}],121:[function(require,module,exports){ /** * Compiles a querystring * Returns string representation of the object @@ -29605,7 +29730,7 @@ exports.decode = function(qs){ return qry; }; -},{}],118:[function(require,module,exports){ +},{}],122:[function(require,module,exports){ /** * Parses an URI * @@ -29646,7 +29771,7 @@ module.exports = function parseuri(str) { return uri; }; -},{}],119:[function(require,module,exports){ +},{}],123:[function(require,module,exports){ /** * Module dependencies. @@ -29691,7 +29816,7 @@ function ws(uri, protocols, opts) { if (WebSocket) ws.prototype = WebSocket.prototype; -},{}],120:[function(require,module,exports){ +},{}],124:[function(require,module,exports){ (function (global){ /* @@ -29753,9 +29878,9 @@ function hasBinary(data) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":121}],121:[function(require,module,exports){ -arguments[4][112][0].apply(exports,arguments) -},{"dup":112}],122:[function(require,module,exports){ +},{"isarray":125}],125:[function(require,module,exports){ +arguments[4][116][0].apply(exports,arguments) +},{"dup":116}],126:[function(require,module,exports){ var indexOf = [].indexOf; @@ -29766,7 +29891,7 @@ module.exports = function(arr, obj){ } return -1; }; -},{}],123:[function(require,module,exports){ +},{}],127:[function(require,module,exports){ /** * HOP ref. @@ -29851,7 +29976,7 @@ exports.length = function(obj){ exports.isEmpty = function(obj){ return 0 == exports.length(obj); }; -},{}],124:[function(require,module,exports){ +},{}],128:[function(require,module,exports){ /** * Parses an URI * @@ -29878,7 +30003,7 @@ module.exports = function parseuri(str) { return uri; }; -},{}],125:[function(require,module,exports){ +},{}],129:[function(require,module,exports){ (function (global){ /*global Blob,File*/ @@ -30023,7 +30148,7 @@ exports.removeBlobs = function(data, callback) { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./is-buffer":127,"isarray":128}],126:[function(require,module,exports){ +},{"./is-buffer":131,"isarray":132}],130:[function(require,module,exports){ /** * Module dependencies. @@ -30425,7 +30550,7 @@ function error(data){ }; } -},{"./binary":125,"./is-buffer":127,"component-emitter":89,"debug":90,"isarray":128,"json3":129}],127:[function(require,module,exports){ +},{"./binary":129,"./is-buffer":131,"component-emitter":93,"debug":94,"isarray":132,"json3":133}],131:[function(require,module,exports){ (function (global){ module.exports = isBuf; @@ -30442,9 +30567,9 @@ function isBuf(obj) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],128:[function(require,module,exports){ -arguments[4][112][0].apply(exports,arguments) -},{"dup":112}],129:[function(require,module,exports){ +},{}],132:[function(require,module,exports){ +arguments[4][116][0].apply(exports,arguments) +},{"dup":116}],133:[function(require,module,exports){ /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */ ;(function (window) { // Convenience aliases. @@ -31307,7 +31432,7 @@ arguments[4][112][0].apply(exports,arguments) } }(this)); -},{}],130:[function(require,module,exports){ +},{}],134:[function(require,module,exports){ module.exports = toArray function toArray(list, index) { @@ -31322,14 +31447,14 @@ function toArray(list, index) { return array } -},{}],131:[function(require,module,exports){ +},{}],135:[function(require,module,exports){ var MediaStreamType = { VIDEO_TYPE: "Video", AUDIO_TYPE: "Audio" }; module.exports = MediaStreamType; -},{}],132:[function(require,module,exports){ +},{}],136:[function(require,module,exports){ var RTCEvents = { RTC_READY: "rtc.ready", DATA_CHANNEL_OPEN: "rtc.data_channel_open", @@ -31341,7 +31466,7 @@ var RTCEvents = { }; module.exports = RTCEvents; -},{}],133:[function(require,module,exports){ +},{}],137:[function(require,module,exports){ var Resolutions = { "1080": { width: 1920, @@ -31395,7 +31520,7 @@ var Resolutions = { } }; module.exports = Resolutions; -},{}],134:[function(require,module,exports){ +},{}],138:[function(require,module,exports){ var AuthenticationEvents = { /** * Event callback arguments: @@ -31409,7 +31534,7 @@ var AuthenticationEvents = { }; module.exports = AuthenticationEvents; -},{}],135:[function(require,module,exports){ +},{}],139:[function(require,module,exports){ var DesktopSharingEventTypes = { /** * An event which indicates that the jidesha extension for Firefox is @@ -31420,7 +31545,7 @@ var DesktopSharingEventTypes = { module.exports = DesktopSharingEventTypes; -},{}],136:[function(require,module,exports){ +},{}],140:[function(require,module,exports){ module.exports = { /** * An event carrying connection statistics. @@ -31436,12 +31561,12 @@ module.exports = { STOP: "statistics.stop" }; -},{}],137:[function(require,module,exports){ +},{}],141:[function(require,module,exports){ var Constants = { LOCAL_JID: 'local' }; module.exports = Constants; -},{}],138:[function(require,module,exports){ +},{}],142:[function(require,module,exports){ var XMPPEvents = { // Designates an event indicating that the connection to the XMPP server // failed. @@ -31457,11 +31582,6 @@ var XMPPEvents = { CALL_INCOMING: "xmpp.callincoming.jingle", // Designates an event indicating that we were kicked from the XMPP MUC. KICKED: "xmpp.kicked", - // Designates an event indicating that the userID for a specific JID has - // changed. - // Note: currently this event fires every time we receive presence from - // someone (regardless of whether or not the "userID" changed). - USER_ID_CHANGED: "xmpp.user_id_changed", // Designates an event indicating that we have joined the XMPP MUC. MUC_JOINED: "xmpp.muc_joined", // Designates an event indicating that a participant joined the XMPP MUC. @@ -31506,11 +31626,6 @@ var XMPPEvents = { // Designates an event indicating that we should join the conference with // audio and/or video muted. START_MUTED_FROM_FOCUS: "xmpp.start_muted_from_focus", - // Designates an event indicating that a remote participant's available - // devices (whether he supports a audio and/or video) changed. - // Note: currently this event fires every time we receive presence from - // someone (regardless of whether or not the devices changed). - DEVICE_AVAILABLE: "xmpp.device_available", PEERCONNECTION_READY: "xmpp.peerconnection_ready", diff --git a/modules/UI/UI.js b/modules/UI/UI.js index fd49dd641..8b991e3a4 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -842,4 +842,8 @@ UI.showExtensionRequiredDialog = function (url) { "dialog.firefoxExtensionPrompt", {url: url})); }; +UI.updateDevicesAvailability = function (id, devices) { + VideoLayout.setDeviceAvailabilityIcons(id, devices); +}; + module.exports = UI; diff --git a/modules/UI/videolayout/LargeVideo.js b/modules/UI/videolayout/LargeVideo.js index 05783cdbc..f7dd1f797 100644 --- a/modules/UI/videolayout/LargeVideo.js +++ b/modules/UI/videolayout/LargeVideo.js @@ -154,9 +154,7 @@ class VideoContainer extends LargeContainer { } get id () { - if (this.stream) { - return getStreamId(this.stream); - } + return getStreamId(this.stream); } constructor (onPlay) { diff --git a/modules/UI/videolayout/VideoLayout.js b/modules/UI/videolayout/VideoLayout.js index 57510511b..c8f848a6c 100644 --- a/modules/UI/videolayout/VideoLayout.js +++ b/modules/UI/videolayout/VideoLayout.js @@ -187,16 +187,18 @@ var VideoLayout = { * @param resourceJid the jid of user * @param devices available devices */ - setDeviceAvailabilityIcons (resourceJid, devices) { - if(!devices) - return; - - if(!resourceJid) { + setDeviceAvailabilityIcons (id, devices) { + if (APP.conference.isLocalId(id)) { localVideoThumbnail.setDeviceAvailabilityIcons(devices); - } else { - if(remoteVideos[resourceJid]) - remoteVideos[resourceJid].setDeviceAvailabilityIcons(devices); + return; } + + let video = remoteVideos[id]; + if (!video) { + return; + } + + video.setDeviceAvailabilityIcons(devices); }, /**