| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | import _ from 'lodash';
import JitsiMeetJS from '../base/lib-jitsi-meet';
declare var APP: Object;
/**
 * Contains all the callbacks to be notified when stats are updated.
 *
 * {
 *     userId: Function[]
 * }
 */
const subscribers = {};
/**
 * A singleton that acts as a pub/sub service for connection stat updates.
 */
const statsEmitter = {
    /**
     * Have {@code statsEmitter} subscribe to stat updates from a given
     * conference.
     *
     * @param {JitsiConference} conference - The conference for which
     * {@code statsEmitter} should subscribe for stat updates.
     * @returns {void}
     */
    startListeningForStats(conference) {
        const { connectionQuality } = JitsiMeetJS.events;
        conference.on(connectionQuality.LOCAL_STATS_UPDATED,
            stats => this._onStatsUpdated(conference.myUserId(), stats));
        conference.on(connectionQuality.REMOTE_STATS_UPDATED,
            (id, stats) => this._emitStatsUpdate(id, stats));
    },
    /**
     * Add a subscriber to be notified when stats are updated for a specified
     * user id.
     *
     * @param {string} id - The user id whose stats updates are of interest.
     * @param {Function} callback - The function to invoke when stats for the
     * user have been updated.
     * @returns {void}
     */
    subscribeToClientStats(id, callback) {
        if (!id) {
            return;
        }
        if (!subscribers[id]) {
            subscribers[id] = [];
        }
        subscribers[id].push(callback);
    },
    /**
     * Remove a subscriber that is listening for stats updates for a specified
     * user id.
     *
     * @param {string} id - The user id whose stats updates are no longer of
     * interest.
     * @param {Function} callback - The function that is currently subscribed to
     * stat updates for the specified user id.
     * @returns {void}
     */
    unsubscribeToClientStats(id, callback) {
        if (!subscribers[id]) {
            return;
        }
        const filteredSubscribers = subscribers[id].filter(
            subscriber => subscriber !== callback);
        if (filteredSubscribers.length) {
            subscribers[id] = filteredSubscribers;
        } else {
            delete subscribers[id];
        }
    },
    /**
     * Emit a stat update to all those listening for a specific user's
     * connection stats.
     *
     * @param {string} id - The user id the stats are associated with.
     * @param {Object} stats - New connection stats for the user.
     * @returns {void}
     */
    _emitStatsUpdate(id, stats = {}) {
        const callbacks = subscribers[id] || [];
        callbacks.forEach(callback => {
            callback(stats);
        });
    },
    /**
     * Emit a stat update to all those listening for local stat updates. Will
     * also update listeners of remote user stats of changes related to their
     * stats.
     *
     * @param {string} currentUserId - The user id for the local user.
     * @param {Object} stats - Connection stats for the local user as provided
     * by the library.
     * @returns {void}
     */
    _onStatsUpdated(currentUserId, stats) {
        const allUserFramerates = stats.framerate;
        const allUserResolutions = stats.resolution;
        const currentUserFramerate = allUserFramerates[currentUserId];
        const currentUserResolution = allUserResolutions[currentUserId];
        // FIXME resolution and framerate are hashes keyed off of user ids with
        // stat values. Receivers of stats expect resolution and framerate to
        // be primatives, not hashes, so overwrites the 'lib-jitsi-meet' stats
        // objects.
        stats.framerate = currentUserFramerate;
        stats.resolution = currentUserResolution;
        this._emitStatsUpdate(currentUserId, stats);
        // Get all the unique user ids from the framerate and resolution stats
        // and update remote user stats as needed.
        const framerateUserIds = Object.keys(allUserFramerates);
        const resolutionUserIds = Object.keys(allUserResolutions);
        _.union(framerateUserIds, resolutionUserIds)
            .filter(id => id !== currentUserId)
            .forEach(id => {
                const remoteUserStats = {};
                const framerate = allUserFramerates[id];
                if (framerate) {
                    remoteUserStats.framerate = framerate;
                }
                const resolution = allUserResolutions[id];
                if (resolution) {
                    remoteUserStats.resolution = resolution;
                }
                this._emitStatsUpdate(id, remoteUserStats);
            });
    }
};
export default statsEmitter;
 |