123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /* global APP, interfaceConfig, $ */
- /* jshint -W101 */
-
- import CanvasUtil from './CanvasUtils';
-
- const LOCAL_LEVEL = 'local';
-
- let ASDrawContext = null;
- let audioLevelCanvasCache = {};
-
- function initActiveSpeakerAudioLevels() {
- let ASRadius = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2;
- let ASCenter = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + ASRadius) / 2;
-
- // Draw a circle.
- ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI);
-
- // 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;
- }
-
- /**
- * Indicates that the remote video has been resized.
- */
- $(document).bind('remotevideo.resized', function (event, width, height) {
- let resized = false;
-
- $('#remoteVideos>span>canvas').each(function() {
- let canvas = $(this).get(0);
- if (canvas.width !== width + interfaceConfig.CANVAS_EXTRA) {
- canvas.width = width + interfaceConfig.CANVAS_EXTRA;
- resized = true;
- }
-
- if (canvas.height !== height + interfaceConfig.CANVAS_EXTRA) {
- canvas.height = height + interfaceConfig.CANVAS_EXTRA;
- resized = true;
- }
- });
-
- if (resized) {
- Object.keys(audioLevelCanvasCache).forEach(function (id) {
- audioLevelCanvasCache[id].width = width + interfaceConfig.CANVAS_EXTRA;
- audioLevelCanvasCache[id].height = height + interfaceConfig.CANVAS_EXTRA;
- });
- }
- });
-
- /**
- * The audio Levels plugin.
- */
- const AudioLevels = {
-
- init () {
- ASDrawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d');
- initActiveSpeakerAudioLevels();
- },
-
- /**
- * Updates the audio level canvas for the given id. If the canvas
- * didn't exist we create it.
- */
- updateAudioLevelCanvas (id, VideoLayout) {
- let videoSpanId = 'localVideoContainer';
- if (id) {
- videoSpanId = `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`);
-
- let videoSpaceWidth = $('#remoteVideos').width();
- let thumbnailSize = VideoLayout.calculateThumbnailSize(videoSpaceWidth);
- let thumbnailWidth = thumbnailSize[0];
- let thumbnailHeight = thumbnailSize[1];
-
- 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, thumbnailWidth, thumbnailHeight);
-
- videoSpan.appendChild(audioLevelCanvas);
- } else {
- audioLevelCanvas = audioLevelCanvas.get(0);
-
- resizeAudioLevelCanvas(audioLevelCanvas, thumbnailWidth, thumbnailHeight);
- }
- },
-
- /**
- * 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.localId;
- if (!id) {
- return;
- }
- }
-
- if(id === largeVideoId) {
- window.requestAnimationFrame(function () {
- AudioLevels.updateActiveSpeakerAudioLevel(audioLevel);
- });
- }
- },
-
- updateActiveSpeakerAudioLevel (audioLevel) {
- if($("#activeSpeaker").css("visibility") == "hidden" || ASDrawContext === null) {
- return;
- }
-
- ASDrawContext.clearRect(0, 0, 300, 300);
- if (!audioLevel) {
- return;
- }
-
- ASDrawContext.shadowBlur = getShadowLevel(audioLevel);
-
-
- // Fill the shape.
- ASDrawContext.fill();
- }
- };
-
- export default AudioLevels;
|