Переглянути джерело

Integrates callstats.io API.

master
hristoterezov 10 роки тому
джерело
коміт
506312ac95

+ 3
- 0
config.js Переглянути файл

35
 //    startAudioMuted: 10, //every participant after the Nth will start audio muted
35
 //    startAudioMuted: 10, //every participant after the Nth will start audio muted
36
 //    startVideoMuted: 10, //every participant after the Nth will start video muted
36
 //    startVideoMuted: 10, //every participant after the Nth will start video muted
37
 //    defaultLanguage: "en",
37
 //    defaultLanguage: "en",
38
+// To enable sending statistics to callstats.io you should provide Applicaiton ID and Secret.
39
+//    callStatsID: "",//Application ID for callstats.io API
40
+//    callStatsSecret: ""//Secret for callstats.io API
38
     /*noticeMessage: 'Service update is scheduled for 16th March 2015. ' +
41
     /*noticeMessage: 'Service update is scheduled for 16th March 2015. ' +
39
     'During that time service will not be available. ' +
42
     'During that time service will not be available. ' +
40
     'Apologise for inconvenience.'*/
43
     'Apologise for inconvenience.'*/

+ 5
- 2
index.html Переглянути файл

9
     <meta itemprop="name" content="Jitsi Meet"/>
9
     <meta itemprop="name" content="Jitsi Meet"/>
10
     <meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
10
     <meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
12
+    <script src="https://api.callstats.io/static/callstats.min.js"></script>
12
     <script src="libs/jquery-2.1.1.min.js"></script>
13
     <script src="libs/jquery-2.1.1.min.js"></script>
13
-    <script src="config.js?v=9"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
14
+    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
15
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/1.5.0/sha.js"></script>
16
+    <script src="config.js?v=10"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
14
     <script src="libs/strophe/strophe.min.js?v=1"></script>
17
     <script src="libs/strophe/strophe.min.js?v=1"></script>
15
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
18
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
16
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
19
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
19
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
22
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
20
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
23
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
21
     <script src="interface_config.js?v=5"></script>
24
     <script src="interface_config.js?v=5"></script>
22
-    <script src="libs/app.bundle.js?v=90"></script>
25
+    <script src="libs/app.bundle.js?v=91"></script>
23
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
26
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
24
     <link rel="stylesheet" href="css/font.css?v=7"/>
27
     <link rel="stylesheet" href="css/font.css?v=7"/>
25
     <link rel="stylesheet" href="css/toastr.css?v=1">
28
     <link rel="stylesheet" href="css/toastr.css?v=1">

+ 1076
- 967
libs/app.bundle.js
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 19
- 2
modules/RTC/LocalStream.js Переглянути файл

1
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
1
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
2
+var RTCEvents = require("../../service/RTC/RTCEvents");
2
 
3
 
3
 
4
 
4
 function LocalStream(stream, type, eventEmitter, videoType, isGUMStream)
5
 function LocalStream(stream, type, eventEmitter, videoType, isGUMStream)
54
         for (var idx = 0; idx < tracks.length; idx++) {
55
         for (var idx = 0; idx < tracks.length; idx++) {
55
             tracks[idx].enabled = mute;
56
             tracks[idx].enabled = mute;
56
         }
57
         }
58
+        this.eventEmitter.emit(
59
+            (this.type == "audio"? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE),
60
+            !mute);
57
     }
61
     }
58
     else
62
     else
59
     {
63
     {
60
         if(mute === false) {
64
         if(mute === false) {
61
             APP.xmpp.removeStream(this.stream);
65
             APP.xmpp.removeStream(this.stream);
62
             this.stream.stop();
66
             this.stream.stop();
67
+            this.eventEmitter.emit(
68
+                (this.type == "audio"? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE),
69
+                true);
63
         }
70
         }
64
         else
71
         else
65
         {
72
         {
69
                 function (stream) {
76
                 function (stream) {
70
                     if(self.isAudioStream())
77
                     if(self.isAudioStream())
71
                     {
78
                     {
72
-                        APP.RTC.changeLocalAudio(stream, function () {});
79
+                        APP.RTC.changeLocalAudio(stream,
80
+                            function () {
81
+                                self.eventEmitter.emit(
82
+                                    (self.type == "audio"? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE),
83
+                                    true);
84
+                            });
73
                     }
85
                     }
74
                     else
86
                     else
75
                     {
87
                     {
76
-                        APP.RTC.changeLocalVideo(stream, false, function () {});
88
+                        APP.RTC.changeLocalVideo(stream, false,
89
+                            function () {
90
+                                self.eventEmitter.emit(
91
+                                    (self.type == "audio"? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE),
92
+                                    true);
93
+                            });
77
                     }
94
                     }
78
                 });
95
                 });
79
         }
96
         }

