From d1267dff53b2ca239c1ca99bd1faec52ca412aeb Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 16 Apr 2014 17:11:30 +0000 Subject: [PATCH] * wip on new ftue --- web/app/assets/javascripts/fakeJamClient.js | 5 + web/app/assets/javascripts/gear_wizard.js | 379 ++++++++++++++---- .../views/clients/gear/_gear_wizard.html.haml | 4 +- 3 files changed, 300 insertions(+), 88 deletions(-) diff --git a/web/app/assets/javascripts/fakeJamClient.js b/web/app/assets/javascripts/fakeJamClient.js index ee3d67d7e..39732919b 100644 --- a/web/app/assets/javascripts/fakeJamClient.js +++ b/web/app/assets/javascripts/fakeJamClient.js @@ -157,6 +157,10 @@ return 'Good Device'; } + function FTUEIsMusicDeviceWDM() { + return false; + } + function RegisterVolChangeCallBack(functionName) { dbg('RegisterVolChangeCallBack'); } @@ -684,6 +688,7 @@ this.FTUEGetAllAudioConfigurations = FTUEGetAllAudioConfigurations; this.FTUEGetGoodAudioConfigurations = FTUEGetGoodAudioConfigurations; this.FTUEGetConfigurationDevice = FTUEGetConfigurationDevice; + this.FTUEIsMusicDeviceWDM = FTUEIsMusicDeviceWDM; // Session this.SessionAddTrack = SessionAddTrack; diff --git a/web/app/assets/javascripts/gear_wizard.js b/web/app/assets/javascripts/gear_wizard.js index 4926c6777..634710d76 100644 --- a/web/app/assets/javascripts/gear_wizard.js +++ b/web/app/assets/javascripts/gear_wizard.js @@ -16,6 +16,9 @@ var self = null; var operatingSystem = null; + // populated by loadDevices + var deviceInformation = null; + // SELECT DEVICE STATE var validScore = false; @@ -32,18 +35,27 @@ var audioDeviceBehavior = { MacOSX_builtin : { + display: 'MacOSX Built-In', videoURL: undefined }, MACOSX_interface : { + display: 'MacOSX external interface', videoURL: undefined }, Win32_wdm : { + display: 'Windows WDM', videoURL: undefined }, Win32_asio : { + display: 'Windows ASIO', videoURL: undefined }, Win32_asio4all : { + display: 'Windows ASIO4ALL', + videoURL: undefined + }, + Linux : { + display: 'Linux', videoURL: undefined } } @@ -65,8 +77,66 @@ var $audioOutput = $currentWizardStep.find('.select-audio-output-device'); var $bufferIn = $currentWizardStep.find('.select-buffer-in'); var $bufferOut = $currentWizardStep.find('.select-buffer-out'); - var $nextButton = $ftueButtons.find('.btn-next'); var $frameSize = $currentWizardStep.find('.select-frame-size'); + var $inputPorts = $currentWizardStep.find('.input-ports'); + var $outputPorts = $currentWizardStep.find('.output-ports'); + var $scoreReport = $currentWizardStep.find('.results'); + var $nextButton = $ftueButtons.find('.btn-next'); + + // should return one of: + // * MacOSX_builtin + // * MACOSX_interface + // * Win32_wdm + // * Win32_asio + // * Win32_asio4all + // * Linux + function determineDeviceType(deviceId, displayName) { + if(operatingSystem == "MacOSX") { + if(displayName.toLowerCase().trim() == "built-in") { + return "MacOSX_builtin"; + } + else { + return "MacOSX_interface"; + } + } + else if(operatingSystem == "Win32") { + if(context.jamClient.FTUEIsMusicDeviceWDM(deviceId)) { + return "Win32_wdm"; + } + else if(displayName.toLowerCase().indexOf("asio4all") > -1) { + return "Win32_asio4all" + } + else { + return "Win32_asio"; + } + } + else { + return "Linux"; + } + } + + + function loadDevices() { + var devices = context.jamClient.FTUEGetDevices(false); + + var loadedDevices = {}; + + // augment these devices by determining their type + context._.each(devices, function(displayName, deviceId) { + var deviceInfo = {}; + + deviceInfo.id = deviceId; + deviceInfo.type = determineDeviceType(deviceId, displayName); + deviceInfo.displayType = audioDeviceBehavior[deviceInfo.type].display; + deviceInfo.displayName = deviceInfo.displayName; + + loadedDevices[deviceId] = deviceInfo; + }) + + deviceInformation = context._.keys(loadedDevices).sort(); + + logger.debug(context.JK.dlen(deviceInformation) + " devices loaded." , deviceInformation); + } // returns a deviceInfo hash for the device matching the deviceId, or null. function findDevice(deviceId) { @@ -81,18 +151,214 @@ return $audioOutput.val(); } + function selectedFramesize() { + return parseFloat($frameSize.val()); + } + + function selectedBufferIn() { + return parseFloat($frameSize.val()); + } + + function selectedBufferOut() { + return parseFloat($frameSize.val()); + } + function initializeNextButtonState() { + console.log(context.jamClient.FTUEGetDevices(false)); + console.log("chat devices", jamClient.FTUEGetChatInputs()); $nextButton.removeClass('button-orange button-grey'); if(validScore) $nextButton.addClass('button-orange'); else $nextButton.addClass('button-grey'); } - function audioDeviceUnselected() { + function initializeAudioInput() { + var optionsHtml = ''; + optionsHtml = ''; + context._.each(deviceInformation, function(deviceInfo, deviceId) { + optionsHtml += ''; + }); + $audioInput.html(optionsHtml); + alert(optionsHtml) + context.JK.dropdown($audioInput); + + initializeAudioInputChanged(); + } + + function initializeAudioOutput() { + var optionsHtml = ''; + optionsHtml = ''; + context._.each(deviceInformation, function(deviceInfo, deviceId) { + optionsHtml += ''; + }); + $audioOutput.html(optionsHtml); + context.JK.dropdown($audioOutput); + + initializeAudioOutputChanged(); + } + + function initializeFramesize() { + + } + + function initializeFormElements() { + if(!deviceInformation) throw "devices are not initialized"; + + initializeAudioInput(); + initializeAudioOutput(); + initializeFramesize(); + initializeBuffers(); + } + + function resetFrameBuffers() { + $frameSize.val('2.5'); + $bufferIn.val('0'); + $bufferOut.val('0'); + } + + function clearInputPorts() { + $inputPorts.empty(); + } + + function clearOutputPorts() { + $outputPorts.empty(); + } + + function resetScoreReport() { + $scoreReport.empty(); + } + + function updateScoreReport(latencyResult) { + var latencyClass = "neutral"; + var latencyValue = 'N/A'; + var validLatency = false; + if (latencyResult && latencyResult.latencyknown) { + var latency = latencyResult.latency; + latencyValue = Math.round(latencyValue * 100) / 100; + if (latency.latency <= 10) { + latencyClass = "good"; + validLatency = true; + } else if (latency.latency <= 20) { + latencyClass = "acceptable"; + validLatency = true; + } else { + latencyClass = "bad"; + } + } + + validScore = validLatency; // validScore may become based on IO variance too + + $scoreReport.html(latencyValue); + } + + function loadAudioDrivers() { + var drivers = context.jamClient.FTUEGetDevices(false); + var chatDrivers = jamClient.FTUEGetChatInputs(); + var optionsHtml = ''; + var chatOptionsHtml = ''; + + + var driverOptionFunc = function (driverKey, index, list) { + if(!drivers[driverKey]) { + logger.debug("skipping unknown device:", driverKey) + } + else { + optionsHtml += ''; + } + }; + + var chatOptionFunc = function (driverKey, index, list) { + chatOptionsHtml += ''; + }; + + var selectors = [ + '[layout-wizard-step="0"] .settings-2-device select', + '[layout-wizard-step="2"] .settings-driver select' + ]; + + // handle standard devices + var sortedDeviceKeys = context._.keys(drivers).sort(); + context._.each(sortedDeviceKeys, driverOptionFunc); + $.each(selectors, function (index, selector) { + var $select = $(selector); + $select.empty(); + $select.html(optionsHtml); + context.JK.dropdown($select); + }); + + selectors = ['[layout-wizard-step="0"] .settings-2-voice select']; + var sortedVoiceDeviceKeys = context._.keys(chatDrivers).sort(); + + // handle voice inputs + context._.each(sortedVoiceDeviceKeys, chatOptionFunc); + $.each(selectors, function (index, selector) { + var $select = $(selector); + $select.empty(); + $select.html(chatOptionsHtml); + context.JK.dropdown($select); + }); + + } + function audioInputDeviceUnselected() { validScore = false; - - initializeNextButtonState(); + resetFrameBuffers(); + clearInputPorts(); + } + + function renderScoringStarted() { + validScore = false; + initializeNextButtonState(); + resetScoreReport(); + } + + function renderScoringStopped() { + initializeNextButtonState(); + } + + + // 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() { @@ -103,7 +369,7 @@ context.JK.Banner.showAlert('You must first choose an Audio Input Device so that we can determine which video to show you.'); } else { - var videoURL = audioDeviceBehavior[audioDevice.type]; + var videoURL = audioDeviceBehavior[audioDevice.type].videoURL; if(videoURL) { $(this).attr('href', videoURL); @@ -124,7 +390,7 @@ throw "this button should be hidden"; } else { - var videoURL = audioDeviceBehavior[audioDevice.type]; + var videoURL = audioDeviceBehavior[audioDevice.type].videoURL; if(videoURL) { $(this).attr('href', videoURL); @@ -143,102 +409,43 @@ $audioInput.unbind('change').change(function(evt) { var audioDeviceId = selectedAudioInput(); - if(!audioDeviceId) { - audioDeviceUnselected(); + audioInputDeviceUnselected(); return false; } var audioDevice = findDevice(selectedAudioInput()); - if(!audioDevice) { - context.JK.alertSupportedNeeded('Unable to find device information for: ' + audioDevice); + context.JK.alertSupportedNeeded('Unable to find device information for: ' + audioDeviceId); + return false; } - releaseDropdown(function () { - renderStartNewFtueLatencyTesting(); - var $select = $(evt.currentTarget); + renderScoringStarted(); - var $audioSelect = $('.ftue-new .settings-2-device select'); - var audioDriverId = $audioSelect.val(); + jamClient.FTUESetMusicDevice(audioDeviceId); + jamClient.FTUESetInputLatency(selectedAudioInput()); + jamClient.FTUESetOutputLatency(selectedAudioOutput()); + jamClient.FTUESetFrameSize(selectedFramesize()); - if (!audioDriverId) { - context.JK.alertSupportNeeded(); + logger.debug("Calling FTUESave(false)"); + jamClient.FTUESave(false); - renderStopNewFtueLatencyTesting(); - // reset back to 'Choose...' - newFtueEnableControls(false); - return; - } - jamClient.FTUESetMusicDevice(audioDriverId); + var latency = jamClient.FTUEGetExpectedLatency(); + console.log("FTUEGetExpectedLatency: %o", latency); - 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) - renderStopNewFtueLatencyTesting(); - console.log("invalid kin/kout %o/%o", kin, kout); - return; - } - - newFtueUpdateLatencyView('loading'); - - newFtueEnableControls(true); - newFtueOsSpecificSettings(); - // make sure whatever the user sees in the frontend is what the backend thinks - // this is necesasry because if you do a FTUE pass, close the client, and pick the same device - // the backend will *silently* use values from before, because the frontend does not query the backend - // for these values anywhere. - - // setting all 3 of these cause 3 FTUE's. Instead, we set batchModify to true so that they don't call FtueSave(false), and call later ourselves - batchModify = true; - newFtueAsioFrameSizeToBackend($('#ftue-2-asio-framesize')); - newFtueAsioInputLatencyToBackend($('#ftue-2-asio-input-latency')); - newFtueAsioOutputLatencyToBackend($('#ftue-2-asio-output-latency')); - batchModify = false; - - //setLevels(0); - renderVolumes(); - - logger.debug("Calling FTUESave(" + false + ")"); - jamClient.FTUESave(false) - pendingFtueSave = false; // this is not really used in any real fashion. just setting back to false due to batch modify above - - setVuCallbacks(); - - var latency = jamClient.FTUEGetExpectedLatency(); - console.log("FTUEGetExpectedLatency: %o", latency); - newFtueUpdateLatencyView(latency); - }); - - }) + renderScoringStopped(); + }); } + + function initializeAudioOutputChanged() { + + } + function initializeStep() { + loadDevices(); + initializeFormElements(); initializeNextButtonState(); initializeWatchVideo(); - initializeAudioInputChanged(); } initializeStep(); diff --git a/web/app/views/clients/gear/_gear_wizard.html.haml b/web/app/views/clients/gear/_gear_wizard.html.haml index 09d99a642..0ce16062d 100644 --- a/web/app/views/clients/gear/_gear_wizard.html.haml +++ b/web/app/views/clients/gear/_gear_wizard.html.haml @@ -38,7 +38,7 @@ %select.w100.select-audio-input-device %option None %h2 Audio Input Ports - .ftue-box.list.ports.output-ports + .ftue-box.list.ports.input-ports %a.button-orange.asio-settings-btn ASIO SETTINGS... %a.button-orange.resync-btn RESYNC .wizard-step-column @@ -46,7 +46,7 @@ %select.w100.select-audio-output-device %option Same as input %h2 Audio Output Ports - .ftue-box.list.ports.input-ports + .ftue-box.list.ports.output-ports .frame-and-buffers .framesize %h2 Frame