770 lines
32 KiB
JavaScript
770 lines
32 KiB
JavaScript
/**
|
|
* FtueAudioSelectionScreen
|
|
* Javascript that goes with the screen where initial
|
|
* selection of the audio devices takes place.
|
|
* Corresponds to /#ftue2
|
|
*/
|
|
(function(context,$) {
|
|
|
|
"use strict";
|
|
|
|
context.JK = context.JK || {};
|
|
context.JK.FtueWizard = function(app) {
|
|
context.JK.FtueWizard.latencyTimeout = true;
|
|
context.JK.FtueWizard.latencyMS = Number.MAX_VALUE;
|
|
var rest = context.JK.Rest();
|
|
|
|
var logger = context.JK.logger;
|
|
var jamClient = context.jamClient;
|
|
var win32 = true;
|
|
|
|
var deviceSetMap = {
|
|
'audio-input': jamClient.FTUESetMusicInput,
|
|
'audio-output': jamClient.FTUESetMusicOutput,
|
|
'voice-chat-input': jamClient.FTUESetChatInput
|
|
};
|
|
|
|
var faderMap = {
|
|
'ftue-2-audio-input-fader': jamClient.FTUESetInputVolume,
|
|
'ftue-2-voice-input-fader': jamClient.FTUESetOutputVolume,
|
|
'ftue-audio-input-fader': jamClient.FTUESetInputVolume,
|
|
'ftue-voice-input-fader': jamClient.FTUESetChatInputVolume,
|
|
'ftue-audio-output-fader': jamClient.FTUESetOutputVolume
|
|
};
|
|
|
|
function latencyTimeoutCheck() {
|
|
if (context.JK.FtueWizard.latencyTimeout) {
|
|
jamClient.FTUERegisterLatencyCallback('');
|
|
context.JK.app.setWizardStep("5");
|
|
}
|
|
}
|
|
|
|
function afterHide(data) {
|
|
// Unsubscribe from FTUE VU callbacks.
|
|
jamClient.FTUERegisterVUCallbacks('','','');
|
|
}
|
|
|
|
function beforeShow(data) {
|
|
var vuMeters = [
|
|
'#ftue-2-audio-input-vu-left',
|
|
'#ftue-2-audio-input-vu-right',
|
|
'#ftue-2-voice-input-vu-left',
|
|
'#ftue-2-voice-input-vu-right',
|
|
'#ftue-audio-input-vu-left',
|
|
'#ftue-audio-input-vu-right',
|
|
'#ftue-voice-input-vu-left',
|
|
'#ftue-voice-input-vu-right',
|
|
'#ftue-audio-output-vu-left',
|
|
'#ftue-audio-output-vu-right'
|
|
];
|
|
$.each(vuMeters, function() {
|
|
context.JK.VuHelpers.renderVU(this,
|
|
{vuType:"horizontal", lightCount: 12, lightWidth: 15, lightHeight: 3});
|
|
});
|
|
|
|
var faders = context._.keys(faderMap);
|
|
$.each(faders, function() {
|
|
var fid = this;
|
|
context.JK.FaderHelpers.renderFader('#' + fid,
|
|
{faderId: fid, faderType:"horizontal", width:163});
|
|
context.JK.FaderHelpers.subscribe(fid, faderChange);
|
|
});
|
|
}
|
|
|
|
function afterShow(data) {}
|
|
|
|
function faderChange(faderId, newValue, dragging) {
|
|
var setFunction = faderMap[faderId];
|
|
// TODO - using hardcoded range of -80 to 20 for output levels.
|
|
var mixerLevel = newValue - 80; // Convert our [0-100] to [-80 - +20] range
|
|
setFunction(mixerLevel);
|
|
}
|
|
|
|
function settingsInit() {
|
|
jamClient.FTUEInit();
|
|
setLevels(0);
|
|
// Always reset the driver select box to "Choose..." which forces everything
|
|
// to sync properly when the user reselects their driver of choice.
|
|
// VRFS-375 and VRFS-561
|
|
$('[layout-wizard="ftue"] [layout-wizard-step="0"] .settings-2-device select').val("");
|
|
$('[layout-wizard="ftue"] [layout-wizard-step="0"] .settings-2-voice select').val("");
|
|
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .asio-settings .settings-driver select').val("");
|
|
}
|
|
|
|
function setLevels(db) {
|
|
if (db < -80 || db > 20) {
|
|
throw ("BUG! ftue.js:setLevels db arg must be between -80 and 20");
|
|
}
|
|
var trackIds = jamClient.SessionGetIDs();
|
|
var controlStates = jamClient.SessionGetControlState(trackIds);
|
|
$.each(controlStates, function(index, value) {
|
|
context.JK.Mixer.fillTrackVolume(value, false);
|
|
// Default input/output to 0 DB
|
|
context.trackVolumeObject.volL = db;
|
|
context.trackVolumeObject.volR = db;
|
|
jamClient.SessionSetControlState(trackIds[index]);
|
|
});
|
|
$.each(context._.keys(faderMap), function(index, faderId) {
|
|
// faderChange takes a value from 0-100
|
|
var $fader = $('[fader-id="' + faderId + '"]');
|
|
context.JK.FaderHelpers.setHandlePosition($fader, db + 80);
|
|
});
|
|
}
|
|
|
|
function testComplete() {
|
|
logger.debug("Test complete");
|
|
var latencyMS = context.JK.FtueWizard.latencyMS;
|
|
var ftueSucceeded = latencyMS <= 20;
|
|
if (ftueSucceeded) {
|
|
logger.debug(latencyMS + " is <= 20. Setting FTUE status to true");
|
|
ftueSave(true); // Save the profile
|
|
context.jamClient.FTUESetStatus(true); // No FTUE wizard next time
|
|
rest.userCertifiedGear({success:true});
|
|
|
|
// notify anyone curious about how it went
|
|
$('div[layout-id=ftue]').trigger('ftue_success');
|
|
}
|
|
else {
|
|
rest.userCertifiedGear({success:false, reason:"latency=" + latencyMS});
|
|
}
|
|
|
|
updateGauge();
|
|
}
|
|
|
|
function updateGauge() {
|
|
var latencyMS = context.JK.FtueWizard.latencyMS;
|
|
// Round to 2 decimal places
|
|
latencyMS = (Math.round(latencyMS * 100)) / 100;
|
|
logger.debug("Latency Value: " + latencyMS);
|
|
if (latencyMS > 20) {
|
|
$('#ftue-latency-congrats').hide();
|
|
$('#ftue-latency-fail').show();
|
|
} else {
|
|
$('#ftue-latency-ms').html(latencyMS);
|
|
$('#ftue-latency-congrats').show();
|
|
$('#ftue-latency-fail').hide();
|
|
if (latencyMS <= 10) {
|
|
$('[layout-wizard-step="6"] .btnHelp').hide();
|
|
$('[layout-wizard-step="6"] .btnRepeat').hide();
|
|
}
|
|
}
|
|
setNeedleValue(latencyMS);
|
|
}
|
|
|
|
// Function to calculate an absolute value and an absolute value range into
|
|
// a number of degrees on a circualar "speedometer" gauge. The 0 degrees value
|
|
// points straight up to the middle of the real-world value range.
|
|
// Arguments:
|
|
// value: The real-world value (e.g. 20 milliseconds)
|
|
// minValue: The real-world minimum value (e.g. 0 milliseconds)
|
|
// maxValue: The real-world maximum value (e.g. 40 milliseconds)
|
|
// degreesUsed: The number of degrees used to represent the full real-world
|
|
// range. 360 would be the entire circle. 270 would be 3/4ths
|
|
// of the circle. The unused gap will be at the bottom of the
|
|
// gauge.
|
|
// (e.g. 300)
|
|
function degreesFromRange(value, minValue, maxValue, degreesUsed) {
|
|
if (value > maxValue) { value = maxValue; }
|
|
if (value < minValue) { value = minValue; }
|
|
var range = maxValue-minValue;
|
|
var floatVal = value/range;
|
|
var degrees = Math.round(floatVal * degreesUsed);
|
|
degrees -= Math.round(degreesUsed/2);
|
|
if (degrees < 0) {
|
|
degrees += 360;
|
|
}
|
|
return degrees;
|
|
}
|
|
|
|
// Given a number of MS, and assuming the gauge has a range from
|
|
// 0 to 40 ms. Update the gauge to the proper value.
|
|
function setNeedleValue(ms) {
|
|
logger.debug("setNeedleValue: " + ms);
|
|
var deg = degreesFromRange(ms, 0, 40, 300);
|
|
|
|
// Supporting Firefix, Chrome, Safari, Opera and IE9+.
|
|
// Should we need to support < IE9, this will need more work
|
|
// to compute the matrix transformations in those browsers -
|
|
// and I don't believe they support transparent PNG graphic
|
|
// rotation, so we'll have to change the needle itself.
|
|
var css = {
|
|
//"behavior":"url(-ms-transform.htc)",
|
|
/* Firefox */
|
|
"-moz-transform":"rotate(" + deg + "deg)",
|
|
/* Safari and Chrome */
|
|
"-webkit-transform":"rotate(" + deg + "deg)",
|
|
/* Opera */
|
|
"-o-transform":"rotate(" + deg + "deg)",
|
|
/* IE9 */
|
|
"-ms-transform":"rotate(" + deg + "deg)"
|
|
/* IE6,IE7 */
|
|
//"filter": "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)",
|
|
/* IE8 */
|
|
//"-ms-filter": '"progid:DXImageTransform.Microsoft.Matrix(SizingMethod=\'auto expand\', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"'
|
|
};
|
|
|
|
$('#ftue-latency-numerical').html(ms);
|
|
$('#ftue-latency-needle').css(css);
|
|
|
|
}
|
|
|
|
function testLatency() {
|
|
// we'll just register for call back right here and unregister in the callback.
|
|
context.JK.FtueWizard.latencyTimeout = true;
|
|
var cbFunc = 'JK.ftueLatencyCallback';
|
|
logger.debug("Registering latency callback: " + cbFunc);
|
|
jamClient.FTUERegisterLatencyCallback('JK.ftueLatencyCallback');
|
|
var now = new Date();
|
|
logger.debug("Starting Latency Test..." + now);
|
|
context.setTimeout(latencyTimeoutCheck, 300 * 1000); // Timeout to 5 minutes
|
|
jamClient.FTUEStartLatency();
|
|
}
|
|
|
|
function openASIOControlPanel(evt) {
|
|
if (win32) {
|
|
logger.debug("Calling FTUEOpenControlPanel()");
|
|
jamClient.FTUEOpenControlPanel();
|
|
}
|
|
}
|
|
|
|
function asioResync(evt) {
|
|
jamClient.FTUERefreshDevices();
|
|
ftueSave(false);
|
|
}
|
|
|
|
function ftueSave(persist) {
|
|
// Explicitly set inputs and outputs to dropdown values
|
|
// before save as the client seems to want this on changes to
|
|
// things like frame size, etc..
|
|
var $audioSelects = $('[layout-wizard-step="2"] .settings-controls select');
|
|
$.each($audioSelects, function(index, value) {
|
|
var $select = $(value);
|
|
setAudioDevice($select);
|
|
});
|
|
if (musicInAndOutSet()) {
|
|
|
|
// If there is no voice-chat-input selected, let the back-end know
|
|
// that we're using music for voice-chat.
|
|
if ($('[layout-wizard-step="2"] select[data-device="voice-chat-input"]').val()) {
|
|
// Voice input selected
|
|
jamClient.TrackSetChatEnable(true);
|
|
} else {
|
|
// No voice input selected.
|
|
jamClient.TrackSetChatEnable(false);
|
|
}
|
|
|
|
logger.debug("Calling FTUESave(" + persist + ")");
|
|
var response = jamClient.FTUESave(persist);
|
|
setLevels(0);
|
|
if (response) {
|
|
logger.warn(response);
|
|
// TODO - we may need to do something about errors on save.
|
|
// per VRFS-368, I'm hiding the alert, and logging a warning.
|
|
// context.alert(response);
|
|
}
|
|
} else {
|
|
logger.debug("Aborting FTUESave as we need input + output selected.");
|
|
}
|
|
}
|
|
|
|
function setAsioFrameSize(evt) {
|
|
var val = parseFloat($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetFrameSize(" + val + ")");
|
|
jamClient.FTUESetFrameSize(val);
|
|
ftueSave(false);
|
|
}
|
|
function setAsioInputLatency(evt) {
|
|
var val = parseInt($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetInputLatency(" + val + ")");
|
|
jamClient.FTUESetInputLatency(val);
|
|
ftueSave(false);
|
|
}
|
|
function setAsioOutputLatency(evt) {
|
|
var val = parseInt($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
|
|
jamClient.FTUESetOutputLatency(val);
|
|
ftueSave(false);
|
|
}
|
|
|
|
function videoLinkClicked(evt) {
|
|
var myOS = jamClient.GetOSAsString();
|
|
var link;
|
|
if (myOS === 'MacOSX') {
|
|
link = $(evt.currentTarget).attr('external-link-mac');
|
|
} else if (myOS === 'Win32') {
|
|
link = $(evt.currentTarget).attr('external-link-win');
|
|
}
|
|
if (link) {
|
|
context.jamClient.OpenSystemBrowser(link);
|
|
}
|
|
}
|
|
|
|
function events() {
|
|
$('.ftue-video-link').hover(
|
|
function(evt) { // handlerIn
|
|
$(this).addClass('hover');
|
|
},
|
|
function(evt) { // handlerOut
|
|
$(this).removeClass('hover');
|
|
}
|
|
);
|
|
$('.ftue-video-link').on('click', videoLinkClicked);
|
|
$('[layout-wizard-step="2"] .settings-driver select').on('change', audioDriverChanged);
|
|
$('[layout-wizard-step="2"] .settings-controls select').on('change', audioDeviceChanged);
|
|
$('#btn-asio-control-panel').on('click', openASIOControlPanel);
|
|
$('#btn-asio-resync').on('click', asioResync);
|
|
$('#asio-framesize').on('change', setAsioFrameSize);
|
|
$('#asio-input-latency').on('change', setAsioInputLatency);
|
|
$('#asio-output-latency').on('change', setAsioOutputLatency);
|
|
// New FTUE events
|
|
$('.ftue-new .settings-2-device select').on('change', newFtueAudioDeviceChanged);
|
|
$('.ftue-new .settings-2-voice select').on('change', newFtueAudioDeviceChanged);
|
|
$('#btn-ftue-2-asio-resync').on('click', newFtueAsioResync);
|
|
$('#btn-ftue-2-asio-control-panel').on('click', openASIOControlPanel);
|
|
$('#ftue-2-asio-framesize').on('change', newFtueSetAsioFrameSize);
|
|
$('#ftue-2-asio-input-latency').on('change', newFtueSetAsioInputLatency);
|
|
$('#ftue-2-asio-output-latency').on('change', newFtueSetAsioOutputLatency);
|
|
$('#btn-ftue-2-save').on('click', newFtueSaveSettingsHandler);
|
|
}
|
|
|
|
/**
|
|
* This function loads the available audio devices from jamClient, and
|
|
* builds up the select dropdowns in the audio-settings step of the FTUE wizard.
|
|
*/
|
|
function loadAudioDevices() {
|
|
var funcs = [
|
|
jamClient.FTUEGetMusicInputs,
|
|
jamClient.FTUEGetChatInputs,
|
|
jamClient.FTUEGetMusicOutputs
|
|
];
|
|
var selectors = [
|
|
'[layout-wizard-step="2"] .audio-input select',
|
|
'[layout-wizard-step="2"] .voice-chat-input select',
|
|
'[layout-wizard-step="2"] .audio-output select'
|
|
];
|
|
var optionsHtml = '';
|
|
var deviceOptionFunc = function(deviceKey, index, list) {
|
|
optionsHtml += '<option title="' + devices[deviceKey] + '" value="' + deviceKey + '">' +
|
|
devices[deviceKey] + '</option>';
|
|
};
|
|
for (var i=0; i<funcs.length; i++) {
|
|
optionsHtml = '<option selected="selected" value="">Choose...</option>';
|
|
|
|
var devices = funcs[i](); // returns hash of device id: device name
|
|
var $select = $(selectors[i]);
|
|
$select.empty();
|
|
var sortedDeviceKeys = context._.keys(devices).sort();
|
|
context._.each(sortedDeviceKeys, deviceOptionFunc);
|
|
$select.html(optionsHtml);
|
|
$select.removeAttr("disabled");
|
|
$('[layout-wizard-step="2"] .settings-asio select').removeAttr("disabled");
|
|
// Set selects to lowest possible values to start:
|
|
$('#asio-framesize').val('2.5').change();
|
|
$('#asio-input-latency').val('0').change();
|
|
$('#asio-output-latency').val('0').change();
|
|
// Special-case for a non-ASIO device, set to 1
|
|
if (jamClient.GetOSAsString() === "Win32") { // Limit this check to Windows only.
|
|
if (!(jamClient.FTUEHasControlPanel())) {
|
|
$('#asio-input-latency').val('1').change();
|
|
$('#asio-output-latency').val('1').change();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load available drivers and populate the driver select box.
|
|
*/
|
|
function loadAudioDrivers() {
|
|
var drivers = jamClient.FTUEGetDevices();
|
|
|
|
var driverOptionFunc = function(driverKey, index, list) {
|
|
optionsHtml += '<option title="' + drivers[driverKey] + '"value="' + driverKey + '">' +
|
|
drivers[driverKey] + '</option>';
|
|
};
|
|
|
|
var optionsHtml = '<option selected="selected" value="">Choose...</option>';
|
|
var selectors = [
|
|
'[layout-wizard-step="0"] .settings-2-device select',
|
|
'[layout-wizard-step="0"] .settings-2-voice select',
|
|
'[layout-wizard-step="2"] .settings-driver select'
|
|
];
|
|
var sortedDeviceKeys = context._.keys(drivers).sort();
|
|
context._.each(sortedDeviceKeys, driverOptionFunc);
|
|
$.each(selectors, function(index, selector) {
|
|
var $select = $(selector);
|
|
$select.empty();
|
|
$select.html(optionsHtml);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handler for the new FTUE save button.
|
|
*/
|
|
function newFtueSaveSettingsHandler(evt) {
|
|
evt.preventDefault();
|
|
var selectedAudioDevice = $('.ftue-new .settings-2-device select').val();
|
|
logger.dbg('newFtueSave. selectedAudioDevice:' + selectedAudioDevice);
|
|
if (!(selectedAudioDevice)) {
|
|
app.notify({
|
|
title: "Please select an audio device",
|
|
text: "Please choose a usable audio device, or select cancel."
|
|
});
|
|
return false;
|
|
}
|
|
jamClient.FTUESave(true);
|
|
jamClient.FTUESetStatus(true); // No FTUE wizard next time
|
|
rest.userCertifiedGear({success:true});
|
|
app.layout.closeDialog('ftue');
|
|
if (app.afterFtue) {
|
|
// If there's a function to invoke, invoke it.
|
|
logger.dbg("afterFTUE function:");
|
|
logger.dbg(app.afterFtue);
|
|
app.afterFtue();
|
|
app.afterFtue = null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Handler for when the audio device is changed in the new FTUE screen
|
|
// This works differently from the old FTUE. There is no input/output selection,
|
|
// as soon as the user chooses a driver, we auto-assign inputs and outputs.
|
|
// We also call jamClient.FTUEGetExpectedLatency, which returns a structure like:
|
|
// { latency: 11.1875, latencyknown: true, latencyvar: 1}
|
|
function newFtueAudioDeviceChanged(evt) {
|
|
var $select = $(evt.currentTarget);
|
|
|
|
var $audioSelect = $('.ftue-new .settings-2-device select');
|
|
var $voiceSelect = $('.ftue-new .settings-2-voice select');
|
|
var audioDriverId = $audioSelect.val();
|
|
var voiceDriverId = $voiceSelect.val();
|
|
jamClient.FTUESetMusicDevice(audioDriverId);
|
|
jamClient.FTUESetChatInput(voiceDriverId);
|
|
if (voiceDriverId) { // Let the back end know whether a voice device is selected
|
|
jamClient.TrackSetChatEnable(true);
|
|
} else {
|
|
jamClient.TrackSetChatEnable(false);
|
|
}
|
|
if (!audioDriverId) {
|
|
// reset back to 'Choose...'
|
|
newFtueEnableControls(false);
|
|
return;
|
|
}
|
|
var musicInputs = jamClient.FTUEGetMusicInputs();
|
|
var musicOutputs = jamClient.FTUEGetMusicOutputs();
|
|
|
|
// set the music input to the first available input,
|
|
// and output to the first available output
|
|
var kin = null, kout = null, k = null;
|
|
// TODO FIXME - this jamClient call returns a dictionary.
|
|
// It's difficult to know what to auto-choose.
|
|
// For example, with my built-in audio, the keys I get back are
|
|
// digital in, line in, mic in and stereo mix. Which should we pick for them?
|
|
for (k in musicInputs) {
|
|
kin = k;
|
|
break;
|
|
}
|
|
for (k in musicOutputs) {
|
|
kout = k;
|
|
break;
|
|
}
|
|
var result;
|
|
if (kin && kout) {
|
|
jamClient.FTUESetMusicInput(kin);
|
|
jamClient.FTUESetMusicOutput(kout);
|
|
} else {
|
|
// TODO FIXME - how to handle a driver selection where we are unable to
|
|
// autoset both inputs and outputs? (I'd think this could happen if either
|
|
// the input or output side returned no values)
|
|
context.alert("TODO - handle 'unable to set both inputs/outputs' case");
|
|
return;
|
|
}
|
|
|
|
newFtueEnableControls(true);
|
|
newFtueOsSpecificSettings();
|
|
setLevels(0);
|
|
newFtueUpdateLatencyView('loading');
|
|
jamClient.FTUESave(false);
|
|
setVuCallbacks();
|
|
|
|
var latency = jamClient.FTUEGetExpectedLatency();
|
|
newFtueUpdateLatencyView(latency);
|
|
|
|
}
|
|
|
|
function newFtueSave(persist) {
|
|
newFtueUpdateLatencyView('loading');
|
|
jamClient.FTUESave(persist);
|
|
var latency = jamClient.FTUEGetExpectedLatency();
|
|
newFtueUpdateLatencyView(latency);
|
|
}
|
|
|
|
function newFtueAsioResync(evt) {
|
|
// In theory, we should be calling the following, but it causes
|
|
// us to not have both inputs/outputs loaded, and simply calling
|
|
// FTUE Save appears to resync things.
|
|
//jamClient.FTUERefreshDevices();
|
|
newFtueSave(false);
|
|
}
|
|
|
|
function newFtueSetAsioFrameSize(evt) {
|
|
var val = parseFloat($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetFrameSize(" + val + ")");
|
|
jamClient.FTUESetFrameSize(val);
|
|
newFtueSave(false);
|
|
}
|
|
function newFtueSetAsioInputLatency(evt) {
|
|
var val = parseInt($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetInputLatency(" + val + ")");
|
|
jamClient.FTUESetInputLatency(val);
|
|
newFtueSave(false);
|
|
}
|
|
function newFtueSetAsioOutputLatency(evt) {
|
|
var val = parseInt($(evt.currentTarget).val(),10);
|
|
if (isNaN(val)) {
|
|
return;
|
|
}
|
|
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
|
|
jamClient.FTUESetOutputLatency(val);
|
|
newFtueSave(false);
|
|
}
|
|
|
|
// Enable or Disable the frame/buffer controls in the new FTUE screen
|
|
function newFtueEnableControls(enable) {
|
|
var $frame = $('#ftue-2-asio-framesize');
|
|
var $bin = $('#ftue-2-asio-input-latency');
|
|
var $bout = $('#ftue-2-asio-output-latency');
|
|
if (enable) {
|
|
$frame.removeAttr("disabled");
|
|
$bin.removeAttr("disabled");
|
|
$bout.removeAttr("disabled");
|
|
} else {
|
|
$frame.attr("disabled", "disabled");
|
|
$bin.attr("disabled", "disabled");
|
|
$bout.attr("disabled", "disabled");
|
|
}
|
|
}
|
|
|
|
// Based on OS and Audio Hardware, set Frame/Buffer settings appropriately
|
|
// and show/hide the ASIO button.
|
|
function newFtueOsSpecificSettings() {
|
|
var $frame = $('#ftue-2-asio-framesize');
|
|
var $bin = $('#ftue-2-asio-input-latency');
|
|
var $bout = $('#ftue-2-asio-output-latency');
|
|
var $asioBtn = $('#btn-ftue-2-asio-control-panel');
|
|
if (jamClient.GetOSAsString() === "Win32") {
|
|
if (jamClient.FTUEHasControlPanel()) {
|
|
// Win32 + ControlPanel = ASIO
|
|
// frame=2.5, buffers=0
|
|
$asioBtn.show();
|
|
$frame.val(2.5);
|
|
$bin.val(0);
|
|
$bout.val(0);
|
|
} else {
|
|
// Win32, no ControlPanel = WDM/Kernel Streaming
|
|
// frame=10, buffers=0
|
|
$asioBtn.hide();
|
|
$frame.val(10);
|
|
// TODO FIXME - the old FTUE set the buffers to 1 for WDM/Kernel streaming
|
|
// The new FTUE spec says to use 0, as I've done here...
|
|
$bin.val(0);
|
|
$bout.val(0);
|
|
}
|
|
} else { // Assuming Mac. TODO: Linux check here
|
|
// frame=2.5, buffers=0
|
|
$asioBtn.hide();
|
|
$frame.val(2.5);
|
|
$bin.val(0);
|
|
$bout.val(0);
|
|
}
|
|
|
|
}
|
|
|
|
// Given a latency structure, update the view.
|
|
function newFtueUpdateLatencyView(latency) {
|
|
var $report = $('.ftue-new .latency .report');
|
|
var $instructions = $('.ftue-new .latency .instructions');
|
|
var latencyClass = "neutral";
|
|
var latencyValue = "N/A";
|
|
if (latency && latency.latencyknown) {
|
|
latencyValue = latency.latency;
|
|
// Round latency to two decimal places.
|
|
latencyValue = Math.round(latencyValue * 100) / 100;
|
|
if (latency.latency <= 10) {
|
|
latencyClass = "good";
|
|
} else if (latency.latency <= 20) {
|
|
latencyClass = "acceptable";
|
|
} else {
|
|
latencyClass = "bad";
|
|
}
|
|
} else {
|
|
// TODO FIXME - handle unknown expected latency
|
|
// latency unknown...
|
|
}
|
|
|
|
$('.ms-label', $report).html(latencyValue);
|
|
$('p', $report).html('milliseconds');
|
|
|
|
$report.removeClass('good acceptable bad');
|
|
$report.addClass(latencyClass);
|
|
|
|
var instructionClasses = ['neutral', 'good', 'acceptable', 'bad', 'start', 'loading'];
|
|
$.each(instructionClasses, function(idx, val) {
|
|
$('p.' + val, $instructions).hide();
|
|
});
|
|
if (latency === 'loading') {
|
|
$('p.loading', $instructions).show();
|
|
} else {
|
|
$('p.' + latencyClass, $instructions).show();
|
|
}
|
|
}
|
|
|
|
function audioDriverChanged(evt) {
|
|
var $select = $(evt.currentTarget);
|
|
var driverId = $select.val();
|
|
jamClient.FTUESetMusicDevice(driverId);
|
|
loadAudioDevices();
|
|
setAsioSettingsVisibility();
|
|
}
|
|
|
|
function audioDeviceChanged(evt) {
|
|
var $select = $(evt.currentTarget);
|
|
setAudioDevice($select);
|
|
if (musicInAndOutSet()) {
|
|
ftueSave(false);
|
|
setVuCallbacks();
|
|
}
|
|
}
|
|
|
|
function setAudioDevice($select) {
|
|
var device = $select.data('device');
|
|
var deviceId = $select.val();
|
|
// Note: We always set, even on the "Choose" value of "", which clears
|
|
// the current setting.
|
|
var setFunction = deviceSetMap[device];
|
|
setFunction(deviceId);
|
|
}
|
|
|
|
/**
|
|
* Return a boolean indicating whether both the MusicInput
|
|
* and MusicOutput devices are set.
|
|
*/
|
|
function musicInAndOutSet() {
|
|
var audioInput = $('[layout-wizard-step="2"] .audio-input select').val();
|
|
var audioOutput = $('[layout-wizard-step="2"] .audio-output select').val();
|
|
return (audioInput && audioOutput);
|
|
}
|
|
|
|
function setVuCallbacks() {
|
|
jamClient.FTUERegisterVUCallbacks(
|
|
"JK.ftueAudioOutputVUCallback",
|
|
"JK.ftueAudioInputVUCallback",
|
|
"JK.ftueChatInputVUCallback"
|
|
);
|
|
jamClient.SetVURefreshRate(200);
|
|
}
|
|
|
|
function setAsioSettingsVisibility() {
|
|
logger.debug("jamClient.FTUEHasControlPanel()=" + jamClient.FTUEHasControlPanel());
|
|
if (jamClient.FTUEHasControlPanel()) {
|
|
logger.debug("Showing ASIO button");
|
|
$('#btn-asio-control-panel').show();
|
|
}
|
|
else {
|
|
logger.debug("Hiding ASIO button");
|
|
$('#btn-asio-control-panel').hide();
|
|
}
|
|
}
|
|
|
|
function initialize() {
|
|
// If not on windows, hide ASIO settings
|
|
if (jamClient.GetOSAsString() != "Win32") {
|
|
logger.debug("Not on Win32 - modifying UI for Mac/Linux");
|
|
win32 = false;
|
|
$('[layout-wizard-step="2"] p[os="win32"]').hide();
|
|
$('[layout-wizard-step="2"] p[os="mac"]').show();
|
|
$('#btn-asio-control-panel').hide();
|
|
$('[layout-wizard-step="2"] .settings-controls select').removeAttr("disabled");
|
|
loadAudioDevices();
|
|
}
|
|
|
|
setAsioSettingsVisibility();
|
|
|
|
events();
|
|
var dialogBindings = { 'beforeShow': beforeShow,
|
|
'afterShow': afterShow, 'afterHide': afterHide };
|
|
app.bindDialog('ftue', dialogBindings);
|
|
app.registerWizardStepFunction("0", settingsInit);
|
|
app.registerWizardStepFunction("2", settingsInit);
|
|
app.registerWizardStepFunction("4", testLatency);
|
|
app.registerWizardStepFunction("6", testComplete);
|
|
loadAudioDrivers();
|
|
}
|
|
|
|
// Expose publics
|
|
this.initialize = initialize;
|
|
|
|
// Expose degreesFromRange outside for testing
|
|
this._degreesFromRange = degreesFromRange;
|
|
|
|
return this;
|
|
};
|
|
|
|
|
|
|
|
// Common VU updater taking a dbValue (-80 to 20) and a CSS selector for the VU.
|
|
context.JK.ftueVUCallback = function(dbValue, selector) {
|
|
// Convert DB into a value from 0.0 - 1.0
|
|
var floatValue = (dbValue + 80) / 100;
|
|
context.JK.VuHelpers.updateVU(selector, floatValue);
|
|
};
|
|
|
|
context.JK.ftueAudioInputVUCallback = function(dbValue) {
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-2-audio-input-vu-left');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-2-audio-input-vu-right');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-audio-input-vu-left');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-audio-input-vu-right');
|
|
};
|
|
context.JK.ftueAudioOutputVUCallback = function(dbValue) {
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-audio-output-vu-left');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-audio-output-vu-right');
|
|
};
|
|
context.JK.ftueChatInputVUCallback = function(dbValue) {
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-2-voice-input-vu-left');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-2-voice-input-vu-right');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-voice-input-vu-left');
|
|
context.JK.ftueVUCallback(dbValue, '#ftue-voice-input-vu-right');
|
|
};
|
|
|
|
// Latency Callback
|
|
context.JK.ftueLatencyCallback = function(latencyMS) {
|
|
// We always show gauge screen if we hit this.
|
|
// Clear out the 'timeout' variable.
|
|
context.JK.FtueWizard.latencyTimeout = false;
|
|
var now = new Date();
|
|
context.console.debug("ftueLatencyCallback: " + now);
|
|
context.JK.FtueWizard.latencyMS = latencyMS;
|
|
|
|
// Unregister callback:
|
|
context.jamClient.FTUERegisterLatencyCallback('');
|
|
// Go to 'congrats' screen -- although latency may be too high.
|
|
context.JK.app.setWizardStep("6");
|
|
};
|
|
|
|
|
|
})(window,jQuery); |