use statistics module from the library
This commit is contained in:
parent
103b5d71d0
commit
d19789005e
6
app.js
6
app.js
|
@ -17,7 +17,6 @@ import URLProcessor from "./modules/config/URLProcessor";
|
||||||
import RoomnameGenerator from './modules/util/RoomnameGenerator';
|
import RoomnameGenerator from './modules/util/RoomnameGenerator';
|
||||||
|
|
||||||
import UI from "./modules/UI/UI";
|
import UI from "./modules/UI/UI";
|
||||||
import statistics from "./modules/statistics/statistics";
|
|
||||||
import settings from "./modules/settings/Settings";
|
import settings from "./modules/settings/Settings";
|
||||||
import conference from './conference';
|
import conference from './conference';
|
||||||
import API from './modules/API/API';
|
import API from './modules/API/API';
|
||||||
|
@ -59,13 +58,10 @@ function buildRoomName () {
|
||||||
|
|
||||||
const APP = {
|
const APP = {
|
||||||
UI,
|
UI,
|
||||||
statistics,
|
|
||||||
settings,
|
settings,
|
||||||
conference,
|
conference,
|
||||||
API,
|
API,
|
||||||
init () {
|
init () {
|
||||||
this.connectionquality =
|
|
||||||
require("./modules/connectionquality/connectionquality");
|
|
||||||
this.desktopsharing =
|
this.desktopsharing =
|
||||||
require("./modules/desktopsharing/desktopsharing");
|
require("./modules/desktopsharing/desktopsharing");
|
||||||
this.keyboardshortcut =
|
this.keyboardshortcut =
|
||||||
|
@ -87,8 +83,6 @@ function init() {
|
||||||
});
|
});
|
||||||
|
|
||||||
APP.desktopsharing.init(JitsiMeetJS.isDesktopSharingEnabled());
|
APP.desktopsharing.init(JitsiMeetJS.isDesktopSharingEnabled());
|
||||||
APP.statistics.start();
|
|
||||||
APP.connectionquality.init();
|
|
||||||
APP.keyboardshortcut.init();
|
APP.keyboardshortcut.init();
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -5,6 +5,8 @@ import createRoomLocker from './modules/UI/authentication/RoomLocker';
|
||||||
//FIXME:
|
//FIXME:
|
||||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||||
|
|
||||||
|
import ConnectionQuality from './modules/connectionquality/connectionquality';
|
||||||
|
|
||||||
import CQEvents from './service/connectionquality/CQEvents';
|
import CQEvents from './service/connectionquality/CQEvents';
|
||||||
import UIEvents from './service/UI/UIEvents';
|
import UIEvents from './service/UI/UIEvents';
|
||||||
import DSEvents from './service/desktopsharing/DesktopSharingEventTypes';
|
import DSEvents from './service/desktopsharing/DesktopSharingEventTypes';
|
||||||
|
@ -154,6 +156,7 @@ class ConferenceConnector {
|
||||||
case ConferenceErrors.CONFERENCE_DESTROYED:
|
case ConferenceErrors.CONFERENCE_DESTROYED:
|
||||||
{
|
{
|
||||||
let [reason] = params;
|
let [reason] = params;
|
||||||
|
APP.UI.hideStats();
|
||||||
APP.UI.notifyConferenceDestroyed(reason);
|
APP.UI.notifyConferenceDestroyed(reason);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -556,6 +559,7 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
room.on(ConferenceEvents.KICKED, () => {
|
room.on(ConferenceEvents.KICKED, () => {
|
||||||
|
APP.UI.hideStats();
|
||||||
APP.UI.notifyKicked();
|
APP.UI.notifyKicked();
|
||||||
// FIXME close
|
// FIXME close
|
||||||
});
|
});
|
||||||
|
@ -599,14 +603,17 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
APP.connectionquality.addListener(
|
room.on(ConferenceEvents.CONNECTION_STATS, function (stats) {
|
||||||
|
ConnectionQuality.updateLocalStats(stats);
|
||||||
|
});
|
||||||
|
ConnectionQuality.addListener(
|
||||||
CQEvents.LOCALSTATS_UPDATED,
|
CQEvents.LOCALSTATS_UPDATED,
|
||||||
(percent, stats) => {
|
(percent, stats) => {
|
||||||
APP.UI.updateLocalStats(percent, stats);
|
APP.UI.updateLocalStats(percent, stats);
|
||||||
|
|
||||||
// send local stats to other users
|
// send local stats to other users
|
||||||
room.sendCommandOnce(Commands.CONNECTION_QUALITY, {
|
room.sendCommandOnce(Commands.CONNECTION_QUALITY, {
|
||||||
children: APP.connectionquality.convertToMUCStats(stats),
|
children: ConnectionQuality.convertToMUCStats(stats),
|
||||||
attributes: {
|
attributes: {
|
||||||
xmlns: 'http://jitsi.org/jitmeet/stats'
|
xmlns: 'http://jitsi.org/jitmeet/stats'
|
||||||
}
|
}
|
||||||
|
@ -614,17 +621,12 @@ export default {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
APP.connectionquality.addListener(CQEvents.STOP, () => {
|
|
||||||
APP.UI.hideStats();
|
|
||||||
room.removeCommand(Commands.CONNECTION_QUALITY);
|
|
||||||
});
|
|
||||||
|
|
||||||
// listen to remote stats
|
// listen to remote stats
|
||||||
room.addCommandListener(Commands.CONNECTION_QUALITY,(values, from) => {
|
room.addCommandListener(Commands.CONNECTION_QUALITY,(values, from) => {
|
||||||
APP.connectionquality.updateRemoteStats(from, values);
|
ConnectionQuality.updateRemoteStats(from, values);
|
||||||
});
|
});
|
||||||
|
|
||||||
APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,
|
ConnectionQuality.addListener(CQEvents.REMOTESTATS_UPDATED,
|
||||||
(id, percent, stats) => {
|
(id, percent, stats) => {
|
||||||
APP.UI.updateRemoteStats(id, percent, stats);
|
APP.UI.updateRemoteStats(id, percent, stats);
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,7 +59,7 @@ ConnectionIndicator.getStringFromArray = function (array) {
|
||||||
* @returns {string} the html content.
|
* @returns {string} the html content.
|
||||||
*/
|
*/
|
||||||
ConnectionIndicator.prototype.generateText = function () {
|
ConnectionIndicator.prototype.generateText = function () {
|
||||||
var downloadBitrate, uploadBitrate, packetLoss, resolution, i;
|
var downloadBitrate, uploadBitrate, packetLoss, i;
|
||||||
|
|
||||||
var translate = APP.translation.translateString;
|
var translate = APP.translation.translateString;
|
||||||
|
|
||||||
|
@ -86,44 +86,12 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
"%";
|
"%";
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolutionValue = null;
|
// GENERATE RESOLUTIONS STRING
|
||||||
if(this.resolution && this.id) {
|
let resolutions = this.resolution || {};
|
||||||
var keys = Object.keys(this.resolution);
|
let resolutionStr = Object.keys(resolutions).map(function (ssrc) {
|
||||||
for(var ssrc in this.resolution) {
|
let {width, height} = resolutions[ssrc];
|
||||||
// skip resolutions for ssrc that don't have this info
|
return `${width}x${height}`;
|
||||||
// like receive-only ssrc for FF
|
}).join(', ') || 'N/A';
|
||||||
if(this.resolution[ssrc]
|
|
||||||
&& this.resolution[ssrc].height != -1
|
|
||||||
&& this.resolution[ssrc].width != -1)
|
|
||||||
resolutionValue = this.resolution[ssrc];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.id === null) {
|
|
||||||
resolution = "";
|
|
||||||
if(this.resolution === null || !Object.keys(this.resolution) ||
|
|
||||||
Object.keys(this.resolution).length === 0) {
|
|
||||||
resolution = "N/A";
|
|
||||||
} else {
|
|
||||||
for (i in this.resolution) {
|
|
||||||
resolutionValue = this.resolution[i];
|
|
||||||
if (resolutionValue) {
|
|
||||||
if (resolutionValue.height &&
|
|
||||||
resolutionValue.width) {
|
|
||||||
resolution += (resolution === "" ? "" : ", ") +
|
|
||||||
resolutionValue.width + "x" +
|
|
||||||
resolutionValue.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(!resolutionValue ||
|
|
||||||
!resolutionValue.height ||
|
|
||||||
!resolutionValue.width) {
|
|
||||||
resolution = "N/A";
|
|
||||||
} else {
|
|
||||||
resolution = resolutionValue.width + "x" + resolutionValue.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = "<table style='width:100%'>" +
|
var result = "<table style='width:100%'>" +
|
||||||
"<tr>" +
|
"<tr>" +
|
||||||
|
@ -139,7 +107,7 @@ ConnectionIndicator.prototype.generateText = function () {
|
||||||
"</tr><tr>" +
|
"</tr><tr>" +
|
||||||
"<td><span class='jitsipopover_blue' data-i18n='connectionindicator.resolution'>" +
|
"<td><span class='jitsipopover_blue' data-i18n='connectionindicator.resolution'>" +
|
||||||
translate("connectionindicator.resolution") + "</span></td>" +
|
translate("connectionindicator.resolution") + "</span></td>" +
|
||||||
"<td>" + resolution + "</td></tr></table>";
|
"<td>" + resolutionStr + "</td></tr></table>";
|
||||||
|
|
||||||
if(this.videoContainer.videoSpanId == "localVideoContainer") {
|
if(this.videoContainer.videoSpanId == "localVideoContainer") {
|
||||||
result += "<div class=\"jitsipopover_showmore\" " +
|
result += "<div class=\"jitsipopover_showmore\" " +
|
||||||
|
|
|
@ -728,13 +728,9 @@ var VideoLayout = {
|
||||||
* @param object
|
* @param object
|
||||||
*/
|
*/
|
||||||
updateLocalConnectionStats (percent, object) {
|
updateLocalConnectionStats (percent, object) {
|
||||||
let resolutions = {};
|
let resolutions = object.resolution;
|
||||||
if (object.resolution !== null) {
|
|
||||||
resolutions = object.resolution;
|
object.resolution = resolutions[APP.conference.localId];
|
||||||
var id = Strophe.getResourceFromJid(
|
|
||||||
APP.conference._room.room.session.me);
|
|
||||||
object.resolution = resolutions[id];
|
|
||||||
}
|
|
||||||
localVideoThumbnail.updateStatsIndicator(percent, object);
|
localVideoThumbnail.updateStatsIndicator(percent, object);
|
||||||
|
|
||||||
Object.keys(resolutions).forEach(function (id) {
|
Object.keys(resolutions).forEach(function (id) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
/* global APP, require */
|
/* global APP, require */
|
||||||
/* jshint -W101 */
|
/* jshint -W101 */
|
||||||
var EventEmitter = require("events");
|
import EventEmitter from "events";
|
||||||
var eventEmitter = new EventEmitter();
|
|
||||||
var CQEvents = require("../../service/connectionquality/CQEvents");
|
import CQEvents from "../../service/connectionquality/CQEvents";
|
||||||
var StatisticsEvents = require("../../service/statistics/Events");
|
|
||||||
|
const eventEmitter = new EventEmitter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* local stats
|
* local stats
|
||||||
|
@ -50,16 +51,7 @@ function parseMUCStats(stats) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var ConnectionQuality = {
|
export default {
|
||||||
init: function () {
|
|
||||||
APP.statistics.addListener(
|
|
||||||
StatisticsEvents.CONNECTION_STATS, this.updateLocalStats
|
|
||||||
);
|
|
||||||
APP.statistics.addListener(
|
|
||||||
StatisticsEvents.STOP, this.stopSendingStats
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the local statistics
|
* Updates the local statistics
|
||||||
* @param data new statistics
|
* @param data new statistics
|
||||||
|
@ -87,14 +79,6 @@ var ConnectionQuality = {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops statistics sending.
|
|
||||||
*/
|
|
||||||
stopSendingStats: function () {
|
|
||||||
//notify UI about stopping statistics gathering
|
|
||||||
eventEmitter.emit(CQEvents.STOP);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the local statistics.
|
* Returns the local statistics.
|
||||||
*/
|
*/
|
||||||
|
@ -125,5 +109,3 @@ var ConnectionQuality = {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = ConnectionQuality;
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global config JitsiMeetJS */
|
/* global config, JitsiMeetJS */
|
||||||
|
|
||||||
// Load the integration of a third-party analytics API such as Google Analytics.
|
// Load the integration of a third-party analytics API such as Google Analytics.
|
||||||
// Since we cannot guarantee the quality of the third-party service (e.g. their
|
// Since we cannot guarantee the quality of the third-party service (e.g. their
|
||||||
|
|
|
@ -1,664 +0,0 @@
|
||||||
/* global require, ssrc2jid */
|
|
||||||
/* jshint -W117 */
|
|
||||||
/* jshint -W101 */
|
|
||||||
var RTCBrowserType = require("../RTC/RTCBrowserType");
|
|
||||||
var StatisticsEvents = require("../../service/statistics/Events");
|
|
||||||
|
|
||||||
/* Whether we support the browser we are running into for logging statistics */
|
|
||||||
var browserSupported = RTCBrowserType.isChrome() ||
|
|
||||||
RTCBrowserType.isOpera() || RTCBrowserType.isFirefox();
|
|
||||||
/**
|
|
||||||
* Calculates packet lost percent using the number of lost packets and the
|
|
||||||
* number of all packet.
|
|
||||||
* @param lostPackets the number of lost packets
|
|
||||||
* @param totalPackets the number of all packets.
|
|
||||||
* @returns {number} packet loss percent
|
|
||||||
*/
|
|
||||||
function calculatePacketLoss(lostPackets, totalPackets) {
|
|
||||||
if(!totalPackets || totalPackets <= 0 || !lostPackets || lostPackets <= 0)
|
|
||||||
return 0;
|
|
||||||
return Math.round((lostPackets/totalPackets)*100);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatValue(item, name) {
|
|
||||||
var browserType = RTCBrowserType.getBrowserType();
|
|
||||||
if (!keyMap[browserType][name])
|
|
||||||
throw "The property isn't supported!";
|
|
||||||
var key = keyMap[browserType][name];
|
|
||||||
return (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) ?
|
|
||||||
item.stat(key) : item[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Peer statistics data holder.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function PeerStats()
|
|
||||||
{
|
|
||||||
this.ssrc2Loss = {};
|
|
||||||
this.ssrc2AudioLevel = {};
|
|
||||||
this.ssrc2bitrate = {};
|
|
||||||
this.ssrc2resolution = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The bandwidth
|
|
||||||
* @type {{}}
|
|
||||||
*/
|
|
||||||
PeerStats.bandwidth = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The bit rate
|
|
||||||
* @type {{}}
|
|
||||||
*/
|
|
||||||
PeerStats.bitrate = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The packet loss rate
|
|
||||||
* @type {{}}
|
|
||||||
*/
|
|
||||||
PeerStats.packetLoss = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets packets loss rate for given <tt>ssrc</tt> that blong to the peer
|
|
||||||
* represented by this instance.
|
|
||||||
* @param ssrc audio or video RTP stream SSRC.
|
|
||||||
* @param lossRate new packet loss rate value to be set.
|
|
||||||
*/
|
|
||||||
PeerStats.prototype.setSsrcLoss = function (ssrc, lossRate)
|
|
||||||
{
|
|
||||||
this.ssrc2Loss[ssrc] = lossRate;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets resolution for given <tt>ssrc</tt> that belong to the peer
|
|
||||||
* represented by this instance.
|
|
||||||
* @param ssrc audio or video RTP stream SSRC.
|
|
||||||
* @param resolution new resolution value to be set.
|
|
||||||
*/
|
|
||||||
PeerStats.prototype.setSsrcResolution = function (ssrc, resolution)
|
|
||||||
{
|
|
||||||
if(resolution === null && this.ssrc2resolution[ssrc])
|
|
||||||
{
|
|
||||||
delete this.ssrc2resolution[ssrc];
|
|
||||||
}
|
|
||||||
else if(resolution !== null)
|
|
||||||
this.ssrc2resolution[ssrc] = resolution;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the bit rate for given <tt>ssrc</tt> that blong to the peer
|
|
||||||
* represented by this instance.
|
|
||||||
* @param ssrc audio or video RTP stream SSRC.
|
|
||||||
* @param bitrate new bitrate value to be set.
|
|
||||||
*/
|
|
||||||
PeerStats.prototype.setSsrcBitrate = function (ssrc, bitrate)
|
|
||||||
{
|
|
||||||
if(this.ssrc2bitrate[ssrc])
|
|
||||||
{
|
|
||||||
this.ssrc2bitrate[ssrc].download += bitrate.download;
|
|
||||||
this.ssrc2bitrate[ssrc].upload += bitrate.upload;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.ssrc2bitrate[ssrc] = bitrate;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets new audio level(input or output) for given <tt>ssrc</tt> that identifies
|
|
||||||
* the stream which belongs to the peer represented by this instance.
|
|
||||||
* @param ssrc RTP stream SSRC for which current audio level value will be
|
|
||||||
* updated.
|
|
||||||
* @param audioLevel the new audio level value to be set. Value is truncated to
|
|
||||||
* fit the range from 0 to 1.
|
|
||||||
*/
|
|
||||||
PeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)
|
|
||||||
{
|
|
||||||
// Range limit 0 - 1
|
|
||||||
this.ssrc2AudioLevel[ssrc] = formatAudioLevel(audioLevel);
|
|
||||||
};
|
|
||||||
|
|
||||||
function formatAudioLevel(audioLevel) {
|
|
||||||
return Math.min(Math.max(audioLevel, 0), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array with the transport information.
|
|
||||||
* @type {Array}
|
|
||||||
*/
|
|
||||||
PeerStats.transport = [];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <tt>StatsCollector</tt> registers for stats updates of given
|
|
||||||
* <tt>peerconnection</tt> in given <tt>interval</tt>. On each update particular
|
|
||||||
* stats are extracted and put in {@link PeerStats} objects. Once the processing
|
|
||||||
* is done <tt>audioLevelsUpdateCallback</tt> is called with <tt>this</tt>
|
|
||||||
* instance as an event source.
|
|
||||||
*
|
|
||||||
* @param peerconnection webRTC peer connection object.
|
|
||||||
* @param interval stats refresh interval given in ms.
|
|
||||||
* @param {function(StatsCollector)} audioLevelsUpdateCallback the callback
|
|
||||||
* called on stats update.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function StatsCollector(peerconnection, audioLevelsInterval, statsInterval, eventEmitter)
|
|
||||||
{
|
|
||||||
this.peerconnection = peerconnection;
|
|
||||||
this.baselineAudioLevelsReport = null;
|
|
||||||
this.currentStatsReport = null;
|
|
||||||
this.baselineStatsReport = null;
|
|
||||||
this.audioLevelsIntervalId = null;
|
|
||||||
this.eventEmitter = eventEmitter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gather PeerConnection stats once every this many milliseconds.
|
|
||||||
*/
|
|
||||||
this.GATHER_INTERVAL = 15000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log stats via the focus once every this many milliseconds.
|
|
||||||
*/
|
|
||||||
this.LOG_INTERVAL = 60000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gather stats and store them in this.statsToBeLogged.
|
|
||||||
*/
|
|
||||||
this.gatherStatsIntervalId = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the stats already saved in this.statsToBeLogged to be logged via
|
|
||||||
* the focus.
|
|
||||||
*/
|
|
||||||
this.logStatsIntervalId = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the statistics which will be send to the focus to be logged.
|
|
||||||
*/
|
|
||||||
this.statsToBeLogged =
|
|
||||||
{
|
|
||||||
timestamps: [],
|
|
||||||
stats: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Updates stats interval
|
|
||||||
this.audioLevelsIntervalMilis = audioLevelsInterval;
|
|
||||||
|
|
||||||
this.statsIntervalId = null;
|
|
||||||
this.statsIntervalMilis = statsInterval;
|
|
||||||
// Map of jids to PeerStats
|
|
||||||
this.jid2stats = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = StatsCollector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops stats updates.
|
|
||||||
*/
|
|
||||||
StatsCollector.prototype.stop = function () {
|
|
||||||
if (this.audioLevelsIntervalId) {
|
|
||||||
clearInterval(this.audioLevelsIntervalId);
|
|
||||||
this.audioLevelsIntervalId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.statsIntervalId)
|
|
||||||
{
|
|
||||||
clearInterval(this.statsIntervalId);
|
|
||||||
this.statsIntervalId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.logStatsIntervalId)
|
|
||||||
{
|
|
||||||
clearInterval(this.logStatsIntervalId);
|
|
||||||
this.logStatsIntervalId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.gatherStatsIntervalId)
|
|
||||||
{
|
|
||||||
clearInterval(this.gatherStatsIntervalId);
|
|
||||||
this.gatherStatsIntervalId = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback passed to <tt>getStats</tt> method.
|
|
||||||
* @param error an error that occurred on <tt>getStats</tt> call.
|
|
||||||
*/
|
|
||||||
StatsCollector.prototype.errorCallback = function (error)
|
|
||||||
{
|
|
||||||
console.error("Get stats error", error);
|
|
||||||
this.stop();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts stats updates.
|
|
||||||
*/
|
|
||||||
StatsCollector.prototype.start = function ()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
if (!config.disableAudioLevels) {
|
|
||||||
this.audioLevelsIntervalId = setInterval(
|
|
||||||
function () {
|
|
||||||
// Interval updates
|
|
||||||
self.peerconnection.getStats(
|
|
||||||
function (report) {
|
|
||||||
var results = null;
|
|
||||||
if (!report || !report.result ||
|
|
||||||
typeof report.result != 'function') {
|
|
||||||
results = report;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
results = report.result();
|
|
||||||
}
|
|
||||||
//console.error("Got interval report", results);
|
|
||||||
self.baselineAudioLevelsReport = results;
|
|
||||||
},
|
|
||||||
self.errorCallback
|
|
||||||
);
|
|
||||||
},
|
|
||||||
self.audioLevelsIntervalMilis
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.disableStats && browserSupported) {
|
|
||||||
this.statsIntervalId = setInterval(
|
|
||||||
function () {
|
|
||||||
// Interval updates
|
|
||||||
self.peerconnection.getStats(
|
|
||||||
function (report) {
|
|
||||||
var results = null;
|
|
||||||
if (!report || !report.result ||
|
|
||||||
typeof report.result != 'function') {
|
|
||||||
//firefox
|
|
||||||
results = report;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//chrome
|
|
||||||
results = report.result();
|
|
||||||
}
|
|
||||||
//console.error("Got interval report", results);
|
|
||||||
self.currentStatsReport = results;
|
|
||||||
try {
|
|
||||||
self.processStatsReport();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error("Unsupported key:" + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.baselineStatsReport = self.currentStatsReport;
|
|
||||||
},
|
|
||||||
self.errorCallback
|
|
||||||
);
|
|
||||||
},
|
|
||||||
self.statsIntervalMilis
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logging statistics does not support firefox
|
|
||||||
if (config.logStats && (browserSupported && !RTCBrowserType.isFirefox())) {
|
|
||||||
this.gatherStatsIntervalId = setInterval(
|
|
||||||
function () {
|
|
||||||
self.peerconnection.getStats(
|
|
||||||
function (report) {
|
|
||||||
self.addStatsToBeLogged(report.result());
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
this.GATHER_INTERVAL
|
|
||||||
);
|
|
||||||
|
|
||||||
this.logStatsIntervalId = setInterval(
|
|
||||||
function() { self.logStats(); },
|
|
||||||
this.LOG_INTERVAL);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a certain record should be included in the logged statistics.
|
|
||||||
*/
|
|
||||||
function acceptStat(reportId, reportType, statName) {
|
|
||||||
if (reportType == "googCandidatePair" && statName == "googChannelId")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (reportType == "ssrc") {
|
|
||||||
if (statName == "googTrackId" ||
|
|
||||||
statName == "transportId" ||
|
|
||||||
statName == "ssrc")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a certain record should be included in the logged statistics.
|
|
||||||
*/
|
|
||||||
function acceptReport(id, type) {
|
|
||||||
if (id.substring(0, 15) == "googCertificate" ||
|
|
||||||
id.substring(0, 9) == "googTrack" ||
|
|
||||||
id.substring(0, 20) == "googLibjingleSession")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (type == "googComponent")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the stats to the format used for logging, and saves the data in
|
|
||||||
* this.statsToBeLogged.
|
|
||||||
* @param reports Reports as given by webkitRTCPerConnection.getStats.
|
|
||||||
*/
|
|
||||||
StatsCollector.prototype.addStatsToBeLogged = function (reports) {
|
|
||||||
var self = this;
|
|
||||||
var num_records = this.statsToBeLogged.timestamps.length;
|
|
||||||
this.statsToBeLogged.timestamps.push(new Date().getTime());
|
|
||||||
reports.map(function (report) {
|
|
||||||
if (!acceptReport(report.id, report.type))
|
|
||||||
return;
|
|
||||||
var stat = self.statsToBeLogged.stats[report.id];
|
|
||||||
if (!stat) {
|
|
||||||
stat = self.statsToBeLogged.stats[report.id] = {};
|
|
||||||
}
|
|
||||||
stat.type = report.type;
|
|
||||||
report.names().map(function (name) {
|
|
||||||
if (!acceptStat(report.id, report.type, name))
|
|
||||||
return;
|
|
||||||
var values = stat[name];
|
|
||||||
if (!values) {
|
|
||||||
values = stat[name] = [];
|
|
||||||
}
|
|
||||||
while (values.length < num_records) {
|
|
||||||
values.push(null);
|
|
||||||
}
|
|
||||||
values.push(report.stat(name));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
StatsCollector.prototype.logStats = function () {
|
|
||||||
|
|
||||||
if(!APP.conference._room.xmpp.sendLogs(this.statsToBeLogged))
|
|
||||||
return;
|
|
||||||
// Reset the stats
|
|
||||||
this.statsToBeLogged.stats = {};
|
|
||||||
this.statsToBeLogged.timestamps = [];
|
|
||||||
};
|
|
||||||
var keyMap = {};
|
|
||||||
keyMap[RTCBrowserType.RTC_BROWSER_FIREFOX] = {
|
|
||||||
"ssrc": "ssrc",
|
|
||||||
"packetsReceived": "packetsReceived",
|
|
||||||
"packetsLost": "packetsLost",
|
|
||||||
"packetsSent": "packetsSent",
|
|
||||||
"bytesReceived": "bytesReceived",
|
|
||||||
"bytesSent": "bytesSent"
|
|
||||||
};
|
|
||||||
keyMap[RTCBrowserType.RTC_BROWSER_CHROME] = {
|
|
||||||
"receiveBandwidth": "googAvailableReceiveBandwidth",
|
|
||||||
"sendBandwidth": "googAvailableSendBandwidth",
|
|
||||||
"remoteAddress": "googRemoteAddress",
|
|
||||||
"transportType": "googTransportType",
|
|
||||||
"localAddress": "googLocalAddress",
|
|
||||||
"activeConnection": "googActiveConnection",
|
|
||||||
"ssrc": "ssrc",
|
|
||||||
"packetsReceived": "packetsReceived",
|
|
||||||
"packetsSent": "packetsSent",
|
|
||||||
"packetsLost": "packetsLost",
|
|
||||||
"bytesReceived": "bytesReceived",
|
|
||||||
"bytesSent": "bytesSent",
|
|
||||||
"googFrameHeightReceived": "googFrameHeightReceived",
|
|
||||||
"googFrameWidthReceived": "googFrameWidthReceived",
|
|
||||||
"googFrameHeightSent": "googFrameHeightSent",
|
|
||||||
"googFrameWidthSent": "googFrameWidthSent",
|
|
||||||
"audioInputLevel": "audioInputLevel",
|
|
||||||
"audioOutputLevel": "audioOutputLevel"
|
|
||||||
};
|
|
||||||
keyMap[RTCBrowserType.RTC_BROWSER_OPERA] =
|
|
||||||
keyMap[RTCBrowserType.RTC_BROWSER_CHROME];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stats processing logic.
|
|
||||||
*/
|
|
||||||
StatsCollector.prototype.processStatsReport = function () {
|
|
||||||
if (!this.baselineStatsReport) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var idx in this.currentStatsReport) {
|
|
||||||
var now = this.currentStatsReport[idx];
|
|
||||||
try {
|
|
||||||
if (getStatValue(now, 'receiveBandwidth') ||
|
|
||||||
getStatValue(now, 'sendBandwidth')) {
|
|
||||||
PeerStats.bandwidth = {
|
|
||||||
"download": Math.round(
|
|
||||||
(getStatValue(now, 'receiveBandwidth')) / 1000),
|
|
||||||
"upload": Math.round(
|
|
||||||
(getStatValue(now, 'sendBandwidth')) / 1000)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(e){/*not supported*/}
|
|
||||||
|
|
||||||
if(now.type == 'googCandidatePair')
|
|
||||||
{
|
|
||||||
var ip, type, localIP, active;
|
|
||||||
try {
|
|
||||||
ip = getStatValue(now, 'remoteAddress');
|
|
||||||
type = getStatValue(now, "transportType");
|
|
||||||
localIP = getStatValue(now, "localAddress");
|
|
||||||
active = getStatValue(now, "activeConnection");
|
|
||||||
}
|
|
||||||
catch(e){/*not supported*/}
|
|
||||||
if(!ip || !type || !localIP || active != "true")
|
|
||||||
continue;
|
|
||||||
var addressSaved = false;
|
|
||||||
for(var i = 0; i < PeerStats.transport.length; i++)
|
|
||||||
{
|
|
||||||
if(PeerStats.transport[i].ip == ip &&
|
|
||||||
PeerStats.transport[i].type == type &&
|
|
||||||
PeerStats.transport[i].localip == localIP)
|
|
||||||
{
|
|
||||||
addressSaved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(addressSaved)
|
|
||||||
continue;
|
|
||||||
PeerStats.transport.push({localip: localIP, ip: ip, type: type});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(now.type == "candidatepair")
|
|
||||||
{
|
|
||||||
if(now.state == "succeeded")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var local = this.currentStatsReport[now.localCandidateId];
|
|
||||||
var remote = this.currentStatsReport[now.remoteCandidateId];
|
|
||||||
PeerStats.transport.push({localip: local.ipAddress + ":" + local.portNumber,
|
|
||||||
ip: remote.ipAddress + ":" + remote.portNumber, type: local.transport});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (now.type != 'ssrc' && now.type != "outboundrtp" &&
|
|
||||||
now.type != "inboundrtp") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var before = this.baselineStatsReport[idx];
|
|
||||||
if (!before) {
|
|
||||||
console.warn(getStatValue(now, 'ssrc') + ' not enough data');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ssrc = getStatValue(now, 'ssrc');
|
|
||||||
if(!ssrc)
|
|
||||||
continue;
|
|
||||||
var jid = APP.conference._room.room.getJidBySSRC(ssrc);
|
|
||||||
if (!jid && (Date.now() - now.timestamp) < 3000) {
|
|
||||||
console.warn("No jid for ssrc: " + ssrc);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var jidStats = this.jid2stats[jid];
|
|
||||||
if (!jidStats) {
|
|
||||||
jidStats = new PeerStats();
|
|
||||||
this.jid2stats[jid] = jidStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var isDownloadStream = true;
|
|
||||||
var key = 'packetsReceived';
|
|
||||||
var packetsNow = getStatValue(now, key);
|
|
||||||
if (typeof packetsNow === 'undefined' || packetsNow === null) {
|
|
||||||
isDownloadStream = false;
|
|
||||||
key = 'packetsSent';
|
|
||||||
packetsNow = getStatValue(now, key);
|
|
||||||
if (typeof packetsNow === 'undefined' || packetsNow === null) {
|
|
||||||
console.warn("No packetsReceived nor packetsSent stat found");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!packetsNow || packetsNow < 0)
|
|
||||||
packetsNow = 0;
|
|
||||||
|
|
||||||
var packetsBefore = getStatValue(before, key);
|
|
||||||
if (!packetsBefore || packetsBefore < 0)
|
|
||||||
packetsBefore = 0;
|
|
||||||
var packetRate = packetsNow - packetsBefore;
|
|
||||||
if (!packetRate || packetRate < 0)
|
|
||||||
packetRate = 0;
|
|
||||||
var currentLoss = getStatValue(now, 'packetsLost');
|
|
||||||
if (!currentLoss || currentLoss < 0)
|
|
||||||
currentLoss = 0;
|
|
||||||
var previousLoss = getStatValue(before, 'packetsLost');
|
|
||||||
if (!previousLoss || previousLoss < 0)
|
|
||||||
previousLoss = 0;
|
|
||||||
var lossRate = currentLoss - previousLoss;
|
|
||||||
if (!lossRate || lossRate < 0)
|
|
||||||
lossRate = 0;
|
|
||||||
var packetsTotal = (packetRate + lossRate);
|
|
||||||
|
|
||||||
jidStats.setSsrcLoss(ssrc,
|
|
||||||
{"packetsTotal": packetsTotal,
|
|
||||||
"packetsLost": lossRate,
|
|
||||||
"isDownloadStream": isDownloadStream});
|
|
||||||
|
|
||||||
|
|
||||||
var bytesReceived = 0, bytesSent = 0;
|
|
||||||
if(getStatValue(now, "bytesReceived")) {
|
|
||||||
bytesReceived = getStatValue(now, "bytesReceived") -
|
|
||||||
getStatValue(before, "bytesReceived");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getStatValue(now, "bytesSent")) {
|
|
||||||
bytesSent = getStatValue(now, "bytesSent") -
|
|
||||||
getStatValue(before, "bytesSent");
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = Math.round((now.timestamp - before.timestamp) / 1000);
|
|
||||||
if(bytesReceived <= 0 || time <= 0) {
|
|
||||||
bytesReceived = 0;
|
|
||||||
} else {
|
|
||||||
bytesReceived = Math.round(((bytesReceived * 8) / time) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bytesSent <= 0 || time <= 0) {
|
|
||||||
bytesSent = 0;
|
|
||||||
} else {
|
|
||||||
bytesSent = Math.round(((bytesSent * 8) / time) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
jidStats.setSsrcBitrate(ssrc, {
|
|
||||||
"download": bytesReceived,
|
|
||||||
"upload": bytesSent});
|
|
||||||
|
|
||||||
var resolution = {height: null, width: null};
|
|
||||||
try {
|
|
||||||
if (getStatValue(now, "googFrameHeightReceived") &&
|
|
||||||
getStatValue(now, "googFrameWidthReceived")) {
|
|
||||||
resolution.height = getStatValue(now, "googFrameHeightReceived");
|
|
||||||
resolution.width = getStatValue(now, "googFrameWidthReceived");
|
|
||||||
}
|
|
||||||
else if (getStatValue(now, "googFrameHeightSent") &&
|
|
||||||
getStatValue(now, "googFrameWidthSent")) {
|
|
||||||
resolution.height = getStatValue(now, "googFrameHeightSent");
|
|
||||||
resolution.width = getStatValue(now, "googFrameWidthSent");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(e){/*not supported*/}
|
|
||||||
|
|
||||||
if(resolution.height && resolution.width) {
|
|
||||||
jidStats.setSsrcResolution(ssrc, resolution);
|
|
||||||
} else {
|
|
||||||
jidStats.setSsrcResolution(ssrc, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
// Jid stats
|
|
||||||
var totalPackets = {download: 0, upload: 0};
|
|
||||||
var lostPackets = {download: 0, upload: 0};
|
|
||||||
var bitrateDownload = 0;
|
|
||||||
var bitrateUpload = 0;
|
|
||||||
var resolutions = {};
|
|
||||||
Object.keys(this.jid2stats).forEach(
|
|
||||||
function (jid) {
|
|
||||||
Object.keys(self.jid2stats[jid].ssrc2Loss).forEach(
|
|
||||||
function (ssrc) {
|
|
||||||
var type = "upload";
|
|
||||||
if(self.jid2stats[jid].ssrc2Loss[ssrc].isDownloadStream)
|
|
||||||
type = "download";
|
|
||||||
totalPackets[type] +=
|
|
||||||
self.jid2stats[jid].ssrc2Loss[ssrc].packetsTotal;
|
|
||||||
lostPackets[type] +=
|
|
||||||
self.jid2stats[jid].ssrc2Loss[ssrc].packetsLost;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
Object.keys(self.jid2stats[jid].ssrc2bitrate).forEach(
|
|
||||||
function (ssrc) {
|
|
||||||
bitrateDownload +=
|
|
||||||
self.jid2stats[jid].ssrc2bitrate[ssrc].download;
|
|
||||||
bitrateUpload +=
|
|
||||||
self.jid2stats[jid].ssrc2bitrate[ssrc].upload;
|
|
||||||
|
|
||||||
delete self.jid2stats[jid].ssrc2bitrate[ssrc];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
resolutions[jid] = self.jid2stats[jid].ssrc2resolution;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
PeerStats.bitrate = {"upload": bitrateUpload, "download": bitrateDownload};
|
|
||||||
|
|
||||||
PeerStats.packetLoss = {
|
|
||||||
total:
|
|
||||||
calculatePacketLoss(lostPackets.download + lostPackets.upload,
|
|
||||||
totalPackets.download + totalPackets.upload),
|
|
||||||
download:
|
|
||||||
calculatePacketLoss(lostPackets.download, totalPackets.download),
|
|
||||||
upload:
|
|
||||||
calculatePacketLoss(lostPackets.upload, totalPackets.upload)
|
|
||||||
};
|
|
||||||
|
|
||||||
let idResolution = {};
|
|
||||||
if (resolutions) { // use id instead of jid
|
|
||||||
Object.keys(resolutions).forEach(function (jid) {
|
|
||||||
let id = Strophe.getResourceFromJid(jid);
|
|
||||||
idResolution[id] = resolutions[jid];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.eventEmitter.emit(StatisticsEvents.CONNECTION_STATS,
|
|
||||||
{
|
|
||||||
"bitrate": PeerStats.bitrate,
|
|
||||||
"packetLoss": PeerStats.packetLoss,
|
|
||||||
"bandwidth": PeerStats.bandwidth,
|
|
||||||
"resolution": idResolution,
|
|
||||||
"transport": PeerStats.transport
|
|
||||||
});
|
|
||||||
PeerStats.transport = [];
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,71 +0,0 @@
|
||||||
/* global require, APP */
|
|
||||||
/**
|
|
||||||
* Created by hristo on 8/4/14.
|
|
||||||
*/
|
|
||||||
var RTPStats = require("./RTPStatsCollector.js");
|
|
||||||
var EventEmitter = require("events");
|
|
||||||
var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
|
|
||||||
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
|
||||||
var RTCEvents = require("../../service/RTC/RTCEvents");
|
|
||||||
var StatisticsEvents = require("../../service/statistics/Events");
|
|
||||||
|
|
||||||
var eventEmitter = new EventEmitter();
|
|
||||||
|
|
||||||
var rtpStats = null;
|
|
||||||
|
|
||||||
function stopRemote() {
|
|
||||||
if (rtpStats) {
|
|
||||||
rtpStats.stop();
|
|
||||||
eventEmitter.emit(StatisticsEvents.STOP);
|
|
||||||
rtpStats = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startRemoteStats (peerconnection) {
|
|
||||||
if (rtpStats) {
|
|
||||||
rtpStats.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
rtpStats = new RTPStats(peerconnection, 200, 2000, eventEmitter);
|
|
||||||
rtpStats.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDisposeConference(onUnload) {
|
|
||||||
stopRemote();
|
|
||||||
if (onUnload) {
|
|
||||||
eventEmitter.removeAllListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
/**
|
|
||||||
* Indicates that this audio level is for local jid.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
LOCAL_JID: 'local',
|
|
||||||
|
|
||||||
addListener: function(type, listener) {
|
|
||||||
eventEmitter.on(type, listener);
|
|
||||||
},
|
|
||||||
removeListener: function (type, listener) {
|
|
||||||
eventEmitter.removeListener(type, listener);
|
|
||||||
},
|
|
||||||
stop: function () {
|
|
||||||
stopRemote();
|
|
||||||
if (eventEmitter) {
|
|
||||||
eventEmitter.removeAllListeners();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
start: function () {
|
|
||||||
const xmpp = APP.conference._room.xmpp;
|
|
||||||
xmpp.addListener(
|
|
||||||
XMPPEvents.DISPOSE_CONFERENCE,
|
|
||||||
onDisposeConference
|
|
||||||
);
|
|
||||||
//FIXME: we may want to change CALL INCOMING event to
|
|
||||||
// onnegotiationneeded
|
|
||||||
xmpp.addListener(XMPPEvents.CALL_INCOMING, function (event) {
|
|
||||||
startRemoteStats(event.peerconnection);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,18 +0,0 @@
|
||||||
var RTCEvents = {
|
|
||||||
RTC_READY: "rtc.ready",
|
|
||||||
DATA_CHANNEL_OPEN: "rtc.data_channel_open",
|
|
||||||
CREATE_OFFER_FAILED: "rtc.create_offer_failed",
|
|
||||||
CREATE_ANSWER_FAILED: "rtc.create_answer_failed",
|
|
||||||
SET_LOCAL_DESCRIPTION_FAILED: "rtc.set_local_description_failed",
|
|
||||||
SET_REMOTE_DESCRIPTION_FAILED: "rtc.set_remote_description_failed",
|
|
||||||
ADD_ICE_CANDIDATE_FAILED: "rtc.add_ice_candidate_failed",
|
|
||||||
GET_USER_MEDIA_FAILED: "rtc.get_user_media_failed",
|
|
||||||
LASTN_CHANGED: "rtc.lastn_changed",
|
|
||||||
DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed",
|
|
||||||
LASTN_ENDPOINT_CHANGED: "rtc.lastn_endpoint_changed",
|
|
||||||
AVAILABLE_DEVICES_CHANGED: "rtc.available_devices_changed",
|
|
||||||
AUDIO_MUTE: "rtc.audio_mute",
|
|
||||||
VIDEO_MUTE: "rtc.video_mute"
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = RTCEvents;
|
|
|
@ -1,13 +0,0 @@
|
||||||
var StreamEventTypes = {
|
|
||||||
EVENT_TYPE_LOCAL_CREATED: "stream.local_created",
|
|
||||||
|
|
||||||
EVENT_TYPE_LOCAL_CHANGED: "stream.local_changed",
|
|
||||||
|
|
||||||
EVENT_TYPE_LOCAL_ENDED: "stream.local_ended",
|
|
||||||
|
|
||||||
EVENT_TYPE_REMOTE_CREATED: "stream.remote_created",
|
|
||||||
|
|
||||||
EVENT_TYPE_REMOTE_ENDED: "stream.remote_ended"
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = StreamEventTypes;
|
|
|
@ -1,12 +0,0 @@
|
||||||
var AuthenticationEvents = {
|
|
||||||
/**
|
|
||||||
* Event callback arguments:
|
|
||||||
* function(authenticationEnabled, userIdentity)
|
|
||||||
* authenticationEnabled - indicates whether authentication has been enabled
|
|
||||||
* in this session
|
|
||||||
* userIdentity - if user has been logged in then it contains user name. If
|
|
||||||
* contains 'null' or 'undefined' then user is not logged in.
|
|
||||||
*/
|
|
||||||
IDENTITY_UPDATED: "authentication.identity_updated"
|
|
||||||
};
|
|
||||||
module.exports = AuthenticationEvents;
|
|
|
@ -1,14 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
/**
|
|
||||||
* An event carrying connection statistics.
|
|
||||||
*/
|
|
||||||
CONNECTION_STATS: "statistics.connectionstats",
|
|
||||||
/**
|
|
||||||
* FIXME: needs documentation.
|
|
||||||
*/
|
|
||||||
AUDIO_LEVEL: "statistics.audioLevel",
|
|
||||||
/**
|
|
||||||
* FIXME: needs documentation.
|
|
||||||
*/
|
|
||||||
STOP: "statistics.stop"
|
|
||||||
};
|
|
|
@ -1,92 +0,0 @@
|
||||||
var XMPPEvents = {
|
|
||||||
// Designates an event indicating that the connection to the XMPP server
|
|
||||||
// failed.
|
|
||||||
CONNECTION_FAILED: "xmpp.connection.failed",
|
|
||||||
// Designates an event indicating that the media (ICE) connection was
|
|
||||||
// interrupted. This should go to the RTC module.
|
|
||||||
CONNECTION_INTERRUPTED: "xmpp.connection.interrupted",
|
|
||||||
// Designates an event indicating that the media (ICE) connection was
|
|
||||||
// restored. This should go to the RTC module.
|
|
||||||
CONNECTION_RESTORED: "xmpp.connection.restored",
|
|
||||||
// Designates an event indicating that an offer (e.g. Jingle
|
|
||||||
// session-initiate) was received.
|
|
||||||
CALL_INCOMING: "xmpp.callincoming.jingle",
|
|
||||||
// Designates an event indicating that we were kicked from the XMPP MUC.
|
|
||||||
KICKED: "xmpp.kicked",
|
|
||||||
// Designates an event indicating that the userID for a specific JID has
|
|
||||||
// changed.
|
|
||||||
// Note: currently this event fires every time we receive presence from
|
|
||||||
// someone (regardless of whether or not the "userID" changed).
|
|
||||||
USER_ID_CHANGED: "xmpp.user_id_changed",
|
|
||||||
// Designates an event indicating that we have joined the XMPP MUC.
|
|
||||||
MUC_JOINED: "xmpp.muc_joined",
|
|
||||||
// Designates an event indicating that a participant joined the XMPP MUC.
|
|
||||||
MUC_MEMBER_JOINED: "xmpp.muc_member_joined",
|
|
||||||
// Designates an event indicating that a participant left the XMPP MUC.
|
|
||||||
MUC_MEMBER_LEFT: "xmpp.muc_member_left",
|
|
||||||
// Designates an event indicating that the MUC role of a participant has
|
|
||||||
// changed.
|
|
||||||
MUC_ROLE_CHANGED: "xmpp.muc_role_changed",
|
|
||||||
// Designates an event indicating that the XMPP MUC was destroyed.
|
|
||||||
MUC_DESTROYED: "xmpp.muc_destroyed",
|
|
||||||
// Designates an event indicating that the display name of a participant
|
|
||||||
// has changed.
|
|
||||||
DISPLAY_NAME_CHANGED: "xmpp.display_name_changed",
|
|
||||||
// Designates an event indicating that we received statistics from a
|
|
||||||
// participant in the MUC.
|
|
||||||
REMOTE_STATS: "xmpp.remote_stats",
|
|
||||||
// Designates an event indicating that our role in the XMPP MUC has changed.
|
|
||||||
LOCAL_ROLE_CHANGED: "xmpp.localrole_changed",
|
|
||||||
// Designates an event indicating that the subject of the XMPP MUC has
|
|
||||||
// changed.
|
|
||||||
SUBJECT_CHANGED: "xmpp.subject_changed",
|
|
||||||
// Designates an event indicating that an XMPP message in the MUC was
|
|
||||||
// received.
|
|
||||||
MESSAGE_RECEIVED: "xmpp.message_received",
|
|
||||||
// Designates an event indicating that we sent an XMPP message to the MUC.
|
|
||||||
SENDING_CHAT_MESSAGE: "xmpp.sending_chat_message",
|
|
||||||
// Designates an event indicating that the video type (e.g. 'camera' or
|
|
||||||
// 'screen') for a participant has changed.
|
|
||||||
// Note: currently this event fires every time we receive presence from
|
|
||||||
// someone (regardless of whether or not the "video type" changed).
|
|
||||||
PARTICIPANT_VIDEO_TYPE_CHANGED: "xmpp.video_type",
|
|
||||||
// Designates an event indicating that a participant in the XMPP MUC has
|
|
||||||
// advertised that they have audio muted (or unmuted).
|
|
||||||
PARTICIPANT_AUDIO_MUTED: "xmpp.audio_muted",
|
|
||||||
// Designates an event indicating that a participant in the XMPP MUC has
|
|
||||||
// advertised that they have video muted (or unmuted).
|
|
||||||
PARTICIPANT_VIDEO_MUTED: "xmpp.video_muted",
|
|
||||||
// Designates an event indicating that the focus has asked us to mute our
|
|
||||||
// audio.
|
|
||||||
AUDIO_MUTED_BY_FOCUS: "xmpp.audio_muted_by_focus",
|
|
||||||
// Designates an event indicating that a moderator in the room changed the
|
|
||||||
// "start muted" settings for the conference.
|
|
||||||
START_MUTED_SETTING_CHANGED: "xmpp.start_muted_setting_changed",
|
|
||||||
// Designates an event indicating that we should join the conference with
|
|
||||||
// audio and/or video muted.
|
|
||||||
START_MUTED_FROM_FOCUS: "xmpp.start_muted_from_focus",
|
|
||||||
// Designates an event indicating that a remote participant's available
|
|
||||||
// devices (whether he supports a audio and/or video) changed.
|
|
||||||
// Note: currently this event fires every time we receive presence from
|
|
||||||
// someone (regardless of whether or not the devices changed).
|
|
||||||
DEVICE_AVAILABLE: "xmpp.device_available",
|
|
||||||
|
|
||||||
|
|
||||||
PEERCONNECTION_READY: "xmpp.peerconnection_ready",
|
|
||||||
CONFERENCE_SETUP_FAILED: "xmpp.conference_setup_failed",
|
|
||||||
PASSWORD_REQUIRED: "xmpp.password_required",
|
|
||||||
AUTHENTICATION_REQUIRED: "xmpp.authentication_required",
|
|
||||||
CHAT_ERROR_RECEIVED: "xmpp.chat_error_received",
|
|
||||||
ETHERPAD: "xmpp.etherpad",
|
|
||||||
BRIDGE_DOWN: "xmpp.bridge_down",
|
|
||||||
PRESENCE_STATUS: "xmpp.presence_status",
|
|
||||||
RESERVATION_ERROR: "xmpp.room_reservation_error",
|
|
||||||
DISPOSE_CONFERENCE: "xmpp.dispose_conference",
|
|
||||||
GRACEFUL_SHUTDOWN: "xmpp.graceful_shutdown",
|
|
||||||
JINGLE_FATAL_ERROR: 'xmpp.jingle_fatal_error',
|
|
||||||
PROMPT_FOR_LOGIN: 'xmpp.prompt_for_login',
|
|
||||||
FOCUS_DISCONNECTED: 'xmpp.focus_disconnected',
|
|
||||||
// xmpp is connected and obtained user media
|
|
||||||
READY_TO_JOIN: 'xmpp.ready_to_join'
|
|
||||||
};
|
|
||||||
module.exports = XMPPEvents;
|
|
Loading…
Reference in New Issue