123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /* global APP, interfaceConfig, $ */
- /* jshint -W101 */
-
- import CanvasUtil from './CanvasUtils';
- import FilmStrip from '../videolayout/FilmStrip';
-
- const LOCAL_LEVEL = 'local';
-
- let ASDrawContext = null;
- let audioLevelCanvasCache = {};
- let dominantSpeakerAudioElement = null;
-
- function _initDominantSpeakerAudioLevels(dominantSpeakerAvatarSize) {
- let ASRadius = dominantSpeakerAvatarSize / 2;
- let ASCenter = (dominantSpeakerAvatarSize + ASRadius) / 2;
-
- // Draw a circle.
- ASDrawContext.beginPath();
- ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI);
- ASDrawContext.closePath();
-
- // Add a shadow around the circle
- ASDrawContext.shadowColor = interfaceConfig.SHADOW_COLOR;
- ASDrawContext.shadowOffsetX = 0;
- ASDrawContext.shadowOffsetY = 0;
- }
-
- /**
- * Resizes the given audio level canvas to match the given thumbnail size.
- */
- function _resizeAudioLevelCanvas( audioLevelCanvas,
- thumbnailWidth,
- thumbnailHeight) {
- audioLevelCanvas.width = thumbnailWidth + interfaceConfig.CANVAS_EXTRA;
- audioLevelCanvas.height = thumbnailHeight + interfaceConfig.CANVAS_EXTRA;
- }
-
- /**
- * Draws the audio level canvas into the cached canvas object.
- *
- * @param id of the user for whom we draw the audio level
- * @param audioLevel the newAudio level to render
- */
- function drawAudioLevelCanvas(id, audioLevel) {
- if (!audioLevelCanvasCache[id]) {
-
- let videoSpanId = getVideoSpanId(id);
-
- let audioLevelCanvasOrig = $(`#${videoSpanId}>canvas`).get(0);
-
- /*
- * FIXME Testing has shown that audioLevelCanvasOrig may not exist.
- * In such a case, the method CanvasUtil.cloneCanvas may throw an
- * error. Since audio levels are frequently updated, the errors have
- * been observed to pile into the console, strain the CPU.
- */
- if (audioLevelCanvasOrig) {
- audioLevelCanvasCache[id]
- = CanvasUtil.cloneCanvas(audioLevelCanvasOrig);
- }
- }
-
- let canvas = audioLevelCanvasCache[id];
-
- if (!canvas) {
- return;
- }
-
- let drawContext = canvas.getContext('2d');
-
- drawContext.clearRect(0, 0, canvas.width, canvas.height);
-
- let shadowLevel = getShadowLevel(audioLevel);
-
- if (shadowLevel > 0) {
- // drawContext, x, y, w, h, r, shadowColor, shadowLevel
- CanvasUtil.drawRoundRectGlow(
- drawContext,
- interfaceConfig.CANVAS_EXTRA / 2, interfaceConfig.CANVAS_EXTRA / 2,
- canvas.width - interfaceConfig.CANVAS_EXTRA,
- canvas.height - interfaceConfig.CANVAS_EXTRA,
- interfaceConfig.CANVAS_RADIUS,
- interfaceConfig.SHADOW_COLOR,
- shadowLevel);
- }
- }
-
- /**
- * Returns the shadow/glow level for the given audio level.
- *
- * @param audioLevel the audio level from which we determine the shadow
- * level
- */
- function getShadowLevel (audioLevel) {
- let shadowLevel = 0;
-
- if (audioLevel <= 0.3) {
- shadowLevel = Math.round(
- interfaceConfig.CANVAS_EXTRA/2*(audioLevel/0.3));
- } else if (audioLevel <= 0.6) {
- shadowLevel = Math.round(
- interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.3) / 0.3));
- } else {
- shadowLevel = Math.round(
- interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4));
- }
-
- return shadowLevel;
- }
-
- /**
- * Returns the video span id corresponding to the given user id
- */
- function getVideoSpanId(id) {
- let videoSpanId = null;
-
- if (id === LOCAL_LEVEL || APP.conference.isLocalId(id)) {
- videoSpanId = 'localVideoContainer';
- } else {
- videoSpanId = `participant_${id}`;
- }
-
- return videoSpanId;
- }
-
- /**
- * The audio Levels plugin.
- */
- const AudioLevels = {
-
- init () {
- dominantSpeakerAudioElement = $('#dominantSpeakerAudioLevel')[0];
- ASDrawContext = dominantSpeakerAudioElement.getContext('2d');
-
- let parentContainer = $("#dominantSpeaker");
- let dominantSpeakerWidth = parentContainer.width();
- let dominantSpeakerHeight = parentContainer.height();
-
- dominantSpeakerAudioElement.width = dominantSpeakerWidth;
- dominantSpeakerAudioElement.height = dominantSpeakerHeight;
-
- let dominantSpeakerAvatar = $("#dominantSpeakerAvatar");
- _initDominantSpeakerAudioLevels(dominantSpeakerAvatar.width());
- },
-
- /**
- * Updates the audio level canvas for the given id. If the canvas
- * didn't exist we create it.
- */
- createAudioLevelCanvas (id, thumbWidth, thumbHeight) {
-
- let videoSpanId = (id === "local")
- ? "localVideoContainer"
- : `participant_${id}`;
-
- let videoSpan = document.getElementById(videoSpanId);
-
- if (!videoSpan) {
- if (id) {
- console.error("No video element for id", id);
- } else {
- console.error("No video element for local video.");
- }
- return;
- }
-
- let audioLevelCanvas = $(`#${videoSpanId}>canvas`);
-
- if (!audioLevelCanvas || audioLevelCanvas.length === 0) {
-
- audioLevelCanvas = document.createElement('canvas');
- audioLevelCanvas.className = "audiolevel";
- audioLevelCanvas.style.bottom
- = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
- audioLevelCanvas.style.left
- = `-${interfaceConfig.CANVAS_EXTRA/2}px`;
- _resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
-
- videoSpan.appendChild(audioLevelCanvas);
- } else {
- audioLevelCanvas = audioLevelCanvas.get(0);
-
- _resizeAudioLevelCanvas(audioLevelCanvas, thumbWidth, thumbHeight);
- }
- },
-
- /**
- * Updates the audio level UI for the given id.
- *
- * @param id id of the user for whom we draw the audio level
- * @param audioLevel the newAudio level to render
- */
- updateAudioLevel (id, audioLevel, largeVideoId) {
- drawAudioLevelCanvas(id, audioLevel);
-
- let videoSpanId = getVideoSpanId(id);
-
- let audioLevelCanvas = $(`#${videoSpanId}>canvas`).get(0);
-
- if (!audioLevelCanvas) {
- return;
- }
-
- let drawContext = audioLevelCanvas.getContext('2d');
-
- let canvasCache = audioLevelCanvasCache[id];
-
- drawContext.clearRect(
- 0, 0, audioLevelCanvas.width, audioLevelCanvas.height
- );
- drawContext.drawImage(canvasCache, 0, 0);
-
- if (id === LOCAL_LEVEL) {
- id = APP.conference.getMyUserId();
- if (!id) {
- return;
- }
- }
-
- if(id === largeVideoId) {
- window.requestAnimationFrame(function () {
- AudioLevels.updateDominantSpeakerAudioLevel(audioLevel);
- });
- }
- },
-
- updateDominantSpeakerAudioLevel (audioLevel) {
- if($("#dominantSpeaker").css("visibility") == "hidden"
- || ASDrawContext === null) {
- return;
- }
-
- ASDrawContext.clearRect(0, 0,
- dominantSpeakerAudioElement.width,
- dominantSpeakerAudioElement.height);
-
- if (!audioLevel) {
- return;
- }
-
- ASDrawContext.shadowBlur = getShadowLevel(audioLevel);
-
- // Fill the shape.
- ASDrawContext.fill();
- },
-
- updateCanvasSize (localVideo, remoteVideo) {
- let localCanvasWidth
- = localVideo.thumbWidth + interfaceConfig.CANVAS_EXTRA;
- let localCanvasHeight
- = localVideo.thumbHeight + interfaceConfig.CANVAS_EXTRA;
- let remoteCanvasWidth
- = remoteVideo.thumbWidth + interfaceConfig.CANVAS_EXTRA;
- let remoteCanvasHeight
- = remoteVideo.thumbHeight + interfaceConfig.CANVAS_EXTRA;
-
- let { remoteThumbs, localThumb } = FilmStrip.getThumbs();
-
- remoteThumbs.children('canvas').each(function () {
- $(this).attr('width', remoteCanvasWidth);
- $(this).attr('height', remoteCanvasHeight);
- });
-
- if(localThumb) {
- localThumb.children('canvas').each(function () {
- $(this).attr('width', localCanvasWidth);
- $(this).attr('height', localCanvasHeight);
- });
- }
- }
- };
-
- export default AudioLevels;
|