ソースを参照

Fixes the issues with mute, audio levels and remove events that were attached to the conference

master
hristoterezov 10年前
コミット
8409bab854

+ 80
- 44
JitsiConference.js ファイルの表示

2
 var logger = require("jitsi-meet-logger").getLogger(__filename);
2
 var logger = require("jitsi-meet-logger").getLogger(__filename);
3
 var RTC = require("./modules/RTC/RTC");
3
 var RTC = require("./modules/RTC/RTC");
4
 var XMPPEvents = require("./service/xmpp/XMPPEvents");
4
 var XMPPEvents = require("./service/xmpp/XMPPEvents");
5
-var StreamEventTypes = require("./service/RTC/StreamEventTypes");
6
 var RTCEvents = require("./service/RTC/RTCEvents");
5
 var RTCEvents = require("./service/RTC/RTCEvents");
7
 var EventEmitter = require("events");
6
 var EventEmitter = require("events");
8
 var JitsiConferenceEvents = require("./JitsiConferenceEvents");
7
 var JitsiConferenceEvents = require("./JitsiConferenceEvents");
9
 var JitsiParticipant = require("./JitsiParticipant");
8
 var JitsiParticipant = require("./JitsiParticipant");
10
 var Statistics = require("./modules/statistics/statistics");
9
 var Statistics = require("./modules/statistics/statistics");
10
+var JitsiTrackEvents = require("./JitsiTrackEvents");
11
 
11
 
12
 /**
12
 /**
13
  * Creates a JitsiConference object with the given name and properties.
13
  * Creates a JitsiConference object with the given name and properties.
32
     this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config);
32
     this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config);
33
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
33
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
34
     this.rtc = new RTC(this.room, options);
34
     this.rtc = new RTC(this.room, options);
35
-    if(!options.config.disableAudioLevels)
35
+    if(!RTC.options.disableAudioLevels)
36
         this.statistics = new Statistics();
36
         this.statistics = new Statistics();
37
     setupListeners(this);
37
     setupListeners(this);
38
     this.participants = {};
38
     this.participants = {};
88
  */
88
  */
89
 JitsiConference.prototype.off = function (eventId, handler) {
89
 JitsiConference.prototype.off = function (eventId, handler) {
90
     if(this.eventEmitter)
90
     if(this.eventEmitter)
91
-        this.eventEmitter.removeListener(eventId, listener);
91
+        this.eventEmitter.removeListener(eventId, handler);
92
 }
92
 }
93
 
93
 
94
 // Common aliases for event emitter
94
 // Common aliases for event emitter
95
-JitsiConference.prototype.addEventListener = JitsiConference.prototype.on
96
-JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
95
+JitsiConference.prototype.addEventListener = JitsiConference.prototype.on;
96
+JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off;
97
 
97
 
98
 /**
98
 /**
99
- * Receives notifications from another participants for commands / custom events(send by sendPresenceCommand method).
99
+ * Receives notifications from another participants for commands / custom events
100
+ * (send by sendPresenceCommand method).
100
  * @param command {String} the name of the command
101
  * @param command {String} the name of the command
101
  * @param handler {Function} handler for the command
102
  * @param handler {Function} handler for the command
102
  */
103
  */
172
  * @param track the JitsiLocalTrack object.
173
  * @param track the JitsiLocalTrack object.
173
  */
174
  */
174
 JitsiConference.prototype.addTrack = function (track) {
175
 JitsiConference.prototype.addTrack = function (track) {
175
-    this.rtc.addLocalStream(track);
176
-    this.room.addStream(track.getOriginalStream(), function () {});
176
+    this.room.addStream(track.getOriginalStream(), function () {
177
+        this.rtc.addLocalStream(track);
178
+        var muteHandler = this._fireMuteChangeEvent.bind(this, track);
179
+        var stopHandler = this.removeTrack.bind(this, track);
180
+        var audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
181
+        track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
182
+        track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
183
+        track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
184
+            audioLevelHandler);
185
+        this.addEventListener(JitsiConferenceEvents.TRACK_REMOVED, function (track) {
186
+            track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED,
187
+                muteHandler);
188
+            track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED,
189
+                stopHandler);
190
+            track.removeEventListener(
191
+                JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
192
+        })
193
+        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);
194
+    }.bind(this));
195
+
196
+}
197
+
198
+/**
199
+ * Fires TRACK_AUDIO_LEVEL_CHANGED change conference event.
200
+ * @param audioLevel the audio level
201
+ */
202
+JitsiConference.prototype._fireAudioLevelChangeEvent = function (audioLevel) {
203
+    this.eventEmitter.emit(
204
+        JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
205
+        this.myUserId(), audioLevel);
177
 }
206
 }
178
 
207
 
208
+/**
209
+ * Fires TRACK_MUTE_CHANGED change conference event.
210
+ * @param track the JitsiTrack object related to the event.
211
+ */
212
+JitsiConference.prototype._fireMuteChangeEvent = function (track) {
213
+    this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
214
+};
215
+
179
 /**
216
 /**
180
  * Removes JitsiLocalTrack object to the conference.
217
  * Removes JitsiLocalTrack object to the conference.
181
  * @param track the JitsiLocalTrack object.
218
  * @param track the JitsiLocalTrack object.
182
  */
219
  */
183
 JitsiConference.prototype.removeTrack = function (track) {
220
 JitsiConference.prototype.removeTrack = function (track) {
184
-    this.room.removeStream(track.getOriginalStream());
185
-    this.rtc.removeLocalStream(track);
221
+    this.room.removeStream(track.getOriginalStream(), function(){
222
+        this.rtc.removeLocalStream(track);
223
+        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
224
+    }.bind(this));
186
 }
225
 }
187
 
226
 
188
 /**
227
 /**
247
         if(conference.statistics)
286
         if(conference.statistics)
248
             conference.statistics.startRemoteStats(event.peerconnection);
287
             conference.statistics.startRemoteStats(event.peerconnection);
249
     });
288
     });
289
+
250
     conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED,
290
     conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED,
251
-        conference.rtc.createRemoteStream.bind(conference.rtc));
291
+        function (data, sid, thessrc) {
292
+            var track = conference.rtc.createRemoteStream(data, sid, thessrc);
293
+            if(!track)
294
+                return;
295
+            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED,
296
+                track);
297
+            track.addEventListener(JitsiTrackEvents.TRACK_STOPPED,
298
+                function () {
299
+                    conference.eventEmitter.emit(
300
+                        JitsiConferenceEvents.TRACK_REMOVED, track);
301
+                });
302
+            track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED,
303
+                function () {
304
+                    conference.eventEmitter.emit(
305
+                        JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
306
+                });
307
+            var userId = track.getParitcipantId();
308
+            track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
309
+                function (audioLevel) {
310
+                    conference.eventEmitter.emit(
311
+                        JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
312
+                        userId, audioLevel);
313
+                });
314
+        }
315
+    );
252
 
316
 
253
     conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
317
     conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
254
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
318
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
285
         conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED);
349
         conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED);
286
     });
350
     });
287
 
351
 
288
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED,
289
-        function (stream) {
290
-            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, stream);
291
-        });
292
-
293
-//FIXME: Maybe remove event should not be associated with the conference.
294
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_ENDED, function (stream) {
295
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream);
296
-    });
297
-//FIXME: Maybe remove event should not be associated with the conference.
298
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, function (stream) {
299
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream);
300
-        conference.removeTrack(stream);
301
-    });
302
-
303
-    conference.rtc.addListener(StreamEventTypes.TRACK_MUTE_CHANGED, function (track) {
304
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
305
-    });
306
-
307
     conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {
352
     conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {
308
         if(conference.lastActiveSpeaker !== id && conference.room) {
353
         if(conference.lastActiveSpeaker !== id && conference.room) {
309
             conference.lastActiveSpeaker = id;
354
             conference.lastActiveSpeaker = id;
325
         //FIXME: Maybe remove event should not be associated with the conference.
370
         //FIXME: Maybe remove event should not be associated with the conference.
326
         conference.statistics.addAudioLevelListener(function (ssrc, level) {
371
         conference.statistics.addAudioLevelListener(function (ssrc, level) {
327
             var userId = null;
372
             var userId = null;
328
-            if (ssrc === Statistics.LOCAL_JID) {
329
-                userId = conference.myUserId();
330
-            } else {
331
-                var jid = conference.room.getJidBySSRC(ssrc);
332
-                if (!jid)
333
-                    return;
334
-
335
-                userId = Strophe.getResourceFromJid(jid);
336
-            }
337
-            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
338
-                userId, level);
339
-        });
340
-        conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_CREATED, function (stream) {
341
-            conference.statistics.startLocalStats(stream);
373
+            var jid = conference.room.getJidBySSRC(ssrc);
374
+            if (!jid)
375
+                return;
376
+
377
+            conference.rtc.setAudioLevel(jid, level);
342
         });
378
         });
343
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
379
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
344
             function () {
380
             function () {

+ 21
- 2
JitsiMeetJS.js ファイルの表示

7
 var JitsiTrackErrors = require("./JitsiTrackErrors");
7
 var JitsiTrackErrors = require("./JitsiTrackErrors");
8
 var Logger = require("jitsi-meet-logger");
8
 var Logger = require("jitsi-meet-logger");
9
 var RTC = require("./modules/RTC/RTC");
9
 var RTC = require("./modules/RTC/RTC");
10
+var Statistics = require("./modules/statistics/statistics");
10
 
11
 
11
 /**
12
 /**
12
  * Namespace for the interface of Jitsi Meet Library.
13
  * Namespace for the interface of Jitsi Meet Library.
42
      * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.
43
      * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.
43
      * @param {string} options.cameraDeviceId
44
      * @param {string} options.cameraDeviceId
44
      * @param {string} options.micDeviceId
45
      * @param {string} options.micDeviceId
45
-     * @returns {Promise.<{Array.<JitsiTrack>}, JitsiConferenceError>} A promise that returns an array of created JitsiTracks if resolved,
46
+     * @returns {Promise.<{Array.<JitsiTrack>}, JitsiConferenceError>}
47
+     *     A promise that returns an array of created JitsiTracks if resolved,
46
      *     or a JitsiConferenceError if rejected.
48
      *     or a JitsiConferenceError if rejected.
47
      */
49
      */
48
     createLocalTracks: function (options) {
50
     createLocalTracks: function (options) {
49
-        return RTC.obtainAudioAndVideoPermissions(options || {});
51
+        return RTC.obtainAudioAndVideoPermissions(options || {}).then(
52
+            function(tracks) {
53
+                if(!RTC.options.disableAudioLevels)
54
+                    for(var i = 0; i < tracks.length; i++) {
55
+                        var track = tracks[i];
56
+                        var mStream = track.getOriginalStream();
57
+                        if(track.getType() === "audio"){
58
+                            Statistics.startLocalStats(mStream,
59
+                                track.setAudioLevel.bind(track));
60
+                            track.addEventListener(
61
+                                JitsiTrackEvents.TRACK_STOPPED,
62
+                                function(){
63
+                                    Statistics.stopLocalStats(mStream);
64
+                                });
65
+                        }
66
+                    }
67
+                return tracks;
68
+            });
50
     },
69
     },
