Browse Source

Implements reload method in JitsiConference

dev1
hristoterezov 9 years ago
parent
commit
faeda96206

+ 17
- 431
JitsiConference.js View File

@@ -3,8 +3,6 @@
3 3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4 4
 var RTC = require("./modules/RTC/RTC");
5 5
 var XMPPEvents = require("./service/xmpp/XMPPEvents");
6
-var AuthenticationEvents = require("./service/authentication/AuthenticationEvents");
7
-var RTCEvents = require("./service/RTC/RTCEvents");
8 6
 var EventEmitter = require("events");
9 7
 var JitsiConferenceEvents = require("./JitsiConferenceEvents");
10 8
 var JitsiConferenceErrors = require("./JitsiConferenceErrors");
@@ -17,7 +15,7 @@ var JitsiTrackError = require("./JitsiTrackError");
17 15
 var Settings = require("./modules/settings/Settings");
18 16
 var ComponentsVersions = require("./modules/version/ComponentsVersions");
19 17
 var GlobalOnErrorHandler = require("./modules/util/GlobalOnErrorHandler");
20
-var MediaType = require("./service/RTC/MediaType");
18
+var JitsiConferenceEventManager = require("./JitsiConferenceEventManager");
21 19
 
22 20
 /**
23 21
  * Creates a JitsiConference object with the given name and properties.
@@ -47,7 +45,8 @@ function JitsiConference(options) {
47 45
             this.options.config.disableThirdPartyRequests,
48 46
         roomName: this.options.name
49 47
     });
50
-    setupListeners(this);
48
+    this.eventManager = new JitsiConferenceEventManager(this);
49
+    this._setupListeners();
51 50
     this.participants = {};
52 51
     this.lastDominantSpeaker = null;
53 52
     this.dtmfManager = null;
@@ -89,7 +88,6 @@ JitsiConference.prototype._init = function (options) {
89 88
         this.settings);
90 89
     this.componentsVersions = new ComponentsVersions(this.room);
91 90
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
92
-
93 91
 }
94 92
 
95 93
 /**
@@ -97,10 +95,15 @@ JitsiConference.prototype._init = function (options) {
97 95
  * @param options {object} options to be overriden
98 96
  */
99 97
 JitsiConference.prototype.reload = function (options) {
100
-    this.leave().then(function(){
101
-        this._init(options || {});
102
-        this.join();
103
-    }.bind(this));
98
+    this.statistics.stopCallStats();
99
+    this.rtc.closeAllDataChannels();
100
+    this._leaveRoomAndRemoveParticipants();
101
+    this._init(options || {});
102
+    this.eventManager.setupChatRoomListeners();
103
+    //if we have new xmpp instance we should set it's listeners again.
104
+    if(options.connection)
105
+        this.eventManager.setupXMPPListeners();
106
+    this.join();
104 107
 }
105 108
 
106 109
 /**
@@ -1061,429 +1064,12 @@ JitsiConference.prototype._onTrackAttach = function(track, container) {
1061 1064
 
1062 1065
 /**
1063 1066
  * Setups the listeners needed for the conference.
1064
- * @param conference the conference
1065 1067
  */