+ 1
- 1
modules/UI/videolayout/VideoLayout.js Переглянути файл

808
     my.onStatsStop = function () {
808
     my.onStatsStop = function () {
809
         for(var video in remoteVideos)
809
         for(var video in remoteVideos)
810
         {
810
         {
811
-            video.hideIndicator();
811
+            remoteVideos[video].hideIndicator();
812
         }
812
         }
813
         localVideoThumbnail.hideIndicator();
813
         localVideoThumbnail.hideIndicator();
814
     };
814
     };

+ 76
- 0
modules/statistics/CallStats.js Переглянути файл

1
+var callStats = null;
2
+
3
+function initCallback (err, msg) {
4
+    console.log("Initializing Status: err="+err+" msg="+msg);
5
+}
6
+
7
+var CallStats = {
8
+    init: function (jingleSession) {
9
+
10
+        if(!config.callStatsID || !config.callStatsSecret || callStats !== null)
11
+            return;
12
+
13
+        callStats = new callstats($,io,jsSHA);
14
+
15
+        this.session = jingleSession;
16
+        this.peerconnection = jingleSession.peerconnection.peerconnection;
17
+
18
+        this.userID =  APP.xmpp.myResource();
19
+
20
+        var roomJid = APP.UI.getRoomName();
21
+        this.confID = roomJid? Strophe.getNodeFromJid(roomJid) : null;
22
+
23
+        //userID is generated or given by the origin server
24
+        callStats.initialize(config.callStatsID,
25
+            config.callStatsSecret,
26
+            this.userID,
27
+            initCallback);
28
+
29
+        var usage = callStats.fabricUsage.unbundled;
30
+        if(config.useBundle)
31
+            usage = callStats.fabricUsage.multiplex;
32
+
33
+        callStats.addNewFabric(this.peerconnection,
34
+            Strophe.getResourceFromJid(jingleSession.peerjid),
35
+            usage,
36
+            this.confID,
37
+            this.pcCallback.bind(this));
38
+    },
39
+    pcCallback: function (err, msg) {
40
+        if(!callStats)
41
+            return;
42
+        console.log("Monitoring status: "+ err + " msg: " + msg);
43
+        callStats.sendFabricEvent(this.peerconnection,
44
+            callStats.fabricEvent.fabricSetup, this.confID);
45
+    },
46
+    sendMuteEvent: function (mute, type) {
47
+        if(!callStats)
48
+            return;
49
+        var event = null;
50
+        if(type === "video")
51
+        {
52
+            event = (mute? callStats.fabricEvent.videoPause :
53
+                callStats.fabricEvent.videoResume);
54
+        }
55
+        else
56
+        {
57
+            event = (mute? callStats.fabricEvent.audioMute :
58
+                callStats.fabricEvent.audioUnmute);
59
+        }
60
+        callStats.sendFabricEvent(this.peerconnection, event, this.confID);
61
+    },
62
+    sendTerminateEvent: function () {
63
+        if(!callStats)
64
+            return;
65
+        callStats.sendFabricEvent(this.peerconnection,
66
+            callStats.fabricEvent.fabricTerminated, this.confID);
67
+    },
68
+    sendSetupFailedEvent: function () {
69
+        if(!callStats)
70
+            return;
71
+        callStats.sendFabricEvent(this.peerconnection,
72
+            callStats.fabricEvent.fabricSetupFailed, this.confID);
73
+    }
74
+
75
+};
76
+module.exports = CallStats;

+ 17
- 0
modules/statistics/statistics.js Переглянути файл

6
 var EventEmitter = require("events");
6
 var EventEmitter = require("events");
7
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
7
 var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