51
     isDeviceListAvailable: function () {
70
     isDeviceListAvailable: function () {
52
         return RTC.isDeviceListAvailable();
71
         return RTC.isDeviceListAvailable();

+ 2
- 1
JitsiTrackErrors.js ファイルの表示

1
 module.exports = {
1
 module.exports = {
2
     /**
2
     /**
3
-     * Returns JitsiTrackErrors based on the error object passed by GUM * @param error the error
3
+     * Returns JitsiTrackErrors based on the error object passed by GUM
4
+     * @param error the error
4
      * @param {Object} options the options object given to GUM.
5
      * @param {Object} options the options object given to GUM.
5
      */
6
      */
6
     parseError: function (error, options) {
7
     parseError: function (error, options) {

+ 1
- 1
JitsiTrackEvents.js ファイルの表示

10
     /**
10
     /**
11
      * The media track was removed to the conference.
11
      * The media track was removed to the conference.
12
      */
12
      */
13
-    TRACK_STOPPED: "track.TRACK_STOPPED",
13
+    TRACK_STOPPED: "track.stopped"
14
 };
14
 };
15
 
15
 
16
 module.exports = JitsiTrackEvents;
16
 module.exports = JitsiTrackEvents;

+ 31
- 6
doc/example/example.js ファイルの表示

9
 }
9
 }
10
 
10
 
11
 var confOptions = {
11
 var confOptions = {
12
-    openSctp: true,
13
-    disableAudioLevels: true
12
+    openSctp: true
14
 }
13
 }
15
 
14
 
16
 /**
15
 /**
22
     localTracks = tracks;
21
     localTracks = tracks;
23
     for(var i = 0; i < localTracks.length; i++)
22
     for(var i = 0; i < localTracks.length; i++)
24
     {
23
     {
24
+        localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
25
+            function (audioLevel) {
26
+                console.debug("Audio Level local: " + audioLevel);
27
+            });
28
+        localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
29
+            function () {
30
+                console.debug("local track muted");
31
+            });
32
+        localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_STOPPED,
33
+            function () {
34
+                console.debug("local track stoped");
35
+            });
25
         if(localTracks[i].getType() == "video") {
36
         if(localTracks[i].getType() == "video") {
26
             $("body").append("<video autoplay='1' id='localVideo" + i + "' />");
37
             $("body").append("<video autoplay='1' id='localVideo" + i + "' />");
27
             localTracks[i].attach($("#localVideo" + i ));
38
             localTracks[i].attach($("#localVideo" + i ));
29
             $("body").append("<audio autoplay='1' id='localAudio" + i + "' />");
40
             $("body").append("<audio autoplay='1' id='localAudio" + i + "' />");
30
             localTracks[i].attach($("#localAudio" + i ));
41
             localTracks[i].attach($("#localAudio" + i ));
31
         }
42
         }
32
-        console.log(localTracks[i]);
33
     }
43
     }
34
 }
44
 }
35
 
45
 
38
  * @param track JitsiTrack object
48
  * @param track JitsiTrack object
39
  */
49
  */
40
 function onRemoteTrack(track) {
50
 function onRemoteTrack(track) {
51
+    if(track.isLocal())
52
+        return;
41
     var participant = track.getParitcipantId();
53
     var participant = track.getParitcipantId();
42
     if(!remoteTracks[participant])
54
     if(!remoteTracks[participant])
43
         remoteTracks[participant] = [];
55
         remoteTracks[participant] = [];
44
     var idx = remoteTracks[participant].push(track);
56
     var idx = remoteTracks[participant].push(track);
57
+    track.addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
58
+        function (audioLevel) {
59
+            console.debug("Audio Level remote: " + audioLevel);
60
+        });
61
+    track.addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
62
+        function () {
63
+            console.debug("remote track muted");
64
+        });
65
+    track.addEventListener(JitsiMeetJS.events.track.TRACK_STOPPED,
66
+        function () {
67
+            console.debug("remote track stoped");
68
+        });
45
     var id = participant + track.getType() + idx;
69
     var id = participant + track.getType() + idx;
46
     if(track.getType() == "video") {
70
     if(track.getType() == "video") {
47
         $("body").append("<video autoplay='1' id='" + participant + "video" + idx + "' />");
71
         $("body").append("<video autoplay='1' id='" + participant + "video" + idx + "' />");
74
 function onConnectionSuccess(){
98
 function onConnectionSuccess(){
75
     room = connection.initJitsiConference("conference2", confOptions);
99
     room = connection.initJitsiConference("conference2", confOptions);
76
     room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
100
     room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
77
-    room.on(JitsiMeetJS.events.conference.TRACK_REMOVED, function () {
78
-        console.debug("track removed!!!");
101
+    room.on(JitsiMeetJS.events.conference.TRACK_REMOVED, function (track) {
102
+        console.debug("track removed!!!" + track);
79
     });
103
     });
80
     room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
104
     room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
81
     room.on(JitsiMeetJS.events.conference.USER_JOINED, function(id){ remoteTracks[id] = [];});
105
     room.on(JitsiMeetJS.events.conference.USER_JOINED, function(id){ remoteTracks[id] = [];});
88
     });
112
     });
89
     room.on(JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED,
113
     room.on(JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED,
90
       function(userID, audioLevel){
114
       function(userID, audioLevel){
91
-          // console.log(userID + " - " + audioLevel);
115
+          console.log(userID + " - " + audioLevel);
92
       });
116
       });
93
     room.join();
117
     room.join();
94
 };
118
 };
120
 
144
 
121
 // JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
145
 // JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
122
 var initOptions = {
146
 var initOptions = {
147
+    // disableAudioLevels: true,
123
     // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
148
     // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
124
     desktopSharingChromeMethod: 'ext',
149
     desktopSharingChromeMethod: 'ext',
125
     // The ID of the jidesha extension for Chrome.
150
     // The ID of the jidesha extension for Chrome.

+ 283
- 195
lib-jitsi-meet.js ファイルの表示

4
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4
 var logger = require("jitsi-meet-logger").getLogger(__filename);
5
 var RTC = require("./modules/RTC/RTC");
5
 var RTC = require("./modules/RTC/RTC");
6
 var XMPPEvents = require("./service/xmpp/XMPPEvents");
6
 var XMPPEvents = require("./service/xmpp/XMPPEvents");
7
-var StreamEventTypes = require("./service/RTC/StreamEventTypes");
8
 var RTCEvents = require("./service/RTC/RTCEvents");
7
 var RTCEvents = require("./service/RTC/RTCEvents");
9
 var EventEmitter = require("events");
8
 var EventEmitter = require("events");
10
 var JitsiConferenceEvents = require("./JitsiConferenceEvents");
9
 var JitsiConferenceEvents = require("./JitsiConferenceEvents");
11
 var JitsiParticipant = require("./JitsiParticipant");
10
 var JitsiParticipant = require("./JitsiParticipant");
12
 var Statistics = require("./modules/statistics/statistics");
11
 var Statistics = require("./modules/statistics/statistics");
12
+var JitsiTrackEvents = require("./JitsiTrackEvents");
13
 
13
 
14
 /**
14
 /**
15
  * Creates a JitsiConference object with the given name and properties.
15
  * Creates a JitsiConference object with the given name and properties.
34
     this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config);
34
     this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config);
35
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
35
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
36
     this.rtc = new RTC(this.room, options);
36
     this.rtc = new RTC(this.room, options);
37
-    if(!options.config.disableAudioLevels)
37
+    if(!RTC.options.disableAudioLevels)
38
         this.statistics = new Statistics();
38
         this.statistics = new Statistics();
39
     setupListeners(this);
39
     setupListeners(this);
40
     this.participants = {};
40
     this.participants = {};
90
  */
90
  */
91
 JitsiConference.prototype.off = function (eventId, handler) {
91
 JitsiConference.prototype.off = function (eventId, handler) {
92
     if(this.eventEmitter)
92
     if(this.eventEmitter)
93
-        this.eventEmitter.removeListener(eventId, listener);
93
+        this.eventEmitter.removeListener(eventId, handler);
94
 }
94
 }
95
 
95
 
96
 // Common aliases for event emitter
96
 // Common aliases for event emitter
97
-JitsiConference.prototype.addEventListener = JitsiConference.prototype.on
98
-JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
97
+JitsiConference.prototype.addEventListener = JitsiConference.prototype.on;
98
+JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off;
99
 
99
 
100
 /**
100
 /**
101
- * Receives notifications from another participants for commands / custom events(send by sendPresenceCommand method).
101
+ * Receives notifications from another participants for commands / custom events
102
+ * (send by sendPresenceCommand method).
102
  * @param command {String} the name of the command
103
  * @param command {String} the name of the command
103
  * @param handler {Function} handler for the command
104
  * @param handler {Function} handler for the command
104
  */
105
  */
174
  * @param track the JitsiLocalTrack object.
175
  * @param track the JitsiLocalTrack object.
175
  */
176
  */
176
 JitsiConference.prototype.addTrack = function (track) {
177
 JitsiConference.prototype.addTrack = function (track) {
177
-    this.rtc.addLocalStream(track);
178
-    this.room.addStream(track.getOriginalStream(), function () {});
178
+    this.room.addStream(track.getOriginalStream(), function () {
179
+        this.rtc.addLocalStream(track);
180
+        var muteHandler = this._fireMuteChangeEvent.bind(this, track);
181
+        var stopHandler = this.removeTrack.bind(this, track);
182
+        var audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
183
+        track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
184
+        track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
185
+        track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
186
+            audioLevelHandler);
187
+        this.addEventListener(JitsiConferenceEvents.TRACK_REMOVED, function (track) {
188
+            track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED,
189
+                muteHandler);
190
+            track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED,
191
+                stopHandler);
192
+            track.removeEventListener(
193
+                JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
194
+        })
195
+        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);
196
+    }.bind(this));
197
+
198
+}
199
+
200
+/**
201
+ * Fires TRACK_AUDIO_LEVEL_CHANGED change conference event.
202
+ * @param audioLevel the audio level
203
+ */
204
+JitsiConference.prototype._fireAudioLevelChangeEvent = function (audioLevel) {
205
+    this.eventEmitter.emit(
206
+        JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
207
+        this.myUserId(), audioLevel);
179
 }
208
 }
180
 
209
 
210
+/**
211
+ * Fires TRACK_MUTE_CHANGED change conference event.
212
+ * @param track the JitsiTrack object related to the event.
213
+ */
214
+JitsiConference.prototype._fireMuteChangeEvent = function (track) {
215
+    this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
216
+};
217
+
181
 /**
218
 /**
182
  * Removes JitsiLocalTrack object to the conference.
219
  * Removes JitsiLocalTrack object to the conference.
183
  * @param track the JitsiLocalTrack object.
220
  * @param track the JitsiLocalTrack object.
184
  */
221
  */
185
 JitsiConference.prototype.removeTrack = function (track) {
222
 JitsiConference.prototype.removeTrack = function (track) {
186
-    this.room.removeStream(track.getOriginalStream());
187
-    this.rtc.removeLocalStream(track);
223
+    this.room.removeStream(track.getOriginalStream(), function(){
224
+        this.rtc.removeLocalStream(track);
225
+        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
226
+    }.bind(this));
188
 }
227
 }
189
 
228
 
