Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

audio_levels.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /**
  2. * The audio Levels plugin.
  3. */
  4. var AudioLevels = (function(my) {
  5. var CANVAS_EXTRA = 104;
  6. var CANVAS_RADIUS = 7;
  7. var SHADOW_COLOR = '#00ccff';
  8. var audioLevelCanvasCache = {};
  9. my.LOCAL_LEVEL = 'local';
  10. /**
  11. * Updates the audio level canvas for the given peerJid. If the canvas
  12. * didn't exist we create it.
  13. */
  14. my.updateAudioLevelCanvas = function (peerJid) {
  15. var resourceJid = null;
  16. var videoSpanId = null;
  17. if (!peerJid)
  18. videoSpanId = 'localVideoContainer';
  19. else {
  20. resourceJid = Strophe.getResourceFromJid(peerJid);
  21. videoSpanId = 'participant_' + resourceJid;
  22. }
  23. videoSpan = document.getElementById(videoSpanId);
  24. if (!videoSpan) {
  25. if (resourceJid)
  26. console.error("No video element for jid", resourceJid);
  27. else
  28. console.error("No video element for local video.");
  29. return;
  30. }
  31. var audioLevelCanvas = $('#' + videoSpanId + '>canvas');
  32. var videoSpaceWidth = $('#remoteVideos').width();
  33. var thumbnailSize
  34. = VideoLayout.calculateThumbnailSize(videoSpaceWidth);
  35. var thumbnailWidth = thumbnailSize[0];
  36. var thumbnailHeight = thumbnailSize[1];
  37. if (!audioLevelCanvas || audioLevelCanvas.length === 0) {
  38. audioLevelCanvas = document.createElement('canvas');
  39. audioLevelCanvas.className = "audiolevel";
  40. audioLevelCanvas.style.bottom = "-" + CANVAS_EXTRA/2 + "px";
  41. audioLevelCanvas.style.left = "-" + CANVAS_EXTRA/2 + "px";
  42. resizeAudioLevelCanvas( audioLevelCanvas,
  43. thumbnailWidth,
  44. thumbnailHeight);
  45. videoSpan.appendChild(audioLevelCanvas);
  46. } else {
  47. audioLevelCanvas = audioLevelCanvas.get(0);
  48. resizeAudioLevelCanvas( audioLevelCanvas,
  49. thumbnailWidth,
  50. thumbnailHeight);
  51. }
  52. };
  53. /**
  54. * Updates the audio level UI for the given resourceJid.
  55. *
  56. * @param resourceJid the resource jid indicating the video element for
  57. * which we draw the audio level
  58. * @param audioLevel the newAudio level to render
  59. */
  60. my.updateAudioLevel = function (resourceJid, audioLevel) {
  61. drawAudioLevelCanvas(resourceJid, audioLevel);
  62. var videoSpanId = getVideoSpanId(resourceJid);
  63. var audioLevelCanvas = $('#' + videoSpanId + '>canvas').get(0);
  64. if (!audioLevelCanvas)
  65. return;
  66. var drawContext = audioLevelCanvas.getContext('2d');
  67. var canvasCache = audioLevelCanvasCache[resourceJid];
  68. drawContext.clearRect (0, 0,
  69. audioLevelCanvas.width, audioLevelCanvas.height);
  70. drawContext.drawImage(canvasCache, 0, 0);
  71. };
  72. /**
  73. * Resizes the given audio level canvas to match the given thumbnail size.
  74. */
  75. function resizeAudioLevelCanvas(audioLevelCanvas,
  76. thumbnailWidth,
  77. thumbnailHeight) {
  78. audioLevelCanvas.width = thumbnailWidth + CANVAS_EXTRA;
  79. audioLevelCanvas.height = thumbnailHeight + CANVAS_EXTRA;
  80. };
  81. /**
  82. * Draws the audio level canvas into the cached canvas object.
  83. *
  84. * @param resourceJid the resource jid indicating the video element for
  85. * which we draw the audio level
  86. * @param audioLevel the newAudio level to render
  87. */
  88. function drawAudioLevelCanvas(resourceJid, audioLevel) {
  89. if (!audioLevelCanvasCache[resourceJid]) {
  90. var videoSpanId = getVideoSpanId(resourceJid);
  91. var audioLevelCanvasOrig = $('#' + videoSpanId + '>canvas').get(0);
  92. /*
  93. * FIXME Testing has shown that audioLevelCanvasOrig may not exist.
  94. * In such a case, the method CanvasUtil.cloneCanvas may throw an
  95. * error. Since audio levels are frequently updated, the errors have
  96. * been observed to pile into the console, strain the CPU.
  97. */
  98. if (audioLevelCanvasOrig)
  99. {
  100. audioLevelCanvasCache[resourceJid]
  101. = CanvasUtil.cloneCanvas(audioLevelCanvasOrig);
  102. }
  103. }
  104. var canvas = audioLevelCanvasCache[resourceJid];
  105. if (!canvas)
  106. return;
  107. var drawContext = canvas.getContext('2d');
  108. drawContext.clearRect(0, 0, canvas.width, canvas.height);
  109. var shadowLevel = getShadowLevel(audioLevel);
  110. if (shadowLevel > 0)
  111. // drawContext, x, y, w, h, r, shadowColor, shadowLevel
  112. CanvasUtil.drawRoundRectGlow( drawContext,
  113. CANVAS_EXTRA/2, CANVAS_EXTRA/2,
  114. canvas.width - CANVAS_EXTRA,
  115. canvas.height - CANVAS_EXTRA,
  116. CANVAS_RADIUS,
  117. SHADOW_COLOR,
  118. shadowLevel);
  119. };
  120. /**
  121. * Returns the shadow/glow level for the given audio level.
  122. *
  123. * @param audioLevel the audio level from which we determine the shadow
  124. * level
  125. */
  126. function getShadowLevel (audioLevel) {
  127. var shadowLevel = 0;
  128. if (audioLevel <= 0.3) {
  129. shadowLevel = Math.round(CANVAS_EXTRA/2*(audioLevel/0.3));
  130. }
  131. else if (audioLevel <= 0.6) {
  132. shadowLevel = Math.round(CANVAS_EXTRA/2*((audioLevel - 0.3) / 0.3));
  133. }
  134. else {
  135. shadowLevel = Math.round(CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4));
  136. }
  137. return shadowLevel;
  138. };
  139. /**
  140. * Returns the video span id corresponding to the given resourceJid or local
  141. * user.
  142. */
  143. function getVideoSpanId(resourceJid) {
  144. var videoSpanId = null;
  145. if (resourceJid === AudioLevels.LOCAL_LEVEL
  146. || (connection.emuc.myroomjid && resourceJid
  147. === Strophe.getResourceFromJid(connection.emuc.myroomjid)))
  148. videoSpanId = 'localVideoContainer';
  149. else
  150. videoSpanId = 'participant_' + resourceJid;
  151. return videoSpanId;
  152. };
  153. /**
  154. * Indicates that the remote video has been resized.
  155. */
  156. $(document).bind('remotevideo.resized', function (event, width, height) {
  157. var resized = false;
  158. $('#remoteVideos>span>canvas').each(function() {
  159. var canvas = $(this).get(0);
  160. if (canvas.width !== width + CANVAS_EXTRA) {
  161. canvas.width = width + CANVAS_EXTRA;
  162. resized = true;
  163. }
  164. if (canvas.heigh !== height + CANVAS_EXTRA) {
  165. canvas.height = height + CANVAS_EXTRA;
  166. resized = true;
  167. }
  168. });
  169. if (resized)
  170. Object.keys(audioLevelCanvasCache).forEach(function (resourceJid) {
  171. audioLevelCanvasCache[resourceJid].width
  172. = width + CANVAS_EXTRA;
  173. audioLevelCanvasCache[resourceJid].height
  174. = height + CANVAS_EXTRA;
  175. });
  176. });
  177. return my;
  178. })(AudioLevels || {});