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.

mod_speakerstats_component.lua 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. local get_room_from_jid = module:require "util".get_room_from_jid;
  2. local jid_resource = require "util.jid".resource;
  3. local ext_events = module:require "ext_events"
  4. local muc_component_host = module:get_option_string("muc_component");
  5. if muc_component_host == nil then
  6. log("error", "No muc_component specified. No muc to operate on!");
  7. return;
  8. end
  9. local muc_module = module:context("conference."..muc_component_host);
  10. if muc_module == nil then
  11. log("error", "No such muc found, check muc_component config.");
  12. return;
  13. end
  14. log("debug", "Starting speakerstats for %s", muc_component_host);
  15. -- receives messages from client currently connected to the room
  16. -- clients indicates their own dominant speaker events
  17. function on_message(event)
  18. -- Check the type of the incoming stanza to avoid loops:
  19. if event.stanza.attr.type == "error" then
  20. return; -- We do not want to reply to these, so leave.
  21. end
  22. local speakerStats
  23. = event.stanza:get_child('speakerstats', 'http://jitsi.org/jitmeet');
  24. if speakerStats then
  25. local roomAddress = speakerStats.attr.room;
  26. local room = get_room_from_jid(roomAddress);
  27. if not room then
  28. log("warn", "No room found %s", roomAddress);
  29. return false;
  30. end
  31. local roomSpeakerStats = room.speakerStats;
  32. local from = event.stanza.attr.from;
  33. local occupant = room:get_occupant_by_real_jid(from);
  34. if not occupant then
  35. log("warn", "No occupant %s found for %s", from, roomAddress);
  36. return false;
  37. end
  38. local newDominantSpeaker = roomSpeakerStats[occupant.jid];
  39. local oldDominantSpeakerId = roomSpeakerStats['dominantSpeakerId'];
  40. if oldDominantSpeakerId then
  41. roomSpeakerStats[oldDominantSpeakerId]:setIsDominantSpeaker(false);
  42. end
  43. if newDominantSpeaker then
  44. newDominantSpeaker:setIsDominantSpeaker(true);
  45. end
  46. room.speakerStats['dominantSpeakerId'] = occupant.jid;
  47. end
  48. return true
  49. end
  50. --- Start SpeakerStats implementation
  51. local SpeakerStats = {};
  52. SpeakerStats.__index = SpeakerStats;
  53. function new_SpeakerStats(nick)
  54. return setmetatable({
  55. totalDominantSpeakerTime = 0;
  56. _dominantSpeakerStart = nil;
  57. _isDominantSpeaker = false;
  58. nick = nick;
  59. displayName = nil;
  60. }, SpeakerStats);
  61. end
  62. -- Changes the dominantSpeaker data for current occupant
  63. -- saves start time if it is new dominat speaker
  64. -- or calculates and accumulates time of speaking
  65. function SpeakerStats:setIsDominantSpeaker(isNowDominantSpeaker)
  66. log("debug",
  67. "set isDominant %s for %s", tostring(isNowDominantSpeaker), self.nick);
  68. if not self._isDominantSpeaker and isNowDominantSpeaker then
  69. self._dominantSpeakerStart = os.time();
  70. elseif self._isDominantSpeaker and not isNowDominantSpeaker then
  71. local now = os.time();
  72. local timeElapsed = now - (self._dominantSpeakerStart or 0);
  73. self.totalDominantSpeakerTime
  74. = self.totalDominantSpeakerTime + timeElapsed;
  75. self._dominantSpeakerStart = nil;
  76. end
  77. self._isDominantSpeaker = isNowDominantSpeaker;
  78. end
  79. --- End SpeakerStats
  80. -- create speakerStats for the room
  81. function room_created(event)
  82. local room = event.room;
  83. room.speakerStats = {};
  84. end
  85. -- Create SpeakerStats object for the joined user
  86. function occupant_joined(event)
  87. local room = event.room;
  88. local occupant = event.occupant;
  89. local nick = jid_resource(occupant.nick);
  90. if room.speakerStats then
  91. room.speakerStats[occupant.jid] = new_SpeakerStats(nick);
  92. end
  93. end
  94. -- Occupant left set its dominant speaker to false and update the store the
  95. -- display name
  96. function occupant_leaving(event)
  97. local room = event.room;
  98. local occupant = event.occupant;
  99. local speakerStatsForOccupant = room.speakerStats[occupant.jid];
  100. if speakerStatsForOccupant then
  101. speakerStatsForOccupant:setIsDominantSpeaker(false);
  102. -- set display name
  103. local displayName = occupant:get_presence():get_child_text(
  104. 'nick', 'http://jabber.org/protocol/nick');
  105. speakerStatsForOccupant.displayName = displayName;
  106. end
  107. end
  108. -- Conference ended, send speaker stats
  109. function room_destroyed(event)
  110. local room = event.room;
  111. ext_events.speaker_stats(room, room.speakerStats);
  112. end
  113. module:hook("message/host", on_message);
  114. muc_module:hook("muc-room-created", room_created, -1);
  115. muc_module:hook("muc-occupant-joined", occupant_joined, -1);
  116. muc_module:hook("muc-occupant-pre-leave", occupant_leaving, -1);
  117. muc_module:hook("muc-room-destroyed", room_destroyed, -1);