190
 /**
229
 /**
249
         if(conference.statistics)
288
         if(conference.statistics)
250
             conference.statistics.startRemoteStats(event.peerconnection);
289
             conference.statistics.startRemoteStats(event.peerconnection);
251
     });
290
     });
291
+
252
     conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED,
292
     conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED,
253
-        conference.rtc.createRemoteStream.bind(conference.rtc));
293
+        function (data, sid, thessrc) {
294
+            var track = conference.rtc.createRemoteStream(data, sid, thessrc);
295
+            if(!track)
296
+                return;
297
+            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED,
298
+                track);
299
+            track.addEventListener(JitsiTrackEvents.TRACK_STOPPED,
300
+                function () {
301
+                    conference.eventEmitter.emit(
302
+                        JitsiConferenceEvents.TRACK_REMOVED, track);
303
+                });
304
+            track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED,
305
+                function () {
306
+                    conference.eventEmitter.emit(
307
+                        JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
308
+                });
309
+            var userId = track.getParitcipantId();
310
+            track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
311
+                function (audioLevel) {
312
+                    conference.eventEmitter.emit(
313
+                        JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
314
+                        userId, audioLevel);
315
+                });
316
+        }
317
+    );
254
 
318
 
255
     conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
319
     conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
256
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
320
         conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
287
         conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED);
351
         conference.eventEmitter.emit(JitsiConferenceEvents.SETUP_FAILED);
288
     });
352
     });
289
 
353
 
290
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED,
291
-        function (stream) {
292
-            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, stream);
293
-        });
294
-
295
-//FIXME: Maybe remove event should not be associated with the conference.
296
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_REMOTE_ENDED, function (stream) {
297
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream);
298
-    });
299
-//FIXME: Maybe remove event should not be associated with the conference.
300
-    conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, function (stream) {
301
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, stream);
302
-        conference.removeTrack(stream);
303
-    });
304
-
305
-    conference.rtc.addListener(StreamEventTypes.TRACK_MUTE_CHANGED, function (track) {
306
-        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);
307
-    });
308
-
309
     conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {
354
     conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {
310
         if(conference.lastActiveSpeaker !== id && conference.room) {
355
         if(conference.lastActiveSpeaker !== id && conference.room) {
311
             conference.lastActiveSpeaker = id;
356
             conference.lastActiveSpeaker = id;
327
         //FIXME: Maybe remove event should not be associated with the conference.
372
         //FIXME: Maybe remove event should not be associated with the conference.
328
         conference.statistics.addAudioLevelListener(function (ssrc, level) {
373
         conference.statistics.addAudioLevelListener(function (ssrc, level) {
329
             var userId = null;
374
             var userId = null;
330
-            if (ssrc === Statistics.LOCAL_JID) {
331
-                userId = conference.myUserId();
332
-            } else {
333
-                var jid = conference.room.getJidBySSRC(ssrc);
334
-                if (!jid)
335
-                    return;
375
+            var jid = conference.room.getJidBySSRC(ssrc);
376
+            if (!jid)
377
+                return;
336
 
378
 
337
-                userId = Strophe.getResourceFromJid(jid);
338
-            }
339
-            conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,
340
-                userId, level);
341
-        });
342
-        conference.rtc.addListener(StreamEventTypes.EVENT_TYPE_LOCAL_CREATED, function (stream) {
343
-            conference.statistics.startLocalStats(stream);
379
+            conference.rtc.setAudioLevel(jid, level);
344
         });
380
         });
345
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
381
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
346
             function () {
382
             function () {
357
 module.exports = JitsiConference;
393
 module.exports = JitsiConference;
358
 
394
 
359
 }).call(this,"/JitsiConference.js")
395
 }).call(this,"/JitsiConference.js")
360
-},{"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./modules/RTC/RTC":15,"./modules/statistics/statistics":23,"./service/RTC/RTCEvents":82,"./service/RTC/StreamEventTypes":84,"./service/xmpp/XMPPEvents":89,"events":42,"jitsi-meet-logger":46}],2:[function(require,module,exports){
396
+},{"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/RTC/RTC":15,"./modules/statistics/statistics":23,"./service/RTC/RTCEvents":82,"./service/xmpp/XMPPEvents":88,"events":42,"jitsi-meet-logger":46}],2:[function(require,module,exports){
361
 /**
397
 /**
362
  * Enumeration with the errors for the conference.
398
  * Enumeration with the errors for the conference.
363
  * @type {{string: string}}
399
  * @type {{string: string}}
627
 var JitsiTrackErrors = require("./JitsiTrackErrors");
663
 var JitsiTrackErrors = require("./JitsiTrackErrors");
628
 var Logger = require("jitsi-meet-logger");
664
 var Logger = require("jitsi-meet-logger");
629
 var RTC = require("./modules/RTC/RTC");
665
 var RTC = require("./modules/RTC/RTC");
666
+var Statistics = require("./modules/statistics/statistics");
630
 
667
 
631
 /**
668
 /**
632
  * Namespace for the interface of Jitsi Meet Library.
669
  * Namespace for the interface of Jitsi Meet Library.
662
      * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.
699
      * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.
663
      * @param {string} options.cameraDeviceId
700
      * @param {string} options.cameraDeviceId
664
      * @param {string} options.micDeviceId
701
      * @param {string} options.micDeviceId
665
-     * @returns {Promise.<{Array.<JitsiTrack>}, JitsiConferenceError>} A promise that returns an array of created JitsiTracks if resolved,
702
+     * @returns {Promise.<{Array.<JitsiTrack>}, JitsiConferenceError>}
703
+     *     A promise that returns an array of created JitsiTracks if resolved,
666
      *     or a JitsiConferenceError if rejected.
704
      *     or a JitsiConferenceError if rejected.
667
      */
705
      */
668
     createLocalTracks: function (options) {
706
     createLocalTracks: function (options) {
669
-        return RTC.obtainAudioAndVideoPermissions(options || {});
707
+        return RTC.obtainAudioAndVideoPermissions(options || {}).then(
708
+            function(tracks) {
709
+                if(!RTC.options.disableAudioLevels)
710
+                    for(var i = 0; i < tracks.length; i++) {
711
+                        var track = tracks[i];
712
+                        var mStream = track.getOriginalStream();
713
+                        if(track.getType() === "audio"){
714
+                            Statistics.startLocalStats(mStream,
715
+                                track.setAudioLevel.bind(track));
716
+                            track.addEventListener(
717
+                                JitsiTrackEvents.TRACK_STOPPED,
718
+                                function(){
719
+                                    Statistics.stopLocalStats(mStream);
720
+                                });
721
+                        }
722
+                    }
723
+                return tracks;
724
+            });
670
     },
725
     },
671
     isDeviceListAvailable: function () {
726
     isDeviceListAvailable: function () {
672
         return RTC.isDeviceListAvailable();
727
         return RTC.isDeviceListAvailable();
682
 
737
 
683
 module.exports = LibJitsiMeet;
738
 module.exports = LibJitsiMeet;
684
 
739
 
685
-},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":15,"es6-promise":44,"jitsi-meet-logger":46}],8:[function(require,module,exports){
740
+},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":15,"./modules/statistics/statistics":23,"es6-promise":44,"jitsi-meet-logger":46}],8:[function(require,module,exports){
686
 /**
741
 /**
687
  * Represents a participant in (a member of) a conference.
742
  * Represents a participant in (a member of) a conference.
688
  */
743
  */
823
 },{}],9:[function(require,module,exports){
878
 },{}],9:[function(require,module,exports){
824
 module.exports = {
879
 module.exports = {
825
     /**
880
     /**
826
-     * Returns JitsiTrackErrors based on the error object passed by GUM * @param error the error
881
+     * Returns JitsiTrackErrors based on the error object passed by GUM
882
+     * @param error the error
827
      * @param {Object} options the options object given to GUM.
883
      * @param {Object} options the options object given to GUM.
828
      */
884
      */
829
     parseError: function (error, options) {
885
     parseError: function (error, options) {
858
     /**
914
     /**
859
      * The media track was removed to the conference.
915
      * The media track was removed to the conference.
860
      */
916
      */
861
-    TRACK_STOPPED: "track.TRACK_STOPPED",
917
+    TRACK_STOPPED: "track.stopped"
862
 };
918
 };
863
 
919
 
864
 module.exports = JitsiTrackEvents;
920
 module.exports = JitsiTrackEvents;
1081
 }).call(this,"/modules/RTC/DataChannels.js")
1137
 }).call(this,"/modules/RTC/DataChannels.js")
1082
 },{"../../service/RTC/RTCEvents":82,"jitsi-meet-logger":46}],12:[function(require,module,exports){
1138
 },{"../../service/RTC/RTCEvents":82,"jitsi-meet-logger":46}],12:[function(require,module,exports){
1083
 var JitsiTrack = require("./JitsiTrack");
1139
 var JitsiTrack = require("./JitsiTrack");
1084
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
1085
 var RTCBrowserType = require("./RTCBrowserType");
1140
 var RTCBrowserType = require("./RTCBrowserType");
1141
+var JitsiTrackEvents = require('../../JitsiTrackEvents');
1086
 var RTC = require("./RTCUtils");
1142
 var RTC = require("./RTCUtils");
1087
 
1143
 
1088
 /**
1144
 /**
1095
     this.videoType = videoType;
1151
     this.videoType = videoType;
1096
     this.dontFireRemoveEvent = false;
1152
     this.dontFireRemoveEvent = false;
1097
     this.resolution = resolution;
1153
     this.resolution = resolution;
1154
+    this.startMuted = false;
1098
     var self = this;
1155
     var self = this;
1099
     JitsiTrack.call(this, null, stream,
1156
     JitsiTrack.call(this, null, stream,
1100
         function () {
1157
         function () {
1101
-            if(!self.dontFireRemoveEvent && self.rtc)
1102
-                self.rtc.eventEmitter.emit(
1103
-                    StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, self);
1104
-            self.dontFireRemoveEvent = false;
1105
-        });
1158
+            if(!this.dontFireRemoveEvent)
1159
+                this.eventEmitter.emit(
1160
+                    JitsiTrackEvents.TRACK_STOPPED);
1161
+            this.dontFireRemoveEvent = false;
1162
+        }.bind(this));
1106
 
1163
 
1107
 }
1164
 }
1108
 
1165
 
1115
  */
1172
  */
1116
 JitsiLocalTrack.prototype._setMute = function (mute) {
1173
 JitsiLocalTrack.prototype._setMute = function (mute) {
1117
     if(!this.rtc) {
1174
     if(!this.rtc) {
1118
-        console.error("Mute is not supported for streams not attached to conference!");
1175
+        this.startMuted = mute;
1119
         return;
1176
         return;
1120
     }
1177
     }
1121
     var isAudio = this.type === JitsiTrack.AUDIO;
1178
     var isAudio = this.type === JitsiTrack.AUDIO;
1122
     this.dontFireRemoveEvent = false;
1179
     this.dontFireRemoveEvent = false;
1123
 
1180
 
1124
     if ((window.location.protocol != "https:") ||
1181
     if ((window.location.protocol != "https:") ||
1125
-        (isAudio) || this.videoType === "screen" ||
1182
+        (isAudio) || this.videoType === "desktop" ||
1126
         // FIXME FF does not support 'removeStream' method used to mute
1183
         // FIXME FF does not support 'removeStream' method used to mute
1127
         RTCBrowserType.isFirefox()) {
1184
         RTCBrowserType.isFirefox()) {
1128
 
1185
 
1134
             this.rtc.room.setAudioMute(mute);
1191
             this.rtc.room.setAudioMute(mute);
1135
         else
1192
         else
1136
             this.rtc.room.setVideoMute(mute);
1193
             this.rtc.room.setVideoMute(mute);
1137
-        this.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
1194
+        this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
1138
     } else {
1195
     } else {
1139
         if (mute) {
1196
         if (mute) {
1140
             this.dontFireRemoveEvent = true;
1197
             this.dontFireRemoveEvent = true;
1145
             else
1202
             else
1146
                 this.rtc.room.setVideoMute(mute);
1203
                 this.rtc.room.setVideoMute(mute);
1147
             this.stream = null;
1204
             this.stream = null;
1148
-            this.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
1205
+            this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
1149
             //FIXME: Maybe here we should set the SRC for the containers to something
1206
             //FIXME: Maybe here we should set the SRC for the containers to something
1150
         } else {
1207
         } else {
1151
             var self = this;
1208
             var self = this;
1177
                                 self.rtc.room.setAudioMute(mute);
1234
                                 self.rtc.room.setAudioMute(mute);
1178
                             else
1235
                             else
1179
                                 self.rtc.room.setVideoMute(mute);
1236
                                 self.rtc.room.setVideoMute(mute);
1180
-                            self.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, self);
1237
+                            self.eventEmitter.emit(
1238
+                                JitsiTrackEvents.TRACK_MUTE_CHANGED);
1181
                         });
1239
                         });
1182
                 });
1240
                 });
1183
         }
1241
         }
1193
         return;
1251
         return;
1194
     if(this.rtc)
1252
     if(this.rtc)
1195
         this.rtc.room.removeStream(this.stream);
1253
         this.rtc.room.removeStream(this.stream);
1196
-    this.rtc.stopMediaStream(this.stream);
1254
+    RTC.stopMediaStream(this.stream);
1197
     this.detach();
1255
     this.detach();
1198
 }
1256
 }
1199
 
1257
 
1230
     this.rtc = rtc;
1288
     this.rtc = rtc;
1231
 };
1289
 };
1232
 
1290
 
1291
+/**
1292
+ * Return true;
1293
+ */
1294
+JitsiLocalTrack.prototype.isLocal = function () {
1295
+    return true;
1296
+}
1297
+
1233
 module.exports = JitsiLocalTrack;
1298
 module.exports = JitsiLocalTrack;
1234
 
1299
 