1066
-function setupListeners(conference) {
1067
-    conference.xmpp.addListener(
1068
-        XMPPEvents.CALL_INCOMING, conference.onIncomingCall.bind(conference));
1069
-
1070
-    conference.room.addListener(XMPPEvents.ICE_RESTARTING, function () {
1071
-        // All data channels have to be closed, before ICE restart
1072
-        // otherwise Chrome will not trigger "opened" event for the channel
1073
-        // established with the new bridge
1074
-        conference.rtc.closeAllDataChannels();
1075
-    });
1076
-
1077
-    conference.room.addListener(XMPPEvents.REMOTE_TRACK_ADDED,
1078
-        function (data) {
1079
-            var track = conference.rtc.createRemoteTrack(data);
1080
-            if (track) {
1081
-                conference.onTrackAdded(track);
1082
-            }
1083
-        }
1084
-    );
1085
-    conference.room.addListener(XMPPEvents.REMOTE_TRACK_REMOVED,
1086
-        function (streamId, trackId) {
1087
-            conference.getParticipants().forEach(function(participant) {
1088
-                var tracks = participant.getTracks();
1089
-                for(var i = 0; i < tracks.length; i++) {
1090
-                    if(tracks[i]
1091
-                        && tracks[i].getStreamId() == streamId
1092
-                        && tracks[i].getTrackId() == trackId) {
1093
-                        var track = participant._tracks.splice(i, 1)[0];
1094
-                        conference.eventEmitter.emit(
1095
-                            JitsiConferenceEvents.TRACK_REMOVED, track);
1096
-                        return;
1097
-                    }
1098
-                }
1099
-            });
1100
-        }
1101
-    );
1102
-
1103
-    conference.room.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS,
1104
-        function (value) {
1105
-            // set isMutedByFocus when setAudioMute Promise ends
1106
-            conference.rtc.setAudioMute(value).then(
1107
-                function() {
1108
-                    conference.isMutedByFocus = true;
1109
-                },
1110
-                function() {
1111
-                    logger.warn(
1112
-                        "Error while audio muting due to focus request");
1113
-                });
1114
-        }
1115
-    );
1116
-
1117
-    conference.room.addListener(XMPPEvents.SUBJECT_CHANGED, function (subject) {
1118
-        conference.eventEmitter.emit(JitsiConferenceEvents.SUBJECT_CHANGED,
1119
-            subject);
1120
-    });
1121
-
1122
-    conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
1123
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);
1124
-    });
1125
-    conference.room.addListener(XMPPEvents.ROOM_JOIN_ERROR, function (pres) {
1126
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
1127
-            JitsiConferenceErrors.CONNECTION_ERROR, pres);
1128
-    });
1129
-    conference.room.addListener(XMPPEvents.ROOM_CONNECT_ERROR, function (pres) {
1130
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
1131
-            JitsiConferenceErrors.CONNECTION_ERROR, pres);
1132
-    });
1133
-    conference.room.addListener(XMPPEvents.ROOM_MAX_USERS_ERROR,
1134
-    function (pres) {
1135
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
1136
-            JitsiConferenceErrors.CONFERENCE_MAX_USERS, pres);
1137
-    });
1138
-    conference.room.addListener(XMPPEvents.PASSWORD_REQUIRED, function (pres) {
1139
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.PASSWORD_REQUIRED, pres);
1140
-    });
1141
-    conference.room.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, function () {
1142
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.AUTHENTICATION_REQUIRED);
1143
-    });
1144
-    conference.room.addListener(XMPPEvents.BRIDGE_DOWN, function () {
1145
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE);
1146
-    });
1147
-    conference.room.addListener(XMPPEvents.RESERVATION_ERROR, function (code, msg) {
1148
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.RESERVATION_ERROR, code, msg);
1149
-    });
1150
-    conference.room.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () {
1151
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.GRACEFUL_SHUTDOWN);
1152
-    });
1153
-    conference.room.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function (session, error) {
1154
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.JINGLE_FATAL_ERROR, error);
1155
-    });
1156
-    conference.room.addListener(XMPPEvents.MUC_DESTROYED, function (reason) {
1157
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONFERENCE_DESTROYED, reason);
1158
-    });
1159
-    conference.room.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, function (err, msg) {
1160
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_ERROR, JitsiConferenceErrors.CHAT_ERROR, err, msg);
1161
-    });
1162
-    conference.room.addListener(XMPPEvents.FOCUS_DISCONNECTED, function (focus, retrySec) {
1163
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.FOCUS_DISCONNECTED, focus, retrySec);
1164
-    });
1165
-    conference.room.addListener(XMPPEvents.FOCUS_LEFT, function () {
1166
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.FOCUS_LEFT);
1167
-    });
1168
-    conference.room.setParticipantPropertyListener(function (node, from) {
1169
-        var participant = conference.getParticipantById(from);
1170
-        if (!participant) {
1171
-            return;
1172
-        }
1173
-
1174
-        participant.setProperty(
1175
-            node.tagName.substring("jitsi_participant_".length),
1176
-            node.value);
1177
-    });
1178
-//    FIXME
1179
-//    conference.room.addListener(XMPPEvents.MUC_JOINED, function () {
1180
-//        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT);
1181
-//    });
1182
-
1183
-    conference.room.addListener(XMPPEvents.KICKED, function () {
1184
-        conference.eventEmitter.emit(JitsiConferenceEvents.KICKED);
1185
-    });
1186
-
1187
-    conference.room.addListener(XMPPEvents.MUC_MEMBER_JOINED, conference.onMemberJoined.bind(conference));
1188
-    conference.room.addListener(XMPPEvents.MUC_MEMBER_LEFT, conference.onMemberLeft.bind(conference));
1189
-
1190
-    conference.room.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, conference.onDisplayNameChanged.bind(conference));
1191
-
1192
-    conference.room.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, function (role) {
1193
-        conference.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED, conference.myUserId(), role);
1194
-
1195
-        // log all events for the recorder operated by the moderator
1196
-        if (conference.statistics && conference.isModerator()) {
1197
-            conference.on(JitsiConferenceEvents.RECORDER_STATE_CHANGED,
1198
-                function (status, error) {
1199
-                    Statistics.sendLog(
1200
-                        "[Recorder] status: " + status
1201
-                            + (error? " error: " + error : ""));
1202
-                });
1203
-        }
1204
-    });
1205
-    conference.room.addListener(XMPPEvents.MUC_ROLE_CHANGED, conference.onUserRoleChanged.bind(conference));
1206
-
1207
-    conference.room.addListener(XMPPEvents.CONNECTION_INTERRUPTED, function () {
1208
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_INTERRUPTED);
1209
-    });
1210
-
1211
-    conference.room.addListener(XMPPEvents.RECORDER_STATE_CHANGED,
1212
-        function (state) {
1213
-            conference.eventEmitter.emit(
1214
-                JitsiConferenceEvents.RECORDER_STATE_CHANGED, state);
1215
-        });
1216
-
1217
-    conference.room.addListener(XMPPEvents.PHONE_NUMBER_CHANGED, function () {
1218
-        conference.eventEmitter.emit(
1219
-            JitsiConferenceEvents.PHONE_NUMBER_CHANGED);
1220
-    });
1221
-
1222
-    conference.room.addListener(XMPPEvents.CONNECTION_RESTORED, function () {
1223
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_RESTORED);
1224
-    });
1225
-    conference.room.addListener(XMPPEvents.CONFERENCE_SETUP_FAILED,
1226
-    function (error) {
1227
-        conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
1228
-            JitsiConferenceErrors.SETUP_FAILED, error);
1229
-    });
1230
-
1231
-    conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED, function (authEnabled, authIdentity) {
1232
-        conference.authEnabled = authEnabled;
1233
-        conference.authIdentity = authIdentity;
1234
-        conference.eventEmitter.emit(JitsiConferenceEvents.AUTH_STATUS_CHANGED, authEnabled, authIdentity);
1235
-    });
1236
-
1237
-    conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) {
1238
-        var id = Strophe.getResourceFromJid(jid);
1239
-        conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED, id, txt, ts);
1240
-    });
1241
-
1242
-    conference.room.addListener(XMPPEvents.PRESENCE_STATUS, function (jid, status) {
1243
-        var id = Strophe.getResourceFromJid(jid);
1244
-        var participant = conference.getParticipantById(id);
1245
-        if (!participant || participant._status === status) {
1246
-            return;
1247
-        }
1248
-        participant._status = status;
1249
-        conference.eventEmitter.emit(JitsiConferenceEvents.USER_STATUS_CHANGED, id, status);
1250
-    });
1251
-
1252
-    conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {
1253
-        if(conference.lastDominantSpeaker !== id && conference.room) {
1254
-            conference.lastDominantSpeaker = id;
1255
-            conference.eventEmitter.emit(JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED, id);
1256
-        }
1257
-        if (conference.statistics && conference.myUserId() === id) {
1258
-            // We are the new dominant speaker.
1259
-            conference.statistics.sendDominantSpeakerEvent();
1260
-        }
1261
-    });
1262
-
1263
-    conference.rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, function () {
1264
-        var now = window.performance.now();
1265
-        logger.log("(TIME) data channel opened ", now);
1266
-        conference.room.connectionTimes["data.channel.opened"] = now;
1267
-    });
1268
-
1269
-    conference.rtc.addListener(RTCEvents.LASTN_CHANGED, function (oldValue, newValue) {
1270
-        conference.eventEmitter.emit(JitsiConferenceEvents.IN_LAST_N_CHANGED, oldValue, newValue);
1271
-    });
1272
-
1273
-    conference.rtc.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,
1274
-        function (lastNEndpoints, endpointsEnteringLastN) {
1275
-            conference.eventEmitter.emit(JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
1276
-                lastNEndpoints, endpointsEnteringLastN);
1277
-        });
1278
-
1279
-    conference.xmpp.addListener(XMPPEvents.START_MUTED_FROM_FOCUS,
1280
-        function (audioMuted, videoMuted) {
1281
-            conference.startAudioMuted = audioMuted;
1282
-            conference.startVideoMuted = videoMuted;
1283
-
1284
-            // mute existing local tracks because this is initial mute from
1285
-            // Jicofo
1286
-            conference.getLocalTracks().forEach(function (track) {
1287
-                if (conference.startAudioMuted && track.isAudioTrack()) {
1288
-                    track.mute();
1289
-                }
1290
-                if (conference.startVideoMuted && track.isVideoTrack()) {
1291
-                    track.mute();
1292
-                }
1293
-            });
1294
-
1295
-            conference.eventEmitter.emit(JitsiConferenceEvents.STARTED_MUTED);
1296
-        });
1297
-
1298
-    conference.room.addPresenceListener("startmuted", function (data, from) {
1299
-        var isModerator = false;
1300
-        if (conference.myUserId() === from && conference.isModerator()) {
1301
-            isModerator = true;
1302
-        } else {
1303
-            var participant = conference.getParticipantById(from);
1304
-            if (participant && participant.isModerator()) {
1305
-                isModerator = true;
1306
-            }
1307
-        }
1308
-
1309
-        if (!isModerator) {
1310
-            return;
1311
-        }
1312
-
1313
-        var startAudioMuted = data.attributes.audio === 'true';
1314
-        var startVideoMuted = data.attributes.video === 'true';
1315
-
1316
-        var updated = false;
1317
-
1318
-        if (startAudioMuted !== conference.startMutedPolicy.audio) {
1319
-            conference.startMutedPolicy.audio = startAudioMuted;
1320
-            updated = true;
1321
-        }
1322
-
1323
-        if (startVideoMuted !== conference.startMutedPolicy.video) {
1324
-            conference.startMutedPolicy.video = startVideoMuted;
1325
-            updated = true;
1326
-        }
1327
-
1328
-        if (updated) {
1329
-            conference.eventEmitter.emit(
1330
-                JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,
1331
-                conference.startMutedPolicy
1332
-            );
1333
-        }
1334
-    });
1335
-
1336
-    conference.rtc.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) {
1337
-        conference.room.updateDeviceAvailability(devices);
1338
-    });
1339
-
1340
-    conference.room.addPresenceListener("videomuted", function (values, from) {
1341
-        conference.rtc.handleRemoteTrackMute(MediaType.VIDEO,
1342
-            values.value == "true", from);
1343
-    });
1344
-
1345
-    conference.room.addPresenceListener("audiomuted", function (values, from) {
1346
-        conference.rtc.handleRemoteTrackMute(MediaType.AUDIO,
1347
-            values.value == "true", from);
1348
-    });
1349
-
1350
-    conference.room.addPresenceListener("videoType", function(data, from) {
1351
-        conference.rtc.handleRemoteTrackVideoTypeChanged(data.value, from);
1352
-    });
1353
-
1354
-    conference.room.addPresenceListener("devices", function (data, from) {
1355
-        var isAudioAvailable = false;
1356
-        var isVideoAvailable = false;
1357
-        data.children.forEach(function (config) {
1358
-            if (config.tagName === 'audio') {
1359
-                isAudioAvailable = config.value === 'true';
1360
-            }
1361
-            if (config.tagName === 'video') {
1362
-                isVideoAvailable = config.value === 'true';
1363
-            }
1364
-        });
1365
-
1366
-        var availableDevices;
1367
-        if (conference.myUserId() === from) {
1368
-            availableDevices = conference.availableDevices;
1369
-        } else {
1370
-            var participant = conference.getParticipantById(from);
1371
-            if (!participant) {
1372
-                return;
1373
-            }
1374
-
1375
-            availableDevices = participant._availableDevices;
1376
-        }
1377
-
1378
-        var updated = false;
1379
-
1380
-        if (availableDevices.audio !== isAudioAvailable) {
1381
-            updated = true;
1382
-            availableDevices.audio = isAudioAvailable;
1383
-        }
1384
-
1385
-        if (availableDevices.video !== isVideoAvailable) {
1386
-            updated = true;
1387
-            availableDevices.video = isVideoAvailable;
1388
-        }
1389
-
1390
-        if (updated) {
1391
-            conference.eventEmitter.emit(
1392
-                JitsiConferenceEvents.AVAILABLE_DEVICES_CHANGED,
1393
-                from, availableDevices);
1394
-        }
1395
-    });
1396
-
1397
-    if(conference.statistics) {
1398
-        //FIXME: Maybe remove event should not be associated with the conference.
1399
-        conference.statistics.addAudioLevelListener(function (ssrc, level) {
1400
-            var userId = null;
1401
-
1402
-            var resource = conference.rtc.getResourceBySSRC(ssrc);
1403
-            if (!resource)
1404
-                return;
1405
-
1406
-            conference.rtc.setAudioLevel(resource, level);
1407
-        });
1408
-        conference.statistics.addConnectionStatsListener(function (stats) {
1409
-            var ssrc2resolution = stats.resolution;
1410
-
1411
-            var id2resolution = {};
1412
-
1413
-            // preprocess resolutions: group by user id, skip incorrect
1414
-            // resolutions etc.
1415
-            Object.keys(ssrc2resolution).forEach(function (ssrc) {
1416
-                var resolution = ssrc2resolution[ssrc];
1417
-
1418
-                if (!resolution.width || !resolution.height ||
1419
-                    resolution.width == -1 || resolution.height == -1) {
1420
-                    return;
1421
-                }
1422
-
1423
-                var id = conference.rtc.getResourceBySSRC(ssrc);
1424
-                if (!id) {
1425
-                    return;
1426
-                }
1427
-
1428
-                // ssrc to resolution map for user id
1429
-                var idResolutions = id2resolution[id] || {};
1430
-                idResolutions[ssrc] = resolution;
1431
-
1432
-                id2resolution[id] = idResolutions;
1433
-            });
1434
-
1435
-            stats.resolution = id2resolution;
1436
-
1437
-            conference.eventEmitter.emit(
1438
-                JitsiConferenceEvents.CONNECTION_STATS, stats);
1439
-        });
1440
-        conference.room.addListener(XMPPEvents.DISPOSE_CONFERENCE,
1441
-            function () {
1442
-                conference.statistics.dispose();
1443
-            });
1444
-
1445
-        conference.room.addListener(XMPPEvents.CONNECTION_ICE_FAILED,
1446
-            function (pc) {
1447
-                conference.statistics.sendIceConnectionFailedEvent(pc);
1448
-                conference.room.eventEmitter.emit(
1449
-                    XMPPEvents.CONFERENCE_SETUP_FAILED,
1450
-                    new Error("ICE fail"));
1451
-            });
1452
-
1453
-        conference.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED,
1454
-            function (track) {
1455
-                if(!track.isLocal())
1456
-                    return;
1457
-                var type = (track.getType() === "audio")? "audio" : "video";
1458
-                conference.statistics.sendMuteEvent(track.isMuted(), type);
1459
-            });
1460
-
1461
-        conference.room.addListener(XMPPEvents.CREATE_OFFER_FAILED, function (e, pc) {
1462
-            conference.statistics.sendCreateOfferFailed(e, pc);
1463
-        });
1464
-
1465
-        conference.room.addListener(XMPPEvents.CREATE_ANSWER_FAILED, function (e, pc) {
1466
-            conference.statistics.sendCreateAnswerFailed(e, pc);
1467
-        });
1468
-
1469
-        conference.room.addListener(XMPPEvents.SET_LOCAL_DESCRIPTION_FAILED,
1470
-            function (e, pc) {
1471
-                conference.statistics.sendSetLocalDescFailed(e, pc);
1472
-            }
1473
-        );
1474
-
1475
-        conference.room.addListener(XMPPEvents.SET_REMOTE_DESCRIPTION_FAILED,
1476
-            function (e, pc) {
1477
-                conference.statistics.sendSetRemoteDescFailed(e, pc);
1478
-            }
1479
-        );
1480
-
1481
-        conference.room.addListener(XMPPEvents.ADD_ICE_CANDIDATE_FAILED,
1482
-            function (e, pc) {
1483
-                conference.statistics.sendAddIceCandidateFailed(e, pc);
1484
-            }
1485
-        );
1486
-    }
1068
+JitsiConference.prototype._setupListeners = function () {
1069
+    this.eventManager.setupXMPPListeners();
1070
+    this.eventManager.setupChatRoomListeners();
1071
+    this.eventManager.setupRTCListeners();
1072
+    this.eventManager.setupStatisticsListeners();
1487 1073
 }
