Просмотр исходного кода

Merge branch 'master' into audio_problem_detection

dev1
hristoterezov 9 лет назад
Родитель
Сommit
72892e7cd3

+ 38
- 14
JitsiConference.js Просмотреть файл

@@ -309,17 +309,27 @@ JitsiConference.prototype.setSubject = function (subject) {
309 309
  * Adds JitsiLocalTrack object to the conference.
310 310
  * @param track the JitsiLocalTrack object.
311 311
  * @returns {Promise<JitsiLocalTrack>}
312
- * @throws will throw and error if track is video track
313
- * and there is already another video track in the conference.
312
+ * @throws {Error} if the specified track is a video track and there is already
313
+ * another video track in the conference.
314 314
  */
315 315
 JitsiConference.prototype.addTrack = function (track) {
316
-    if(track.disposed)
317
-    {
316
+    if (track.disposed) {
318 317
         throw new JitsiTrackError(JitsiTrackErrors.TRACK_IS_DISPOSED);
319 318
     }
320 319
 
321
-    if (track.isVideoTrack() && this.rtc.getLocalVideoTrack()) {
322
-        throw new Error("cannot add second video track to the conference");
320
+    if (track.isVideoTrack()) {
321
+        // Ensure there's exactly 1 local video track in the conference.
322
+        var localVideoTrack = this.rtc.getLocalVideoTrack();
323
+        if (localVideoTrack) {
324
+            // Don't be excessively harsh and severe if the API client happens
325
+            // to attempt to add the same local video track twice.
326
+            if (track === localVideoTrack) {
327
+                return Promise.resolve(track);
328
+            } else {
329
+                throw new Error(
330
+                        "cannot add second video track to the conference");
331
+            }
332
+        }
323 333
     }
324 334
 
325 335
     track.ssrcHandler = function (conference, ssrcMap) {
@@ -332,6 +342,18 @@ JitsiConference.prototype.addTrack = function (track) {
332 342
     this.room.addListener(XMPPEvents.SENDRECV_STREAMS_CHANGED,
333 343
         track.ssrcHandler);
334 344
 
345
+    if(track.isAudioTrack() || (track.isVideoTrack() &&
346
+        track.videoType !== "desktop")) {
347
+        // Report active device to statistics
348
+        var devices = RTC.getCurrentlyAvailableMediaDevices();
349
+        device = devices.find(function (d) {
350
+            return d.kind === track.getTrack().kind + 'input'
351
+                && d.label === track.getTrack().label;
352
+        });
353
+        if(device)
354
+            Statistics.sendActiveDeviceListEvent(
355
+                RTC.getEventDataForActiveDevice(device));
356
+    }
335 357
     return new Promise(function (resolve, reject) {
336 358
         this.room.addStream(track.getOriginalStream(), function () {
337 359
             if (track.isVideoTrack()) {
@@ -1146,6 +1168,16 @@ function setupListeners(conference) {
1146 1168
 
1147 1169
     conference.room.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, function (role) {
1148 1170
         conference.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED, conference.myUserId(), role);
1171
+
1172
+        // log all events for the recorder operated by the moderator
1173
+        if (conference.statistics && conference.isModerator()) {
1174
+            conference.on(JitsiConferenceEvents.RECORDER_STATE_CHANGED,
1175
+                function (status, error) {
1176
+                    Statistics.sendLog(
1177
+                        "[Recorder] status: " + status
1178
+                            + (error? " error: " + error : ""));
1179
+                });
1180
+        }
1149 1181
     });
1150 1182
     conference.room.addListener(XMPPEvents.MUC_ROLE_CHANGED, conference.onUserRoleChanged.bind(conference));
1151 1183
 
@@ -1404,14 +1436,6 @@ function setupListeners(conference) {
1404 1436
                 conference.statistics.sendMuteEvent(track.isMuted(), type);
1405 1437
             });
1406 1438
 
1407
-        // log all events for the recorder operated by the moderator
1408
-        if (conference.isModerator()) {
1409
-            conference.on(JitsiConferenceEvents.RECORDER_STATE_CHANGED,
1410
-                function (status, error) {
1411
-                    conference.statistics.sendLog("Recorder: " + status);
1412
-                });
1413
-        }
1414
-
1415 1439
         conference.room.addListener(XMPPEvents.CREATE_OFFER_FAILED, function (e, pc) {
1416 1440
             conference.statistics.sendCreateOfferFailed(e, pc);
1417 1441
         });

+ 35
- 0
JitsiMediaDevices.js Просмотреть файл

@@ -3,6 +3,7 @@ var RTCEvents = require('./service/RTC/RTCEvents');
3 3
 var RTC = require("./modules/RTC/RTC");
4 4
 var MediaType = require('./service/RTC/MediaType');
5 5
 var JitsiMediaDevicesEvents = require('./JitsiMediaDevicesEvents');
6
+var Statistics = require("./modules/statistics/statistics");
6 7
 
7 8
 var eventEmitter = new EventEmitter();
8 9
 
@@ -11,6 +12,30 @@ RTC.addListener(RTCEvents.DEVICE_LIST_CHANGED,
11 12
         eventEmitter.emit(JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED, devices);
12 13
     });
13 14
 
15
+RTC.addListener(RTCEvents.DEVICE_LIST_AVAILABLE,
16
+    function (devices) {
17
+        // log output device
18
+        logOutputDevice(
19
+            JitsiMediaDevices.getAudioOutputDevice(),
20
+            devices);
21
+    });
22
+
23
+/**
24
+ * Gathers data and sends it to statistics.
25
+ * @param deviceID the device id to log
26
+ * @param devices list of devices
27
+ */
28
+function logOutputDevice (deviceID, devices) {
29
+    var device = devices.find(function (d) {
30
+        return d.kind === 'audiooutput' && d.deviceId === deviceID;
31
+    });
32
+
33
+    if (device) {
34
+        Statistics.sendActiveDeviceListEvent(
35
+            RTC.getEventDataForActiveDevice(device));
36
+    }
37
+}
38
+
14 39
 var JitsiMediaDevices = {
15 40
     /**
16 41
      * Executes callback with list of media devices connected.
@@ -71,6 +96,16 @@ var JitsiMediaDevices = {
71 96
      *      otherwise
72 97
      */
73 98
     setAudioOutputDevice: function (deviceId) {
99
+
100
+        var availableDevices = RTC.getCurrentlyAvailableMediaDevices();
101
+        if (availableDevices && availableDevices.length > 0)
102
+        {
103
+            // if we have devices info report device to stats
104
+            // normally this will not happen on startup as this method is called
105
+            // too early. This will happen only on user selection of new device
106
+            logOutputDevice(deviceId, RTC.getCurrentlyAvailableMediaDevices());
107
+        }
108
+
74 109
         return RTC.setAudioOutputDevice(deviceId);
75 110
     },
76 111
     /**

+ 3
- 4
JitsiMeetJS.js Просмотреть файл

@@ -60,6 +60,9 @@ var LibJitsiMeet = {
60 60
         recorder: JitsiRecorderErrors,
61 61
         track: JitsiTrackErrors
62 62
     },
63
+    errorTypes: {
64
+        JitsiTrackError: JitsiTrackError
65
+    },
63 66
     logLevels: Logger.levels,
64 67
     mediaDevices: JitsiMediaDevices,
65 68
     init: function (options) {
@@ -237,10 +240,6 @@ var LibJitsiMeet = {
237 240
     }
238 241
 };
239 242
 
240
-// expose JitsiTrackError this way to give library consumers to do checks like
241
-// if (error instanceof JitsiMeetJS.JitsiTrackError) { }
242
-LibJitsiMeet.JitsiTrackError = JitsiTrackError;
243
-
244 243
 //Setups the promise object.
245 244
 window.Promise = window.Promise || require("es6-promise").Promise;
246 245
 

+ 3
- 0
doc/API.md Просмотреть файл

@@ -171,6 +171,9 @@ JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
171 171
         - CHROME_EXTENSION_INSTALLATION_ERROR - an error which indicates that the jidesha extension for Chrome is failed to install.
172 172
         - FIREFOX_EXTENSION_NEEDED - An error which indicates that the jidesha extension for Firefox is needed to proceed with screen sharing, and that it is not installed.
173 173
         
174
+* ```JitsiMeetJS.errorTypes``` - constructors for Error instances that can be produced by library. Are useful for checks like ```error instanceof JitsiMeetJS.errorTypes.JitsiTrackError```. Following Errors are available:
175
+    1. ```JitsiTrackError``` - Error that happened to a JitsiTrack.
176
+        
174 177
 * ```JitsiMeetJS.logLevels``` - object with the log levels:
175 178
     1. TRACE
176 179
     2. DEBUG

+ 17
- 4
modules/RTC/RTC.js Просмотреть файл

@@ -313,10 +313,6 @@ RTC.getStreamID = function (stream) {
313 313
     return RTCUtils.getStreamID(stream);
314 314
 };
315 315
 
316
-RTC.getVideoSrc = function (element) {
317
-    return RTCUtils.getVideoSrc(element);
318
-};
319
-
320 316
 /**
321 317
  * Returns true if retrieving the the list of input devices is supported and
322 318
  * false if not.
@@ -345,6 +341,23 @@ RTC.getAudioOutputDevice = function () {
345 341
     return RTCUtils.getAudioOutputDevice();
346 342
 };
347 343
 
344
+/**
345
+ * Returns list of available media devices if its obtained, otherwise an
346
+ * empty array is returned/
347
+ * @returns {Array} list of available media devices.
348
+ */
349
+RTC.getCurrentlyAvailableMediaDevices = function () {
350
+    return RTCUtils.getCurrentlyAvailableMediaDevices();
351
+};
352
+
353
+/**
354
+ * Returns event data for device to be reported to stats.
355
+ * @returns {MediaDeviceInfo} device.
356
+ */
357
+RTC.getEventDataForActiveDevice = function (device) {
358
+    return RTCUtils.getEventDataForActiveDevice(device);
359
+};
360
+
348 361
 /**
349 362
  * Sets current audio output device.
350 363
  * @param {string} deviceId - id of 'audiooutput' device from

+ 0
- 10
modules/RTC/RTCUIHelper.js Просмотреть файл

@@ -60,16 +60,6 @@ var RTCUIHelper = {
60 60
         if (!RTCBrowserType.isIExplorer()) {
61 61
             streamElement.autoplay = true;
62 62
         }
63
-    },
64
-
65
-    /**
66
-     * Extract video stream id from the video element.
67
-     * @param {Element} element
68
-     * @returns {string} video stream id or empty string
69
-     */
70
-    getVideoId: function (element) {
71
-        var src = RTC.getVideoSrc(element);
72
-        return src ? String(src) : '';
73 63
     }
74 64
 };
75 65
 

+ 42
- 78
modules/RTC/RTCUtils.js Просмотреть файл

@@ -386,12 +386,24 @@ function onReady (options, GUM) {
386 386
     eventEmitter.emit(RTCEvents.RTC_READY, true);
387 387
     screenObtainer.init(options, GUM);
388 388
 
389
-    if (isDeviceChangeEventSupported && RTCUtils.isDeviceListAvailable()) {
390
-        navigator.mediaDevices.addEventListener('devicechange', function () {
391
-            RTCUtils.enumerateDevices(onMediaDevicesListChanged);
389
+    if (RTCUtils.isDeviceListAvailable() && rawEnumerateDevicesWithCallback) {
390
+        rawEnumerateDevicesWithCallback(function (devices) {
391
+            currentlyAvailableMediaDevices = devices.splice(0);
392
+
393
+            eventEmitter.emit(RTCEvents.DEVICE_LIST_AVAILABLE,
394
+                currentlyAvailableMediaDevices);
395
+
396
+            if (isDeviceChangeEventSupported) {
397
+                navigator.mediaDevices.addEventListener(
398
+                    'devicechange',
399
+                    function () {
400
+                        RTCUtils.enumerateDevices(
401
+                            onMediaDevicesListChanged);
402
+                    });
403
+            } else {
404
+                pollForAvailableMediaDevices();
405
+            }
392 406
         });
393
-    } else if (RTCUtils.isDeviceListAvailable()) {
394
-        pollForAvailableMediaDevices();
395 407
     }
396 408
 }
397 409
 
@@ -630,59 +642,6 @@ function wrapAttachMediaStream(origAttachMediaStream) {
630 642
     }
631 643
 }
632 644
 
633
-/**
634
- * Represents a default implementation of {@link RTCUtils#getVideoSrc} which
635
- * tries to be browser-agnostic through feature checking. Note though that it
636
- * was not completely clear from the predating browser-specific implementations
637
- * what &quot;videoSrc&quot; was because one implementation would return
638
- * <tt>MediaStream</tt> (e.g. Firefox), another a <tt>string</tt> representation
639
- * of the <tt>URL</tt> of the <tt>MediaStream</tt> (e.g. Chrome) and the return
640
- * value was only used by {@link RTCUIHelper#getVideoId} which itself did not
641
- * appear to be used anywhere. Generally, the implementation will try to follow
642
- * the related standards i.e. work with the <tt>srcObject</tt> and <tt>src</tt>
643
- * properties of the specified <tt>element</tt> taking into account vender
644
- * prefixes.
645
- *
646
- * @param element the element to get the associated video source/src of
647
- * @return the video source/src of the specified <tt>element</tt>
648
- */
649
-function defaultGetVideoSrc(element) {
650
-    // https://www.w3.org/TR/mediacapture-streams/
651
-    //
652
-    // User Agents that support this specification must support the srcObject
653
-    // attribute of the HTMLMediaElement interface defined in [HTML51].
654
-
655
-    // https://www.w3.org/TR/2015/WD-html51-20150506/semantics.html#dom-media-srcobject
656
-    //
657
-    // There are three ways to specify a media resource: the srcObject IDL
658
-    // attribute, the src content attribute, and source elements. The IDL
659
-    // attribute takes priority, followed by the content attribute, followed by
660
-    // the elements.
661
-
662
-    // srcObject
663
-    var srcObject = element.srcObject || element.mozSrcObject;
664
-    if (srcObject) {
665
-        // Try the optimized path to the URL of a MediaStream.
666
-        var url = srcObject.jitsiObjectURL;
667
-        if (url) {
668
-            return url.toString();
669
-        }
670
-        // Go via the unoptimized path to the URL of a MediaStream then.
671
-        var URL = (window.URL || webkitURL);
672
-        if (URL) {
673
-            url = URL.createObjectURL(srcObject);
674
-            try {
675
-                return url.toString();
676
-            } finally {
677
-                URL.revokeObjectURL(url);
678
-            }
679
-        }
680
-    }
681
-
682
-    // src
683
-    return element.src;
684
-}
685
-
686 645
 /**
687 646
  * Represents a default implementation of setting a <tt>MediaStream</tt> as the
688 647
  * source of a video element that tries to be browser-agnostic through feature
@@ -787,7 +746,6 @@ var RTCUtils = {
787 746
                     }
788 747
                     return SDPUtil.filter_special_chars(id);
789 748
                 };
790
-                this.getVideoSrc = defaultGetVideoSrc;
791 749
                 RTCSessionDescription = mozRTCSessionDescription;
792 750
                 RTCIceCandidate = mozRTCIceCandidate;
793 751
             } else if (RTCBrowserType.isChrome() ||
@@ -825,7 +783,6 @@ var RTCUtils = {
825 783
                             ? id
826 784
                             : SDPUtil.filter_special_chars(id));
827 785
                 };
828
-                this.getVideoSrc = defaultGetVideoSrc;
829 786
                 // DTLS should now be enabled by default but..
830 787
                 this.pc_constraints = {'optional': [
831 788
                     {'DtlsSrtpKeyAgreement': 'true'}
@@ -886,24 +843,6 @@ var RTCUtils = {
886 843
                     self.getStreamID = function (stream) {
887 844
                         return SDPUtil.filter_special_chars(stream.label);
888 845
                     };
889
-                    self.getVideoSrc = function (element) {
890
-                        // There's nothing standard about getVideoSrc in the
891
-                        // case of Temasys so there's no point to try to
892
-                        // generalize it through defaultGetVideoSrc.
893
-                        if (!element) {
894
-                            logger.warn(
895
-                                "Attempt to get video SRC of null element");
896
-                            return null;
897
-                        }
898
-                        var children = element.children;
899
-                        for (var i = 0; i !== children.length; ++i) {
900
-                            if (children[i].name === 'streamId') {
901
-                                return children[i].value;
902
-                            }
903
-                        }
904
-                        //logger.info(element.id + " SRC: " + src);
905
-                        return null;
906
-                    };
907 846
 
908 847
                     onReady(options, self.getUserMediaWithConstraints);
909 848
                     resolve();
@@ -1207,6 +1146,31 @@ var RTCUtils = {
1207 1146
      */
1208 1147
     getAudioOutputDevice: function () {
1209 1148
         return audioOutputDeviceId;
1149
+    },
1150
+
1151
+    /**
1152
+     * Returns list of available media devices if its obtained, otherwise an
1153
+     * empty array is returned/
1154
+     * @returns {Array} list of available media devices.
1155
+     */
1156
+    getCurrentlyAvailableMediaDevices: function () {
1157
+        return currentlyAvailableMediaDevices;
1158
+    },
1159
+
1160
+    /**
1161
+     * Returns event data for device to be reported to stats.
1162
+     * @returns {MediaDeviceInfo} device.
1163
+     */
1164
+    getEventDataForActiveDevice: function (device) {
1165
+        var devices = [];
1166
+        var deviceData = {
1167
+            "deviceId": device.deviceId,
1168
+            "kind":     device.kind,
1169
+            "label":    device.label,
1170
+            "groupId":  device.groupId
1171
+        };
1172
+        devices.push(deviceData);
1173
+        return { deviceList: devices };
1210 1174
     }
1211 1175
 };
1212 1176
 

+ 93
- 34
modules/statistics/CallStats.js Просмотреть файл

@@ -20,7 +20,7 @@ var wrtcFuncNames = {
20 20
     getUserMedia:         "getUserMedia",
21 21
     iceConnectionFailure: "iceConnectionFailure",
22 22
     signalingError:       "signalingError",
23
-    applicationError:     "applicationError"
23
+    applicationLog:       "applicationLog"
24 24
 };
25 25
 
26 26
 /**
@@ -41,7 +41,8 @@ var fabricEvent = {
41 41
     fabricTerminated:"fabricTerminated",
42 42
     screenShareStart:"screenShareStart",
43 43
     screenShareStop:"screenShareStop",
44
-    dominantSpeaker:"dominantSpeaker"
44
+    dominantSpeaker:"dominantSpeaker",
45
+    activeDeviceList:"activeDeviceList"
45 46
 };
46 47
 
47 48
 var callStats = null;
@@ -53,20 +54,47 @@ function initCallback (err, msg) {
53 54
     if (err !== 'success')
54 55
         return;
55 56
 
57
+    CallStats.initialized = true;
58
+
59
+    var ret = callStats.addNewFabric(this.peerconnection,
60
+        Strophe.getResourceFromJid(this.session.peerjid),
61
+        callStats.fabricUsage.multiplex,
62
+        this.confID,
63
+        this.pcCallback.bind(this));
64
+
65
+    var fabricInitialized = (ret.status === 'success');
66
+
67
+    if(!fabricInitialized)
68
+        console.log("callstats fabric not initilized", ret.message);
69
+
56 70
     // notify callstats about failures if there were any
57 71
     if (CallStats.reportsQueue.length) {
58 72
         CallStats.reportsQueue.forEach(function (report) {
59
-            if (report.type === reportType.ERROR)
60
-            {
73
+            if (report.type === reportType.ERROR) {
61 74
                 var error = report.data;
62 75
                 CallStats._reportError.call(this, error.type, error.error,
63 76
                     error.pc);
64 77
             }
65
-            else if (report.type === reportType.EVENT)
66
-            {
67
-                var data = report.data;
78
+            // if we have and event to report and we failed to add fabric
79
+            // this event will not be reported anyway, returning an error
80
+            else if (report.type === reportType.EVENT
81
+                && fabricInitialized) {
82
+                var eventData = report.data;
68 83
                 callStats.sendFabricEvent(
69
-                    this.peerconnection, data.event, this.confID);
84
+                    this.peerconnection,
85
+                    eventData.event,
86
+                    this.confID,
87
+                    eventData.eventData);
88
+            } else if (report.type === reportType.MST_WITH_USERID) {
89
+                var data = report.data;
90
+                callStats.associateMstWithUserID(
91
+                    this.peerconnection,
92
+                    data.callStatsId,
93
+                    this.confID,
94
+                    data.ssrc,
95
+                    data.usageLabel,
96
+                    data.containerId
97
+                );
70 98
             }
71 99
         }, this);
72 100
         CallStats.reportsQueue.length = 0;
@@ -123,11 +151,6 @@ var CallStats = _try_catch(function(jingleSession, Settings, options) {
123 151
             this.userID,
124 152
             initCallback.bind(this));
125 153
 
126
-        callStats.addNewFabric(this.peerconnection,
127
-            Strophe.getResourceFromJid(jingleSession.peerjid),
128
-            callStats.fabricUsage.multiplex,
129
-            this.confID,
130
-            this.pcCallback.bind(this));
131 154
     } catch (e) {
132 155
         // The callstats.io API failed to initialize (e.g. because its
133 156
         // download failed to succeed in general or on time). Further
@@ -143,13 +166,21 @@ var CallStats = _try_catch(function(jingleSession, Settings, options) {
143 166
 // and send them to callstats on init
144 167
 CallStats.reportsQueue = [];
145 168
 
169
+/**
170
+ * Whether the library was successfully initialized using its initialize method.
171
+ * And whether we had successfully called addNewFabric.
172
+ * @type {boolean}
173
+ */
174
+CallStats.initialized = false;
175
+
146 176
 /**
147 177
  * Type of pending reports, can be event or an error.
148 178
  * @type {{ERROR: string, EVENT: string}}
149 179
  */
150 180
 var reportType = {
151 181
     ERROR: "error",
152
-    EVENT: "event"
182
+    EVENT: "event",
183
+    MST_WITH_USERID: "mstWithUserID"
153 184
 };
154 185
 
155 186
 CallStats.prototype.pcCallback = _try_catch(function (err, msg) {
@@ -162,6 +193,7 @@ CallStats.prototype.pcCallback = _try_catch(function (err, msg) {
162 193
 /**
163 194
  * Lets CallStats module know where is given SSRC rendered by providing renderer
164 195
  * tag ID.
196
+ * If the lib is not initialized yet queue the call for later, when its ready.
165 197
  * @param ssrc {number} the SSRC of the stream
166 198
  * @param isLocal {boolean} <tt>true<tt> if this stream is local or
167 199
  *        <tt>false</tt> otherwise.
@@ -191,14 +223,27 @@ function (ssrc, isLocal, usageLabel, containerId) {
191 223
             usageLabel,
192 224
             containerId
193 225
         );
194
-        callStats.associateMstWithUserID(
195
-            this.peerconnection,
196
-            callStatsId,
197
-            this.confID,
198
-            ssrc,
199
-            usageLabel,
200
-            containerId
201
-        );
226
+        if(CallStats.initialized) {
227
+            callStats.associateMstWithUserID(
228
+                this.peerconnection,
229
+                callStatsId,
230
+                this.confID,
231
+                ssrc,
232
+                usageLabel,
233
+                containerId
234
+            );
235
+        }
236
+        else {
237
+            CallStats.reportsQueue.push({
238
+                type: reportType.MST_WITH_USERID,
239
+                data: {
240
+                    callStatsId: callStatsId,
241
+                    ssrc: ssrc,
242
+                    usageLabel: usageLabel,
243
+                    containerId: containerId
244
+                }
245
+            });
246
+        }
202 247
     }).bind(this)();
203 248
 };
204 249
 
@@ -206,6 +251,7 @@ function (ssrc, isLocal, usageLabel, containerId) {
206 251
  * Notifies CallStats for mute events
207 252
  * @param mute {boolean} true for muted and false for not muted
208 253
  * @param type {String} "audio"/"video"
254
+ * @param {CallStats} cs callstats instance related to the event
209 255
  */
210 256
 CallStats.sendMuteEvent = _try_catch(function (mute, type, cs) {
211 257
 
@@ -224,6 +270,7 @@ CallStats.sendMuteEvent = _try_catch(function (mute, type, cs) {
224 270
  * Notifies CallStats for screen sharing events
225 271
  * @param start {boolean} true for starting screen sharing and
226 272
  * false for not stopping
273
+ * @param {CallStats} cs callstats instance related to the event
227 274
  */
228 275
 CallStats.sendScreenSharingEvent = _try_catch(function (start, cs) {
229 276
 
@@ -233,6 +280,7 @@ CallStats.sendScreenSharingEvent = _try_catch(function (start, cs) {
233 280
 
234 281
 /**
235 282
  * Notifies CallStats that we are the new dominant speaker in the conference.
283
+ * @param {CallStats} cs callstats instance related to the event
236 284
  */
237 285
 CallStats.sendDominantSpeakerEvent = _try_catch(function (cs) {
238 286
 
@@ -240,21 +288,33 @@ CallStats.sendDominantSpeakerEvent = _try_catch(function (cs) {
240 288
         fabricEvent.dominantSpeaker);
241 289
 });
242 290
 
291
+/**
292
+ * Notifies CallStats about active device.
293
+ * @param {{deviceList: {String:String}}} list of devices with their data
294
+ * @param {CallStats} cs callstats instance related to the event
295
+ */
296
+CallStats.sendActiveDeviceListEvent = _try_catch(function (devicesData, cs) {
297
+
298
+    CallStats._reportEvent.call(cs, fabricEvent.activeDeviceList, devicesData);
299
+});
300
+
243 301
 /**
244 302
  * Reports an error to callstats.
245 303
  *
246 304
  * @param type the type of the error, which will be one of the wrtcFuncNames
247 305
  * @param e the error
248 306
  * @param pc the peerconnection
307
+ * @param eventData additional data to pass to event
249 308
  * @private
250 309
  */
251
-CallStats._reportEvent = function (event) {
252
-    if (callStats) {
253
-        callStats.sendFabricEvent(this.peerconnection, event, this.confID);
310
+CallStats._reportEvent = function (event, eventData) {
311
+    if (CallStats.initialized) {
312
+        callStats.sendFabricEvent(
313
+            this.peerconnection, event, this.confID, eventData);
254 314
     } else {
255 315
         CallStats.reportsQueue.push({
256 316
                 type: reportType.EVENT,
257
-                data: {event: event}
317
+                data: {event: event, eventData: eventData}
258 318
             });
259 319
     }
260 320
 };
@@ -263,7 +323,7 @@ CallStats._reportEvent = function (event) {
263 323
  * Notifies CallStats for connection setup errors
264 324
  */
265 325
 CallStats.prototype.sendTerminateEvent = _try_catch(function () {
266
-    if(!callStats) {
326
+    if(!CallStats.initialized) {
267 327
         return;
268 328
     }
269 329
     callStats.sendFabricEvent(this.peerconnection,
@@ -301,7 +361,7 @@ CallStats.prototype.sendIceConnectionFailedEvent = _try_catch(function (pc, cs){
301 361
  */
302 362
 CallStats.prototype.sendFeedback = _try_catch(
303 363
 function(overallFeedback, detailedFeedback) {
304
-    if(!callStats) {
364
+    if(!CallStats.initialized) {
305 365
         return;
306 366
     }
307 367
     var feedbackString =    '{"userID":"' + this.userID + '"' +
@@ -326,7 +386,7 @@ CallStats._reportError = function (type, e, pc) {
326 386
         logger.warn("No error is passed!");
327 387
         e = new Error("Unknown error");
328 388
     }
329
-    if (callStats) {
389
+    if (CallStats.initialized) {
330 390
         callStats.reportError(pc, this.confID, type, e);
331 391
     } else {
332 392
         CallStats.reportsQueue.push({
@@ -403,15 +463,14 @@ CallStats.sendAddIceCandidateFailed = _try_catch(function (e, pc, cs) {
403 463
 });
404 464
 
405 465
 /**
406
- * Notifies CallStats that there is an unhandled error on the page.
466
+ * Notifies CallStats that there is a log we want to report.
407 467
  *
408
- * @param {Error} e error to send
409
- * @param {RTCPeerConnection} pc connection on which failure occured.
468
+ * @param {Error} e error to send or {String} message
410 469
  * @param {CallStats} cs callstats instance related to the error (optional)
411 470
  */
412
-CallStats.sendUnhandledError = _try_catch(function (e, cs) {
471
+CallStats.sendApplicationLog = _try_catch(function (e, cs) {
413 472
     CallStats._reportError
414
-        .call(cs, wrtcFuncNames.applicationError, e, null);
473
+        .call(cs, wrtcFuncNames.applicationLog, e, null);
415 474
 });
416 475
 
417 476
 module.exports = CallStats;

+ 21
- 26
modules/statistics/statistics.js Просмотреть файл

@@ -259,6 +259,21 @@ Statistics.prototype.sendDominantSpeakerEvent = function () {
259 259
         CallStats.sendDominantSpeakerEvent(this.callstats);
260 260
 };
261 261
 
262
+/**
263
+ * Notifies about active device.
264
+ * @param {{deviceList: {String:String}}} devicesData - list of devices with
265
+ *      their data
266
+ */
267
+Statistics.sendActiveDeviceListEvent = function (devicesData) {
268
+    if (Statistics.callsStatsInstances.length) {
269
+        Statistics.callsStatsInstances.forEach(function (cs) {
270
+            CallStats.sendActiveDeviceListEvent(devicesData, cs);
271
+        });
272
+    } else {
273
+        CallStats.sendActiveDeviceListEvent(devicesData, null);
274
+    }
275
+};
276
+
262 277
 /**
263 278
  * Lets the underlying statistics module know where is given SSRC rendered by
264 279
  * providing renderer tag ID.
@@ -368,40 +383,20 @@ Statistics.prototype.sendDetectedAudioProblem = function (e) {
368 383
 };
369 384
 
370 385
 /**
371
- * Notifies CallStats that there is unhandled exception.
386
+ * Adds to CallStats an application log.
372 387
  *
373
- * @param {Error} e error to send
388
+ * @param {String} a log message to send or an {Error} object to be reported
374 389
  */
375
-Statistics.sendUnhandledError = function (e) {
390
+Statistics.sendLog = function (m) {
376 391
     if (Statistics.callsStatsInstances.length) {
377 392
         Statistics.callsStatsInstances.forEach(function (cs) {
378
-            CallStats.sendUnhandledError(e, cs);
393
+            CallStats.sendApplicationLog(m, cs);
379 394
         });
380 395
     } else {
381
-        CallStats.sendUnhandledError(e, null);
396
+        CallStats.sendApplicationLog(m, null);
382 397
     }
383 398
 };
384 399
 
385
-/**
386
- * Adds to CallStats an application log.
387
- *
388
- * @param {String} a log message to send
389
- */
390
-Statistics.sendLog = function (m) {
391
-    // uses  the same field for cs stat as unhandled error
392
-    Statistics.sendUnhandledError(m);
393
-};
394
-
395
-/**
396
- * Adds to CallStats an application log.
397
- *
398
- * @param {String} a log message to send
399
- */
400
-Statistics.prototype.sendLog = function (m) {
401
-    // uses  the same field for cs stat as unhandled error
402
-    CallStats.sendUnhandledError(m, this.callstats);
403
-};
404
-
405 400
 /**
406 401
  * Sends the given feedback through CallStats.
407 402
  *
@@ -424,7 +419,7 @@ Statistics.reportGlobalError = function (error) {
424 419
     if (error instanceof JitsiTrackError && error.gum) {
425 420
         Statistics.sendGetUserMediaFailed(error);
426 421
     } else {
427
-        Statistics.sendUnhandledError(error);
422
+        Statistics.sendLog(error);
428 423
     }
429 424
 };
430 425
 

+ 2
- 1
service/RTC/RTCEvents.js Просмотреть файл

@@ -7,7 +7,8 @@ var RTCEvents = {
7 7
     AVAILABLE_DEVICES_CHANGED: "rtc.available_devices_changed",
8 8
     TRACK_ATTACHED: "rtc.track_attached",
9 9
     AUDIO_OUTPUT_DEVICE_CHANGED: "rtc.audio_output_device_changed",
10
-    DEVICE_LIST_CHANGED: "rtc.device_list_changed"
10
+    DEVICE_LIST_CHANGED: "rtc.device_list_changed",
11
+    DEVICE_LIST_AVAILABLE: "rtc.device_list_available"
11 12
 };
12 13
 
13 14
 module.exports = RTCEvents;

Загрузка…
Отмена
Сохранить