1235
-},{"../../service/RTC/StreamEventTypes":84,"./JitsiTrack":14,"./RTCBrowserType":16,"./RTCUtils":17}],13:[function(require,module,exports){
1300
+},{"../../JitsiTrackEvents":10,"./JitsiTrack":14,"./RTCBrowserType":16,"./RTCUtils":17}],13:[function(require,module,exports){
1236
 var JitsiTrack = require("./JitsiTrack");
1301
 var JitsiTrack = require("./JitsiTrack");
1237
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
1302
+var JitsiTrackEvents = require("../../JitsiTrackEvents");
1238
 
1303
 
1239
 /**
1304
 /**
1240
  * Represents a single media track (either audio or video).
1305
  * Represents a single media track (either audio or video).
1245
  * @param eventEmitter the event emitter
1310
  * @param eventEmitter the event emitter
1246
  * @constructor
1311
  * @constructor
1247
  */
1312
  */
1248
-function JitsiRemoteTrack(RTC, data, sid, ssrc, eventEmitter) {
1313
+function JitsiRemoteTrack(RTC, data, sid, ssrc) {
1249
     JitsiTrack.call(this, RTC, data.stream,
1314
     JitsiTrack.call(this, RTC, data.stream,
1250
         function () {
1315
         function () {
1251
-            eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_ENDED, self);
1252
-        });
1316
+            this.eventEmitter.emit(JitsiTrackEvents.TRACK_STOPPED);
1317
+        }.bind(this));
1253
     this.rtc = RTC;
1318
     this.rtc = RTC;
1254
     this.sid = sid;
1319
     this.sid = sid;
1255
     this.stream = data.stream;
1320
     this.stream = data.stream;
1259
     this.muted = false;
1324
     this.muted = false;
1260
     if((this.type === JitsiTrack.AUDIO && data.audiomuted)
1325
     if((this.type === JitsiTrack.AUDIO && data.audiomuted)
1261
       || (this.type === JitsiTrack.VIDEO && data.videomuted)) {
1326
       || (this.type === JitsiTrack.VIDEO && data.videomuted)) {
1262
-        this.muted = true
1327
+        this.muted = true;
1263
     }
1328
     }
1264
-    this.eventEmitter = eventEmitter;
1265
-    var self = this;
1266
 }
1329
 }
1267
 
1330
 
1268
 JitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);
1331
 JitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);
1275
 JitsiRemoteTrack.prototype.setMute = function (value) {
1338
 JitsiRemoteTrack.prototype.setMute = function (value) {
1276
     this.stream.muted = value;
1339
     this.stream.muted = value;
1277
     this.muted = value;
1340
     this.muted = value;
1278
-    this.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
1341
+    this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
1279
 };
1342
 };
1280
 
1343
 
1281
 /**
1344
 /**
1294
     return Strophe.getResourceFromJid(this.peerjid);
1357
     return Strophe.getResourceFromJid(this.peerjid);
1295
 };
1358
 };
1296
 
1359
 
1360
+/**
1361
+ * Return false;
1362
+ */
1363
+JitsiRemoteTrack.prototype.isLocal = function () {
1364
+    return false;
1365
+}
1366
+
1297
 delete JitsiRemoteTrack.prototype.stop;
1367
 delete JitsiRemoteTrack.prototype.stop;
1298
 
1368
 
1299
 delete JitsiRemoteTrack.prototype.start;
1369
 delete JitsiRemoteTrack.prototype.start;
1300
 
1370
 
1301
 module.exports = JitsiRemoteTrack;
1371
 module.exports = JitsiRemoteTrack;
1302
 
1372
 
1303
-},{"../../service/RTC/StreamEventTypes":84,"./JitsiTrack":14}],14:[function(require,module,exports){
1373
+},{"../../JitsiTrackEvents":10,"./JitsiTrack":14}],14:[function(require,module,exports){
1304
 var RTCBrowserType = require("./RTCBrowserType");
1374
 var RTCBrowserType = require("./RTCBrowserType");
1375
+var JitsiTrackEvents = require("../../JitsiTrackEvents");
1376
+var EventEmitter = require("events");
1305
 
1377
 
1306
 /**
1378
 /**
1307
  * This implements 'onended' callback normally fired by WebRTC after the stream
1379
  * This implements 'onended' callback normally fired by WebRTC after the stream
1357
     this.containers = [];
1429
     this.containers = [];
1358
     this.rtc = rtc;
1430
     this.rtc = rtc;
1359
     this.stream = stream;
1431
     this.stream = stream;
1432
+    this.eventEmitter = new EventEmitter();
1433
+    this.audioLevel = -1;
1360
     this.type = (this.stream.getVideoTracks().length > 0)?
1434
     this.type = (this.stream.getVideoTracks().length > 0)?
1361
         JitsiTrack.VIDEO : JitsiTrack.AUDIO;
1435
         JitsiTrack.VIDEO : JitsiTrack.AUDIO;
1362
     if(this.type == "audio") {
1436
     if(this.type == "audio") {
1487
         return true;
1561
         return true;
1488
 };
1562
 };
1489
 
1563
 
1564
+/**
1565
+ * Attaches a handler for events(For example - "audio level changed".).
1566
+ * All possible event are defined in JitsiTrackEvents.
1567
+ * @param eventId the event ID.
1568
+ * @param handler handler for the event.
1569
+ */
1570
+JitsiTrack.prototype.on = function (eventId, handler) {
1571
+    if(this.eventEmitter)
1572
+        this.eventEmitter.on(eventId, handler);
1573
+}
1574
+
1575
+/**
1576
+ * Removes event listener
1577
+ * @param eventId the event ID.
1578
+ * @param [handler] optional, the specific handler to unbind
1579
+ */
1580
+JitsiTrack.prototype.off = function (eventId, handler) {
1581
+    if(this.eventEmitter)
1582
+        this.eventEmitter.removeListener(eventId, handler);
1583
+}
1584
+
1585
+// Common aliases for event emitter
1586
+JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
1587
+JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;
1588
+
1589
+
1590
+/**
1591
+ * Sets the audio level for the stream
1592
+ * @param audioLevel the new audio level
1593
+ */
1594
+JitsiTrack.prototype.setAudioLevel = function (audioLevel) {
1595
+    if(this.audioLevel !== audioLevel) {
1596
+        this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
1597
+            audioLevel);
1598
+        this.audioLevel = audioLevel;
1599
+    }
1600
+ }
1490
 
1601
 
1491
 module.exports = JitsiTrack;
1602
 module.exports = JitsiTrack;
1492
 
1603
 
1493
-},{"./RTCBrowserType":16,"./RTCUtils":17}],15:[function(require,module,exports){
1604
+},{"../../JitsiTrackEvents":10,"./RTCBrowserType":16,"./RTCUtils":17,"events":42}],15:[function(require,module,exports){
1494
 /* global APP */
1605
 /* global APP */
1495
 var EventEmitter = require("events");
1606
 var EventEmitter = require("events");
1496
 var RTCBrowserType = require("./RTCBrowserType");
1607
 var RTCBrowserType = require("./RTCBrowserType");
1502
 var DesktopSharingEventTypes
1613
 var DesktopSharingEventTypes
1503
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
1614
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
1504
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
1615
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
1505
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
1506
 var RTCEvents = require("../../service/RTC/RTCEvents.js");
1616
 var RTCEvents = require("../../service/RTC/RTCEvents.js");
1507
 
1617
 
1508
 function createLocalTracks(streams) {
1618
 function createLocalTracks(streams) {
1513
         newStreams.push(localStream);
1623
         newStreams.push(localStream);
1514
         if (streams[i].isMuted === true)
1624
         if (streams[i].isMuted === true)
1515
             localStream.setMute(true);
1625
             localStream.setMute(true);
1516
-        //FIXME:
1517
-        // var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
1518
-        //
1519
-        // eventEmitter.emit(eventType, localStream);
1520
     }
1626
     }
1521
     return newStreams;
1627
     return newStreams;
1522
 }
1628
 }
1524
 function RTC(room, options) {
1630
 function RTC(room, options) {
1525
     this.room = room;
1631
     this.room = room;
1526
     this.localStreams = [];
1632
     this.localStreams = [];
1633
+    //FIXME: we should start removing those streams.
1634
+    //FIXME: We should support multiple streams per jid.
1527
     this.remoteStreams = {};
1635
     this.remoteStreams = {};
1528
     this.localAudio = null;
1636
     this.localAudio = null;
1529
     this.localVideo = null;
1637
     this.localVideo = null;
1531
     var self = this;
1639
     var self = this;
1532
     this.options = options || {};
1640
     this.options = options || {};
1533
     room.addPresenceListener("videomuted", function (values, from) {
1641
     room.addPresenceListener("videomuted", function (values, from) {
1534
-        if(self.remoteStreams[from])
1642
+        if(self.remoteStreams[from]) {
1535
             self.remoteStreams[from][JitsiTrack.VIDEO].setMute(values.value == "true");
1643
             self.remoteStreams[from][JitsiTrack.VIDEO].setMute(values.value == "true");
1644
+        }
1536
     });
1645
     });
1537
     room.addPresenceListener("audiomuted", function (values, from) {
1646
     room.addPresenceListener("audiomuted", function (values, from) {
1538
-        if(self.remoteStreams[from])
1647
+        if(self.remoteStreams[from]) {
1539
             self.remoteStreams[from][JitsiTrack.AUDIO].setMute(values.value == "true");
1648
             self.remoteStreams[from][JitsiTrack.AUDIO].setMute(values.value == "true");
1649
+        }
1540
     });
1650
     });
1541
 }
1651
 }
1542
 
1652
 
1597
 }
1707
 }
1598
 
1708
 
1599
 RTC.init = function (options) {
1709
 RTC.init = function (options) {
1600
-    return RTCUtils.init(options || {});
1710
+    this.options = options || {};
1711
+    return RTCUtils.init(this.options);
1601
 }
1712
 }
1602
 
1713
 
1603
 RTC.getDeviceAvailability = function () {
1714
 RTC.getDeviceAvailability = function () {
1625
 };
1736
 };
1626
 
1737
 
1627
 RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
1738
 RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
1628
-    var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc,
1629
-        this.eventEmitter);
1739
+    var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc);
1630
     if(!data.peerjid)
1740
     if(!data.peerjid)
1631
         return;
1741
         return;
1632
     var jid = data.peerjid;
1742
     var jid = data.peerjid;
1634
         this.remoteStreams[jid] = {};
1744
         this.remoteStreams[jid] = {};
1635
     }
1745
     }
1636
     this.remoteStreams[jid][remoteStream.type]= remoteStream;
1746
     this.remoteStreams[jid][remoteStream.type]= remoteStream;
1637
-    this.eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED, remoteStream);
1638
     return remoteStream;
1747
     return remoteStream;
1639
 };
1748
 };
1640
 
1749
 
1686
 RTC.prototype.dispose = function() {
1795
 RTC.prototype.dispose = function() {
1687
 };
1796
 };
1688
 
1797
 
1689
-RTC.prototype.muteRemoteVideoStream = function (jid, value) {
1690
-    var stream;
1691
-
1692
-    if(this.remoteStreams[jid] &&
1693
-        this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
1694
-        stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
1695
-    }
1696
-
1697
-    if(!stream)
1698
-        return true;
1699
-
1700
-    if (value != stream.muted) {
1701
-        stream.setMute(value);
1702
-        return true;
1703
-    }
1704
-    return false;
1705
-};
1706
-
1707
 RTC.prototype.switchVideoStreams = function (newStream) {
1798
 RTC.prototype.switchVideoStreams = function (newStream) {
1708
     this.localVideo.stream = newStream;
1799
     this.localVideo.stream = newStream;
1709
 
1800
 
1715
     this.localStreams.push(this.localVideo);
1806
     this.localStreams.push(this.localVideo);
1716
 };
1807
 };
1717
 
1808
 
1718
-RTC.prototype.isVideoMuted = function (jid) {
1719
-    if (jid === APP.xmpp.myJid()) {
1720
-        var localVideo = APP.RTC.localVideo;
1721
-        return (!localVideo || localVideo.isMuted());
1722
-    } else {
1723
-        if (!this.remoteStreams[jid] ||
1724
-            !this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
1725
-            return null;
1726
-        }
1727
-        return this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
1728
-    }
1729
-};
1730
-
1731
-RTC.prototype.setVideoMute = function (mute, callback, options) {
1732
-    if (!this.localVideo)
1733
-        return;
1734
-
1735
-    if (mute == this.localVideo.isMuted())
1736
-    {
1737
-        APP.xmpp.sendVideoInfoPresence(mute);
1738
-        if (callback)
1739
-            callback(mute);
1740
-    }
1741
-    else
1742
-    {
1743
-        this.localVideo.setMute(mute);
1744
-        this.room.setVideoMute(
1745
-            mute,
1746
-            callback,
1747
-            options);
1748
-    }
1749
-};
1750
-
1809
+RTC.prototype.setAudioLevel = function (jid, audioLevel) {
1810
+    if(this.remoteStreams[jid] && this.remoteStreams[jid][JitsiTrack.AUDIO])
1811
+        this.remoteStreams[jid][JitsiTrack.AUDIO].setAudioLevel(audioLevel);
1812
+}
1751
 module.exports = RTC;