8
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
8
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
9
+var CallStats = require("./callstats");
10
+var RTCEvents = require("../../service/RTC/RTCEvents");
9
 
11
 
10
 var eventEmitter = new EventEmitter();
12
 var eventEmitter = new EventEmitter();
11
 
13
 
54
 }
56
 }
55
 
57
 
56
 function onDisposeConference(onUnload) {
58
 function onDisposeConference(onUnload) {
59
+    CallStats.sendTerminateEvent();
57
     stopRemote();
60
     stopRemote();
58
     if(onUnload) {
61
     if(onUnload) {
59
         stopLocal();
62
         stopLocal();
119
         APP.RTC.addStreamListener(onStreamCreated,
122
         APP.RTC.addStreamListener(onStreamCreated,
120
             StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
123
             StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
121
         APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);
124
         APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);
125
+        //FIXME: we may want to change CALL INCOMING event to onnegotiationneeded
122
         APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function (event) {
126
         APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function (event) {
123
             startRemoteStats(event.peerconnection);
127
             startRemoteStats(event.peerconnection);
128
+//            CallStats.init(event);
129
+        });
130
+        APP.xmpp.addListener(XMPPEvents.PEERCONNECTION_READY, function (session) {
131
+            CallStats.init(session);
132
+        })
133
+        APP.RTC.addListener(RTCEvents.AUDIO_MUTE, function (mute) {
134
+            CallStats.sendMuteEvent(mute, "audio");
135
+        });
136
+        APP.xmpp.addListener(XMPPEvents.CONFERENCE_SETUP_FAILED, function () {
137
+            CallStats.sendSetupFailedEvent();
138
+        })
139
+        APP.RTC.addListener(RTCEvents.VIDEO_MUTE, function (mute) {
140
+            CallStats.sendMuteEvent(mute, "video");
124
         });
141
         });
125
     }
142
     }
126
 
143
 

+ 17
- 3
modules/xmpp/JingleSession.js Переглянути файл

3
 var SDPDiffer = require("./SDPDiffer");
3
 var SDPDiffer = require("./SDPDiffer");
4
 var SDPUtil = require("./SDPUtil");
4
 var SDPUtil = require("./SDPUtil");
5
 var SDP = require("./SDP");
5
 var SDP = require("./SDP");
6
-var RTCBrowserType = require("../../service/RTC/RTCBrowserType");
7
 var async = require("async");
6
 var async = require("async");
8
 var transform = require("sdp-transform");
7
 var transform = require("sdp-transform");
8
+var XMPPEvents = require("../../service/xmpp/XMPPEvents");
9
 
9
 
10
 // Jingle stuff
10
 // Jingle stuff