1488 1074
 
1489 1075
 

+ 486
- 0
JitsiConferenceEventManager.js View File

@@ -0,0 +1,486 @@
1
+/* global Strophe */
2
+var logger = require("jitsi-meet-logger").getLogger(__filename);
3
+var EventEmitterForwarder = require("./modules/util/EventEmitterForwarder");
4
+var XMPPEvents = require("./service/xmpp/XMPPEvents");
5
+var RTCEvents = require("./service/RTC/RTCEvents");
6
+var JitsiConferenceEvents = require("./JitsiConferenceEvents");
7
+var JitsiConferenceErrors = require("./JitsiConferenceErrors");
8
+var AuthenticationEvents =
9
+    require("./service/authentication/AuthenticationEvents");
10
+var Statistics = require("./modules/statistics/statistics");
11
+var MediaType = require("./service/RTC/MediaType");
12
+
13
+/**
14
+ * Setups all event listeners related to conference
15
+ * @param conference {JitsiConference} the conference
16
+ */
17
+function JitsiConferenceEventManager(conference) {
18
+    this.conference = conference;
19
+    this.chatRoomForwarder = new EventEmitterForwarder(this.conference.room,
20
+        this.conference.eventEmitter);
21
+}
22
+
23
+/**
24
+ * Setups event listeners related to conference.chatRoom
25
+ */
26
+JitsiConferenceEventManager.prototype.setupChatRoomListeners = function () {
27
+    var conference = this.conference;
28
+
29
+    conference.room.addListener(XMPPEvents.ICE_RESTARTING, function () {
30
+        // All data channels have to be closed, before ICE restart
31
+        // otherwise Chrome will not trigger "opened" event for the channel
32
+        // established with the new bridge
33
+        conference.rtc.closeAllDataChannels();
34
+    });
35
+
36
+    conference.room.addListener(XMPPEvents.REMOTE_TRACK_ADDED,
37
+        function (data) {
38
+            var track = conference.rtc.createRemoteTrack(data);
39
+            if (track) {
40
+                conference.onTrackAdded(track);
41
+            }
42
+        }
43
+    );
44
+    conference.room.addListener(XMPPEvents.REMOTE_TRACK_REMOVED,
45
+        function (streamId, trackId) {
46
+            conference.getParticipants().forEach(function(participant) {
47
+                var tracks = participant.getTracks();
48
+                for(var i = 0; i < tracks.length; i++) {
49
+                    if(tracks[i]
50
+                        && tracks[i].getStreamId() == streamId
51
+                        && tracks[i].getTrackId() == trackId) {
52
+                        var track = participant._tracks.splice(i, 1)[0];
53
+                        conference.eventEmitter.emit(
54
+                            JitsiConferenceEvents.TRACK_REMOVED, track);
55
+                        return;
56
+                    }
57
+                }
58
+            });
59
+        }
60
+    );
61
+
62
+    conference.room.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS,
63
+        function (value) {
64
+            // set isMutedByFocus when setAudioMute Promise ends
65
+            conference.rtc.setAudioMute(value).then(
66
+                function() {
67
+                    conference.isMutedByFocus = true;
68
+                },
69
+                function() {
70
+                    logger.warn(
71
+                        "Error while audio muting due to focus request");
72
+                });
73
+        }
74
+    );
75
+
76
+    this.chatRoomForwarder.forward(XMPPEvents.SUBJECT_CHANGED,
77
+        JitsiConferenceEvents.SUBJECT_CHANGED);
78
+
79
+    this.chatRoomForwarder.forward(XMPPEvents.MUC_JOINED,
80
+        JitsiConferenceEvents.CONFERENCE_JOINED);
81
+
82
+    this.chatRoomForwarder.forward(XMPPEvents.ROOM_JOIN_ERROR,
83
+        JitsiConferenceEvents.CONFERENCE_FAILED,
84
+        JitsiConferenceErrors.CONNECTION_ERROR);
85
+
86
+    this.chatRoomForwarder.forward(XMPPEvents.ROOM_CONNECT_ERROR,
87
+        JitsiConferenceEvents.CONFERENCE_FAILED,
88
+        JitsiConferenceErrors.CONNECTION_ERROR);
89
+
90
+    this.chatRoomForwarder.forward(XMPPEvents.ROOM_MAX_USERS_ERROR,
91
+        JitsiConferenceEvents.CONFERENCE_FAILED,
92
+        JitsiConferenceErrors.CONFERENCE_MAX_USERS);
93
+
94
+    this.chatRoomForwarder.forward(XMPPEvents.PASSWORD_REQUIRED,
95
+        JitsiConferenceEvents.CONFERENCE_FAILED,
96
+        JitsiConferenceErrors.PASSWORD_REQUIRED);
97
+
98
+    this.chatRoomForwarder.forward(XMPPEvents.AUTHENTICATION_REQUIRED,
99
+        JitsiConferenceEvents.CONFERENCE_FAILED,
100
+        JitsiConferenceErrors.AUTHENTICATION_REQUIRED);
101
+
102
+    this.chatRoomForwarder.forward(XMPPEvents.BRIDGE_DOWN,
103
+        JitsiConferenceEvents.CONFERENCE_FAILED,
104
+        JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE);
105
+
106
+    this.chatRoomForwarder.forward(XMPPEvents.RESERVATION_ERROR,
107
+        JitsiConferenceEvents.CONFERENCE_FAILED,
108
+        JitsiConferenceErrors.RESERVATION_ERROR);
109
+
110
+    this.chatRoomForwarder.forward(XMPPEvents.GRACEFUL_SHUTDOWN,
111
+        JitsiConferenceEvents.CONFERENCE_FAILED,
112
+        JitsiConferenceErrors.GRACEFUL_SHUTDOWN);
113
+
114
+    conference.room.addListener(XMPPEvents.JINGLE_FATAL_ERROR,
115
+        function (session, error) {
116
+            conference.eventEmitter.emit(
117
+                JitsiConferenceEvents.CONFERENCE_FAILED,
118
+                JitsiConferenceErrors.JINGLE_FATAL_ERROR, error);
119
+        });
120
+
121
+    this.chatRoomForwarder.forward(XMPPEvents.MUC_DESTROYED,
122
+        JitsiConferenceEvents.CONFERENCE_FAILED,
123
+        JitsiConferenceErrors.CONFERENCE_DESTROYED);
124
+
125
+    this.chatRoomForwarder.forward(XMPPEvents.CHAT_ERROR_RECEIVED,
126
+        JitsiConferenceEvents.CONFERENCE_ERROR,
127
+        JitsiConferenceErrors.CHAT_ERROR);
128
+
129
+    this.chatRoomForwarder.forward(XMPPEvents.FOCUS_DISCONNECTED,
130
+        JitsiConferenceEvents.CONFERENCE_FAILED,
131
+        JitsiConferenceErrors.FOCUS_DISCONNECTED);
132
+
133
+    this.chatRoomForwarder.forward(XMPPEvents.FOCUS_LEFT,
134
+        JitsiConferenceEvents.CONFERENCE_FAILED,
135
+        JitsiConferenceErrors.FOCUS_LEFT);
136
+
137
+    this.chatRoomForwarder.forward(XMPPEvents.CONNECTION_INTERRUPTED,
138
+        JitsiConferenceEvents.CONNECTION_INTERRUPTED);
139
+
140
+    this.chatRoomForwarder.forward(XMPPEvents.RECORDER_STATE_CHANGED,
141
+        JitsiConferenceEvents.RECORDER_STATE_CHANGED);
142
+
143
+    this.chatRoomForwarder.forward(XMPPEvents.PHONE_NUMBER_CHANGED,
144
+        JitsiConferenceEvents.PHONE_NUMBER_CHANGED);
145
+
146
+    this.chatRoomForwarder.forward(XMPPEvents.CONNECTION_RESTORED,
147
+        JitsiConferenceEvents.CONNECTION_RESTORED);
148
+
149
+    this.chatRoomForwarder.forward(XMPPEvents.CONFERENCE_SETUP_FAILED,
150
+        JitsiConferenceEvents.CONFERENCE_FAILED,
151
+        JitsiConferenceErrors.SETUP_FAILED);
152
+
153
+    conference.room.setParticipantPropertyListener(function (node, from) {
154
+        var participant = conference.getParticipantById(from);
155
+        if (!participant) {
156
+            return;
157
+        }
158
+
159
+        participant.setProperty(
160
+            node.tagName.substring("jitsi_participant_".length),
161
+            node.value);
162
+    });
163
+
164
+    this.chatRoomForwarder.forward(XMPPEvents.KICKED,
165
+        JitsiConferenceEvents.KICKED);
166
+
167
+    conference.room.addListener(XMPPEvents.MUC_MEMBER_JOINED,
168
+        conference.onMemberJoined.bind(conference));
169
+    conference.room.addListener(XMPPEvents.MUC_MEMBER_LEFT,
170
+        conference.onMemberLeft.bind(conference));
171
+
172
+    conference.room.addListener(XMPPEvents.DISPLAY_NAME_CHANGED,
173
+        conference.onDisplayNameChanged.bind(conference));
174
+
175
+    conference.room.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, function (role) {
176
+        conference.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED,
177
+            conference.myUserId(), role);
178
+
179
+        // log all events for the recorder operated by the moderator
180
+        if (conference.statistics && conference.isModerator()) {
181
+            conference.on(JitsiConferenceEvents.RECORDER_STATE_CHANGED,
182
+                function (status, error) {
183
+                    Statistics.sendLog("[Recorder] status: " + status
184
+                        + (error? " error: " + error : ""));
185
+                });
186
+        }
187
+    });
188
+
189
+    conference.room.addListener(XMPPEvents.MUC_ROLE_CHANGED,
190
+        conference.onUserRoleChanged.bind(conference));
191
+
192
+    conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED,
193
+        function (authEnabled, authIdentity) {
194
+            conference.authEnabled = authEnabled;
195
+            conference.authIdentity = authIdentity;
196
+            conference.eventEmitter.emit(
197
+                JitsiConferenceEvents.AUTH_STATUS_CHANGED, authEnabled,
198
+                authIdentity);
199
+        });
200
+
201
+    conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED,
202
+        function (jid, displayName, txt, myJid, ts) {
203
+            var id = Strophe.getResourceFromJid(jid);
204
+            conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED,
205
+                id, txt, ts);
206
+        });
207
+
208
+    conference.room.addListener(XMPPEvents.PRESENCE_STATUS,
209
+        function (jid, status) {
210
+            var id = Strophe.getResourceFromJid(jid);
211
+            var participant = conference.getParticipantById(id);
212
+            if (!participant || participant._status === status) {
213
+                return;
214
+            }
215
+            participant._status = status;
216
+            conference.eventEmitter.emit(
217
+                JitsiConferenceEvents.USER_STATUS_CHANGED, id, status);
218
+        });
219
+
220
+    conference.room.addPresenceListener("startmuted", function (data, from) {
221
+        var isModerator = false;
222
+        if (conference.myUserId() === from && conference.isModerator()) {
223
+            isModerator = true;
224
+        } else {
225
+            var participant = conference.getParticipantById(from);
226
+            if (participant && participant.isModerator()) {
227
+                isModerator = true;
228
+            }
229
+        }
230
+
231
+        if (!isModerator) {
232
+            return;
233
+        }
234
+
235
+        var startAudioMuted = data.attributes.audio === 'true';
236
+        var startVideoMuted = data.attributes.video === 'true';
237
+
238
+        var updated = false;
239
+
240
+        if (startAudioMuted !== conference.startMutedPolicy.audio) {
241
+            conference.startMutedPolicy.audio = startAudioMuted;
242
+            updated = true;
243
+        }
244
+
245
+        if (startVideoMuted !== conference.startMutedPolicy.video) {
246
+            conference.startMutedPolicy.video = startVideoMuted;
247
+            updated = true;
248
+        }
249
+
250
+        if (updated) {
251
+            conference.eventEmitter.emit(
252
+                JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,
253
+                conference.startMutedPolicy
254
+            );
255
+        }
256
+    });
257
+
258
+    conference.room.addPresenceListener("videomuted", function (values, from) {
259
+        conference.rtc.handleRemoteTrackMute(MediaType.VIDEO,
260
+            values.value == "true", from);
261
+    });
262
+
263
+    conference.room.addPresenceListener("audiomuted", function (values, from) {
264
+        conference.rtc.handleRemoteTrackMute(MediaType.AUDIO,
265
+            values.value == "true", from);
266
+    });
267
+
268
+    conference.room.addPresenceListener("videoType", function(data, from) {
269
+        conference.rtc.handleRemoteTrackVideoTypeChanged(data.value, from);
270
+    });
271
+
272
+    conference.room.addPresenceListener("devices", function (data, from) {
273
+        var isAudioAvailable = false;
274
+        var isVideoAvailable = false;
275
+        data.children.forEach(function (config) {
276
+            if (config.tagName === 'audio') {
277
+                isAudioAvailable = config.value === 'true';
278
+            }
279
+            if (config.tagName === 'video') {
280
+                isVideoAvailable = config.value === 'true';
281
+            }
282
+        });
283
+
284
+        var availableDevices;
285
+        if (conference.myUserId() === from) {
286
+            availableDevices = conference.availableDevices;
287
+        } else {
288
+            var participant = conference.getParticipantById(from);
289
+            if (!participant) {
290
+                return;
291
+            }
292
+
293
+            availableDevices = participant._availableDevices;
294
+        }
295
+
296
+        var updated = false;
297
+
298
+        if (availableDevices.audio !== isAudioAvailable) {
299
+            updated = true;
300
+            availableDevices.audio = isAudioAvailable;
301
+        }
302
+
303
+        if (availableDevices.video !== isVideoAvailable) {
304
+            updated = true;
305
+            availableDevices.video = isVideoAvailable;
306
+        }
307
+
308
+        if (updated) {
309
+            conference.eventEmitter.emit(
310
+                JitsiConferenceEvents.AVAILABLE_DEVICES_CHANGED,
311
+                from, availableDevices);
312
+        }
313
+    });
314
+
315
+    if(conference.statistics) {
316
+        conference.room.addListener(XMPPEvents.DISPOSE_CONFERENCE,
317
+            function () {
318
+                conference.statistics.dispose();
319
+            });
320
+
321
+        conference.room.addListener(XMPPEvents.CONNECTION_ICE_FAILED,
322
+            function (pc) {
323
+                conference.statistics.sendIceConnectionFailedEvent(pc);
324
+                conference.room.eventEmitter.emit(
325
+                    XMPPEvents.CONFERENCE_SETUP_FAILED,
326
+                    new Error("ICE fail"));
327
+            });
328
+
329
+        conference.room.addListener(XMPPEvents.CREATE_OFFER_FAILED,
330
+            function (e, pc) {
331
+                conference.statistics.sendCreateOfferFailed(e, pc);
332
+            });
333
+
334
+        conference.room.addListener(XMPPEvents.CREATE_ANSWER_FAILED,
335
+            function (e, pc) {
336
+                conference.statistics.sendCreateAnswerFailed(e, pc);
337
+            });
338
+
339
+        conference.room.addListener(XMPPEvents.SET_LOCAL_DESCRIPTION_FAILED,
340
+            function (e, pc) {
341
+                conference.statistics.sendSetLocalDescFailed(e, pc);
342
+            });
343
+
344
+        conference.room.addListener(XMPPEvents.SET_REMOTE_DESCRIPTION_FAILED,
345
+            function (e, pc) {
346
+                conference.statistics.sendSetRemoteDescFailed(e, pc);
347
+            });
348
+
349
+        conference.room.addListener(XMPPEvents.ADD_ICE_CANDIDATE_FAILED,
350
+            function (e, pc) {
351
+                conference.statistics.sendAddIceCandidateFailed(e, pc);
352
+            });
353
+    }
354
+};
355
+
356
+/**
357
+ * Setups event listeners related to conference.rtc
358
+ */
359
+JitsiConferenceEventManager.prototype.setupRTCListeners = function () {
360
+    var conference = this.conference;
361
+    conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED,
362
+        function (id) {
363
+            if(conference.lastDominantSpeaker !== id && conference.room) {
364
+                conference.lastDominantSpeaker = id;
365
+                conference.eventEmitter.emit(
366
+                    JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED, id);
367
+            }
368
+            if (conference.statistics && conference.myUserId() === id) {
369
+                // We are the new dominant speaker.
370
+                conference.statistics.sendDominantSpeakerEvent();
371
+            }
372
+        });
373
+
374
+    conference.rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, function () {
375
+        var now = window.performance.now();
376
+        logger.log("(TIME) data channel opened ", now);
377
+        conference.room.connectionTimes["data.channel.opened"] = now;
378
+    });
379
+
380
+    conference.rtc.addListener(RTCEvents.LASTN_CHANGED,
381
+        function (oldValue, newValue) {
382
+            conference.eventEmitter.emit(
383
+                JitsiConferenceEvents.IN_LAST_N_CHANGED, oldValue, newValue);
384
+        });
385
+
386
+    conference.rtc.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,
387
+        function (lastNEndpoints, endpointsEnteringLastN) {
388
+            conference.eventEmitter.emit(
389
+                JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
390
+                lastNEndpoints, endpointsEnteringLastN);
391
+        });
392
+
393
+    conference.rtc.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED,
394
+        function (devices) {
395
+            conference.room.updateDeviceAvailability(devices);
396
+        });
397
+};
398
+
399
+/**
400
+ * Setups event listeners related to conference.xmpp
401
+ */
402
+JitsiConferenceEventManager.prototype.setupXMPPListeners = function () {
403
+    var conference = this.conference;
404
+    conference.xmpp.addListener(
405
+        XMPPEvents.CALL_INCOMING, conference.onIncomingCall.bind(conference));
406
+
407
+    conference.xmpp.addListener(XMPPEvents.START_MUTED_FROM_FOCUS,
408
+        function (audioMuted, videoMuted) {
409
+            conference.startAudioMuted = audioMuted;
410
+            conference.startVideoMuted = videoMuted;
411
+
412
+            // mute existing local tracks because this is initial mute from
413
+            // Jicofo
414
+            conference.getLocalTracks().forEach(function (track) {
415
+                if (conference.startAudioMuted && track.isAudioTrack()) {
416
+                    track.mute();
417
+                }
418
+                if (conference.startVideoMuted && track.isVideoTrack()) {
419
+                    track.mute();
420
+                }
421
+            });
422
+
423
+            conference.eventEmitter.emit(JitsiConferenceEvents.STARTED_MUTED);
424
+        });
425
+};
426
+
427
+/**
428
+ * Setups event listeners related to conference.statistics
429
+ */
430
+JitsiConferenceEventManager.prototype.setupStatisticsListeners = function () {
431
+    var conference = this.conference;
432
+    if(!conference.statistics)
433
+        return;
434
+
435
+    conference.statistics.addAudioLevelListener(function (ssrc, level) {
436
+        var userId = null;
437
+
438
+        var resource = conference.rtc.getResourceBySSRC(ssrc);
439
+        if (!resource)
440
+            return;
441
+
442
+        conference.rtc.setAudioLevel(resource, level);
443
+    });
444
+    conference.statistics.addConnectionStatsListener(function (stats) {
445
+        var ssrc2resolution = stats.resolution;
446
+
447
+        var id2resolution = {};
448
+
449
+        // preprocess resolutions: group by user id, skip incorrect
450
+        // resolutions etc.
451
+        Object.keys(ssrc2resolution).forEach(function (ssrc) {
452
+            var resolution = ssrc2resolution[ssrc];
453
+
454
+            if (!resolution.width || !resolution.height ||
455
+                resolution.width == -1 || resolution.height == -1) {
456
+                return;
457
+            }
458
+
459
+            var id = conference.rtc.getResourceBySSRC(ssrc);
460
+            if (!id) {
461
+                return;
462
+            }
463
+
464
+            // ssrc to resolution map for user id
465
+            var idResolutions = id2resolution[id] || {};
466
+            idResolutions[ssrc] = resolution;
467
+
468
+            id2resolution[id] = idResolutions;
469
+        });
470
+
471
+        stats.resolution = id2resolution;
472
+
473
+        conference.eventEmitter.emit(
474
+            JitsiConferenceEvents.CONNECTION_STATS, stats);
475
+    });
476
+
477
+    conference.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED,
478
+        function (track) {
479
+            if(!track.isLocal())
480
+                return;
481
+            var type = (track.getType() === "audio")? "audio" : "video";
482
+            conference.statistics.sendMuteEvent(track.isMuted(), type);
483
+        });
484
+};
485
+
486
+module.exports = JitsiConferenceEventManager;

