diff options
-rw-r--r-- | css/video.scss | 27 | ||||
-rw-r--r-- | js/views/mediacontrolsview.js | 23 | ||||
-rw-r--r-- | js/views/templates.js | 4 | ||||
-rw-r--r-- | js/views/templates/mediacontrolsview.handlebars | 5 |
4 files changed, 56 insertions, 3 deletions
diff --git a/css/video.scss b/css/video.scss index 8a0d909a4..981e50b4e 100644 --- a/css/video.scss +++ b/css/video.scss @@ -446,3 +446,30 @@ video { opacity: 1; } } + + + +#muteWrapper { + display: inline-block; + + /* Make the wrapper the positioning context of the volume indicator. */ + position: relative; +} + +#muteWrapper .volume-indicator { + position: absolute; + + width: 3px; + right: 0px; + + /* The button height is 44px; the volume indicator button is 36px at + * maximum, but its value will be changed based on the current volume; the + * height change will reveal more or less of the gradient, which has + * absolute dimensions and thus does not change when the height changes. */ + height: 36px; + bottom: 4px; + + background: linear-gradient(0deg, green, yellow, red 36px); + + opacity: 0.7; +} diff --git a/js/views/mediacontrolsview.js b/js/views/mediacontrolsview.js index 5335af592..58f26ec84 100644 --- a/js/views/mediacontrolsview.js +++ b/js/views/mediacontrolsview.js @@ -56,6 +56,7 @@ ui: { 'audioButton': '#mute', + 'volumeIndicator': '#muteWrapper .volume-indicator', 'videoButton': '#hideVideo', 'screensharingButton': '#screensharing-button', 'screensharingMenu': '#screensharing-menu', @@ -84,6 +85,8 @@ this._webrtc = options.webrtc; this._sharedScreens = options.sharedScreens; + this._handleVolumeChangeBound = this._handleVolumeChange.bind(this); + this._audioAvailable = true; this._videoAvailable = true; @@ -92,7 +95,13 @@ }, setWebRtc: function(webrtc) { + if (this._webrtc && this._webrtc.webrtc) { + this._webrtc.webrtc.off('volumeChange', this._handleVolumeChangeBound); + } + this._webrtc = webrtc; + + this._webrtc.webrtc.on('volumeChange', this._handleVolumeChangeBound); }, setSharedScreens: function(sharedScreens) { @@ -153,6 +162,20 @@ this._audioAvailable = audioAvailable; }, + _handleVolumeChange: function(currentVolume, threshold) { + // WebRTC volume goes from -100 (silence) to 0 (loudest sound in the + // system); for the volume indicator only sounds above the threshold + // are taken into account. + var currentVolumeProportion = 0; + if (currentVolume > threshold) { + currentVolumeProportion = (threshold - currentVolume) / threshold; + } + + var maximumVolumeIndicatorHeight = this.getUI('volumeIndicator').parent().outerHeight() - (parseInt(this.getUI('volumeIndicator').css('bottom'), 10) * 2); + + this.getUI('volumeIndicator').height(maximumVolumeIndicatorHeight * currentVolumeProportion); + }, + toggleVideo: function() { if (!this._videoAvailable) { return; diff --git a/js/views/templates.js b/js/views/templates.js index bd497b66e..f88adf8c8 100644 --- a/js/views/templates.js +++ b/js/views/templates.js @@ -243,9 +243,9 @@ templates['localvideoview'] = template({"compiler":[7,">= 4.0.0"],"main":functio templates['mediacontrolsview'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; - return "<button id=\"mute\" class=\"icon-audio force-icon-white-in-call icon-shadow\" data-placement=\"top\" data-toggle=\"tooltip\" data-original-title=\"" + return "<div id=\"muteWrapper\">\n <button id=\"mute\" class=\"icon-audio force-icon-white-in-call icon-shadow\" data-placement=\"top\" data-toggle=\"tooltip\" data-original-title=\"" + alias4(((helper = (helper = helpers.muteAudioButtonTitle || (depth0 != null ? depth0.muteAudioButtonTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"muteAudioButtonTitle","hash":{},"data":data}) : helper))) - + "\"></button>\n<button id=\"hideVideo\" class=\"icon-video force-icon-white-in-call icon-shadow\" data-placement=\"top\" data-toggle=\"tooltip\" data-original-title=\"" + + "\"></button>\n <span class=\"volume-indicator\"></span>\n</div>\n<button id=\"hideVideo\" class=\"icon-video force-icon-white-in-call icon-shadow\" data-placement=\"top\" data-toggle=\"tooltip\" data-original-title=\"" + alias4(((helper = (helper = helpers.hideVideoButtonTitle || (depth0 != null ? depth0.hideVideoButtonTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"hideVideoButtonTitle","hash":{},"data":data}) : helper))) + "\"></button>\n<button id=\"screensharing-button\" class=\"app-navigation-entry-utils-menu-button icon-screen-off force-icon-white-in-call icon-shadow screensharing-disabled\" data-placement=\"top\" data-toggle=\"tooltip\" data-original-title=\"" + alias4(((helper = (helper = helpers.screensharingButtonTitle || (depth0 != null ? depth0.screensharingButtonTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"screensharingButtonTitle","hash":{},"data":data}) : helper))) diff --git a/js/views/templates/mediacontrolsview.handlebars b/js/views/templates/mediacontrolsview.handlebars index b6c0e58c5..593667139 100644 --- a/js/views/templates/mediacontrolsview.handlebars +++ b/js/views/templates/mediacontrolsview.handlebars @@ -1,4 +1,7 @@ -<button id="mute" class="icon-audio force-icon-white-in-call icon-shadow" data-placement="top" data-toggle="tooltip" data-original-title="{{muteAudioButtonTitle}}"></button> +<div id="muteWrapper"> + <button id="mute" class="icon-audio force-icon-white-in-call icon-shadow" data-placement="top" data-toggle="tooltip" data-original-title="{{muteAudioButtonTitle}}"></button> + <span class="volume-indicator"></span> +</div> <button id="hideVideo" class="icon-video force-icon-white-in-call icon-shadow" data-placement="top" data-toggle="tooltip" data-original-title="{{hideVideoButtonTitle}}"></button> <button id="screensharing-button" class="app-navigation-entry-utils-menu-button icon-screen-off force-icon-white-in-call icon-shadow screensharing-disabled" data-placement="top" data-toggle="tooltip" data-original-title="{{screensharingButtonTitle}}"></button> <div id="screensharing-menu" class="app-navigation-entry-menu"> |