You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

statsEmitter.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import JitsiMeetJS from '../base/lib-jitsi-meet';
  2. declare var APP: Object;
  3. /**
  4. * Contains all the callbacks to be notified when stats are updated.
  5. *
  6. * {
  7. * userId: Function[]
  8. * }
  9. */
  10. const subscribers = {};
  11. /**
  12. * A singleton that acts as a pub/sub service for connection stat updates.
  13. */
  14. const statsEmitter = {
  15. /**
  16. * Have {@code statsEmitter} subscribe to stat updates from a given
  17. * conference.
  18. *
  19. * @param {JitsiConference} conference - The conference for which
  20. * {@code statsEmitter} should subscribe for stat updates.
  21. * @returns {void}
  22. */
  23. startListeningForStats(conference) {
  24. const { connectionQuality } = JitsiMeetJS.events;
  25. conference.on(connectionQuality.LOCAL_STATS_UPDATED,
  26. stats => this._onStatsUpdated(stats));
  27. conference.on(connectionQuality.REMOTE_STATS_UPDATED,
  28. (id, stats) => this._emitStatsUpdate(id, stats));
  29. },
  30. /**
  31. * Add a subscriber to be notified when stats are updated for a specified
  32. * user id.
  33. *
  34. * @param {string} id - The user id whose stats updates are of interest.
  35. * @param {Function} callback - The function to invoke when stats for the
  36. * user have been updated.
  37. * @returns {void}
  38. */
  39. subscribeToClientStats(id, callback) {
  40. if (!id) {
  41. return;
  42. }
  43. if (!subscribers[id]) {
  44. subscribers[id] = [];
  45. }
  46. subscribers[id].push(callback);
  47. },
  48. /**
  49. * Remove a subscriber that is listening for stats updates for a specified
  50. * user id.
  51. *
  52. * @param {string} id - The user id whose stats updates are no longer of
  53. * interest.
  54. * @param {Function} callback - The function that is currently subscribed to
  55. * stat updates for the specified user id.
  56. * @returns {void}
  57. */
  58. unsubscribeToClientStats(id, callback) {
  59. if (!subscribers[id]) {
  60. return;
  61. }
  62. const filteredSubscribers = subscribers[id].filter(
  63. subscriber => subscriber !== callback);
  64. if (filteredSubscribers.length) {
  65. subscribers[id] = filteredSubscribers;
  66. } else {
  67. delete subscribers[id];
  68. }
  69. },
  70. /**
  71. * Emit a stat update to all those listening for a specific user's
  72. * connection stats.
  73. *
  74. * @param {string} id - The user id the stats are associated with.
  75. * @param {Object} stats - New connection stats for the user.
  76. * @returns {void}
  77. */
  78. _emitStatsUpdate(id, stats = {}) {
  79. const callbacks = subscribers[id] || [];
  80. callbacks.forEach(callback => {
  81. callback(stats);
  82. });
  83. },
  84. /**
  85. * Emit a stat update to all those listening for local stat updates. Will
  86. * also update listeners of remote user stats of changes related to their
  87. * stats.
  88. *
  89. * @param {Object} stats - Connection stats for the local user as provided
  90. * by the library.
  91. * @returns {void}
  92. */
  93. _onStatsUpdated(stats) {
  94. const allUserFramerates = stats.framerate;
  95. const allUserResolutions = stats.resolution;
  96. const currentUserId = APP.conference.getMyUserId();
  97. const currentUserFramerate = allUserFramerates[currentUserId];
  98. const currentUserResolution = allUserResolutions[currentUserId];
  99. // FIXME resolution and framerate are hashes keyed off of user ids with
  100. // stat values. Receivers of stats expect resolution and framerate to
  101. // be primatives, not hashes, so overwrites the 'lib-jitsi-meet' stats
  102. // objects.
  103. stats.framerate = currentUserFramerate;
  104. stats.resolution = currentUserResolution;
  105. this._emitStatsUpdate(currentUserId, stats);
  106. Object.keys(allUserFramerates)
  107. .filter(id => id !== currentUserId)
  108. .forEach(id => {
  109. const framerate = allUserFramerates[id];
  110. if (framerate) {
  111. this._emitStatsUpdate(id, { framerate });
  112. }
  113. });
  114. Object.keys(allUserResolutions)
  115. .filter(id => id !== currentUserId)
  116. .forEach(id => {
  117. const resolution = allUserResolutions[id];
  118. if (resolution) {
  119. this._emitStatsUpdate(id, { resolution });
  120. }
  121. });
  122. }
  123. };
  124. export default statsEmitter;