From b6a665e0076c7cb876722ad20d8ba2d43b6169de Mon Sep 17 00:00:00 2001 From: fo Date: Wed, 10 Dec 2014 11:52:40 +0200 Subject: [PATCH] Adds audio levels for the active speaker avatar. --- audio_levels.js | 57 ++++++++++++++++++++++++++++++++----- avatar.js | 1 + css/videolayout_default.css | 8 ++++++ index.html | 9 +++--- videolayout.js | 9 ++++-- 5 files changed, 70 insertions(+), 14 deletions(-) diff --git a/audio_levels.js b/audio_levels.js index e7df33108..5db737793 100644 --- a/audio_levels.js +++ b/audio_levels.js @@ -21,7 +21,7 @@ var AudioLevels = (function(my) { videoSpanId = 'participant_' + resourceJid; } - videoSpan = document.getElementById(videoSpanId); + var videoSpan = document.getElementById(videoSpanId); if (!videoSpan) { if (resourceJid) @@ -35,8 +35,7 @@ var AudioLevels = (function(my) { var audioLevelCanvas = $('#' + videoSpanId + '>canvas'); var videoSpaceWidth = $('#remoteVideos').width(); - var thumbnailSize - = VideoLayout.calculateThumbnailSize(videoSpaceWidth); + var thumbnailSize = VideoLayout.calculateThumbnailSize(videoSpaceWidth); var thumbnailWidth = thumbnailSize[0]; var thumbnailHeight = thumbnailSize[1]; @@ -84,6 +83,50 @@ var AudioLevels = (function(my) { drawContext.clearRect (0, 0, audioLevelCanvas.width, audioLevelCanvas.height); drawContext.drawImage(canvasCache, 0, 0); + + if(resourceJid === AudioLevels.LOCAL_LEVEL) { + resourceJid = Strophe.getResourceFromJid(connection.emuc.myroomjid); + } + + if(resourceJid === VideoLayout.getLargeVideoState().userResourceJid) { + AudioLevels.updateActiveSpeakerAudioLevel(audioLevel); + } + }; + + my.updateActiveSpeakerAudioLevel = function(audioLevel) { + var drawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d'); + var r = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2; + var center = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + r) / 2; + + // Save the previous state of the context. + drawContext.save(); + + drawContext.clearRect(0, 0, 300, 300); + + // Draw a circle. + drawContext.arc(center, center, r, 0, 2 * Math.PI); + + // Add a shadow around the circle + drawContext.shadowColor = interfaceConfig.SHADOW_COLOR; + drawContext.shadowBlur = getShadowLevel(audioLevel); + drawContext.shadowOffsetX = 0; + drawContext.shadowOffsetY = 0; + + // Fill the shape. + drawContext.fill(); + + drawContext.save(); + + drawContext.restore(); + + + drawContext.arc(center, center, r, 0, 2 * Math.PI); + + drawContext.clip(); + drawContext.clearRect(0, 0, 277, 200); + + // Restore the previous context state. + drawContext.restore(); }; /** @@ -94,7 +137,7 @@ var AudioLevels = (function(my) { thumbnailHeight) { audioLevelCanvas.width = thumbnailWidth + interfaceConfig.CANVAS_EXTRA; audioLevelCanvas.height = thumbnailHeight + interfaceConfig.CANVAS_EXTRA; - }; + } /** * Draws the audio level canvas into the cached canvas object. @@ -143,7 +186,7 @@ var AudioLevels = (function(my) { interfaceConfig.CANVAS_RADIUS, interfaceConfig.SHADOW_COLOR, shadowLevel); - }; + } /** * Returns the shadow/glow level for the given audio level. @@ -164,7 +207,7 @@ var AudioLevels = (function(my) { shadowLevel = Math.round(interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4)); } return shadowLevel; - }; + } /** * Returns the video span id corresponding to the given resourceJid or local @@ -180,7 +223,7 @@ var AudioLevels = (function(my) { videoSpanId = 'participant_' + resourceJid; return videoSpanId; - }; + } /** * Indicates that the remote video has been resized. diff --git a/avatar.js b/avatar.js index 190367ccc..98be20478 100644 --- a/avatar.js +++ b/avatar.js @@ -78,6 +78,7 @@ var Avatar = (function(my) { if (activeSpeakerJid === jid && VideoLayout.isLargeVideoOnTop()) { setVisibility($("#largeVideo"), !show); setVisibility($('#activeSpeakerAvatar'), show); + setVisibility($('#activeSpeakerAudioLevel'), show); setVisibility(avatar, false); setVisibility(video, false); } else { diff --git a/css/videolayout_default.css b/css/videolayout_default.css index 24b451de6..d26eeb7cc 100644 --- a/css/videolayout_default.css +++ b/css/videolayout_default.css @@ -377,6 +377,13 @@ pointer-events: none; } +#activeSpeakerAudioLevel { + visibility: hidden; + position: absolute; + top: 113px; + z-index: 1; +} + #mixedstream { display:none !important; } @@ -388,6 +395,7 @@ margin: auto; position: relative; border-radius: 50px; + z-index: 2; } .userAvatar { diff --git a/index.html b/index.html index d60835465..b08db0c19 100644 --- a/index.html +++ b/index.html @@ -49,12 +49,12 @@ - + - + @@ -66,11 +66,11 @@ - + - + @@ -265,6 +265,7 @@
powered by jitsi.org +
diff --git a/videolayout.js b/videolayout.js index d67c13d24..308a43372 100644 --- a/videolayout.js +++ b/videolayout.js @@ -174,6 +174,7 @@ var VideoLayout = (function (my) { if (RTC.getVideoSrc($('#largeVideo')[0]) !== newSrc) { $('#activeSpeakerAvatar').css('visibility', 'hidden'); + $('#activeSpeakerAudioLevel').css('visibility', 'hidden'); // Due to the simulcast the localVideoSrc may have changed when the // fadeOut event triggers. In that case the getJidFromVideoSrc and // isVideoSrcDesktop methods will not function correctly. @@ -1038,9 +1039,11 @@ var VideoLayout = (function (my) { $('#largeVideoContainer').width(availableWidth); $('#largeVideoContainer').height(availableHeight); - - $('#activeSpeakerAvatar').css('top', - (availableHeight - interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE) / 2); + var avatarSize = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE; + var top = (availableHeight - avatarSize) / 2; + $('#activeSpeakerAvatar').css('top', top); + $('#activeSpeakerAudioLevel').css('top', top - avatarSize / 4); + $('#activeSpeakerAudioLevel').css('left', availableWidth / 2 - avatarSize * 3 / 4); VideoLayout.resizeThumbnails(); };