+ 2
- 1
modules/RTC/RTC.js View File

@@ -373,7 +373,8 @@ RTC.isDesktopSharingEnabled = function () {
373 373
  * Closes all currently opened data channels.
374 374
  */
375 375
 RTC.prototype.closeAllDataChannels = function () {
376
-    this.dataChannels.closeAllChannels();
376
+    if(this.dataChannels)
377
+        this.dataChannels.closeAllChannels();
377 378
 };
378 379
 
379 380
 RTC.prototype.dispose = function() {

+ 8
- 0
modules/statistics/CallStats.js View File

@@ -461,4 +461,12 @@ CallStats.sendApplicationLog = _try_catch(function (e, cs) {
461 461
         .call(cs, wrtcFuncNames.applicationLog, e, null);
462 462
 });
463 463
 
464
+/**
465
+ * Clears allocated resources.
466
+ */
467
+CallStats.dispose = function () {
468
+    callStats = null;
469
+    CallStats.initialized = false;
470
+};
471
+
464 472
 module.exports = CallStats;

+ 28
- 4
modules/statistics/statistics.js View File

@@ -8,6 +8,11 @@ var CallStats = require("./CallStats");
8 8
 var ScriptUtil = require('../util/ScriptUtil');
9 9
 var JitsiTrackError = require("../../JitsiTrackError");
10 10
 
11
+/**
12
+ * True if callstats API is loaded
13
+ */
14
+ var isCallstatsLoaded = false;
15
+
11 16
 // Since callstats.io is a third party, we cannot guarantee the quality of their
12 17
 // service. More specifically, their server may take noticeably long time to
13 18
 // respond. Consequently, it is in our best interest (in the sense that the
@@ -16,10 +21,12 @@ var JitsiTrackError = require("../../JitsiTrackError");
16 21
 // downloading their API as soon as possible and (2) do the downloading
17 22
 // asynchronously.
18 23
 function loadCallStatsAPI() {
19
-    ScriptUtil.loadScript(
20
-            'https://api.callstats.io/static/callstats.min.js',
21
-            /* async */ true,
22
-            /* prepend */ true);
24
+    if(!isCallstatsLoaded)
25
+        ScriptUtil.loadScript(
26
+                'https://api.callstats.io/static/callstats.min.js',
27
+                /* async */ true,
28
+                /* prepend */ true);
29
+    isCallstatsLoaded = true;
23 30
     // FIXME At the time of this writing, we hope that the callstats.io API will
24 31
     // have loaded by the time we needed it (i.e. CallStats.init is invoked).
25 32
 }
@@ -202,6 +209,23 @@ Statistics.prototype.startCallStats = function (session, settings) {
202 209
     }
203 210
 };
204 211
 
212
+/**
213
+ * Removes the callstats.io instances.
214
+ */
215
+Statistics.prototype.stopCallStats = function () {
216
+    if(this.callStatsIntegrationEnabled && this.callstats) {
217
+        var callstatsList = Statistics.callsStatsInstances;
218
+        for(var i = 0;i < callstatsList.length; i++) {
219
+            if(this.callstats === callstatsList[i]) {
220
+                Statistics.callsStatsInstances.splice(i, 1);
221
+                break;
222
+            }
223
+        }
224
+        this.callstats = null;
225
+        CallStats.dispose();
226
+    }
227
+};
228
+
205 229
 /**
206 230
  * Returns true if the callstats integration is enabled, otherwise returns
207 231
  * false.

+ 37
- 0
modules/util/EventEmitterForwarder.js View File

@@ -0,0 +1,37 @@
1
+var EventEmitter = require("events");
2
+
3
+/**
4
+ * Implements utility to forward events from one eventEmitter to another.
5
+ * @param src {object} instance of EventEmitter or another class that implements
6
+ * addListener method which will register listener to EventEmitter instance.
7
+ * @param dest {object} instance of EventEmitter or another class that
8
+ * implements emit method which will emit an event.
9
+ */
10
+function EventEmitterForwarder (src, dest) {
11
+    if (!src || !dest || typeof(src.addListener) !== "function" ||
12
+        typeof(dest.emit) !== "function")
13
+        throw new Error("Invalid arguments passed to EventEmitterForwarder");
14
+    this.src = src;
15
+    this.dest = dest;
16
+}
17
+
18
+/**
19
+ * Adds event to be forwarded from src to dest.
20
+ * @param srcEvent {string} the event that EventEmitterForwarder is listening
21
+ * for.
22
+ * @param dstEvent {string} the event that will be fired from dest.
23
+ * @param arguments all other passed arguments are going to be fired with
24
+ * dstEvent.
25
+ */
26
+EventEmitterForwarder.prototype.forward = function () {
27
+    // This line is only for fixing jshint errors.
28
+    var args = arguments;
29
+    var srcEvent = args[0];
30
+    //This will be the "this" value for emit function.
31
+    args[0] = this.dest;
32
+    //Using bind.apply to pass the arguments as Array-like object ("arguments")
33
+    this.src.addListener(srcEvent,
34
+        this.dest.emit.bind.apply(this.dest.emit, args));
35
+};
36
+
37
+module.exports = EventEmitterForwarder;

Loading…
Cancel
Save