* wip
This commit is contained in:
parent
d39f91e186
commit
df5fae1981
|
|
@ -67,7 +67,7 @@
|
|||
|
||||
function handleStartAudioQualification() {
|
||||
|
||||
if(true) {
|
||||
if(false) {
|
||||
app.layout.startNewFtue();
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
//= require jquery.monkeypatch
|
||||
//= require jquery_ujs
|
||||
//= require jquery.ui.draggable
|
||||
//= require jquery.ui.droppable
|
||||
//= require jquery.bt
|
||||
//= require jquery.icheck
|
||||
//= require jquery.color
|
||||
|
|
|
|||
|
|
@ -124,6 +124,83 @@
|
|||
"Multichannel (FW AP Multi) - Channel 1/Multichannel (FW AP Multi) - Channel 2"
|
||||
};
|
||||
}
|
||||
function FTUEGetChannels() {
|
||||
return {
|
||||
"inputs": [
|
||||
{
|
||||
"assignment": 1,
|
||||
"chat": false,
|
||||
"device_id": "Built-in Microph",
|
||||
"device_type": 5,
|
||||
"id": "i~5~Built-in Microph~0~0~Built-in",
|
||||
"name": "Built-in Microph - Left",
|
||||
"number": 0
|
||||
},
|
||||
{
|
||||
"assignment": 0,
|
||||
"chat": false,
|
||||
"device_id": "Built-in Microph",
|
||||
"device_type": 5,
|
||||
"id": "i~5~Built-in Microph~1~0~Built-in",
|
||||
"name": "Built-in Microph - Right",
|
||||
"number": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"assignment": -1,
|
||||
"chat": false,
|
||||
"device_id": "Built-in Output",
|
||||
"device_type": 5,
|
||||
"id": "o~5~Built-in Output~0~0~Built-in",
|
||||
"name": "Built-in Output - Left",
|
||||
"number": 0
|
||||
},
|
||||
{
|
||||
"assignment": -1,
|
||||
"chat": false,
|
||||
"device_id": "Built-in Output",
|
||||
"device_type": 5,
|
||||
"id": "o~5~Built-in Output~1~0~Built-in",
|
||||
"name": "Built-in Output - Right",
|
||||
"number": 1
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
function FTUEGetAudioDevices() {
|
||||
return {
|
||||
"devices": [
|
||||
{
|
||||
"display_name": "Built-in",
|
||||
"guid": "Built-in",
|
||||
"input_count": 1,
|
||||
"name": "Built-in",
|
||||
"output_count": 1,
|
||||
"port_audio_name": "Built-in"
|
||||
},
|
||||
{
|
||||
"display_name": "JamKazam Virtual Monitor",
|
||||
"guid": "JamKazam Virtual Monitor",
|
||||
"input_count": 0,
|
||||
"name": "JamKazam Virtual Monitor",
|
||||
"output_count": 1,
|
||||
"port_audio_name": "JamKazam Virtual Monitor"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
function FTUEStartIoPerfTest() {}
|
||||
function FTUEGetIoPerfData() {
|
||||
return {
|
||||
"in_var" : 0.15,
|
||||
"out_var" : 0.25,
|
||||
"in_median" : 399.9,
|
||||
"out_median" : 400.3,
|
||||
"in_target" : 400,
|
||||
"out_target" : 400
|
||||
};
|
||||
}
|
||||
function FTUESetInputMusicDevice() { }
|
||||
function FTUESetOutputMusicDevice() { }
|
||||
function FTUEGetInputMusicDevice() { return null; }
|
||||
|
|
@ -678,6 +755,10 @@
|
|||
this.FTUEGetOutputMusicDevice = FTUEGetOutputMusicDevice;
|
||||
this.FTUEGetChatInputVolume = FTUEGetChatInputVolume;
|
||||
this.FTUEGetChatInputs = FTUEGetChatInputs;
|
||||
this.FTUEGetChannels = FTUEGetChannels;
|
||||
this.FTUEGetAudioDevices = FTUEGetAudioDevices;
|
||||
this.FTUEStartIoPerfTest = FTUEStartIoPerfTest;
|
||||
this.FTUEGetIoPerfData = FTUEGetIoPerfData;
|
||||
this.FTUEGetDevices = FTUEGetDevices;
|
||||
this.FTUEGetFrameSize = FTUEGetFrameSize;
|
||||
this.FTUECancel = FTUECancel;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
var $templateButtons = null;
|
||||
var $templateAudioPort = null;
|
||||
var $ftueButtons = null;
|
||||
var $btnBack = null;
|
||||
var $btnNext = null;
|
||||
var $btnBack = null;
|
||||
var $btnClose = null;
|
||||
var $btnCancel = null;
|
||||
|
||||
|
|
@ -48,6 +48,18 @@
|
|||
6: stepSuccess
|
||||
}
|
||||
|
||||
function beforeHideStep($step) {
|
||||
var stepInfo = STEPS[step];
|
||||
|
||||
if (!stepInfo) {
|
||||
throw "unknown step: " + step;
|
||||
}
|
||||
|
||||
if(stepInfo.beforeHide) {
|
||||
stepInfo.beforeHide.call(stepInfo);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeShowStep($step) {
|
||||
var stepInfo = STEPS[step];
|
||||
|
||||
|
|
@ -61,6 +73,8 @@
|
|||
function moveToStep() {
|
||||
var $nextWizardStep = $wizardSteps.filter($('[layout-wizard-step=' + step + ']'));
|
||||
|
||||
beforeHideStep($currentWizardStep);
|
||||
|
||||
$wizardSteps.hide();
|
||||
|
||||
$currentWizardStep = $nextWizardStep;
|
||||
|
|
@ -165,6 +179,12 @@
|
|||
function next() {
|
||||
if ($(this).is('.button-grey')) return false;
|
||||
|
||||
var stepInfo = STEPS[step];
|
||||
if(stepInfo.handleNext) {
|
||||
var result = stepInfo.handleNext.call(stepInfo);
|
||||
if(!result) {return false;}
|
||||
}
|
||||
|
||||
step = step + 1;
|
||||
|
||||
moveToStep();
|
||||
|
|
@ -172,6 +192,7 @@
|
|||
}
|
||||
|
||||
function closeDialog() {
|
||||
beforeHideStep($currentWizardStep);
|
||||
app.layout.closeDialog('gear-wizard');
|
||||
return false;
|
||||
}
|
||||
|
|
@ -198,6 +219,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
function setBackState(enabled) {
|
||||
|
||||
if(!$btnBack) return;
|
||||
|
||||
$btnBack.removeClass('button-orange button-grey');
|
||||
|
||||
if (enabled) {
|
||||
$btnBack.addClass('button-orange');
|
||||
}
|
||||
else {
|
||||
$btnBack.addClass('button-grey');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initialize() {
|
||||
|
||||
// on initial page load, we are not in the FTUE. so cancel the FTUE and call FTUESetStatus(true) if needed
|
||||
|
|
@ -228,6 +264,7 @@
|
|||
}
|
||||
|
||||
this.setNextState = setNextState;
|
||||
this.setBackState = setBackState;
|
||||
this.initialize = initialize;
|
||||
|
||||
self = this;
|
||||
|
|
|
|||
|
|
@ -5,12 +5,111 @@
|
|||
context.JK = context.JK || {};
|
||||
context.JK.StepConfigureTracks = function (app) {
|
||||
|
||||
var $step = null;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var MAX_TRACKS = context.JK.MAX_TRACKS;
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
var $step = null;
|
||||
var $templateAssignablePort = null;
|
||||
var $templateTrackTarget = null;
|
||||
var $unassignedChannelsHolder = null;
|
||||
var $tracksHolder = null;
|
||||
|
||||
|
||||
|
||||
function loadChannels() {
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
|
||||
$unassignedChannelsHolder.empty();
|
||||
$tracksHolder.find('.ftue-inputport').remove();
|
||||
|
||||
var inputChannels = musicPorts.inputs;
|
||||
|
||||
context._.each(inputChannels, function (inputChannel) {
|
||||
if(inputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
var $unassigned = $(context._.template($templateAssignablePort.html(), inputChannel, { variable: 'data' }));
|
||||
$unassignedChannelsHolder.append($unassigned);
|
||||
$unassigned.draggable();
|
||||
|
||||
}
|
||||
else {
|
||||
var $assigned = $(context._.template($templateAssignablePort.html(), inputChannel, { variable: 'data' }));
|
||||
|
||||
// find the track this belongs in
|
||||
|
||||
var trackNumber = inputChannel.assignment - 1;
|
||||
|
||||
var $track = $tracksHolder.find('.track[data-num="' + trackNumber + '"]')
|
||||
|
||||
if($track.length == 0) {
|
||||
context.JK.alertSupportedNeeded('Unable to find a track for channel with assignment ' + inputChannel.assignment);
|
||||
return false;
|
||||
}
|
||||
addChannelToTrack($assigned, $track);
|
||||
$assigned.draggable();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
loadChannels();
|
||||
}
|
||||
|
||||
function removeChannelFromTrack() {
|
||||
|
||||
}
|
||||
function addChannelToTrack($channel, $track) {
|
||||
$track.find('.track-target').append($channel);
|
||||
}
|
||||
|
||||
function initializeUnassignedDroppable() {
|
||||
$unassignedChannelsHolder.droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
console.log("event, ui", event, ui)
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initializeTrackDroppables() {
|
||||
var i;
|
||||
for(i = 0; i < MAX_TRACKS; i++) {
|
||||
var $target = $(context._.template($templateTrackTarget.html(), {num: i }, { variable: 'data' }));
|
||||
$tracksHolder.append($target);
|
||||
$target.droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
console.log("event, ui", event, ui)
|
||||
|
||||
var $target = $(this);
|
||||
var $channel = ui.draggable;
|
||||
addChannelToTrack($channel, $target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
$templateAssignablePort = $('#template-assignable-port');
|
||||
$templateTrackTarget = $('#template-track-target');
|
||||
$unassignedChannelsHolder = $step.find('.unassigned-channels');
|
||||
$tracksHolder = $step.find('.tracks');
|
||||
|
||||
|
||||
initializeUnassignedDroppable();
|
||||
initializeTrackDroppables();
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@
|
|||
|
||||
var $step = null;
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@
|
|||
|
||||
var $step = null;
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@
|
|||
|
||||
var $step = null;
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var self = null;
|
||||
var $step = null;
|
||||
var rest = context.JK.Rest();
|
||||
var $watchVideoInput = null;
|
||||
var $watchVideoOutput = null;
|
||||
var $audioInput = null;
|
||||
|
|
@ -32,20 +33,31 @@
|
|||
var $ioCountdown = null;
|
||||
var $ioCountdownSecs = null;
|
||||
var $resultsText = null;
|
||||
var $unknownText = null;
|
||||
var $asioInputControlBtn = null;
|
||||
var $asioOutputControlBtn = null;
|
||||
var $resyncBtn = null;
|
||||
var $templateAudioPort = null;
|
||||
var $launchLoopbackBtn = null;
|
||||
var $instructions = null;
|
||||
|
||||
var operatingSystem = null;
|
||||
var iCheckIgnore = false;
|
||||
var scoring = false; // are we currently scoring
|
||||
var validDevice = false; // do we currently have a device selected that we can score against?
|
||||
|
||||
// cached values between
|
||||
var deviceInformation = null;
|
||||
var lastSelectedDeviceInfo = null;
|
||||
var shownOutputProdOnce = false;
|
||||
var shownInputProdOnce = false;
|
||||
|
||||
var selectedDeviceInfo = null;
|
||||
var musicPorts = null;
|
||||
var validLatencyScore = false;
|
||||
var validIOScore = false;
|
||||
var lastLatencyScore = null;
|
||||
var lastIOScore = null;
|
||||
|
||||
var audioDeviceBehavior = {
|
||||
MacOSX_builtin: {
|
||||
|
|
@ -86,10 +98,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
var ASIO_SETTINGS_DEFAULT_TEXT = 'ASIO SETTINGS...';
|
||||
var ASIO_SETTINGS_INPUT_TEXT = 'ASIO INPUT SETTINGS...';
|
||||
var ASIO_SETTINGS_OUTPUT_TEXT = 'ASIO OUTPUT SETTINGS...';
|
||||
|
||||
// should return one of:
|
||||
// * MacOSX_builtin
|
||||
// * MACOSX_interface
|
||||
|
|
@ -126,8 +134,7 @@
|
|||
|
||||
var oldDevices = context.jamClient.FTUEGetDevices(false);
|
||||
var devices = context.jamClient.FTUEGetAudioDevices();
|
||||
console.log("oldDevices: " + JSON.stringify(oldDevices));
|
||||
console.log("devices: " + JSON.stringify(devices));
|
||||
logger.debug("FTUEGetAudioDevices: " + JSON.stringify(devices));
|
||||
|
||||
var loadedDevices = {};
|
||||
|
||||
|
|
@ -185,16 +192,19 @@
|
|||
$dialog.setNextState(validLatencyScore && validIOScore);
|
||||
}
|
||||
|
||||
function initializeBackButtonState() {
|
||||
$dialog.setBackState(!scoring);
|
||||
}
|
||||
|
||||
function initializeAudioInput() {
|
||||
var optionsHtml = '';
|
||||
optionsHtml = '<option selected="selected" value="">Choose...</option>';
|
||||
context._.each(deviceInformation, function (deviceInfo, deviceId) {
|
||||
|
||||
console.log(arguments)
|
||||
optionsHtml += '<option title="' + deviceInfo.displayName + '" value="' + deviceId + '">' + deviceInfo.displayName + '</option>';
|
||||
});
|
||||
$audioInput.html(optionsHtml);
|
||||
context.JK.dropdown($audioInput);
|
||||
$audioInput.easyDropDown('enable')
|
||||
|
||||
initializeAudioInputChanged();
|
||||
}
|
||||
|
|
@ -207,6 +217,7 @@
|
|||
});
|
||||
$audioOutput.html(optionsHtml);
|
||||
context.JK.dropdown($audioOutput);
|
||||
$audioOutput.easyDropDown('disable'); // enable once they pick something in input
|
||||
|
||||
initializeAudioOutputChanged();
|
||||
}
|
||||
|
|
@ -225,7 +236,6 @@
|
|||
// and update's the UI accordingly
|
||||
function initializeChannels() {
|
||||
musicPorts = jamClient.FTUEGetChannels();
|
||||
console.log("musicPorts: %o", JSON.stringify(musicPorts));
|
||||
|
||||
initializeInputPorts(musicPorts);
|
||||
initializeOutputPorts(musicPorts);
|
||||
|
|
@ -255,12 +265,14 @@
|
|||
var $unassignedInputs = $inputChannels.find('input[type="checkbox"]:not(:checked)');
|
||||
if ($assignedInputs.length == 0) {
|
||||
if ($allInputs.length >= 2) {
|
||||
logger.debug("selecting 2 inputs")
|
||||
$unassignedInputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
// this is required because iCheck change handler re-writes the inputs. So we have to refetch unassigned outputs
|
||||
$unassignedInputs = $inputChannels.find('input[type="checkbox"]:not(:checked)');
|
||||
$unassignedInputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
}
|
||||
else {
|
||||
logger.debug("selecting 1 inputs")
|
||||
$unassignedInputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
}
|
||||
}
|
||||
|
|
@ -269,15 +281,15 @@
|
|||
var $assignedOutputs = $outputChannels.find('input[type="checkbox"]:checked');
|
||||
var $unassignedOutputs = $outputChannels.find('input[type="checkbox"]:not(:checked)');
|
||||
|
||||
console.log("outputs:", $assignedOutputs, $unassignedOutputs);
|
||||
if ($assignedOutputs.length == 0) {
|
||||
console.log("selecting both outputs")
|
||||
logger.debug("selecting both outputs")
|
||||
$unassignedOutputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
// this is required because iCheck change handler re-writes the inputs. So we have to refetch unassigned outputs
|
||||
$unassignedOutputs = $outputChannels.find('input[type="checkbox"]:not(:checked)');
|
||||
$unassignedOutputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
}
|
||||
else if ($assignedOutputs.length == 1) {
|
||||
logger.debug("selecting 1 output to round out 2 total")
|
||||
$unassignedOutputs.eq(0).iCheck('check').attr('checked', 'checked');
|
||||
}
|
||||
|
||||
|
|
@ -404,6 +416,14 @@
|
|||
});
|
||||
}
|
||||
|
||||
function initializeLoopback() {
|
||||
$launchLoopbackBtn.unbind('click').click(function() {
|
||||
app.setWizardStep(1);
|
||||
app.layout.showDialog('ftue');
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
function initializeFormElements() {
|
||||
if (!deviceInformation) throw "devices are not initialized";
|
||||
|
||||
|
|
@ -411,6 +431,7 @@
|
|||
initializeAudioOutput();
|
||||
initializeFramesize();
|
||||
initializeBuffers();
|
||||
initializeLoopback();
|
||||
}
|
||||
|
||||
function resetFrameBuffers() {
|
||||
|
|
@ -438,6 +459,8 @@
|
|||
$resultsText.removeAttr('latency-score');
|
||||
$resultsText.removeAttr('io-var-score');
|
||||
$resultsText.removeAttr('io-rate-score');
|
||||
$resultsText.removeAttr('scored');
|
||||
$unknownText.hide();
|
||||
}
|
||||
|
||||
function renderLatencyScore(latencyValue, latencyClass) {
|
||||
|
|
@ -448,6 +471,13 @@
|
|||
else {
|
||||
$latencyScore.text('');
|
||||
}
|
||||
|
||||
|
||||
if(latencyClass == 'unknown') {
|
||||
$latencyScore.text('Unknown');
|
||||
$unknownText.show();
|
||||
}
|
||||
|
||||
$latencyHeader.show();
|
||||
$resultsText.attr('latency-score', latencyClass);
|
||||
$latencyScoreSection.removeClass('good acceptable bad unknown starting').addClass(latencyClass);
|
||||
|
|
@ -460,11 +490,11 @@
|
|||
function renderIOScore(std, median, ioData, ioClass, ioRateClass, ioVarClass) {
|
||||
$ioRateScore.text(median !== null ? median : '');
|
||||
$ioVarScore.text(std !== null ? std : '');
|
||||
if (ioClass && ioClass != "starting") {
|
||||
if (ioClass && ioClass != "starting" && ioClass != "skip") {
|
||||
$ioRate.show();
|
||||
$ioVar.show();
|
||||
}
|
||||
if(ioClass == 'starting') {
|
||||
if(ioClass == 'starting' || ioClass == 'skip') {
|
||||
$ioHeader.show();
|
||||
}
|
||||
$resultsText.attr('io-rate-score', ioRateClass);
|
||||
|
|
@ -478,7 +508,7 @@
|
|||
|
||||
function updateScoreReport(latencyResult) {
|
||||
var latencyClass = "neutral";
|
||||
var latencyValue = 'N/A';
|
||||
var latencyValue = null;
|
||||
var validLatency = false;
|
||||
if (latencyResult && latencyResult.latencyknown) {
|
||||
var latencyValue = latencyResult.latency;
|
||||
|
|
@ -503,6 +533,7 @@
|
|||
}
|
||||
|
||||
function audioInputDeviceUnselected() {
|
||||
validDevice = false;
|
||||
validLatencyScore = false;
|
||||
validIOScore = false;
|
||||
initializeNextButtonState();
|
||||
|
|
@ -511,10 +542,8 @@
|
|||
}
|
||||
|
||||
function renderScoringStarted() {
|
||||
validLatencyScore = false;
|
||||
validIOScore = false;
|
||||
initializeNextButtonState();
|
||||
resetScoreReport();
|
||||
initializeNextButtonState();
|
||||
freezeAudioInteraction();
|
||||
renderLatencyScore(null, 'starting');
|
||||
renderIOScore(null, null, null, null, null, null);
|
||||
|
|
@ -523,10 +552,13 @@
|
|||
function renderScoringStopped() {
|
||||
initializeNextButtonState();
|
||||
unfreezeAudioInteraction();
|
||||
$resultsText.attr('scored', 'complete');
|
||||
scoring = false;
|
||||
initializeBackButtonState();
|
||||
}
|
||||
|
||||
|
||||
function freezeAudioInteraction() {
|
||||
logger.debug("freezing audio interaction");
|
||||
$audioInput.attr("disabled", "disabled").easyDropDown('disable');
|
||||
$audioOutput.attr("disabled", "disabled").easyDropDown('disable');
|
||||
$frameSize.attr("disabled", "disabled").easyDropDown('disable');
|
||||
|
|
@ -541,6 +573,7 @@
|
|||
}
|
||||
|
||||
function unfreezeAudioInteraction() {
|
||||
logger.debug("unfreezing audio interaction");
|
||||
$audioInput.removeAttr("disabled").easyDropDown('enable');
|
||||
$audioOutput.removeAttr("disabled").easyDropDown('enable');
|
||||
$frameSize.removeAttr("disabled").easyDropDown('enable');
|
||||
|
|
@ -554,50 +587,6 @@
|
|||
iCheckIgnore = false;
|
||||
}
|
||||
|
||||
// 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";
|
||||
var $saveButton = $('#btn-ftue-2-save');
|
||||
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";
|
||||
setSaveButtonState($saveButton, true);
|
||||
} else if (latency.latency <= 20) {
|
||||
latencyClass = "acceptable";
|
||||
setSaveButtonState($saveButton, true);
|
||||
} else {
|
||||
latencyClass = "bad";
|
||||
setSaveButtonState($saveButton, false);
|
||||
}
|
||||
} else {
|
||||
latencyClass = "unknown";
|
||||
setSaveButtonState($saveButton, false);
|
||||
}
|
||||
|
||||
$('.ms-label', $report).html(latencyValue);
|
||||
$('p', $report).html('milliseconds');
|
||||
|
||||
$report.removeClass('good acceptable bad unknown');
|
||||
$report.addClass(latencyClass);
|
||||
|
||||
var instructionClasses = ['neutral', 'good', 'acceptable', 'unknown', 'bad', 'start', 'loading'];
|
||||
$.each(instructionClasses, function (idx, val) {
|
||||
$('p.' + val, $instructions).hide();
|
||||
});
|
||||
if (latency === 'loading') {
|
||||
$('p.loading', $instructions).show();
|
||||
} else {
|
||||
$('p.' + latencyClass, $instructions).show();
|
||||
renderStopNewFtueLatencyTesting();
|
||||
}
|
||||
}
|
||||
|
||||
function initializeWatchVideo() {
|
||||
$watchVideoInput.unbind('click').click(function () {
|
||||
|
||||
|
|
@ -665,6 +654,10 @@
|
|||
});
|
||||
}
|
||||
|
||||
function postDiagnostic() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
function initializeResync() {
|
||||
$resyncBtn.unbind('click').click(function () {
|
||||
attemptScore();
|
||||
|
|
@ -716,6 +709,9 @@
|
|||
var inputBehavior = audioDeviceBehavior[input.type];
|
||||
var outputBehavior = audioDeviceBehavior[output.type];
|
||||
|
||||
lastSelectedDeviceInfo = selectedDeviceInfo;
|
||||
shownOutputProdOnce = false;
|
||||
shownInputProdOnce = false;
|
||||
selectedDeviceInfo = {
|
||||
input: {
|
||||
id: audioInputDeviceId,
|
||||
|
|
@ -728,6 +724,9 @@
|
|||
behavior: outputBehavior
|
||||
}
|
||||
}
|
||||
|
||||
// prod the user to watch the video if the input or output changes type
|
||||
|
||||
console.log("selectedDeviceInfo", selectedDeviceInfo);
|
||||
}
|
||||
|
||||
|
|
@ -736,6 +735,10 @@
|
|||
var audioInputDeviceId = selectedDeviceInfo.input.id;
|
||||
var audioOutputDeviceId = selectedDeviceInfo.output.id;
|
||||
|
||||
if(audioInputDeviceId) {
|
||||
$audioOutput.easyDropDown('enable');
|
||||
}
|
||||
|
||||
// don't re-assign input/output audio devices because it disturbs input/output track association
|
||||
if (jamClient.FTUEGetInputMusicDevice() != audioInputDeviceId) {
|
||||
jamClient.FTUESetInputMusicDevice(audioInputDeviceId);
|
||||
|
|
@ -746,7 +749,7 @@
|
|||
|
||||
initializeChannels();
|
||||
|
||||
var validDevice = autoSelectMinimumValidChannels();
|
||||
validDevice = autoSelectMinimumValidChannels();
|
||||
|
||||
if (!validDevice) {
|
||||
return false;
|
||||
|
|
@ -767,10 +770,33 @@
|
|||
}
|
||||
}
|
||||
|
||||
function isInputAudioTypeDifferentFromLastTime() {
|
||||
return lastSelectedDeviceInfo && (lastSelectedDeviceInfo.input.type != selectedDeviceInfo.input.type);
|
||||
}
|
||||
|
||||
function isOutputAudioTypeDifferentFromLastTime() {
|
||||
return lastSelectedDeviceInfo && isInputOutputDifferentTypes() && (lastSelectedDeviceInfo.output.type != selectedDeviceInfo.output.type)
|
||||
}
|
||||
|
||||
function isInputOutputDifferentTypes() {
|
||||
return selectedDeviceInfo.input.type != selectedDeviceInfo.output.type;
|
||||
}
|
||||
|
||||
function updateDialogForCurrentDevices() {
|
||||
var inputBehavior = selectedDeviceInfo.input.behavior;
|
||||
var outputBehavior = selectedDeviceInfo.output.behavior;
|
||||
|
||||
// deal with watch video
|
||||
if(isInputOutputDifferentTypes()) {
|
||||
// if we have two types of devices, you need two different videos
|
||||
$watchVideoOutput.show().find('.video-type').show();
|
||||
$watchVideoInput.addClass('audio-output-showing').find('.video-type').show();
|
||||
}
|
||||
else {
|
||||
$watchVideoOutput.hide();
|
||||
$watchVideoInput.removeClass('audio-output-showing').find('.video-type').hide();
|
||||
}
|
||||
|
||||
// handle framesize/buffers
|
||||
if (inputBehavior && (inputBehavior.showKnobs || outputBehavior.showKnobs)) {
|
||||
$knobs.css('visibility', 'visible')
|
||||
|
|
@ -783,18 +809,18 @@
|
|||
if (inputBehavior) {
|
||||
if (inputBehavior.showASIO && !outputBehavior.showASIO) {
|
||||
// show single ASIO button
|
||||
$asioInputControlBtn.text(ASIO_SETTINGS_DEFAULT_TEXT).show();
|
||||
$asioInputControlBtn.show();
|
||||
$asioOutputControlBtn.hide();
|
||||
}
|
||||
else if (!inputBehavior.showASIO && outputBehavior.showASIO) {
|
||||
// show single ASIO button
|
||||
$asioInputControlBtn.text(ASIO_SETTINGS_DEFAULT_TEXT).show();
|
||||
$asioInputControlBtn.show();
|
||||
$asioOutputControlBtn.hide();
|
||||
}
|
||||
else if (inputBehavior.showASIO && outputBehavior.showASIO) {
|
||||
// show two ASIO buttons
|
||||
$asioInputControlBtn.text(ASIO_SETTINGS_INPUT_TEXT).show();
|
||||
$asioOutputControlBtn.text(ASIO_SETTINGS_OUTPUT_TEXT).show();
|
||||
$asioInputControlBtn.show();
|
||||
$asioOutputControlBtn.show();
|
||||
}
|
||||
else {
|
||||
// show no ASIO buttons
|
||||
|
|
@ -817,71 +843,110 @@
|
|||
}
|
||||
}
|
||||
|
||||
function attemptScore() {
|
||||
function processIOScore(io) {
|
||||
// take the higher variance, which is apparently actually std dev
|
||||
var std = io.in_var > io.out_var ? io.in_var : io.out_var;
|
||||
std = Math.round(std * 100) / 100;
|
||||
// take the furthest-off-from-target io rate
|
||||
var median = Math.abs(io.in_median - io.in_target) > Math.abs(io.out_median - io.out_target) ? [io.in_median, io.in_target] : [io.out_median, io.out_target];
|
||||
var medianTarget = median[1];
|
||||
median = Math.round(median[0]);
|
||||
|
||||
var stdIOClass = 'bad';
|
||||
if (std <= 0.50) {
|
||||
stdIOClass = 'good';
|
||||
}
|
||||
else if (std <= 1.00) {
|
||||
stdIOClass = 'acceptable';
|
||||
}
|
||||
|
||||
var medianIOClass = 'bad';
|
||||
if (Math.abs(median - medianTarget) <= 1) {
|
||||
medianIOClass = 'good';
|
||||
}
|
||||
else if (Math.abs(median - medianTarget) <= 2) {
|
||||
medianIOClass = 'acceptable';
|
||||
}
|
||||
|
||||
// take worst between median or std
|
||||
var ioClassToNumber = {bad: 2, acceptable: 1, good: 0}
|
||||
var aggregrateIOClass = ioClassToNumber[stdIOClass] > ioClassToNumber[medianIOClass] ? stdIOClass : medianIOClass;
|
||||
|
||||
// now base the overall IO score based on both values.
|
||||
renderIOScore(std, median, io, aggregrateIOClass, medianIOClass, stdIOClass);
|
||||
|
||||
// lie for now until IO questions finalize
|
||||
validIOScore = true;
|
||||
|
||||
renderScoringStopped();
|
||||
}
|
||||
|
||||
// refocused affects how IO testing occurs.
|
||||
// on refocus=true:
|
||||
// * reuse IO score if it was good/acceptable
|
||||
// * rescore IO if it was bad or skipped from previous try
|
||||
function attemptScore(refocused) {
|
||||
if(scoring) {return;}
|
||||
scoring = true;
|
||||
initializeBackButtonState();
|
||||
validLatencyScore = false;
|
||||
if(!refocused) {
|
||||
// don't reset a valid IO score on refocus
|
||||
validIOScore = false;
|
||||
}
|
||||
renderScoringStarted();
|
||||
|
||||
// timer exists to give UI time to update for renderScoringStarted before blocking nature of jamClient.FTUESave(save) kicks in
|
||||
// this timer exists to give UI time to update for renderScoringStarted before blocking nature of jamClient.FTUESave(save) kicks in
|
||||
setTimeout(function () {
|
||||
logger.debug("Calling FTUESave(false)");
|
||||
jamClient.FTUESave(false);
|
||||
|
||||
var latency = jamClient.FTUEGetExpectedLatency();
|
||||
console.log("FTUEGetExpectedLatency: %o", latency);
|
||||
lastLatencyScore = latency;
|
||||
|
||||
// prod user to watch video if the previous type and new type changed
|
||||
if(!shownInputProdOnce && isInputAudioTypeDifferentFromLastTime()) {
|
||||
context.JK.prodBubble($watchVideoInput, 'ftue-watch-video', {}, {positions:['top', 'right']});
|
||||
shownInputProdOnce = true;
|
||||
}
|
||||
|
||||
// prod user to watch video if the previous type and new type changed
|
||||
if(!shownOutputProdOnce && isOutputAudioTypeDifferentFromLastTime()) {
|
||||
context.JK.prodBubble($watchVideoOutput, 'ftue-watch-video', {}, {positions:['top', 'right']});
|
||||
shownOutputProdOnce = true;
|
||||
}
|
||||
|
||||
updateScoreReport(latency);
|
||||
|
||||
if(refocused) {
|
||||
context.JK.prodBubble($scoreReport, 'refocus-rescore', {validIOScore: validIOScore}, {positions:['top', 'left']});
|
||||
}
|
||||
|
||||
// if there was a valid latency score, go on to the next step
|
||||
if (validLatencyScore) {
|
||||
renderIOScore(null, null, null, 'starting', 'starting', 'starting');
|
||||
var testTimeSeconds = 10; // allow 10 seconds for IO to establish itself
|
||||
context.jamClient.FTUEStartIoPerfTest();
|
||||
renderIOScoringStarted(testTimeSeconds);
|
||||
renderIOCountdown(testTimeSeconds);
|
||||
var interval = setInterval(function () {
|
||||
testTimeSeconds -= 1;
|
||||
// reuse valid IO score if this is on refocus
|
||||
if(refocused && validIOScore) {
|
||||
renderIOScore(null, null, null, 'starting', 'starting', 'starting');
|
||||
processIOScore(lastIOScore);
|
||||
}
|
||||
else {
|
||||
renderIOScore(null, null, null, 'starting', 'starting', 'starting');
|
||||
var testTimeSeconds = gon.ftue_io_wait_time; // allow time for IO to establish itself
|
||||
context.jamClient.FTUEStartIoPerfTest();
|
||||
renderIOScoringStarted(testTimeSeconds);
|
||||
renderIOCountdown(testTimeSeconds);
|
||||
if (testTimeSeconds == 0) {
|
||||
clearInterval(interval);
|
||||
renderIOScoringStopped();
|
||||
var io = context.jamClient.FTUEGetIoPerfData();
|
||||
|
||||
// take the higher variance, which is apparently actually std dev
|
||||
var std = io.in_var > io.out_var ? io.in_var : io.out_var;
|
||||
std = Math.round(std * 100) / 100;
|
||||
// take the furthest-off-from-target io rate
|
||||
var median = Math.abs(io.in_median - io.in_target) > Math.abs(io.out_median - io.out_target) ? [io.in_median, io.in_target] : [io.out_median, io.out_target];
|
||||
var medianTarget = median[1];
|
||||
median = Math.round(median[0]);
|
||||
|
||||
var stdIOClass = 'bad';
|
||||
if (std <= 0.50) {
|
||||
stdIOClass = 'good';
|
||||
var interval = setInterval(function () {
|
||||
testTimeSeconds -= 1;
|
||||
renderIOCountdown(testTimeSeconds);
|
||||
if (testTimeSeconds == 0) {
|
||||
clearInterval(interval);
|
||||
renderIOScoringStopped();
|
||||
var io = context.jamClient.FTUEGetIoPerfData();
|
||||
lastIOScore = io;
|
||||
processIOScore(io);
|
||||
}
|
||||
else if (std <= 1.00) {
|
||||
stdIOClass = 'acceptable';
|
||||
}
|
||||
|
||||
var medianIOClass = 'bad';
|
||||
if (Math.abs(median - medianTarget) <= 1) {
|
||||
medianIOClass = 'good';
|
||||
}
|
||||
else if (Math.abs(median - medianTarget) <= 2) {
|
||||
medianIOClass = 'acceptable';
|
||||
}
|
||||
|
||||
// take worst between median or std
|
||||
var ioClassToNumber = {bad: 2, acceptable: 1, good: 0}
|
||||
var aggregrateIOClass = ioClassToNumber[stdIOClass] > ioClassToNumber[medianIOClass] ? stdIOClass : medianIOClass;
|
||||
|
||||
// now base the overall IO score based on both values.
|
||||
renderIOScore(std, median, io, aggregrateIOClass, medianIOClass, stdIOClass);
|
||||
|
||||
// lie for now until IO questions finalize
|
||||
validIOScore = true;
|
||||
|
||||
renderScoringStopped();
|
||||
}
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderIOScore(null, null, null, 'skip', 'skip', 'skip');
|
||||
|
|
@ -898,6 +963,45 @@
|
|||
$audioOutput.unbind('change').change(audioDeviceChanged);
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
|
||||
var $assignedInputs = $inputChannels.find('input[type="checkbox"]:checked');
|
||||
var $assignedOutputs = $outputChannels.find('input[type="checkbox"]:checked');
|
||||
|
||||
var errors = [];
|
||||
if($assignedInputs.length == 0) {
|
||||
errors.push("There must be at least one selected input ports.");
|
||||
}
|
||||
if($assignedInputs.length > 12) {
|
||||
errors.push("There can only be up to 12 selected inputs ports.");
|
||||
}
|
||||
if($assignedOutputs.length != 2) {
|
||||
errors.push("There must be exactly 2 selected output ports.");
|
||||
}
|
||||
var $errors = $('<ul></ul>');
|
||||
context._.each(errors, function(error) {
|
||||
$errors.append('<li>' + error + '</li>');
|
||||
});
|
||||
|
||||
if(errors.length > 0) {
|
||||
context.JK.Banner.showAlert({html:$errors});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
context.jamClient.FTUESave(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onFocus() {
|
||||
if(!scoring && validDevice) {
|
||||
// in the case the user has been unselecting ports, re-enforce minimum viable channels
|
||||
validDevice = autoSelectMinimumValidChannels();
|
||||
attemptScore(true);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
loadDevices();
|
||||
initializeFormElements();
|
||||
|
|
@ -906,6 +1010,11 @@
|
|||
initializeASIOButtons();
|
||||
initializeKnobs();
|
||||
initializeResync();
|
||||
$(window).on('focus', onFocus);
|
||||
}
|
||||
|
||||
function beforeHide() {
|
||||
$(window).off('focus', onFocus);
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
|
|
@ -934,15 +1043,19 @@
|
|||
$ioCountdown = $scoreReport.find('.io-countdown');
|
||||
$ioCountdownSecs = $scoreReport.find('.io-countdown .secs');
|
||||
$resultsText = $scoreReport.find('.results-text');
|
||||
$unknownText = $scoreReport.find('.unknown-text');
|
||||
$asioInputControlBtn = $step.find('.asio-settings-input-btn');
|
||||
$asioOutputControlBtn = $step.find('.asio-settings-output-btn');
|
||||
$resyncBtn = $step.find('.resync-btn');
|
||||
$templateAudioPort = $('#template-audio-port');
|
||||
|
||||
operatingSystem = context.jamClient.GetOSAsString();
|
||||
$launchLoopbackBtn = $('.loopback-test');
|
||||
$instructions = $('.instructions');
|
||||
operatingSystem = context.JK.GetOSAsString();
|
||||
}
|
||||
|
||||
this.handleNext = handleNext;
|
||||
this.beforeShow = beforeShow;
|
||||
this.beforeHide = beforeHide;
|
||||
this.initialize = initialize;
|
||||
|
||||
self = this;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@
|
|||
|
||||
var $step = null;
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
context.JK.StepUnderstandGear = function (app) {
|
||||
|
||||
var $step = null;
|
||||
var operatingSystem;
|
||||
|
||||
function beforeShow() {
|
||||
var $watchVideo = $step.find('.watch-video');
|
||||
|
|
@ -18,8 +19,11 @@
|
|||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
operatingSystem = context.JK.GetOSAsString();
|
||||
}
|
||||
|
||||
this.beforeShow = beforeShow;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
CHAT: "1"
|
||||
};
|
||||
|
||||
context.JK.MAX_TRACKS = 6;
|
||||
|
||||
// TODO: store these client_id values in instruments table, or store
|
||||
// server_id as the client_id to prevent maintenance nightmares. As it's
|
||||
// set up now, we will have to deploy each time we add new instruments.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"April", "May", "June", "July", "August", "September",
|
||||
"October", "November", "December");
|
||||
|
||||
var os = null;
|
||||
|
||||
context.JK.stringToBool = function (s) {
|
||||
switch (s.toLowerCase()) {
|
||||
|
|
@ -96,7 +97,6 @@
|
|||
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.erb
|
||||
* @param data (optional) data for your template, if applicable
|
||||
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
||||
*
|
||||
*/
|
||||
context.JK.helpBubble = function ($element, templateName, data, options) {
|
||||
if (!data) {
|
||||
|
|
@ -110,6 +110,33 @@
|
|||
context.JK.hoverBubble($element, helpText, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a help bubble immediately with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
* By 'prod' it means to literally prod the user, to make them aware of something important because they did something else
|
||||
*
|
||||
* This will open a bubble immediately and show it for 4 seconds,
|
||||
* if you call it again before the 4 second timer is up, it will renew the 4 second timer.
|
||||
* @param $element The element that should show the help when hovered
|
||||
* @param templateName the name of the help template (without the '#template-help' prefix). Add to _help.html.erb
|
||||
* @param data (optional) data for your template, if applicable
|
||||
* @param options (optional) You can override the default BeautyTips options: https://github.com/dillon-sellars/BeautyTips
|
||||
*/
|
||||
context.JK.prodBubble = function($element, templateName, data, options) {
|
||||
options['trigger'] = 'now';
|
||||
var existingTimer = $element.data("prodTimer");
|
||||
if(existingTimer) {
|
||||
clearTimeout(existingTimer);
|
||||
$element.btOn();
|
||||
}
|
||||
else {
|
||||
context.JK.helpBubble($element, templateName, data, options);
|
||||
$element.btOn();
|
||||
}
|
||||
$element.data("prodTimer", setTimeout(function() {
|
||||
$element.data("prodTimer", null);
|
||||
$element.btOff();
|
||||
}, 4000));
|
||||
}
|
||||
/**
|
||||
* Associates a bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
* @param $element The element that should show the bubble when hovered
|
||||
|
|
@ -487,6 +514,13 @@
|
|||
return $item;
|
||||
}
|
||||
|
||||
context.JK.GetOSAsString = function() {
|
||||
if(!os) {
|
||||
os = context.jamClient.GetOSAsString();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
context.JK.search = function (query, app, callback) {
|
||||
//logger.debug("search: "+ query)
|
||||
$.ajax({
|
||||
|
|
|
|||
|
|
@ -26,5 +26,21 @@
|
|||
.close-btn {
|
||||
display:none;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style:disc;
|
||||
margin-left:20px;
|
||||
}
|
||||
li {
|
||||
margin: 15px 12px 15px 36px;
|
||||
}
|
||||
|
||||
.end-content {
|
||||
height: 0;
|
||||
line-height: 0;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,15 +83,14 @@ div.dialog.ftue .ftue-inner div[layout-wizard-step="0"] {
|
|||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
|
||||
div.dialog.ftue {
|
||||
min-width: 800px;
|
||||
max-width: 800px;
|
||||
min-height: 400px;
|
||||
max-height: 400px;
|
||||
min-height: 500px;
|
||||
max-height: 500px;
|
||||
width: 800px;
|
||||
|
||||
.ftue-inner {
|
||||
line-height: 1.3em;
|
||||
width: auto;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,14 @@
|
|||
}
|
||||
|
||||
&.instructions {
|
||||
height: 230px !important
|
||||
height: 248px !important;
|
||||
line-height:16px;
|
||||
@include border_box_sizing;
|
||||
|
||||
.video-type {
|
||||
font-size:10px;
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
ul li {
|
||||
|
|
@ -128,7 +135,7 @@
|
|||
}
|
||||
|
||||
.watch-video {
|
||||
margin:8px 0 15px 0;
|
||||
margin:8px 0 3px 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,13 +230,27 @@
|
|||
|
||||
|
||||
.ftue-box.results {
|
||||
height: 230px !important;
|
||||
height: 248px !important;
|
||||
padding:0;
|
||||
@include border_box_sizing;
|
||||
|
||||
.io, .latency {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.loopback-button-holder {
|
||||
width:100%;
|
||||
text-align:center;
|
||||
}
|
||||
a.loopback-test {
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.unknown-text {
|
||||
display:none;
|
||||
padding:8px;
|
||||
}
|
||||
|
||||
.scoring-section {
|
||||
font-size:15px;
|
||||
@include border_box_sizing;
|
||||
|
|
@ -241,10 +262,10 @@
|
|||
&.acceptable {
|
||||
background-color:#cc9900;
|
||||
}
|
||||
&.bad, &.skip {
|
||||
&.bad {
|
||||
background-color:#660000;
|
||||
}
|
||||
&.unknown {
|
||||
&.unknown, &.skip {
|
||||
background-color:#999;
|
||||
}
|
||||
&.skip {
|
||||
|
|
@ -284,6 +305,9 @@
|
|||
display:none
|
||||
}
|
||||
|
||||
&[latency-score="unknown"] {
|
||||
display:none;
|
||||
}
|
||||
&[latency-score="good"] li.latency-good {
|
||||
display:list-item;
|
||||
}
|
||||
|
|
@ -311,6 +335,26 @@
|
|||
&[io-rate-score="bad"] li.io-rate-bad {
|
||||
display:list-item;
|
||||
}
|
||||
&[scored="complete"] {
|
||||
li.success {
|
||||
display:list-item;
|
||||
}
|
||||
|
||||
&[io-rate-score="bad"], &[io-var-score="bad"], &[latency-score="bad"]{
|
||||
li.success {
|
||||
display:none;
|
||||
}
|
||||
li.failure {
|
||||
display:list-item;
|
||||
}
|
||||
}
|
||||
|
||||
&[latency-score="unknown"] {
|
||||
li.success {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -323,6 +367,50 @@
|
|||
.wizard-step-content .wizard-step-column {
|
||||
width:25%;
|
||||
}
|
||||
|
||||
|
||||
.ftue-inputport {
|
||||
height: 37px;
|
||||
|
||||
.num {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
height: 34px;
|
||||
line-height: 28px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
position:absolute;
|
||||
}
|
||||
.track {
|
||||
|
||||
}
|
||||
|
||||
|
||||
.ftue-input {
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.track-target {
|
||||
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-left: 15px;
|
||||
margin-bottom: 6px;
|
||||
height:20px;
|
||||
|
||||
.ftue-input {
|
||||
padding:0;
|
||||
border:0;
|
||||
margin-bottom:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wizard-step[layout-wizard-step="3"] {
|
||||
|
|
@ -657,6 +745,11 @@
|
|||
}
|
||||
.audio-input {
|
||||
left:0px;
|
||||
margin-top:30px;
|
||||
|
||||
&.audio-output-showing {
|
||||
margin-top:0;
|
||||
}
|
||||
}
|
||||
.voice-chat-input {
|
||||
left:50%;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,25 @@
|
|||
overflow-x:hidden;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
|
||||
.track {
|
||||
width:70px;
|
||||
height:290px;
|
||||
display:inline-block;
|
||||
margin-right:8px;
|
||||
position:relative;
|
||||
background-color:#242323;
|
||||
|
||||
.disabled-track-overlay {
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
background-color:#555;
|
||||
opacity:0.5;
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -25,16 +44,6 @@
|
|||
color:#666;
|
||||
}
|
||||
|
||||
|
||||
.track {
|
||||
width:70px;
|
||||
height:290px;
|
||||
display:inline-block;
|
||||
margin-right:8px;
|
||||
position:relative;
|
||||
background-color:#242323;
|
||||
}
|
||||
|
||||
.track-empty {
|
||||
min-width:230px;
|
||||
height:201px;
|
||||
|
|
@ -268,23 +277,6 @@ table.vu td {
|
|||
}
|
||||
|
||||
|
||||
.track {
|
||||
width:70px;
|
||||
height:290px;
|
||||
display:inline-block;
|
||||
margin-right:8px;
|
||||
position:relative;
|
||||
background-color:#242323;
|
||||
|
||||
.disabled-track-overlay {
|
||||
width:100%;
|
||||
height:100%;
|
||||
position:absolute;
|
||||
background-color:#555;
|
||||
opacity:0.5;
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.track-empty {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ module ClientHelper
|
|||
gon.fp_apikey = Rails.application.config.filepicker_rails.api_key
|
||||
gon.fp_upload_dir = Rails.application.config.filepicker_upload_dir
|
||||
gon.allow_force_native_client = Rails.application.config.allow_force_native_client
|
||||
gon.ftue_io_wait_time = Rails.application.config.ftue_io_wait_time
|
||||
|
||||
# is this the native client or browser?
|
||||
@nativeClient = is_native_client?
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
</div>
|
||||
<!-- end right column -->
|
||||
<br clear="all">
|
||||
<br clear="all" class="end-content">
|
||||
|
||||
<div class="right buttons">
|
||||
<a class="button-orange close-btn">CLOSE</a>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
<script type="text/template" id="template-help-pre-processed-track">
|
||||
This track has not yet been processed into master form and may include multiple streams from the source musician.
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-help-refocus-rescore">
|
||||
{% if(data.validIOScore) { %}
|
||||
We have re-scored latency based on your changes.
|
||||
{% } else { %}
|
||||
We have re-scored latency and IO based on your changes.
|
||||
{% } %}
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="template-help-ftue-watch-video">
|
||||
Be sure to watch the help video.
|
||||
</script>
|
||||
|
|
@ -31,8 +31,14 @@
|
|||
%li Configure interface settings.
|
||||
%li View test results.
|
||||
.center
|
||||
%a.button-orange.watch-video.audio-input{href:'#', rel:'external'} WATCH VIDEO
|
||||
%a.button-orange.watch-video.audio-output{href:'#', rel:'external'} WATCH VIDEO
|
||||
%a.button-orange.watch-video.audio-input{href:'#', rel:'external'}
|
||||
WATCH VIDEO
|
||||
%br
|
||||
%span.video-type (for input device)
|
||||
%a.button-orange.watch-video.audio-output{href:'#', rel:'external'}
|
||||
WATCH VIDEO
|
||||
%br
|
||||
%span.video-type (for output device)
|
||||
.wizard-step-column
|
||||
%h2 Audio Input Device
|
||||
%select.w100.select-audio-input-device
|
||||
|
|
@ -40,7 +46,6 @@
|
|||
%h2.audio-channels Audio Input Ports
|
||||
.ftue-box.list.ports.input-ports
|
||||
%a.button-orange.asio-settings-input-btn ASIO SETTINGS...
|
||||
%a.button-orange.asio-settings-output-btn ASIO SETTINGS...
|
||||
%a.button-orange.resync-btn RESYNC
|
||||
.wizard-step-column
|
||||
%h2 Audio Output Device
|
||||
|
|
@ -48,6 +53,7 @@
|
|||
%option Same as input
|
||||
%h2.audio-channels Audio Output Ports
|
||||
.ftue-box.list.ports.output-ports
|
||||
%a.button-orange.asio-settings-output-btn ASIO SETTINGS...
|
||||
.frame-and-buffers
|
||||
.framesize
|
||||
%h2 Frame
|
||||
|
|
@ -113,6 +119,12 @@
|
|||
%li.io-var-good Your I/O variance is good.
|
||||
%li.io-var-acceptable Your I/O variance is acceptable.
|
||||
%li.io-var-bad Your I/O variance is poor.
|
||||
%li.success You may proceed to the next step.
|
||||
%li.failure We're sorry, but your audio gear has failed. Please watch video or click HELP button below.
|
||||
.unknown-text
|
||||
%div We cannot accurately predict the latency of your audio gear. To proceed, you must run an audio loopback test. Click button below to do this.
|
||||
%div.loopback-button-holder
|
||||
%a.button-orange.loopback-test{href:'#'} Run Loopback Test
|
||||
.clearall
|
||||
|
||||
.wizard-step{ 'layout-wizard-step' => "2", 'dialog-title' => "Configure Tracks", 'dialog-purpose' => "ConfigureTracks" }
|
||||
|
|
@ -131,8 +143,10 @@
|
|||
%a.button-orange.watch-video{href:'#'} WATCH VIDEO
|
||||
.wizard-step-column
|
||||
%h2 Unassigned Ports
|
||||
.unassigned-channels
|
||||
.wizard-step-column
|
||||
%h2 Track Input Port(s)
|
||||
.tracks
|
||||
.wizard-step-column
|
||||
%h2 Track Instrument
|
||||
|
||||
|
|
@ -230,5 +244,10 @@
|
|||
%span
|
||||
= '{{data.name}}'
|
||||
|
||||
%script{type: 'text/template', id: 'template-assignable-port'}
|
||||
.ftue-input{id: '{{data.id}}'} {{data.name}}
|
||||
|
||||
|
||||
%script{type: 'text/template', id: 'template-track-target'}
|
||||
.track{'data-num' => '{{data.num}}'}
|
||||
.num {{data.num + 1}}:
|
||||
.track-target{'data-num' => '{{data.num}}'}
|
||||
|
|
|
|||
|
|
@ -231,5 +231,8 @@ if defined?(Bundler)
|
|||
# we have to do this for a while until all www.jamkazam.com cookies are gone,
|
||||
# and only .jamkazam.com cookies are around.. 2016?
|
||||
config.middleware.insert_before "ActionDispatch::Cookies", "Middlewares::ClearDuplicatedSession"
|
||||
|
||||
# how long should the frontend wait for the IO to stabilize before asking for a IO score?
|
||||
config.ftue_io_wait_time = 10
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -81,5 +81,7 @@ SampleApp::Application.configure do
|
|||
|
||||
config.vanilla_url = '/forums'
|
||||
config.vanilla_login_url = '/forums/entry/jsconnect'
|
||||
|
||||
config.ftue_io_wait_time = 1
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Gear Wizard", :js => true, :type => :feature, :capybara_feature => true, :slow => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
let(:user) { FactoryGirl.create(:user) }
|
||||
|
||||
before(:each) do
|
||||
sign_in_poltergeist user
|
||||
end
|
||||
|
||||
it "success path" do
|
||||
visit "/client#/home/gear-wizard"
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -143,10 +143,10 @@ jQuery.bt = {version: '0.9.7'};
|
|||
// toggle the on/off right now
|
||||
// note that 'none' gives more control (see below)
|
||||
if ($(this).hasClass('bt-active')) {
|
||||
this.btOff();
|
||||
$(this).btOff();
|
||||
}
|
||||
else {
|
||||
this.btOn();
|
||||
$(this).btOn();
|
||||
}
|
||||
}
|
||||
else if (opts.trigger[0] == 'none') {
|
||||
|
|
@ -158,20 +158,20 @@ jQuery.bt = {version: '0.9.7'};
|
|||
else if (opts.trigger.length > 1 && opts.trigger[0] != opts.trigger[1]) {
|
||||
$(this)
|
||||
.bind(opts.trigger[0], function() {
|
||||
this.btOn();
|
||||
$(this).btOn();
|
||||
})
|
||||
.bind(opts.trigger[1], function() {
|
||||
this.btOff();
|
||||
$(this).btOff();
|
||||
});
|
||||
}
|
||||
else {
|
||||
// toggle using the same event
|
||||
$(this).bind(opts.trigger[0], function() {
|
||||
if ($(this).hasClass('bt-active')) {
|
||||
this.btOff();
|
||||
$(this).btOff();
|
||||
}
|
||||
else {
|
||||
this.btOn();
|
||||
$(this).btOn();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue