From df913500033274166483c34b82e0c5737edc5ec2 Mon Sep 17 00:00:00 2001 From: isymchych Date: Thu, 19 Nov 2015 16:20:54 +0200 Subject: [PATCH 1/2] Use Object.defineProperty instead of Object.prototype._defineGetter_ --- modules/xmpp/TraceablePeerConnection.js | 73 +++++++++++++------------ 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/modules/xmpp/TraceablePeerConnection.js b/modules/xmpp/TraceablePeerConnection.js index dc9606ae7..f9e50f0c6 100644 --- a/modules/xmpp/TraceablePeerConnection.js +++ b/modules/xmpp/TraceablePeerConnection.js @@ -206,45 +206,49 @@ var normalizePlanB = function(desc) { }); }; -if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { - TraceablePeerConnection.prototype.__defineGetter__( - 'signalingState', - function() { return this.peerconnection.signalingState; }); - TraceablePeerConnection.prototype.__defineGetter__( - 'iceConnectionState', - function() { return this.peerconnection.iceConnectionState; }); - TraceablePeerConnection.prototype.__defineGetter__( - 'localDescription', - function() { - var desc = this.peerconnection.localDescription; +var getters = { + signalingState: function () { + return this.peerconnection.signalingState; + }, + iceConnectionState: function () { + return this.peerconnection.iceConnectionState; + }, + localDescription: function() { + var desc = this.peerconnection.localDescription; // TODO this should be after the Unified Plan -> Plan B // transformation. - desc = SSRCReplacement.mungeLocalVideoSSRC(desc); - - this.trace('getLocalDescription::preTransform', dumpSDP(desc)); + desc = SSRCReplacement.mungeLocalVideoSSRC(desc); - // if we're running on FF, transform to Plan B first. - if (RTCBrowserType.usesUnifiedPlan()) { - desc = this.interop.toPlanB(desc); - this.trace('getLocalDescription::postTransform (Plan B)', dumpSDP(desc)); - } - return desc; - }); - TraceablePeerConnection.prototype.__defineGetter__( - 'remoteDescription', - function() { - var desc = this.peerconnection.remoteDescription; - this.trace('getRemoteDescription::preTransform', dumpSDP(desc)); + this.trace('getLocalDescription::preTransform', dumpSDP(desc)); - // if we're running on FF, transform to Plan B first. - if (RTCBrowserType.usesUnifiedPlan()) { - desc = this.interop.toPlanB(desc); - this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc)); - } - return desc; - }); -} + // if we're running on FF, transform to Plan B first. + if (RTCBrowserType.usesUnifiedPlan()) { + desc = this.interop.toPlanB(desc); + this.trace('getLocalDescription::postTransform (Plan B)', dumpSDP(desc)); + } + return desc; + }, + remoteDescription: function() { + var desc = this.peerconnection.remoteDescription; + this.trace('getRemoteDescription::preTransform', dumpSDP(desc)); + + // if we're running on FF, transform to Plan B first. + if (RTCBrowserType.usesUnifiedPlan()) { + desc = this.interop.toPlanB(desc); + this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc)); + } + return desc; + } +}; +Object.keys(getters).forEach(function (prop) { + Object.defineProperty( + TraceablePeerConnection.prototype, + prop, { + get: getters[prop] + } + ); +}); TraceablePeerConnection.prototype.addStream = function (stream) { this.trace('addStream', stream.id); @@ -443,4 +447,3 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) { }; module.exports = TraceablePeerConnection; - From d9b175c7a87220a1ffcdabd4425068c9c1495cc8 Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Tue, 8 Dec 2015 20:25:39 +1100 Subject: [PATCH 2/2] Fixes the issues with mute, audio levels and remove events that were attached to the conference --- JitsiConference.js | 122 ++++-- JitsiMeetJS.js | 23 +- JitsiTrackErrors.js | 3 +- JitsiTrackEvents.js | 2 +- doc/example/example.js | 37 +- lib-jitsi-meet.js | 478 +++++++++++++--------- modules/RTC/JitsiLocalTrack.js | 33 +- modules/RTC/JitsiRemoteTrack.js | 21 +- modules/RTC/JitsiTrack.js | 41 ++ modules/RTC/RTC.js | 75 +--- modules/statistics/LocalStatsCollector.js | 16 +- modules/statistics/statistics.js | 43 +- modules/xmpp/ChatRoom.js | 4 +- modules/xmpp/JingleSessionPC.js | 37 ++ modules/xmpp/xmpp.js | 3 +- 15 files changed, 576 insertions(+), 362 deletions(-) diff --git a/JitsiConference.js b/JitsiConference.js index ed3978b72..87e8a3f94 100644 --- a/JitsiConference.js +++ b/JitsiConference.js @@ -2,12 +2,12 @@ var logger = require("jitsi-meet-logger").getLogger(__filename); var RTC = require("./modules/RTC/RTC"); var XMPPEvents = require("./service/xmpp/XMPPEvents"); -var StreamEventTypes = require("./service/RTC/StreamEventTypes"); var RTCEvents = require("./service/RTC/RTCEvents"); var EventEmitter = require("events"); var JitsiConferenceEvents = require("./JitsiConferenceEvents"); var JitsiParticipant = require("./JitsiParticipant"); var Statistics = require("./modules/statistics/statistics"); +var JitsiTrackEvents = require("./JitsiTrackEvents"); /** * Creates a JitsiConference object with the given name and properties. @@ -32,7 +32,7 @@ function JitsiConference(options) { this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config); this.room.updateDeviceAvailability(RTC.getDeviceAvailability()); this.rtc = new RTC(this.room, options); - if(!options.config.disableAudioLevels) + if(!RTC.options.disableAudioLevels) this.statistics = new Statistics(); setupListeners(this); this.participants = {}; @@ -88,15 +88,16 @@ JitsiConference.prototype.on = function (eventId, handler) { */ JitsiConference.prototype.off = function (eventId, handler) { if(this.eventEmitter) - this.eventEmitter.removeListener(eventId, listener); + this.eventEmitter.removeListener(eventId, handler); } // Common aliases for event emitter -JitsiConference.prototype.addEventListener = JitsiConference.prototype.on -JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off +JitsiConference.prototype.addEventListener = JitsiConference.prototype.on; +JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off; /** - * Receives notifications from another participants for commands / custom events(send by sendPresenceCommand method). + * Receives notifications from another participants for commands / custom events + * (send by sendPresenceCommand method). * @param command {String} the name of the command * @param handler {Function} handler for the command */ @@ -172,17 +173,55 @@ JitsiConference.prototype.setDisplayName = function(name) { * @param track the JitsiLocalTrack object. */ JitsiConference.prototype.addTrack = function (track) { - this.rtc.addLocalStream(track); - this.room.addStream(track.getOriginalStream(), function () {}); + this.room.addStream(track.getOriginalStream(), function () { + this.rtc.addLocalStream(track); + var muteHandler = this._fireMuteChangeEvent.bind(this, track); + var stopHandler = this.removeTrack.bind(this, track); + var audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this); + track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler); + track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler); + track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, + audioLevelHandler); + this.addEventListener(JitsiConferenceEvents.TRACK_REMOVED, function (track) { + track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, + muteHandler); + track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED, + stopHandler); + track.removeEventListener( + JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler); + }) + this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track); + }.bind(this)); + } +/** + * Fires TRACK_AUDIO_LEVEL_CHANGED change conference event. + * @param audioLevel the audio level + */ +JitsiConference.prototype._fireAudioLevelChangeEvent = function (audioLevel) { + this.eventEmitter.emit( + JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, + this.myUserId(), audioLevel); +} + +/** + * Fires TRACK_MUTE_CHANGED change conference event. + * @param track the JitsiTrack object related to the event. + */ +JitsiConference.prototype._fireMuteChangeEvent = function (track) { + this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track); +}; + /** * Removes JitsiLocalTrack object to the conference. * @param track the JitsiLocalTrack object. */ JitsiConference.prototype.removeTrack = function (track) { - this.room.removeStream(track.getOriginalStream()); - this.rtc.removeLocalStream(track); + this.room.removeStream(track.getOriginalStream(), function(){ + this.rtc.removeLocalStream(track); + this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track); + }.bind(this)); } /** @@ -247,8 +286,33 @@ function setupListeners(conference) { if(conference.statistics) conference.statistics.startRemoteStats(event.peerconnection); }); + conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED, - conference.rtc.createRemoteStream.bind(conference.rtc)); + function (data, sid, thessrc) { + var track = conference.rtc.createRemoteStream(data, sid, thessrc); + if(!track) + return; + conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, + track); + track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, + function () { + conference.eventEmitter.emit( + JitsiConferenceEvents.TRACK_REMOVED, track); + }); + track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, + function () { + conference.eventEmitter.emit( + JitsiConferenceEvents.TRACK_MUTE_CHANGED, track); + }); + var userId = track.getParitcipantId(); + track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, + function (audioLevel) { + conference.eventEmitter.emit( + JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, + userId, audioLevel); + }); + } + ); conference.room.addListener(XMPPEvents.MUC_JOINED, function () { conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED); @@ -285,25 +349,6 @@ function setupListeners(conference) { conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED); }); - conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED, - function (stream) { - conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, stream); - }); - -//FIXME: Maybe remove event should not be associated with the conference. - conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_ENDED, function (stream) { - conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream); - }); -//FIXME: Maybe remove event should not be associated with the conference. - conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, function (stream) { - conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream); - conference.removeTrack(stream); - }); - - conference.rtc.addListener(StreamEventTypes.TRACK_MUTE_CHANGED, function (track) { - conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track); - }); - conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) { if(conference.lastActiveSpeaker !== id && conference.room) { conference.lastActiveSpeaker = id; @@ -325,20 +370,11 @@ function setupListeners(conference) { //FIXME: Maybe remove event should not be associated with the conference. conference.statistics.addAudioLevelListener(function (ssrc, level) { var userId = null; - if (ssrc === Statistics.LOCAL_JID) { - userId = conference.myUserId(); - } else { - var jid = conference.room.getJidBySSRC(ssrc); - if (!jid) - return; + var jid = conference.room.getJidBySSRC(ssrc); + if (!jid) + return; - userId = Strophe.getResourceFromJid(jid); - } - conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, - userId, level); - }); - conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_CREATED, function (stream) { - conference.statistics.startLocalStats(stream); + conference.rtc.setAudioLevel(jid, level); }); conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, function () { diff --git a/JitsiMeetJS.js b/JitsiMeetJS.js index 4659357b0..24d5be77e 100644 --- a/JitsiMeetJS.js +++ b/JitsiMeetJS.js @@ -7,6 +7,7 @@ var JitsiTrackEvents = require("./JitsiTrackEvents"); var JitsiTrackErrors = require("./JitsiTrackErrors"); var Logger = require("jitsi-meet-logger"); var RTC = require("./modules/RTC/RTC"); +var Statistics = require("./modules/statistics/statistics"); /** * Namespace for the interface of Jitsi Meet Library. @@ -42,11 +43,29 @@ var LibJitsiMeet = { * will be returned trough the Promise, otherwise JitsiTrack objects will be returned. * @param {string} options.cameraDeviceId * @param {string} options.micDeviceId - * @returns {Promise.<{Array.}, JitsiConferenceError>} A promise that returns an array of created JitsiTracks if resolved, + * @returns {Promise.<{Array.}, JitsiConferenceError>} + * A promise that returns an array of created JitsiTracks if resolved, * or a JitsiConferenceError if rejected. */ createLocalTracks: function (options) { - return RTC.obtainAudioAndVideoPermissions(options || {}); + return RTC.obtainAudioAndVideoPermissions(options || {}).then( + function(tracks) { + if(!RTC.options.disableAudioLevels) + for(var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + var mStream = track.getOriginalStream(); + if(track.getType() === "audio"){ + Statistics.startLocalStats(mStream, + track.setAudioLevel.bind(track)); + track.addEventListener( + JitsiTrackEvents.TRACK_STOPPED, + function(){ + Statistics.stopLocalStats(mStream); + }); + } + } + return tracks; + }); }, isDeviceListAvailable: function () { return RTC.isDeviceListAvailable(); diff --git a/JitsiTrackErrors.js b/JitsiTrackErrors.js index 3a7cc3a66..9239bc6be 100644 --- a/JitsiTrackErrors.js +++ b/JitsiTrackErrors.js @@ -1,6 +1,7 @@ module.exports = { /** - * Returns JitsiTrackErrors based on the error object passed by GUM * @param error the error + * Returns JitsiTrackErrors based on the error object passed by GUM + * @param error the error * @param {Object} options the options object given to GUM. */ parseError: function (error, options) { diff --git a/JitsiTrackEvents.js b/JitsiTrackEvents.js index b7b229efe..cace3e680 100644 --- a/JitsiTrackEvents.js +++ b/JitsiTrackEvents.js @@ -10,7 +10,7 @@ var JitsiTrackEvents = { /** * The media track was removed to the conference. */ - TRACK_STOPPED: "track.TRACK_STOPPED", + TRACK_STOPPED: "track.stopped" }; module.exports = JitsiTrackEvents; diff --git a/doc/example/example.js b/doc/example/example.js index 6a775bfc7..9f91d4a02 100644 --- a/doc/example/example.js +++ b/doc/example/example.js @@ -9,8 +9,7 @@ var options = { } var confOptions = { - openSctp: true, - disableAudioLevels: true + openSctp: true } /** @@ -22,6 +21,18 @@ function onLocalTracks(tracks) localTracks = tracks; for(var i = 0; i < localTracks.length; i++) { + localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED, + function (audioLevel) { + console.debug("Audio Level local: " + audioLevel); + }); + localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED, + function () { + console.debug("local track muted"); + }); + localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_STOPPED, + function () { + console.debug("local track stoped"); + }); if(localTracks[i].getType() == "video") { $("body").append("