1813
 module.exports = RTC;
1752
 
1814
 
1753
-},{"../../service/RTC/MediaStreamTypes":81,"../../service/RTC/RTCEvents.js":82,"../../service/RTC/StreamEventTypes.js":84,"../../service/desktopsharing/DesktopSharingEventTypes":86,"./DataChannels":11,"./JitsiLocalTrack.js":12,"./JitsiRemoteTrack.js":13,"./JitsiTrack":14,"./RTCBrowserType":16,"./RTCUtils.js":17,"events":42}],16:[function(require,module,exports){
1815
+},{"../../service/RTC/MediaStreamTypes":81,"../../service/RTC/RTCEvents.js":82,"../../service/desktopsharing/DesktopSharingEventTypes":85,"./DataChannels":11,"./JitsiLocalTrack.js":12,"./JitsiRemoteTrack.js":13,"./JitsiTrack":14,"./RTCBrowserType":16,"./RTCUtils.js":17,"events":42}],16:[function(require,module,exports){
1754
 
1816
 
1755
 var currentBrowser;
1817
 var currentBrowser;
1756
 
1818
 
3094
 module.exports = ScreenObtainer;
3156
 module.exports = ScreenObtainer;
3095
 
3157
 
3096
 }).call(this,"/modules/RTC/ScreenObtainer.js")
3158
 }).call(this,"/modules/RTC/ScreenObtainer.js")
3097
-},{"../../service/desktopsharing/DesktopSharingEventTypes":86,"./RTCBrowserType":16,"./adapter.screenshare":19,"jitsi-meet-logger":46}],19:[function(require,module,exports){
3159
+},{"../../service/desktopsharing/DesktopSharingEventTypes":85,"./RTCBrowserType":16,"./adapter.screenshare":19,"jitsi-meet-logger":46}],19:[function(require,module,exports){
3098
 (function (__filename){
3160
 (function (__filename){
3099
 /*! adapterjs - v0.12.0 - 2015-09-04 */
3161
 /*! adapterjs - v0.12.0 - 2015-09-04 */
3100
 var console = require("jitsi-meet-logger").getLogger(__filename);
3162
 var console = require("jitsi-meet-logger").getLogger(__filename);
4360
  */
4422
  */
4361
 
4423
 
4362
 var RTCBrowserType = require('../RTC/RTCBrowserType');
4424
 var RTCBrowserType = require('../RTC/RTCBrowserType');
4363
-var StatisticsEvents = require('../../service/statistics/Events');
4364
-
4365
-var LOCAL_JID = require("../../service/statistics/constants").LOCAL_JID;
4366
 
4425
 
4367
 /**
4426
 /**
4368
  * Size of the webaudio analyzer buffer.
4427
  * Size of the webaudio analyzer buffer.
4423
  *
4482
  *
4424
  * @param stream the local stream
4483
  * @param stream the local stream
4425
  * @param interval stats refresh interval given in ms.
4484
  * @param interval stats refresh interval given in ms.
4485
+ * @param callback function that receives the audio levels.
4426
  * @constructor
4486
  * @constructor
4427
  */
4487
  */
4428
-function LocalStatsCollector(stream, interval, statisticsService, eventEmitter) {
4488
+function LocalStatsCollector(stream, interval, callback) {
4429
     window.AudioContext = window.AudioContext || window.webkitAudioContext;
4489
     window.AudioContext = window.AudioContext || window.webkitAudioContext;
4430
     this.stream = stream;
4490
     this.stream = stream;
4431
     this.intervalId = null;
4491
     this.intervalId = null;
4432
     this.intervalMilis = interval;
4492
     this.intervalMilis = interval;
4433
-    this.eventEmitter = eventEmitter;
4434
     this.audioLevel = 0;
4493
     this.audioLevel = 0;
4435
-    this.statisticsService = statisticsService;
4494
+    this.callback = callback;
4436
 }
4495
 }
4437
 
4496
 
4438
 /**
4497
 /**
4462
             var audioLevel = timeDomainDataToAudioLevel(array);
4521
             var audioLevel = timeDomainDataToAudioLevel(array);
4463
             if (audioLevel != self.audioLevel) {
4522
             if (audioLevel != self.audioLevel) {
4464
                 self.audioLevel = animateLevel(audioLevel, self.audioLevel);
4523
                 self.audioLevel = animateLevel(audioLevel, self.audioLevel);
4465
-                self.eventEmitter.emit(
4466
-                    StatisticsEvents.AUDIO_LEVEL,
4467
-                    self.statisticsService.LOCAL_JID,
4468
-                    self.audioLevel);
4524
+                self.callback(self.audioLevel);
4469
             }
4525
             }
4470
         },
4526
         },
4471
         this.intervalMilis
4527
         this.intervalMilis
4483
 };
4539
 };
4484
 
4540
 
4485
 module.exports = LocalStatsCollector;
4541
 module.exports = LocalStatsCollector;
4486
-},{"../../service/statistics/Events":87,"../../service/statistics/constants":88,"../RTC/RTCBrowserType":16}],22:[function(require,module,exports){
4542
+
4543
+},{"../RTC/RTCBrowserType":16}],22:[function(require,module,exports){
4487
 (function (__filename){
4544
 (function (__filename){
4488
 /* global require, ssrc2jid */
4545
 /* global require, ssrc2jid */
4489
 /* jshint -W117 */
4546
 /* jshint -W117 */
5210
 };
5267
 };
5211
 
5268
 
5212
 }).call(this,"/modules/statistics/RTPStatsCollector.js")
5269
 }).call(this,"/modules/statistics/RTPStatsCollector.js")
5213
-},{"../../service/statistics/Events":87,"../RTC/RTCBrowserType":16,"jitsi-meet-logger":46}],23:[function(require,module,exports){
5270
+},{"../../service/statistics/Events":86,"../RTC/RTCBrowserType":16,"jitsi-meet-logger":46}],23:[function(require,module,exports){
5214
 /* global require, APP */
5271
 /* global require, APP */
5215
 var LocalStats = require("./LocalStatsCollector.js");
5272
 var LocalStats = require("./LocalStatsCollector.js");
5216
 var RTPStats = require("./RTPStatsCollector.js");
5273
 var RTPStats = require("./RTPStatsCollector.js");
5231
 //    }
5288
 //    }
5232
 //}
5289
 //}
5233
 
5290
 
5291
+var eventEmitter = new EventEmitter();
5292
+
5234
 function Statistics() {
5293
 function Statistics() {
5235
-    this.localStats = null;
5236
     this.rtpStats = null;
5294
     this.rtpStats = null;
5237
     this.eventEmitter = new EventEmitter();
5295
     this.eventEmitter = new EventEmitter();
5238
 }
5296
 }
5246
     this.rtpStats.start();
5304
     this.rtpStats.start();
5247
 }
5305
 }
5248
 
5306
 
5249
-Statistics.prototype.startLocalStats = function (stream) {
5250
-    if(stream.getType() !== "audio")
5251
-        return;
5252
-    this.localStats = new LocalStats(stream.getOriginalStream(), 200, this,
5253
-        this.eventEmitter);
5254
-    this.localStats.start();
5255
-}
5307
+Statistics.localStats = [];
5256
 
5308
 
5309
+Statistics.startLocalStats = function (stream, callback) {
5310
+    var localStats = new LocalStats(stream, 200, callback);
5311
+    this.localStats.push(localStats);
5312
+    localStats.start();
5313
+}
5257
 
5314
 
5258
 Statistics.prototype.addAudioLevelListener = function(listener)
5315
 Statistics.prototype.addAudioLevelListener = function(listener)
5259
 {
5316
 {
5266
 }
5323
 }
5267
 
5324
 
5268
 Statistics.prototype.dispose = function () {
5325
 Statistics.prototype.dispose = function () {
5269
-    this.stopLocal();
5326
+    Statistics.stopAllLocalStats();
5270
     this.stopRemote();
5327
     this.stopRemote();
5271
     if(this.eventEmitter)
5328
     if(this.eventEmitter)
5272
-    {
5273
         this.eventEmitter.removeAllListeners();
5329
         this.eventEmitter.removeAllListeners();
5274
-    }
5330
+
5331
+    if(eventEmitter)
5332
+        eventEmitter.removeAllListeners();
5275
 }
5333
 }
5276
 
5334
 
5277
 
5335
 
5278
-Statistics.prototype.stopLocal = function () {
5279
-    if (this.localStats) {
5280
-        this.localStats.stop();
5281
-        this.localStats = null;
5282
-    }
5336
+Statistics.stopAllLocalStats = function () {
5337
+    for(var i = 0; i < this.localStats.length; i++)
5338
+        this.localStats[i].stop();
5339
+    this.localStats = [];
5340
+}
5341
+
5342
+Statistics.stopLocalStats = function (stream) {
5343
+    for(var i = 0; i < Statistics.localStats.length; i++)
5344
+        if(Statistics.localStats[i].stream === stream){
5345
+            var localStats = Statistics.localStats.splice(i, 1);
5346
+            localStats.stop();
5347
+            break;
5348
+        }
5283
 }
5349
 }
5284
 
5350
 
5285
 Statistics.prototype.stopRemote = function () {
5351
 Statistics.prototype.stopRemote = function () {
5358
 
5424
 
5359
 
5425
 
5360
 module.exports = Statistics;
5426
 module.exports = Statistics;
5361
-},{"../../service/statistics/Events":87,"../../service/statistics/constants":88,"./LocalStatsCollector.js":21,"./RTPStatsCollector.js":22,"events":42}],24:[function(require,module,exports){
5427
+
5428
+},{"../../service/statistics/Events":86,"../../service/statistics/constants":87,"./LocalStatsCollector.js":21,"./RTPStatsCollector.js":22,"events":42}],24:[function(require,module,exports){
5362
 /**
5429
 /**
5363
 /**
5430
 /**
5364
  * @const
5431
  * @const
5952
 };
6019
 };
5953
 
6020
 
5954
 
6021
 
5955
-ChatRoom.prototype.removeStream = function (stream) {
6022
+ChatRoom.prototype.removeStream = function (stream, callback) {
5956
     if(!this.session)
6023
     if(!this.session)
5957
         return;
6024
         return;
5958
-    this.session.peerconnection.removeStream(stream)
6025
+    this.session.removeStream(stream, callback);
5959
 }
6026
 }
5960
 
6027
 
5961
 ChatRoom.prototype.switchStreams = function (stream, oldStream, callback, isAudio) {
6028
 ChatRoom.prototype.switchStreams = function (stream, oldStream, callback, isAudio) {
6079
 module.exports = ChatRoom;
6146
 module.exports = ChatRoom;
6080
 
6147
 
6081
 }).call(this,"/modules/xmpp/ChatRoom.js")
6148
 }).call(this,"/modules/xmpp/ChatRoom.js")
6082
-},{"../../service/xmpp/XMPPEvents":89,"./moderator":33,"events":42,"jitsi-meet-logger":46}],26:[function(require,module,exports){
6149
+},{"../../service/xmpp/XMPPEvents":88,"./moderator":33,"events":42,"jitsi-meet-logger":46}],26:[function(require,module,exports){
6083
 (function (__filename){
6150
 (function (__filename){
6084
 /*
6151
 /*
6085
  * JingleSession provides an API to manage a single Jingle session. We will
6152
  * JingleSession provides an API to manage a single Jingle session. We will
7454
     });
7521
     });
7455
 }
7522
 }
7456
 
7523
 
7524
+/**
7525
+ * Remove streams.
7526
+ * @param stream stream that will be removed.
7527
+ * @param success_callback callback executed after successful stream addition.
7528
+ */
7529
+JingleSessionPC.prototype.removeStream = function (stream, callback) {
7530
+
7531
+    var self = this;
7532
+
7533
+    // Remember SDP to figure out added/removed SSRCs
7534
+    var oldSdp = null;
7535
+    if(this.peerconnection) {
7536
+        if(this.peerconnection.localDescription) {
7537
+            oldSdp = new SDP(this.peerconnection.localDescription.sdp);
7538
+        }
7539
+        if(stream)
7540
+            this.peerconnection.removeStream(stream);
7541
+    }
7542
+
7543
+    // Conference is not active
7544
+    if(!oldSdp || !this.peerconnection) {
7545
+        callback();
7546
+        return;
7547
+    }
7548
+
7549
+    this.addingStreams = true;
7550
+    this.modifySourcesQueue.push(function() {
7551
+        logger.log('modify sources done');
7552
+
7553
+        callback();
7554
+
7555
+        var newSdp = new SDP(self.peerconnection.localDescription.sdp);
7556
+        logger.log("SDPs", oldSdp, newSdp);
7557
+        self.notifyMySSRCUpdate(oldSdp, newSdp);
7558
+    });
7559
+}
7560
+
7457
 /**
7561
 /**
7458
  * Figures out added/removed ssrcs and send update IQs.
7562
  * Figures out added/removed ssrcs and send update IQs.
7459
  * @param old_sdp SDP object for old description.
7563
  * @param old_sdp SDP object for old description.
7805
 module.exports = JingleSessionPC;
7909
 module.exports = JingleSessionPC;
7806
 
7910
 
7807
 }).call(this,"/modules/xmpp/JingleSessionPC.js")
7911
 }).call(this,"/modules/xmpp/JingleSessionPC.js")
7808
-},{"../../service/xmpp/XMPPEvents":89,"../RTC/RTC":15,"../RTC/RTCBrowserType":16,"./JingleSession":26,"./LocalSSRCReplacement":28,"./SDP":29,"./SDPDiffer":30,"./SDPUtil":31,"./TraceablePeerConnection":32,"async":41,"jitsi-meet-logger":46,"sdp-transform":78}],28:[function(require,module,exports){
7912
+},{"../../service/xmpp/XMPPEvents":88,"../RTC/RTC":15,"../RTC/RTCBrowserType":16,"./JingleSession":26,"./LocalSSRCReplacement":28,"./SDP":29,"./SDPDiffer":30,"./SDPUtil":31,"./TraceablePeerConnection":32,"async":41,"jitsi-meet-logger":46,"sdp-transform":78}],28:[function(require,module,exports){
7809
 (function (__filename){
7913
 (function (__filename){
7810
 /* global $ */
7914
 /* global $ */
7811
 var logger = require("jitsi-meet-logger").getLogger(__filename);
7915
 var logger = require("jitsi-meet-logger").getLogger(__filename);
9742
 module.exports = TraceablePeerConnection;
9846
 module.exports = TraceablePeerConnection;
9743
 
9847
 
9744
 }).call(this,"/modules/xmpp/TraceablePeerConnection.js")