11
-function JingleSession(me, sid, connection, service) {
11
+function JingleSession(me, sid, connection, service, eventEmitter) {
12
     this.me = me;
12
     this.me = me;
13
     this.sid = sid;
13
     this.sid = sid;
14
     this.connection = connection;
14
     this.connection = connection;
47
 
47
 
48
     this.wait = true;
48
     this.wait = true;
49
     this.localStreamsSSRC = null;
49
     this.localStreamsSSRC = null;
50
+    this.eventEmitter = eventEmitter;
50
 
51
 
51
     /**
52
     /**
52
      * The indicator which determines whether the (local) video has been muted
53
      * The indicator which determines whether the (local) video has been muted
89
     this.peerconnection
90
     this.peerconnection
90
         = new TraceablePeerConnection(
91
         = new TraceablePeerConnection(
91
             this.connection.jingle.ice_config,
92
             this.connection.jingle.ice_config,
92
-            this.connection.jingle.pc_constraints );
93
+            this.connection.jingle.pc_constraints,
94
+            this);
93
 
95
 
94
     this.peerconnection.onicecandidate = function (event) {
96
     this.peerconnection.onicecandidate = function (event) {
95
         self.sendIceCandidate(event.candidate);
97
         self.sendIceCandidate(event.candidate);
125
             case 'disconnected':
127
             case 'disconnected':
126
                 this.stopTime = new Date();
128
                 this.stopTime = new Date();
127
                 break;
129
                 break;
130
+            case 'failed':
131
+                self.eventEmitter(XMPPEvents.CONFERENCE_SETUP_FAILED);
132
+                break;
128
         }
133
         }
129
         onIceConnectionStateChange(self.sid, self);
134
         onIceConnectionStateChange(self.sid, self);
130
     };
135
     };
136
+    this.peerconnection.onnegotiationneeded = function (event) {
137
+        self.eventEmitter.emit(XMPPEvents.PEERCONNECTION_READY, self);
138
+    };
131
     // add any local and relayed stream
139
     // add any local and relayed stream
132
     APP.RTC.localStreams.forEach(function(stream) {
140
     APP.RTC.localStreams.forEach(function(stream) {
133
         self.peerconnection.addStream(stream.getOriginalStream());
141
         self.peerconnection.addStream(stream.getOriginalStream());
238
         },
246
         },
239
         function (e) {
247
         function (e) {
240
             console.error('setLocalDescription failed', e);
248
             console.error('setLocalDescription failed', e);
249
+            self.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
241
         }
250
         }
242
     );
251
     );
243
 };
252
 };
448
         },
457
         },
449
         function (e) {
458
         function (e) {
450
             console.error('setLocalDescription failed', e);
459
             console.error('setLocalDescription failed', e);
460
+            self.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
451
         }
461
         }
452
     );
462
     );
453
     var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
463
     var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
622
         },
632
         },
623
         function (e) {
633
         function (e) {
624
             console.error('createAnswer failed', e);
634
             console.error('createAnswer failed', e);
635
+            self.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
625
         },
636
         },
626
         this.media_constraints
637
         this.media_constraints
627
     );
638
     );
681
         },
692
         },
682
         function (e) {
693
         function (e) {
683
             console.error('setLocalDescription failed', e);
694
             console.error('setLocalDescription failed', e);
695
+            self.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
684
         }
696
         }
685
     );
697
     );
686
     var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
698
     var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
1232
     this.connection.emuc.doLeave();
1244
     this.connection.emuc.doLeave();
1233
     APP.UI.messageHandler.showError("dialog.sorry",
1245
     APP.UI.messageHandler.showError("dialog.sorry",
1234
         "dialog.internalError");
1246
         "dialog.internalError");
1247
+    this.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
1235
 }
1248
 }
1236
 
1249
 
1237
 JingleSession.prototype.setLocalDescription = function () {
1250
 JingleSession.prototype.setLocalDescription = function () {
1287
 function sendKeyframe(pc) {
1300
 function sendKeyframe(pc) {
1288
     console.log('sendkeyframe', pc.iceConnectionState);
1301
     console.log('sendkeyframe', pc.iceConnectionState);
1289
     if (pc.iceConnectionState !== 'connected') return; // safe...
1302
     if (pc.iceConnectionState !== 'connected') return; // safe...
1303
+    var self = this;
1290
     pc.setRemoteDescription(
1304
     pc.setRemoteDescription(
1291
         pc.remoteDescription,
1305
         pc.remoteDescription,
1292
         function () {
1306
         function () {

+ 3
- 1
modules/xmpp/TraceablePeerConnection.js Переглянути файл

1
-function TraceablePeerConnection(ice_config, constraints) {
1
+var XMPPEvents = require("../../service/xmpp/XMPPEvents");
2
+
3
+function TraceablePeerConnection(ice_config, constraints, session) {
2
     var self = this;
4
     var self = this;
3
     var RTCPeerconnection = navigator.mozGetUserMedia ? mozRTCPeerConnection : webkitRTCPeerConnection;
5
     var RTCPeerconnection = navigator.mozGetUserMedia ? mozRTCPeerConnection : webkitRTCPeerConnection;
4
     this.peerconnection = new RTCPeerconnection(ice_config, constraints);
6
     this.peerconnection = new RTCPeerconnection(ice_config, constraints);

+ 2
- 2
modules/xmpp/strophe.jingle.js Переглянути файл

119
                     }
119
                     }
120
                     sess = new JingleSession(
120
                     sess = new JingleSession(
121
                         $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
121
                         $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
122
-                        this.connection, XMPP);
122
+                        this.connection, XMPP, eventEmitter);
123
                     // configure session
123
                     // configure session
124
 
124
 
125
                     sess.media_constraints = this.media_constraints;
125
                     sess.media_constraints = this.media_constraints;
199
         initiate: function (peerjid, myjid) { // initiate a new jinglesession to peerjid
199
         initiate: function (peerjid, myjid) { // initiate a new jinglesession to peerjid
200
             var sess = new JingleSession(myjid || this.connection.jid,
200
             var sess = new JingleSession(myjid || this.connection.jid,
201
                 Math.random().toString(36).substr(2, 12), // random string
201
                 Math.random().toString(36).substr(2, 12), // random string
202
-                this.connection, XMPP);
202
+                this.connection, XMPP, eventEmitter);
203
             // configure session
203
             // configure session
204
 
204
 
205
             sess.media_constraints = this.media_constraints;
205
             sess.media_constraints = this.media_constraints;

+ 1
- 1
modules/xmpp/xmpp.js Переглянути файл

315
         return Strophe.getResourceFromJid(connection.emuc.myroomjid);
315
         return Strophe.getResourceFromJid(connection.emuc.myroomjid);
316
     },
316
     },
317
     disposeConference: function (onUnload) {
317
     disposeConference: function (onUnload) {
318
-        eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE, onUnload);
319
         var handler = connection.jingle.activecall;
318
         var handler = connection.jingle.activecall;
320
         if (handler && handler.peerconnection) {
319
         if (handler && handler.peerconnection) {
321
             // FIXME: probably removing streams is not required and close() should
320
             // FIXME: probably removing streams is not required and close() should
330
             }
329
             }
331
             handler.peerconnection.close();
330
             handler.peerconnection.close();
332
         }
331
         }
332
+        eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE, onUnload);
333
         connection.jingle.activecall = null;
333
         connection.jingle.activecall = null;
334
         if(!onUnload)
334
         if(!onUnload)
335
         {
335
         {

+ 3
- 1
service/RTC/RTCEvents.js Переглянути файл

2
     LASTN_CHANGED: "rtc.lastn_changed",
2
     LASTN_CHANGED: "rtc.lastn_changed",
3
     DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed",
3
     DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed",
4
     LASTN_ENDPOINT_CHANGED: "rtc.lastn_endpoint_changed",
4
     LASTN_ENDPOINT_CHANGED: "rtc.lastn_endpoint_changed",
5
-    AVAILABLE_DEVICES_CHANGED: "rtc.available_devices_changed"
5
+    AVAILABLE_DEVICES_CHANGED: "rtc.available_devices_changed",
6
+    AUDIO_MUTE: "rtc.audio_mute",
7
+    VIDEO_MUTE: "rtc.video_mute"
6
 };
8
 };
7
 
9
 
8
 module.exports = RTCEvents;
10
 module.exports = RTCEvents;

+ 3
- 2
service/xmpp/XMPPEvents.js Переглянути файл

1
 var XMPPEvents = {
1
 var XMPPEvents = {
2
     CONNECTION_FAILED: "xmpp.connection.failed",
2
     CONNECTION_FAILED: "xmpp.connection.failed",
3
     CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle",
3
     CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle",
4
-    CALL_TERMINATED: "xmpp.callterminated.jingle",
5
     CALL_INCOMING: "xmpp.callincoming.jingle",
4
     CALL_INCOMING: "xmpp.callincoming.jingle",
6
     DISPOSE_CONFERENCE: "xmpp.dispose_conference",
5
     DISPOSE_CONFERENCE: "xmpp.dispose_conference",
7
     GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
6
     GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
30
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
29
     CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
31
     ETHERPAD: "xmpp.etherpad",
30
     ETHERPAD: "xmpp.etherpad",
32
     DEVICE_AVAILABLE: "xmpp.device_available",
31
     DEVICE_AVAILABLE: "xmpp.device_available",
33
-    START_MUTED: "xmpp.start_muted"
32
+    START_MUTED: "xmpp.start_muted",
33
+    PEERCONNECTION_READY: "xmpp.peerconnection_ready",
34
+    CONFERENCE_SETUP_FAILED: "xmpp.conference_setup_failed"
34
 };
35
 };
35
 module.exports = XMPPEvents;
36
 module.exports = XMPPEvents;

Завантаження…
Відмінити
Зберегти