406 lines
14 KiB
JavaScript
406 lines
14 KiB
JavaScript
(function (context, $) {
|
|
|
|
"use strict";
|
|
|
|
context.JK = context.JK || {};
|
|
context.JK.VoiceChatHelper = function (app) {
|
|
var logger = context.JK.logger;
|
|
var ALERT_NAMES = context.JK.ALERT_NAMES;
|
|
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
|
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
|
var MAX_TRACKS = context.JK.MAX_TRACKS;
|
|
var MAX_OUTPUTS = context.JK.MAX_OUTPUTS;
|
|
var gearUtils = context.JK.GearUtils;
|
|
|
|
var $parent = null;
|
|
|
|
var $reuseAudioInputRadio = null;
|
|
var $useChatInputRadio = null;
|
|
var $chatInputs = null;
|
|
var $templateChatInput = null;
|
|
var $selectedChatInput = null;// should only be used if isChatEnabled = true
|
|
var $voiceChatVuLeft = null;
|
|
var $voiceChatVuRight = null;
|
|
var $voiceChatFader = null;
|
|
|
|
var saveImmediate = null; // if true, then every action by the user results in a save to the backend immediately, false means you have to call trySave to persist
|
|
var uniqueCallbackName = null;
|
|
// needed because iCheck fires iChecked event even when you programmatically change it, unlike when using .val(x)
|
|
var ignoreICheckEvent = false;
|
|
var lastSavedTime = new Date();
|
|
var vuOptions = null;
|
|
var faderHeight = null;
|
|
var startingState = null;
|
|
var resettedOnInvalidDevice = false; // this is set to true when we clear chat, and set to false when the user interacts in anyway
|
|
|
|
function defaultReuse() {
|
|
suppressChange(function(){
|
|
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
|
$useChatInputRadio.removeAttr('checked');
|
|
})
|
|
}
|
|
|
|
function isChatEnabled() {
|
|
return $useChatInputRadio.is(':checked');
|
|
}
|
|
|
|
function onInvalidAudioDevice(e, data) {
|
|
logger.debug("voice_chat_helper: onInvalidAudioDevice")
|
|
|
|
if(resettedOnInvalidDevice) {
|
|
// we've already tried to clear the audio device, and the user hasn't interacted, but still we are getting this event
|
|
// we can't keep taking action, so stop
|
|
logger.error("voice_chat_helper: onInvalidAudioDevice: ignoring event because we have already tried to handle it");
|
|
return;
|
|
}
|
|
resettedOnInvalidDevice = true;
|
|
|
|
$selectedChatInput = null;
|
|
// you can't do this in the event callback; it hangs the app indefinitely, and somehow 'sticks' the mic input into bad state until reboot
|
|
setTimeout(function() {
|
|
context.jamClient.FTUEClearChatInput();
|
|
context.jamClient.TrackSetChatEnable(true);
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
|
|
if(!result || result.length == 0) {
|
|
context.JK.Banner.showAlert('It appears the selected chat input is not functioning. Please try another chat input.');
|
|
}
|
|
else {
|
|
context.JK.alertSupportedNeeded("Unable to unwind invalid chat input selection.")
|
|
}
|
|
}, 1);
|
|
}
|
|
|
|
function beforeShow() {
|
|
userInteracted();
|
|
renderNoVolume();
|
|
context.JK.onBackendEvent(ALERT_NAMES.AUDIO_DEVICE_NOT_PRESENT, 'voice_chat_helper', onInvalidAudioDevice);
|
|
registerVuCallbacks();
|
|
}
|
|
function beforeHide() {
|
|
context.JK.offBackendEvent(ALERT_NAMES.AUDIO_DEVICE_NOT_PRESENT, 'voice_chat_helper', onInvalidAudioDevice);
|
|
jamClient.FTUERegisterVUCallbacks('', '', '');
|
|
}
|
|
|
|
function userInteracted() {
|
|
resettedOnInvalidDevice = false;
|
|
}
|
|
|
|
function reset(forceDisabledChat) {
|
|
|
|
$selectedChatInput = null;
|
|
|
|
if(!forceDisabledChat && context.jamClient.TrackGetChatEnable()) {
|
|
enableChat(false);
|
|
}
|
|
else {
|
|
disableChat(false);
|
|
}
|
|
|
|
$chatInputs.empty();
|
|
|
|
var chatInputs = gearUtils.getChatInputs();
|
|
|
|
context._.each(chatInputs, function(chatInput) {
|
|
if(chatInput.assignment > 0) {
|
|
return;
|
|
}
|
|
var chatChannelName = chatInput.name;
|
|
var chatChannelId = chatInput.id;
|
|
var isCurrentlyChat = chatInput.assignment == ASSIGNMENT.CHAT;
|
|
var $chat = $(context._.template($templateChatInput.html(), {id: chatChannelId, name: chatChannelName}, { variable: 'data' }));
|
|
var $chatInput = $chat.find('input');
|
|
if(isCurrentlyChat) {
|
|
$selectedChatInput = $chatInput;
|
|
$selectedChatInput.attr('checked', 'checked');
|
|
}
|
|
//$chat.hide(); // we'll show it once it's styled with iCheck
|
|
$chatInputs.append($chat);
|
|
});
|
|
|
|
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
|
context.JK.checkbox($radioButtons).on('ifChecked', function(e) {
|
|
userInteracted();
|
|
var $input = $(e.currentTarget);
|
|
$selectedChatInput = $input; // for use in handleNext
|
|
if(saveImmediate) {
|
|
var channelId = $input.attr('data-channel-id');
|
|
lastSavedTime = new Date();
|
|
context.jamClient.TrackSetChatInput(channelId);
|
|
lastSavedTime = new Date();
|
|
//context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.CHAT);
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
|
|
if(!result || result.length == 0) {
|
|
// success
|
|
}
|
|
else {
|
|
context.jamClient.FTUEClearChatInput();
|
|
context.jamClient.TrackSetChatEnable(true);
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
if(!result || result.length == 0) {
|
|
context.JK.Banner.showAlert('Unable to save chat selection. ' + result);
|
|
}
|
|
else {
|
|
context.JK.alertSupportedNeeded("Unable to unwind invalid chat selection.")
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
|
|
if(!isChatEnabled()) {
|
|
disableChatButtonsUI();
|
|
}
|
|
|
|
renderVolumes();
|
|
|
|
startingState = getCurrentState();
|
|
}
|
|
|
|
function disableChatButtonsUI() {
|
|
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
|
$radioButtons.iCheck('disable')
|
|
$chatInputs.addClass('disabled');
|
|
$radioButtons.iCheck('uncheck');
|
|
$selectedChatInput = null;
|
|
}
|
|
|
|
function enableChatButtonsUI() {
|
|
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
|
$radioButtons.iCheck('enable')
|
|
$chatInputs.removeClass('disabled');
|
|
|
|
}
|
|
function suppressChange(proc) {
|
|
|
|
ignoreICheckEvent = true;
|
|
|
|
try {
|
|
proc();
|
|
}
|
|
finally {
|
|
ignoreICheckEvent = false;
|
|
}
|
|
}
|
|
|
|
function disableChat(applyToBackend) {
|
|
if(saveImmediate && applyToBackend) {
|
|
logger.debug("voiceChatHelper: disabling chat to backend");
|
|
var state = getCurrentState();
|
|
//context.jamClient.TrackSetChatEnable(false);
|
|
//if(state.chat_channel) {
|
|
// context.jamClient.TrackSetAssignment(state.chat_channel, true, ASSIGNMENT.UNASSIGNED);
|
|
//}
|
|
context.jamClient.FTUEClearChatInput();
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
|
|
if(!result || result.length == 0) {
|
|
renderNoVolume();
|
|
// success
|
|
suppressChange(function() {
|
|
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
|
$useChatInputRadio.removeAttr('checked');
|
|
})
|
|
}
|
|
else {
|
|
context.JK.Banner.showAlert('Unable to disable chat. ' + result);
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
logger.debug("voiceChatHelper: disabling chat UI only");
|
|
suppressChange(function() {
|
|
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
|
$useChatInputRadio.removeAttr('checked');
|
|
})
|
|
}
|
|
disableChatButtonsUI();
|
|
}
|
|
|
|
function enableChat(applyToBackend) {
|
|
if(saveImmediate && applyToBackend) {
|
|
logger.debug("voiceChatHelper: enabling chat to backend");
|
|
context.jamClient.TrackSetChatEnable(true);
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
|
|
if(!result || result.length == 0) {
|
|
// success
|
|
suppressChange(function() {
|
|
$useChatInputRadio.iCheck('check').attr('checked', 'checked');
|
|
$reuseAudioInputRadio.removeAttr('checked');
|
|
})
|
|
}
|
|
else {
|
|
context.JK.Banner.showAlert('Unable to enable chat. ' + result);
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
logger.debug("voiceChatHelper: enabling chat UI only");
|
|
suppressChange(function() {
|
|
$useChatInputRadio.iCheck('check').attr('checked', 'checked');
|
|
$reuseAudioInputRadio.removeAttr('checked');
|
|
})
|
|
}
|
|
|
|
enableChatButtonsUI();
|
|
renderVolumes();
|
|
}
|
|
|
|
function handleChatEnabledToggle() {
|
|
context.JK.checkbox($reuseAudioInputRadio);
|
|
context.JK.checkbox($useChatInputRadio);
|
|
|
|
// plugin sets to relative on the element; have to do this as an override
|
|
$reuseAudioInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
|
$useChatInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
|
|
|
$reuseAudioInputRadio.on('ifChecked', function() {
|
|
if(!ignoreICheckEvent) {
|
|
userInteracted();
|
|
disableChat(true);
|
|
}
|
|
});
|
|
$useChatInputRadio.on('ifChecked', function() {
|
|
if(!ignoreICheckEvent) {
|
|
userInteracted();
|
|
enableChat(true)
|
|
}
|
|
});
|
|
}
|
|
|
|
// gets the state of the UI
|
|
function getCurrentState() {
|
|
var state = {
|
|
enabled:null,
|
|
chat_channel:null
|
|
};
|
|
|
|
state.enabled = $useChatInputRadio.is(':checked');
|
|
state.chat_channel = $selectedChatInput && $selectedChatInput.attr('data-channel-id');
|
|
logger.debug("desired chat state: enabled=" + state.enabled + ", chat_channel=" + state.chat_channel)
|
|
return state;
|
|
}
|
|
|
|
function cancel() {
|
|
logger.debug("canceling voice chat state");
|
|
return trySave(startingState);
|
|
}
|
|
|
|
|
|
function trySave(state) {
|
|
|
|
if(!state) {
|
|
state = getCurrentState();
|
|
}
|
|
|
|
if(state.enabled && state.chat_channel) {
|
|
logger.debug("enabling chat. chat_channel=" + state.chat_channel);
|
|
context.jamClient.TrackSetChatEnable(true);
|
|
context.jamClient.FTUESetChatInput(state.chat_channel);
|
|
//context.jamClient.TrackSetAssignment(state.chat_channel, true, ASSIGNMENT.CHAT);
|
|
}
|
|
else {
|
|
logger.debug("disabling chat.");
|
|
context.jamClient.FTUEClearChatInput();
|
|
//context.jamClient.TrackSetChatEnable(false);
|
|
//if(state.chat_channel) {
|
|
//context.jamClient.TrackSetAssignment(state.chat_channel, true, ASSIGNMENT.UNASSIGNED);
|
|
//}
|
|
}
|
|
|
|
var result = context.jamClient.TrackSaveAssignments();
|
|
|
|
if(!result || result.length == 0) {
|
|
// success
|
|
if(!state.enabled) {
|
|
renderNoVolume();
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
context.JK.Banner.showAlert('Unable to save chat assignments. ' + result);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function initializeVUMeters() {
|
|
context.JK.VuHelpers.renderVU($voiceChatVuLeft, vuOptions);
|
|
context.JK.VuHelpers.renderVU($voiceChatVuRight, vuOptions);
|
|
|
|
context.JK.FaderHelpers.renderFader($voiceChatFader, {faderId: '', faderType: "vertical", height: faderHeight});
|
|
$voiceChatFader.on('fader_change', faderChange);
|
|
}
|
|
|
|
// renders volumes based on what the backend says
|
|
function renderVolumes() {
|
|
var $fader = $voiceChatFader.find('[control="fader"]');
|
|
var db = context.jamClient.FTUEGetChatInputVolume();
|
|
var faderPct = db + 80;
|
|
context.JK.FaderHelpers.setHandlePosition($fader, faderPct);
|
|
}
|
|
|
|
function renderNoVolume() {
|
|
var $fader = $voiceChatFader.find('[control="fader"]');
|
|
context.JK.FaderHelpers.setHandlePosition($fader, 50);
|
|
context.JK.VuHelpers.updateVU($voiceChatVuLeft, 0);
|
|
context.JK.VuHelpers.updateVU($voiceChatVuRight, 0);
|
|
|
|
}
|
|
|
|
function faderChange(e, data) {
|
|
// TODO - using hardcoded range of -80 to 20 for output levels.
|
|
var mixerLevel = data.percentage - 80; // Convert our [0-100] to [-80 - +20] range
|
|
context.jamClient.FTUESetChatInputVolume(mixerLevel);
|
|
}
|
|
|
|
function registerVuCallbacks() {
|
|
logger.debug("voice-chat-helper: registering vu callbacks");
|
|
jamClient.FTUERegisterVUCallbacks(
|
|
"JK.voiceChatHelperAudioOutputVUCallback",
|
|
"JK.voiceChatHelperAudioInputVUCallback",
|
|
"JK." + uniqueCallbackName
|
|
);
|
|
jamClient.SetVURefreshRate(200);
|
|
}
|
|
|
|
function initialize(_$step, caller, _saveImmediate, _vuOptions, _faderHeight) {
|
|
$parent = _$step;
|
|
saveImmediate = _saveImmediate;
|
|
vuOptions = _vuOptions;
|
|
faderHeight = _faderHeight;
|
|
$reuseAudioInputRadio = $parent.find('.reuse-audio-input input');
|
|
$useChatInputRadio = $parent.find('.use-chat-input input');
|
|
$chatInputs = $parent.find('.chat-inputs');
|
|
$templateChatInput = $('#template-chat-input');
|
|
$voiceChatVuLeft = $parent.find('.voice-chat-vu-left');
|
|
$voiceChatVuRight = $parent.find('.voice-chat-vu-right');
|
|
$voiceChatFader = $parent.find('.chat-fader')
|
|
|
|
handleChatEnabledToggle();
|
|
initializeVUMeters();
|
|
renderVolumes();
|
|
|
|
uniqueCallbackName = 'voiceChatHelperChatInputVUCallback' + caller;
|
|
context.JK[uniqueCallbackName] = function(dbValue) {
|
|
context.JK.ftueVUCallback(dbValue, $voiceChatVuLeft);
|
|
context.JK.ftueVUCallback(dbValue, $voiceChatVuRight);
|
|
}
|
|
}
|
|
|
|
context.JK.voiceChatHelperAudioInputVUCallback = function (dbValue) {};
|
|
context.JK.voiceChatHelperAudioOutputVUCallback = function (dbValue) {};
|
|
|
|
|
|
this.reset = reset;
|
|
this.trySave = trySave;
|
|
this.cancel = cancel;
|
|
this.initialize = initialize;
|
|
this.beforeShow = beforeShow;
|
|
this.beforeHide = beforeHide;
|
|
|
|
return this;
|
|
};
|
|
|
|
})(window, jQuery); |