9848
 }).call(this,"/modules/xmpp/TraceablePeerConnection.js")
9745
-},{"../../service/xmpp/XMPPEvents":89,"../RTC/RTC":15,"../RTC/RTCBrowserType.js":16,"./LocalSSRCReplacement":28,"jitsi-meet-logger":46,"sdp-interop":64,"sdp-simulcast":71,"sdp-transform":78}],33:[function(require,module,exports){
9849
+},{"../../service/xmpp/XMPPEvents":88,"../RTC/RTC":15,"../RTC/RTCBrowserType.js":16,"./LocalSSRCReplacement":28,"jitsi-meet-logger":46,"sdp-interop":64,"sdp-simulcast":71,"sdp-transform":78}],33:[function(require,module,exports){
9746
 (function (__filename){
9850
 (function (__filename){
9747
 /* global $, $iq, APP, config, messageHandler,
9851
 /* global $, $iq, APP, config, messageHandler,
9748
  roomName, sessionTerminated, Strophe, Util */
9852
  roomName, sessionTerminated, Strophe, Util */
10179
 
10283
 
10180
 
10284
 
10181
 }).call(this,"/modules/xmpp/moderator.js")
10285
 }).call(this,"/modules/xmpp/moderator.js")
10182
-},{"../../service/authentication/AuthenticationEvents":85,"../../service/xmpp/XMPPEvents":89,"../settings/Settings":20,"jitsi-meet-logger":46}],34:[function(require,module,exports){
10286
+},{"../../service/authentication/AuthenticationEvents":84,"../../service/xmpp/XMPPEvents":88,"../settings/Settings":20,"jitsi-meet-logger":46}],34:[function(require,module,exports){
10183
 (function (__filename){
10287
 (function (__filename){
10184
 /* jshint -W117 */
10288
 /* jshint -W117 */
10185
 /* a simple MUC connection plugin
10289
 /* a simple MUC connection plugin
10573
 
10677
 
10574
 
10678
 
10575
 }).call(this,"/modules/xmpp/strophe.jingle.js")
10679
 }).call(this,"/modules/xmpp/strophe.jingle.js")
10576
-},{"../../service/xmpp/XMPPEvents":89,"../RTC/RTCBrowserType":16,"./JingleSessionPC":27,"jitsi-meet-logger":46}],36:[function(require,module,exports){
10680
+},{"../../service/xmpp/XMPPEvents":88,"../RTC/RTCBrowserType":16,"./JingleSessionPC":27,"jitsi-meet-logger":46}],36:[function(require,module,exports){
10577
 /* global Strophe */
10681
 /* global Strophe */
10578
 module.exports = function () {
10682
 module.exports = function () {
10579
 
10683
 
10721
 };
10825
 };
10722
 
10826
 
10723
 }).call(this,"/modules/xmpp/strophe.ping.js")
10827
 }).call(this,"/modules/xmpp/strophe.ping.js")
10724
-},{"../../service/xmpp/XMPPEvents":89,"jitsi-meet-logger":46}],38:[function(require,module,exports){
10828
+},{"../../service/xmpp/XMPPEvents":88,"jitsi-meet-logger":46}],38:[function(require,module,exports){
10725
 (function (__filename){
10829
 (function (__filename){
10726
 /* jshint -W117 */
10830
 /* jshint -W117 */
10727
 var logger = require("jitsi-meet-logger").getLogger(__filename);
10831
 var logger = require("jitsi-meet-logger").getLogger(__filename);
10879
 var logger = require("jitsi-meet-logger").getLogger(__filename);
10983
 var logger = require("jitsi-meet-logger").getLogger(__filename);
10880
 var EventEmitter = require("events");
10984
 var EventEmitter = require("events");
10881
 var Pako = require("pako");
10985
 var Pako = require("pako");
10882
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
10883
 var RTCEvents = require("../../service/RTC/RTCEvents");
10986
 var RTCEvents = require("../../service/RTC/RTCEvents");
10884
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
10987
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
10885
 var JitsiConnectionErrors = require("../../JitsiConnectionErrors");
10988
 var JitsiConnectionErrors = require("../../JitsiConnectionErrors");
11000
                         logger.warn("Ping NOT supported by " + pingJid);
11103
                         logger.warn("Ping NOT supported by " + pingJid);
11001
                 }
11104
                 }
11002
             );
11105
             );
11003
-            
11106
+
11004
             if (password)
11107
             if (password)
11005
                 authenticatedUser = true;
11108
                 authenticatedUser = true;
11006
             if (self.connection && self.connection.connected &&
11109
             if (self.connection && self.connection.connected &&
11180
 module.exports = XMPP;
11283
 module.exports = XMPP;
11181
 
11284
 
11182
 }).call(this,"/modules/xmpp/xmpp.js")
11285
 }).call(this,"/modules/xmpp/xmpp.js")
11183
-},{"../../JitsiConnectionErrors":5,"../../JitsiConnectionEvents":6,"../../service/RTC/RTCEvents":82,"../../service/RTC/StreamEventTypes":84,"../../service/xmpp/XMPPEvents":89,"../RTC/RTC":15,"./strophe.emuc":34,"./strophe.jingle":35,"./strophe.logger":36,"./strophe.ping":37,"./strophe.rayo":38,"./strophe.util":39,"events":42,"jitsi-meet-logger":46,"pako":47}],41:[function(require,module,exports){
11286
+},{"../../JitsiConnectionErrors":5,"../../JitsiConnectionEvents":6,"../../service/RTC/RTCEvents":82,"../../service/xmpp/XMPPEvents":88,"../RTC/RTC":15,"./strophe.emuc":34,"./strophe.jingle":35,"./strophe.logger":36,"./strophe.ping":37,"./strophe.rayo":38,"./strophe.util":39,"events":42,"jitsi-meet-logger":46,"pako":47}],41:[function(require,module,exports){
11184
 (function (process){
11287
 (function (process){
11185
 /*!
11288
 /*!
11186
  * async
11289
  * async
22285
 };
22388
 };
22286
 module.exports = Resolutions;
22389
 module.exports = Resolutions;
22287
 },{}],84:[function(require,module,exports){
22390
 },{}],84:[function(require,module,exports){
22288
-var StreamEventTypes = {
22289
-    EVENT_TYPE_LOCAL_CREATED: "stream.local_created",
22290
-
22291
-    EVENT_TYPE_LOCAL_CHANGED: "stream.local_changed",
22292
-
22293
-    EVENT_TYPE_LOCAL_ENDED: "stream.local_ended",
22294
-
22295
-    EVENT_TYPE_REMOTE_CREATED: "stream.remote_created",
22296
-
22297
-    EVENT_TYPE_REMOTE_ENDED: "stream.remote_ended",
22298
-    TRACK_MUTE_CHANGED: "rtc.track_mute_changed"
22299
-};
22300
-
22301
-module.exports = StreamEventTypes;
22302
-},{}],85:[function(require,module,exports){
22303
 var AuthenticationEvents = {
22391
 var AuthenticationEvents = {
22304
     /**
22392
     /**
22305
      * Event callback arguments:
22393
      * Event callback arguments:
22313
 };
22401
 };
22314
 module.exports = AuthenticationEvents;
22402
 module.exports = AuthenticationEvents;
22315
 
22403
 
22316
-},{}],86:[function(require,module,exports){
22404
+},{}],85:[function(require,module,exports){
22317
 var DesktopSharingEventTypes = {
22405
 var DesktopSharingEventTypes = {
22318
     INIT: "ds.init",
22406
     INIT: "ds.init",
22319
 
22407
 
22329
 
22417
 
22330
 module.exports = DesktopSharingEventTypes;
22418
 module.exports = DesktopSharingEventTypes;
22331
 
22419
 
22332
-},{}],87:[function(require,module,exports){
22420
+},{}],86:[function(require,module,exports){
22333
 module.exports = {
22421
 module.exports = {
22334
     /**
22422
     /**
22335
      * An event carrying connection statistics.
22423
      * An event carrying connection statistics.
22345
     STOP: "statistics.stop"
22433
     STOP: "statistics.stop"
22346
 };
22434
 };
22347
 
22435
 
22348
-},{}],88:[function(require,module,exports){
22436
+},{}],87:[function(require,module,exports){
22349
 var Constants = {
22437
 var Constants = {
22350
     LOCAL_JID: 'local'
22438
     LOCAL_JID: 'local'
22351
 };
22439
 };
22352
 module.exports = Constants;
22440
 module.exports = Constants;
22353
-},{}],89:[function(require,module,exports){
22441
+},{}],88:[function(require,module,exports){
22354
 var XMPPEvents = {
22442
 var XMPPEvents = {
22355
     // Designates an event indicating that the connection to the XMPP server
22443
     // Designates an event indicating that the connection to the XMPP server
22356
     // failed.
22444
     // failed.

+ 21
- 12
modules/RTC/JitsiLocalTrack.js ファイルの表示

1
 var JitsiTrack = require("./JitsiTrack");
1
 var JitsiTrack = require("./JitsiTrack");
2
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
3
 var RTCBrowserType = require("./RTCBrowserType");
2
 var RTCBrowserType = require("./RTCBrowserType");
3
+var JitsiTrackEvents = require('../../JitsiTrackEvents');
4
 var RTC = require("./RTCUtils");
4
 var RTC = require("./RTCUtils");
5
 
5
 
6
 /**
6
 /**
13
     this.videoType = videoType;
13
     this.videoType = videoType;
14
     this.dontFireRemoveEvent = false;
14
     this.dontFireRemoveEvent = false;
15
     this.resolution = resolution;
15
     this.resolution = resolution;
16
+    this.startMuted = false;
16
     var self = this;
17
     var self = this;
17
     JitsiTrack.call(this, null, stream,
18
     JitsiTrack.call(this, null, stream,
18
         function () {
19
         function () {
19
-            if(!self.dontFireRemoveEvent && self.rtc)
20
-                self.rtc.eventEmitter.emit(
21
-                    StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, self);
22
-            self.dontFireRemoveEvent = false;
23
-        });
20
+            if(!this.dontFireRemoveEvent)
21
+                this.eventEmitter.emit(
22
+                    JitsiTrackEvents.TRACK_STOPPED);
23
+            this.dontFireRemoveEvent = false;
24
+        }.bind(this));
24
 
25
 
25
 }
26
 }
26
 
27
 
33
  */
34
  */
34
 JitsiLocalTrack.prototype._setMute = function (mute) {
35
 JitsiLocalTrack.prototype._setMute = function (mute) {
35
     if(!this.rtc) {
36
     if(!this.rtc) {
36
-        console.error("Mute is not supported for streams not attached to conference!");
37
+        this.startMuted = mute;
37
         return;
38
         return;
38
     }
39
     }
39
     var isAudio = this.type === JitsiTrack.AUDIO;
40
     var isAudio = this.type === JitsiTrack.AUDIO;
40
     this.dontFireRemoveEvent = false;
41
     this.dontFireRemoveEvent = false;
41
 
42
 
42
     if ((window.location.protocol != "https:") ||
43
     if ((window.location.protocol != "https:") ||
43
-        (isAudio) || this.videoType === "screen" ||
44
+        (isAudio) || this.videoType === "desktop" ||
44
         // FIXME FF does not support 'removeStream' method used to mute
45
         // FIXME FF does not support 'removeStream' method used to mute
45
         RTCBrowserType.isFirefox()) {
46
         RTCBrowserType.isFirefox()) {
46
 
47
 
52
             this.rtc.room.setAudioMute(mute);
53
             this.rtc.room.setAudioMute(mute);
53
         else
54
         else
54
             this.rtc.room.setVideoMute(mute);
55
             this.rtc.room.setVideoMute(mute);
55
-        this.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
56
+        this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
56
     } else {
57
     } else {
57
         if (mute) {
58
         if (mute) {
58
             this.dontFireRemoveEvent = true;
59
             this.dontFireRemoveEvent = true;
63
             else
64
             else
64
                 this.rtc.room.setVideoMute(mute);
65
                 this.rtc.room.setVideoMute(mute);
65
             this.stream = null;
66
             this.stream = null;
66
-            this.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
67
+            this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
67
             //FIXME: Maybe here we should set the SRC for the containers to something
68
             //FIXME: Maybe here we should set the SRC for the containers to something
68
         } else {
69
         } else {
69
             var self = this;
70
             var self = this;
95
                                 self.rtc.room.setAudioMute(mute);
96
                                 self.rtc.room.setAudioMute(mute);
96
                             else
97
                             else
97
                                 self.rtc.room.setVideoMute(mute);
98
                                 self.rtc.room.setVideoMute(mute);
98
-                            self.rtc.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, self);
99
+                            self.eventEmitter.emit(
100
+                                JitsiTrackEvents.TRACK_MUTE_CHANGED);
99
                         });
101
                         });
100
                 });
102
                 });
101
         }
103
         }
111
         return;
113
         return;
112
     if(this.rtc)
114
     if(this.rtc)
113
         this.rtc.room.removeStream(this.stream);
115
         this.rtc.room.removeStream(this.stream);
114
-    this.rtc.stopMediaStream(this.stream);
116
+    RTC.stopMediaStream(this.stream);
115
     this.detach();
117
     this.detach();
116
 }
