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.6KB

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