Adds smart un-mute to the shared video logic

This commit is contained in:
yanas 2016-04-19 13:07:04 -05:00
parent 7ba8b0a24e
commit d08e37b42b
7 changed files with 107 additions and 57 deletions

View File

@ -73,8 +73,11 @@ function getDisplayName (id) {
/** /**
* Mute or unmute local audio stream if it exists. * Mute or unmute local audio stream if it exists.
* @param {boolean} muted if audio stream should be muted or unmuted. * @param {boolean} muted if audio stream should be muted or unmuted.
* @param {boolean} indicates if this local audio mute was a result of user
* interaction
*
*/ */
function muteLocalAudio (muted) { function muteLocalAudio (muted, userInteraction) {
if (!localAudio) { if (!localAudio) {
return; return;
} }

View File

@ -124,6 +124,9 @@
<ul id="micMutedPopup" class="loginmenu"> <ul id="micMutedPopup" class="loginmenu">
<li data-i18n="[html]toolbar.micMutedPopup"></li> <li data-i18n="[html]toolbar.micMutedPopup"></li>
</ul> </ul>
<ul id="unableToUnmutePopup" class="loginmenu">
<li data-i18n="[html]toolbar.unableToUnmutePopup"></li>
</ul>
</a> </a>
<a class="button icon-camera" id="toolbar_button_camera" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" data-i18n="[content]toolbar.videomute" content="Start / stop camera"></a> <a class="button icon-camera" id="toolbar_button_camera" data-container="body" data-toggle="popover" data-placement="bottom" shortcut="toggleVideoPopover" data-i18n="[content]toolbar.videomute" content="Start / stop camera"></a>
<a class="button" id="toolbar_button_record" data-container="body" data-toggle="popover" data-placement="bottom" style="display: none"></a> <a class="button" id="toolbar_button_record" data-container="body" data-toggle="popover" data-placement="bottom" style="display: none"></a>

View File

@ -65,7 +65,8 @@
"logout": "Logout", "logout": "Logout",
"dialpad": "Show dialpad", "dialpad": "Show dialpad",
"sharedVideoMutedPopup": "Your shared video has been muted so<br/>that you can talk to the other participants.", "sharedVideoMutedPopup": "Your shared video has been muted so<br/>that you can talk to the other participants.",
"micMutedPopup": "Your microphone has been muted so that you<br/>would fully enjoy your shared video." "micMutedPopup": "Your microphone has been muted so that you<br/>would fully enjoy your shared video.",
"unableToUnmutePopup": "You're not able to un-mute while the shared video is on."
}, },
"bottomtoolbar": { "bottomtoolbar": {
"chat": "Open / close chat", "chat": "Open / close chat",

View File

@ -331,6 +331,14 @@ function bindEvents() {
$(window).resize(onResize); $(window).resize(onResize);
} }
/**
* Returns the shared document manager object.
* @return {EtherpadManager} the shared document manager object
*/
UI.getSharedVideoManager = function () {
return sharedVideoManager;
};
/** /**
* Starts the UI module and initializes all related components. * Starts the UI module and initializes all related components.
* *

View File

@ -26,6 +26,24 @@ export default class SharedVideoManager {
this.emitter = emitter; this.emitter = emitter;
this.isSharedVideoShown = false; this.isSharedVideoShown = false;
this.isPlayerAPILoaded = false; this.isPlayerAPILoaded = false;
this.mutedWithUserInteraction = false;
}
/**
* Indicates if the player volume is currently on.
*
* @returns {*|player|boolean}
*/
isSharedVideoVolumeOn() {
return (this.player && this.player.getVolume() > 0);
}
/**
* Indicates if the local user is the owner of the shared video.
* @returns {*|boolean}
*/
isSharedVideoOwner() {
return this.from && APP.conference.isLocalId(this.from);
} }
/** /**
@ -170,9 +188,14 @@ export default class SharedVideoManager {
// let's check, if player is not muted lets mute locally // let's check, if player is not muted lets mute locally
if(event.data.volume > 0 && !event.data.muted if(event.data.volume > 0 && !event.data.muted
&& !APP.conference.isLocalAudioMuted()) { && !APP.conference.isLocalAudioMuted()) {
self.emitter.emit(UIEvents.AUDIO_MUTED, true); self.emitter.emit(UIEvents.AUDIO_MUTED, true, false);
self.showMicMutedPopup(true); self.showMicMutedPopup(true);
} }
else if (!self.mutedWithUserInteraction
&& (event.data.volume <=0 || event.data.muted)
&& APP.conference.isLocalAudioMuted()) {
self.emitter.emit(UIEvents.AUDIO_MUTED, false, false);
}
}; };
window.onPlayerReady = function(event) { window.onPlayerReady = function(event) {
@ -231,9 +254,11 @@ export default class SharedVideoManager {
this.processTime(player, attributes, playerPaused); this.processTime(player, attributes, playerPaused);
// lets check the volume // lets check the volume
if (attributes.volume !== undefined && if (attributes.volume !== undefined
player.getVolume() != attributes.volume && player.getVolume() != attributes.volume
&& APP.conference.isLocalAudioMuted()) { && (APP.conference.isLocalAudioMuted()
|| !this.mutedWithUserInteraction)) {
player.setVolume(attributes.volume); player.setVolume(attributes.volume);
console.info("Player change of volume:" + attributes.volume); console.info("Player change of volume:" + attributes.volume);
this.showSharedVideoMutedPopup(false); this.showSharedVideoMutedPopup(false);
@ -393,13 +418,17 @@ export default class SharedVideoManager {
/** /**
* Receives events for local audio mute/unmute by local user. * Receives events for local audio mute/unmute by local user.
* @param muted boolena whether it is muted or not. * @param muted boolena whether it is muted or not.
* @param {boolean} indicates if this mute was a result of user interaction,
* i.e. pressing the mute button or it was programatically triggerred
*/ */
localAudioMuted (muted) { localAudioMuted (muted, userInteraction) {
if(!this.player) if(!this.player)
return; return;
if(muted) if (muted) {
this.mutedWithUserInteraction = userInteraction;
return; return;
}
// if we are un-muting and player is not muted, lets muted // if we are un-muting and player is not muted, lets muted
// to not pollute the conference // to not pollute the conference
@ -415,30 +444,10 @@ export default class SharedVideoManager {
* @param show boolean, show or hide the notification * @param show boolean, show or hide the notification
*/ */
showMicMutedPopup (show) { showMicMutedPopup (show) {
var micMutedPopupSelector = $("#micMutedPopup"); if(show)
if(show) {
this.showSharedVideoMutedPopup(false); this.showSharedVideoMutedPopup(false);
if (!micMutedPopupSelector.is(":visible")) UIUtil.animateShowElement($("#micMutedPopup"), show, 5000);
micMutedPopupSelector.css("display", "inline-block");
// FIXME: we need an utility method for that.
micMutedPopupSelector.fadeIn(300,
() => {micMutedPopupSelector.css({opacity: 1});}
);
setTimeout(
function () {
micMutedPopupSelector.fadeOut(300,
() => {micMutedPopupSelector.css({opacity: 0});}
);
}, 5000);
}
else {
micMutedPopupSelector.fadeOut(300,
() => {micMutedPopupSelector.css({opacity: 0});}
);
}
} }
/** /**
@ -448,30 +457,10 @@ export default class SharedVideoManager {
* @param show boolean, show or hide the notification * @param show boolean, show or hide the notification
*/ */
showSharedVideoMutedPopup (show) { showSharedVideoMutedPopup (show) {
var sharedVideoMutedPopupSelector = $("#sharedVideoMutedPopup"); if(show)
if(show) {
this.showMicMutedPopup(false); this.showMicMutedPopup(false);
if (!sharedVideoMutedPopupSelector.is(":visible")) UIUtil.animateShowElement($("#sharedVideoMutedPopup"), show, 5000);
sharedVideoMutedPopupSelector.css("display", "inline-block");
// FIXME: we need an utility method for that.
sharedVideoMutedPopupSelector.fadeIn(300,
() => {sharedVideoMutedPopupSelector.css({opacity: 1});}
);
setTimeout(
function () {
sharedVideoMutedPopupSelector.fadeOut(300,
() => {sharedVideoMutedPopupSelector.css({opacity: 0});}
);
}, 5000);
}
else {
sharedVideoMutedPopupSelector.fadeOut(300,
() => {sharedVideoMutedPopupSelector.css({opacity: 0});}
);
}
} }
} }

View File

@ -44,12 +44,25 @@ function openLinkDialog () {
const buttonHandlers = { const buttonHandlers = {
"toolbar_button_mute": function () { "toolbar_button_mute": function () {
let sharedVideoManager = APP.UI.getSharedVideoManager();
if (APP.conference.audioMuted) { if (APP.conference.audioMuted) {
// If there's a shared video with the volume "on" and we aren't
// the video owner, we warn the user
// that currently it's not possible to unmute.
if (sharedVideoManager
&& sharedVideoManager.isSharedVideoVolumeOn()
&& !sharedVideoManager.isSharedVideoOwner()) {
UIUtil.animateShowElement(
$("#unableToUnmutePopup"), true, 5000);
}
else {
AnalyticsAdapter.sendEvent('toolbar.audio.unmuted'); AnalyticsAdapter.sendEvent('toolbar.audio.unmuted');
emitter.emit(UIEvents.AUDIO_MUTED, false); emitter.emit(UIEvents.AUDIO_MUTED, false, true);
}
} else { } else {
AnalyticsAdapter.sendEvent('toolbar.audio.muted'); AnalyticsAdapter.sendEvent('toolbar.audio.muted');
emitter.emit(UIEvents.AUDIO_MUTED, true); emitter.emit(UIEvents.AUDIO_MUTED, true, true);
} }
}, },
"toolbar_button_camera": function () { "toolbar_button_camera": function () {

View File

@ -166,6 +166,39 @@
*/ */
isVisible(el) { isVisible(el) {
return (el.offsetParent !== null); return (el.offsetParent !== null);
},
/**
* Shows / hides the element given by {selector} and sets a timeout if the
* {hideDelay} is set to a value > 0.
* @param selector the jquery selector of the element to show/hide.
* @param show a {boolean} that indicates if the element should be shown or
* hidden
* @param hideDelay the value in milliseconds to wait before hiding the
* element
*/
animateShowElement(selector, show, hideDelay) {
if(show) {
if (!selector.is(":visible"))
selector.css("display", "inline-block");
selector.fadeIn(300,
() => {selector.css({opacity: 1});}
);
if (hideDelay && hideDelay > 0)
setTimeout(
function () {
selector.fadeOut(300,
() => {selector.css({opacity: 0});}
);
}, hideDelay);
}
else {
selector.fadeOut(300,
() => {selector.css({opacity: 0});}
);
}
} }
}; };