118
 }
117
 
119
 
148
     this.rtc = rtc;
150
     this.rtc = rtc;
149
 };
151
 };
150
 
152
 
153
+/**
154
+ * Return true;
155
+ */
156
+JitsiLocalTrack.prototype.isLocal = function () {
157
+    return true;
158
+}
159
+
151
 module.exports = JitsiLocalTrack;
160
 module.exports = JitsiLocalTrack;

+ 13
- 8
modules/RTC/JitsiRemoteTrack.js ファイルの表示

1
 var JitsiTrack = require("./JitsiTrack");
1
 var JitsiTrack = require("./JitsiTrack");
2
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
2
+var JitsiTrackEvents = require("../../JitsiTrackEvents");
3
 
3
 
4
 /**
4
 /**
5
  * Represents a single media track (either audio or video).
5
  * Represents a single media track (either audio or video).
10
  * @param eventEmitter the event emitter
10
  * @param eventEmitter the event emitter
11
  * @constructor
11
  * @constructor
12
  */
12
  */
13
-function JitsiRemoteTrack(RTC, data, sid, ssrc, eventEmitter) {
13
+function JitsiRemoteTrack(RTC, data, sid, ssrc) {
14
     JitsiTrack.call(this, RTC, data.stream,
14
     JitsiTrack.call(this, RTC, data.stream,
15
         function () {
15
         function () {
16
-            eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_ENDED, self);
17
-        });
16
+            this.eventEmitter.emit(JitsiTrackEvents.TRACK_STOPPED);
17
+        }.bind(this));
18
     this.rtc = RTC;
18
     this.rtc = RTC;
19
     this.sid = sid;
19
     this.sid = sid;
20
     this.stream = data.stream;
20
     this.stream = data.stream;
24
     this.muted = false;
24
     this.muted = false;
25
     if((this.type === JitsiTrack.AUDIO && data.audiomuted)
25
     if((this.type === JitsiTrack.AUDIO && data.audiomuted)
26
       || (this.type === JitsiTrack.VIDEO && data.videomuted)) {
26
       || (this.type === JitsiTrack.VIDEO && data.videomuted)) {
27
-        this.muted = true
27
+        this.muted = true;
28
     }
28
     }
29
-    this.eventEmitter = eventEmitter;
30
-    var self = this;
31
 }
29
 }
32
 
30
 
33
 JitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);
31
 JitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);
40
 JitsiRemoteTrack.prototype.setMute = function (value) {
38
 JitsiRemoteTrack.prototype.setMute = function (value) {
41
     this.stream.muted = value;
39
     this.stream.muted = value;
42
     this.muted = value;
40
     this.muted = value;
43
-    this.eventEmitter.emit(StreamEventTypes.TRACK_MUTE_CHANGED, this);
41
+    this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
44
 };
42
 };
45
 
43
 
46
 /**
44
 /**
59
     return Strophe.getResourceFromJid(this.peerjid);
57
     return Strophe.getResourceFromJid(this.peerjid);
60
 };
58
 };
61
 
59
 
60
+/**
61
+ * Return false;
62
+ */
63
+JitsiRemoteTrack.prototype.isLocal = function () {
64
+    return false;
65
+}
66
+
62
 delete JitsiRemoteTrack.prototype.stop;
67
 delete JitsiRemoteTrack.prototype.stop;
63
 
68
 
64
 delete JitsiRemoteTrack.prototype.start;
69
 delete JitsiRemoteTrack.prototype.start;

+ 41
- 0
modules/RTC/JitsiTrack.js ファイルの表示

1
 var RTCBrowserType = require("./RTCBrowserType");
1
 var RTCBrowserType = require("./RTCBrowserType");
2
+var JitsiTrackEvents = require("../../JitsiTrackEvents");
3
+var EventEmitter = require("events");
2
 
4
 
3
 /**
5
 /**
4
  * This implements 'onended' callback normally fired by WebRTC after the stream
6
  * This implements 'onended' callback normally fired by WebRTC after the stream
54
     this.containers = [];
56
     this.containers = [];
55
     this.rtc = rtc;
57
     this.rtc = rtc;
56
     this.stream = stream;
58
     this.stream = stream;
59
+    this.eventEmitter = new EventEmitter();
60
+    this.audioLevel = -1;
57
     this.type = (this.stream.getVideoTracks().length > 0)?
61
     this.type = (this.stream.getVideoTracks().length > 0)?
58
         JitsiTrack.VIDEO : JitsiTrack.AUDIO;
62
         JitsiTrack.VIDEO : JitsiTrack.AUDIO;
59
     if(this.type == "audio") {
63
     if(this.type == "audio") {
184
         return true;
188
         return true;
185
 };
189
 };
186
 
190
 
191
+/**
192
+ * Attaches a handler for events(For example - "audio level changed".).
193
+ * All possible event are defined in JitsiTrackEvents.
194
+ * @param eventId the event ID.
195
+ * @param handler handler for the event.
196
+ */
197
+JitsiTrack.prototype.on = function (eventId, handler) {
198
+    if(this.eventEmitter)
199
+        this.eventEmitter.on(eventId, handler);
200
+}
201
+
202
+/**
203
+ * Removes event listener
204
+ * @param eventId the event ID.
205
+ * @param [handler] optional, the specific handler to unbind
206
+ */
207
+JitsiTrack.prototype.off = function (eventId, handler) {
208
+    if(this.eventEmitter)
209
+        this.eventEmitter.removeListener(eventId, handler);
210
+}
211
+
212
+// Common aliases for event emitter
213
+JitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;
214
+JitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;
215
+
216
+
217
+/**
218
+ * Sets the audio level for the stream
219
+ * @param audioLevel the new audio level
220
+ */
221
+JitsiTrack.prototype.setAudioLevel = function (audioLevel) {
222
+    if(this.audioLevel !== audioLevel) {
223
+        this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,
224
+            audioLevel);
225
+        this.audioLevel = audioLevel;
226
+    }
227
+ }
187
 
228
 
188
 module.exports = JitsiTrack;
229
 module.exports = JitsiTrack;

+ 13
- 62
modules/RTC/RTC.js ファイルの表示

9
 var DesktopSharingEventTypes
9
 var DesktopSharingEventTypes
10
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
10
     = require("../../service/desktopsharing/DesktopSharingEventTypes");
11
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
11
 var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
12
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
13
 var RTCEvents = require("../../service/RTC/RTCEvents.js");
12
 var RTCEvents = require("../../service/RTC/RTCEvents.js");
14
 
13
 
15
 function createLocalTracks(streams) {
14
 function createLocalTracks(streams) {
20
         newStreams.push(localStream);
19
         newStreams.push(localStream);
21
         if (streams[i].isMuted === true)
20
         if (streams[i].isMuted === true)
22
             localStream.setMute(true);
21
             localStream.setMute(true);
23
-        //FIXME:
24
-        // var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
25
-        //
26
-        // eventEmitter.emit(eventType, localStream);
27
     }
22
     }
28
     return newStreams;
23
     return newStreams;
29
 }
24
 }
31
 function RTC(room, options) {
26
 function RTC(room, options) {
32
     this.room = room;
27
     this.room = room;
33
     this.localStreams = [];
28
     this.localStreams = [];
29
+    //FIXME: we should start removing those streams.
30
+    //FIXME: We should support multiple streams per jid.
34
     this.remoteStreams = {};
31
     this.remoteStreams = {};
35
     this.localAudio = null;
32
     this.localAudio = null;
36
     this.localVideo = null;
33
     this.localVideo = null;
38
     var self = this;
35
     var self = this;
39
     this.options = options || {};
36
     this.options = options || {};
40
     room.addPresenceListener("videomuted", function (values, from) {
37
     room.addPresenceListener("videomuted", function (values, from) {
41
-        if(self.remoteStreams[from])
38
+        if(self.remoteStreams[from]) {
42
             self.remoteStreams[from][JitsiTrack.VIDEO].setMute(values.value == "true");
39
             self.remoteStreams[from][JitsiTrack.VIDEO].setMute(values.value == "true");
40
+        }
43
     });
41
     });
44
     room.addPresenceListener("audiomuted", function (values, from) {
42
     room.addPresenceListener("audiomuted", function (values, from) {
45
-        if(self.remoteStreams[from])
43
+        if(self.remoteStreams[from]) {
46
             self.remoteStreams[from][JitsiTrack.AUDIO].setMute(values.value == "true");
44
             self.remoteStreams[from][JitsiTrack.AUDIO].setMute(values.value == "true");
45
+        }
47
     });
46
     });
48
 }
47
 }
49
 
48
 
104
 }
103
 }
105
 
104
 
106
 RTC.init = function (options) {
105
 RTC.init = function (options) {
107
-    return RTCUtils.init(options || {});
106
+    this.options = options || {};
107
+    return RTCUtils.init(this.options);
108
 }
108
 }
