(function (context, $) { "use strict"; context.JK = context.JK || {}; context.JK.StepLoopbackTest = function (app, dialog) { var ASSIGNMENT = context.JK.ASSIGNMENT; var AUDIO_DEVICE_BEHAVIOR = context.JK.AUDIO_DEVICE_BEHAVIOR; var gearUtils = context.JK.GearUtils; var logger = context.JK.logger; var $step = null; var frameBuffers = new context.JK.FrameBuffers(app); var gearTest = new context.JK.GearTest(app); var deviceInformation = null; var operatingSystem = null; var selectedDeviceInfo = null; var musicPorts = null; var $asioInputControlBtn = null; var $asioOutputControlBtn = null; var $resyncBtn = null; var $runTestBtn = null; var $audioInputDevice = null; var $audioOutputDevice = null; var $inputChannels = null; var $outputChannels = null; var $templateAudioPort = null; var $scoreReport = null; var faderMap = { 'loopback-audio-input-fader': jamClient.FTUESetInputVolume, 'loopback-audio-output-fader': jamClient.FTUESetOutputVolume }; var faderReadMap = { 'loopback-audio-input-fader': jamClient.FTUEGetInputVolume, 'loopback-audio-output-fader': jamClient.FTUEGetOutputVolume }; function attemptScore() { gearTest.attemptScore(); } function invalidateScore() { gearTest.invalidateScore(); initializeNextButtonState(); } function updateDefaultBuffers() { // handle specific framesize settings if(selectedDeviceInfo && (selectedDeviceInfo.input.info.type == 'Win32_wdm' || selectedDeviceInfo.output.info.type == 'Win32_wdm')) { var framesize = frameBuffers.selectedFramesize(); if(framesize == 2.5) { logger.debug("setting default buffers to 1/1"); frameBuffers.setBufferIn('1'); frameBuffers.setBufferOut('1'); } else if(framesize == 5) { logger.debug("setting default buffers to 3/2"); frameBuffers.setBufferIn('3'); frameBuffers.setBufferOut('2'); } else { logger.debug("setting default buffers to 6/5"); frameBuffers.setBufferIn('6'); frameBuffers.setBufferOut('5'); } } else { logger.debug("setting default buffers to 0/0"); frameBuffers.setBufferIn(0); frameBuffers.setBufferOut(0); } jamClient.FTUESetInputLatency(frameBuffers.selectedBufferIn()); jamClient.FTUESetOutputLatency(frameBuffers.selectedBufferOut()); } function onFramesizeChanged() { context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']}); updateDefaultBuffers(); jamClient.FTUESetFrameSize(frameBuffers.selectedFramesize()); invalidateScore(); } function onBufferInChanged() { context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']}); jamClient.FTUESetInputLatency(frameBuffers.selectedBufferIn()); invalidateScore(); } function onBufferOutChanged() { context.JK.prodBubble($resyncBtn, 'push-resync-when-done', {}, {positions:['top']}); jamClient.FTUESetOutputLatency(frameBuffers.selectedBufferOut()); invalidateScore(); } function freezeAudioInteraction() { logger.debug("loopback: freezing audio interaction"); frameBuffers.disable(); $asioInputControlBtn.on("click", false); $asioOutputControlBtn.on("click", false); $resyncBtn.on('click', false); $runTestBtn.on('click', false); } function unfreezeAudioInteraction() { logger.debug("unfreezing audio interaction"); frameBuffers.enable(); $asioInputControlBtn.off("click", false); $asioOutputControlBtn.off("click", false); $resyncBtn.off('click', false); $runTestBtn.off('click', false); } function getGearTest() { return gearTest; } function handleNext() { return true; } function handleBack() { return true; } function render(){ if(selectedDeviceInfo) { var inputBehavior = selectedDeviceInfo.input.behavior; var outputBehavior = selectedDeviceInfo.output.behavior; } else { var inputBehavior = null; var outputBehavior = null; } // handle ASIO visibility if (inputBehavior) { if (inputBehavior.showASIO) { $asioInputControlBtn.show(); } else { $asioInputControlBtn.hide(); } if(outputBehavior.showASIO && (selectedDeviceInfo.input.id != selectedDeviceInfo.output.id)) { $asioOutputControlBtn.show(); } else { $asioOutputControlBtn.hide(); } } else { // show no ASIO buttons $asioInputControlBtn.hide(); $asioOutputControlBtn.hide(); } if(selectedDeviceInfo) { $audioInputDevice.text(selectedDeviceInfo.input.info.displayName); $audioOutputDevice.text(selectedDeviceInfo.output.info.displayName); } else { $audioInputDevice.text('Unassigned'); $audioOutputDevice.text('Unassigned'); } $inputChannels.empty(); context._.each(musicPorts.inputs, function (inputChannel) { var $inputChannel = $(context._.template($templateAudioPort.html(), inputChannel, { variable: 'data' })); var $checkbox = $inputChannel.find('input'); if (gearUtils.isChannelAssigned(inputChannel)) { $checkbox.attr('checked', 'checked'); } context.JK.checkbox($checkbox).iCheck('disable'); $inputChannels.append($inputChannel); }); $outputChannels.empty(); context._.each(musicPorts.outputs, function (outputChannel) { var $outputPort = $(context._.template($templateAudioPort.html(), outputChannel, { variable: 'data' })); var $checkbox = $outputPort.find('input'); if (gearUtils.isChannelAssigned(outputChannel)) { $checkbox.attr('checked', 'checked'); } context.JK.checkbox($checkbox).iCheck('disable'); $outputChannels.append($outputPort); }); initializeVUMeters(); renderVolumes(); registerVuCallbacks(); } function initializeASIOButtons() { $asioInputControlBtn.unbind('click').click(function () { context.jamClient.FTUEOpenControlPanel(selectedDeviceInfo.input.id); }); $asioOutputControlBtn.unbind('click').click(function () { context.jamClient.FTUEOpenControlPanel(selectedDeviceInfo.output.id); }); } function initializeResync() { $resyncBtn.unbind('click').click(function () { attemptScore(); return false; }) } function initializeVUMeters() { var vuMeters = [ '#loopback-audio-input-vu-left', '#loopback-audio-input-vu-right', '#loopback-audio-output-vu-left', '#loopback-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); }); } // renders volumes based on what the backend says function renderVolumes() { $.each(context._.keys(faderReadMap), function (index, faderId) { // faderChange takes a value from 0-100 var $fader = $('[fader-id="' + faderId + '"]'); var db = faderReadMap[faderId](); var faderPct = db + 80; context.JK.FaderHelpers.setHandlePosition($fader, faderPct); }); } 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 registerVuCallbacks() { logger.debug("loopback-wizard: registering vu callbacks"); jamClient.FTUERegisterVUCallbacks( "JK.loopbackAudioOutputVUCallback", "JK.loopbackAudioInputVUCallback", "JK.loopbackChatInputVUCallback" ); jamClient.SetVURefreshRate(200); } function initializeNextButtonState() { dialog.setNextState(gearTest.isGoodFtue()); } function initializeBackButtonState() { dialog.setBackState(!gearTest.isScoring()); } function renderScoringStarted() { initializeBackButtonState(); initializeNextButtonState(); freezeAudioInteraction(); } function renderScoringStopped() { initializeNextButtonState(); initializeBackButtonState(); unfreezeAudioInteraction(); } function onGearTestStarted(e, data) { renderScoringStarted(); } function onGearTestDone(e, data) { renderScoringStopped(); gearUtils.postDiagnostic(operatingSystem, deviceInformation, selectedDeviceInfo, gearTest, frameBuffers, true); } function onGearTestFail(e, data) { renderScoringStopped(); gearUtils.postDiagnostic(operatingSystem, deviceInformation, selectedDeviceInfo, gearTest, frameBuffers, true); } function beforeShow() { selectedDeviceInfo = gearUtils.selectedDeviceInfo(context.jamClient.FTUEGetInputMusicDevice(), context.jamClient.FTUEGetOutputMusicDevice()); deviceInformation = gearUtils.loadDeviceInfo(); musicPorts = jamClient.FTUEGetChannels(); render(); } function beforeHide() { logger.debug("loopback-wizard: unregistering vu callbacks"); jamClient.FTUERegisterVUCallbacks('', '', ''); } function initialize(_$step) { $step = _$step; $asioInputControlBtn = $step.find('.asio-settings-input-btn'); $asioOutputControlBtn = $step.find('.asio-settings-output-btn'); $resyncBtn = $step.find('.resync-btn'); $runTestBtn = $step.find('.run-test-btn'); $audioInputDevice = $step.find('.audio-device.input') $audioOutputDevice = $step.find('.audio-device.output') $inputChannels = $step.find('.input-ports') $outputChannels = $step.find('.output-ports') $templateAudioPort = $('#template-audio-port'); $scoreReport = $step.find('.results'); operatingSystem = context.JK.GetOSAsString(); frameBuffers.initialize($step.find('.frame-and-buffers')); $(frameBuffers) .on(frameBuffers.FRAMESIZE_CHANGED, onFramesizeChanged) .on(frameBuffers.BUFFER_IN_CHANGED, onBufferInChanged) .on(frameBuffers.BUFFER_OUT_CHANGED, onBufferOutChanged) gearTest.initialize($scoreReport, false) $(gearTest) .on(gearTest.GEAR_TEST_START, onGearTestStarted) .on(gearTest.GEAR_TEST_DONE, onGearTestDone) .on(gearTest.GEAR_TEST_FAIL, onGearTestFail) $runTestBtn.click(attemptScore); initializeASIOButtons(); initializeResync(); } context.JK.loopbackAudioInputVUCallback = function (dbValue) { context.JK.ftueVUCallback(dbValue, '#loopback-audio-input-vu-left'); context.JK.ftueVUCallback(dbValue, '#loopback-audio-input-vu-right'); }; context.JK.loopbackAudioOutputVUCallback = function (dbValue) { context.JK.ftueVUCallback(dbValue, '#loopback-audio-output-vu-left'); context.JK.ftueVUCallback(dbValue, '#loopback-audio-output-vu-right'); }; context.JK.loopbackChatInputVUCallback = function (dbValue) { }; this.getGearTest = getGearTest; this.handleNext = handleNext; this.handleBack = handleBack; this.beforeShow = beforeShow; this.beforeHide = beforeHide; this.initialize = initialize; return this; } })(window, jQuery);