109
 
109
 
110
 RTC.getDeviceAvailability = function () {
110
 RTC.getDeviceAvailability = function () {
132
 };
132
 };
133
 
133
 
134
 RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
134
 RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
135
-    var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc,
136
-        this.eventEmitter);
135
+    var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc);
137
     if(!data.peerjid)
136
     if(!data.peerjid)
138
         return;
137
         return;
139
     var jid = data.peerjid;
138
     var jid = data.peerjid;
141
         this.remoteStreams[jid] = {};
140
         this.remoteStreams[jid] = {};
142
     }
141
     }
143
     this.remoteStreams[jid][remoteStream.type]= remoteStream;
142
     this.remoteStreams[jid][remoteStream.type]= remoteStream;
144
-    this.eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED, remoteStream);
145
     return remoteStream;
143
     return remoteStream;
146
 };
144
 };
147
 
145
 
193
 RTC.prototype.dispose = function() {
191
 RTC.prototype.dispose = function() {
194
 };
192
 };
195
 
193
 
196
-RTC.prototype.muteRemoteVideoStream = function (jid, value) {
197
-    var stream;
198
-
199
-    if(this.remoteStreams[jid] &&
200
-        this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
201
-        stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
202
-    }
203
-
204
-    if(!stream)
205
-        return true;
206
-
207
-    if (value != stream.muted) {
208
-        stream.setMute(value);
209
-        return true;
210
-    }
211
-    return false;
212
-};
213
-
214
 RTC.prototype.switchVideoStreams = function (newStream) {
194
 RTC.prototype.switchVideoStreams = function (newStream) {
215
     this.localVideo.stream = newStream;
195
     this.localVideo.stream = newStream;
216
 
196
 
222
     this.localStreams.push(this.localVideo);
202
     this.localStreams.push(this.localVideo);
223
 };
203
 };
224
 
204
 
225
-RTC.prototype.isVideoMuted = function (jid) {
226
-    if (jid === APP.xmpp.myJid()) {
227
-        var localVideo = APP.RTC.localVideo;
228
-        return (!localVideo || localVideo.isMuted());
229
-    } else {
230
-        if (!this.remoteStreams[jid] ||
231
-            !this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
232
-            return null;
233
-        }
234
-        return this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
235
-    }
236
-};
237
-
238
-RTC.prototype.setVideoMute = function (mute, callback, options) {
239
-    if (!this.localVideo)
240
-        return;
241
-
242
-    if (mute == this.localVideo.isMuted())
243
-    {
244
-        APP.xmpp.sendVideoInfoPresence(mute);
245
-        if (callback)
246
-            callback(mute);
247
-    }
248
-    else
249
-    {
250
-        this.localVideo.setMute(mute);
251
-        this.room.setVideoMute(
252
-            mute,
253
-            callback,
254
-            options);
255
-    }
256
-};
257
-
205
+RTC.prototype.setAudioLevel = function (jid, audioLevel) {
206
+    if(this.remoteStreams[jid] && this.remoteStreams[jid][JitsiTrack.AUDIO])
207
+        this.remoteStreams[jid][JitsiTrack.AUDIO].setAudioLevel(audioLevel);
208
+}
258
 module.exports = RTC;
209
 module.exports = RTC;

+ 5
- 11
modules/statistics/LocalStatsCollector.js ファイルの表示

4
  */
4
  */
5
 
5
 
6
 var RTCBrowserType = require('../RTC/RTCBrowserType');
6
 var RTCBrowserType = require('../RTC/RTCBrowserType');
7
-var StatisticsEvents = require('../../service/statistics/Events');
8
-
9
-var LOCAL_JID = require("../../service/statistics/constants").LOCAL_JID;
10
 
7
 
11
 /**
8
 /**
12
  * Size of the webaudio analyzer buffer.
9
  * Size of the webaudio analyzer buffer.
67
  *
64
  *
68
  * @param stream the local stream
65
  * @param stream the local stream
69
  * @param interval stats refresh interval given in ms.
66
  * @param interval stats refresh interval given in ms.
67
+ * @param callback function that receives the audio levels.
70
  * @constructor
68
  * @constructor
71
  */
69
  */
72
-function LocalStatsCollector(stream, interval, statisticsService, eventEmitter) {
70
+function LocalStatsCollector(stream, interval, callback) {
73
     window.AudioContext = window.AudioContext || window.webkitAudioContext;
71
     window.AudioContext = window.AudioContext || window.webkitAudioContext;
74
     this.stream = stream;
72
     this.stream = stream;
75
     this.intervalId = null;
73
     this.intervalId = null;
76
     this.intervalMilis = interval;
74
     this.intervalMilis = interval;
77
-    this.eventEmitter = eventEmitter;
78
     this.audioLevel = 0;
75
     this.audioLevel = 0;
79
-    this.statisticsService = statisticsService;
76
+    this.callback = callback;
80
 }
77
 }
81
 
78
 
82
 /**
79
 /**
106
             var audioLevel = timeDomainDataToAudioLevel(array);
103
             var audioLevel = timeDomainDataToAudioLevel(array);
107
             if (audioLevel != self.audioLevel) {
104
             if (audioLevel != self.audioLevel) {
108
                 self.audioLevel = animateLevel(audioLevel, self.audioLevel);
105
                 self.audioLevel = animateLevel(audioLevel, self.audioLevel);
109
-                self.eventEmitter.emit(
110
-                    StatisticsEvents.AUDIO_LEVEL,
111
-                    self.statisticsService.LOCAL_JID,
112
-                    self.audioLevel);
106
+                self.callback(self.audioLevel);
113
             }
107
             }
114
         },
108
         },
115
         this.intervalMilis
109
         this.intervalMilis
126
     }
120
     }
127
 };
121
 };
128
 
122
 
129
-module.exports = LocalStatsCollector;
123
+module.exports = LocalStatsCollector;

+ 26
- 17
modules/statistics/statistics.js ファイルの表示

18
 //    }
18
 //    }
19
 //}
19
 //}
20
 
20
 
21
+var eventEmitter = new EventEmitter();
22
+
21
 function Statistics() {
23
 function Statistics() {
22
-    this.localStats = null;
23
     this.rtpStats = null;
24
     this.rtpStats = null;
24
     this.eventEmitter = new EventEmitter();
25
     this.eventEmitter = new EventEmitter();
25
 }
26
 }
33
     this.rtpStats.start();
34
     this.rtpStats.start();
34
 }
35
 }
35
 
36
 
36
-Statistics.prototype.startLocalStats = function (stream) {
37
-    if(stream.getType() !== "audio")
38
-        return;
39
-    this.localStats = new LocalStats(stream.getOriginalStream(), 200, this,
40
-        this.eventEmitter);
41
-    this.localStats.start();
42
-}
37
+Statistics.localStats = [];
43
 
38
 
39
+Statistics.startLocalStats = function (stream, callback) {
40
+    var localStats = new LocalStats(stream, 200, callback);
41
+    this.localStats.push(localStats);
42
+    localStats.start();
43
+}
44
 
44
 
45
 Statistics.prototype.addAudioLevelListener = function(listener)
45
 Statistics.prototype.addAudioLevelListener = function(listener)
46
 {
46
 {
53
 }
53
 }
54
 
54
 
55
 Statistics.prototype.dispose = function () {
55
 Statistics.prototype.dispose = function () {
56
-    this.stopLocal();
56
+    Statistics.stopAllLocalStats();
57
     this.stopRemote();
57
     this.stopRemote();
58
     if(this.eventEmitter)
58
     if(this.eventEmitter)
59
-    {
60
         this.eventEmitter.removeAllListeners();
59
         this.eventEmitter.removeAllListeners();
61
-    }
60
+
61
+    if(eventEmitter)
62
+        eventEmitter.removeAllListeners();
62
 }
63
 }
63
 
64
 
64
 
65
 
65
-Statistics.prototype.stopLocal = function () {
66
-    if (this.localStats) {
67
-        this.localStats.stop();
68
-        this.localStats = null;
69
-    }
66
+Statistics.stopAllLocalStats = function () {
67
+    for(var i = 0; i < this.localStats.length; i++)
68
+        this.localStats[i].stop();
69
+    this.localStats = [];
70
+}
71
+
72
+Statistics.stopLocalStats = function (stream) {
73
+    for(var i = 0; i < Statistics.localStats.length; i++)
74
+        if(Statistics.localStats[i].stream === stream){
75
+            var localStats = Statistics.localStats.splice(i, 1);
76
+            localStats.stop();
77
+            break;
78
+        }
70
 }
79
 }
71
 
80
 
72
 Statistics.prototype.stopRemote = function () {
81
 Statistics.prototype.stopRemote = function () {
144
 
153
 
145
 
154
 
146
 
155
 
147
-module.exports = Statistics;
156
+module.exports = Statistics;

+ 2
- 2
modules/xmpp/ChatRoom.js ファイルの表示

515
 };
515
 };
516
 
516
 
517
 
517
 
518
-ChatRoom.prototype.removeStream = function (stream) {
518
+ChatRoom.prototype.removeStream = function (stream, callback) {
519
     if(!this.session)
519
     if(!this.session)
520
         return;
520
         return;
521
-    this.session.peerconnection.removeStream(stream)
521
+    this.session.removeStream(stream, callback);
522
 }
522
 }
523
 
523
 
524
 ChatRoom.prototype.switchStreams = function (stream, oldStream, callback, isAudio) {
524
 ChatRoom.prototype.switchStreams = function (stream, oldStream, callback, isAudio) {

+ 37
- 0
modules/xmpp/JingleSessionPC.js ファイルの表示

1235
     });
1235
     });
1236
 }
1236
 }
1237
 
1237
 
1238
+/**
1239
+ * Remove streams.
1240
+ * @param stream stream that will be removed.
1241
+ * @param success_callback callback executed after successful stream addition.
1242
+ */
1243
+JingleSessionPC.prototype.removeStream = function (stream, callback) {
1244
+
1245
+    var self = this;
1246
+
1247
+    // Remember SDP to figure out added/removed SSRCs
1248
+    var oldSdp = null;
1249
+    if(this.peerconnection) {
1250
+        if(this.peerconnection.localDescription) {
1251
+            oldSdp = new SDP(this.peerconnection.localDescription.sdp);
1252
+        }
1253
+        if(stream)
1254
+            this.peerconnection.removeStream(stream);
1255
+    }
1256
+
1257
+    // Conference is not active
1258
+    if(!oldSdp || !this.peerconnection) {
1259
+        callback();
1260
+        return;
1261
+    }
1262
+
1263
+    this.addingStreams = true;
1264
+    this.modifySourcesQueue.push(function() {
1265
+        logger.log('modify sources done');
1266
+
1267
+        callback();
1268
+
1269
+        var newSdp = new SDP(self.peerconnection.localDescription.sdp);
1270
+        logger.log("SDPs", oldSdp, newSdp);
1271
+        self.notifyMySSRCUpdate(oldSdp, newSdp);
1272
+    });
1273
+}
1274
+
1238
 /**
1275
 /**
1239
  * Figures out added/removed ssrcs and send update IQs.
1276
  * Figures out added/removed ssrcs and send update IQs.
1240
  * @param old_sdp SDP object for old description.
1277
  * @param old_sdp SDP object for old description.

+ 1
- 2
modules/xmpp/xmpp.js ファイルの表示

3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4
 var EventEmitter = require("events");
4
 var EventEmitter = require("events");
5
 var Pako = require("pako");
5
 var Pako = require("pako");
6
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
7
 var RTCEvents = require("../../service/RTC/RTCEvents");
6
 var RTCEvents = require("../../service/RTC/RTCEvents");
8
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
7
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
9
 var JitsiConnectionErrors = require("../../JitsiConnectionErrors");
8
 var JitsiConnectionErrors = require("../../JitsiConnectionErrors");
124
                         logger.warn("Ping NOT supported by " + pingJid);
123
                         logger.warn("Ping NOT supported by " + pingJid);
125
                 }
124
                 }
126
             );
125
             );
127
-            
126
+
128
             if (password)
127
             if (password)
129
                 authenticatedUser = true;
128
                 authenticatedUser = true;
130
             if (self.connection && self.connection.connected &&
129
             if (self.connection && self.connection.connected &&

読み込み中…
キャンセル
保存