From 0d27a47b4208dacf49d69fcca9cae2a4e9fb9c10 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 6 Mar 2014 11:02:50 -0600 Subject: [PATCH] * VRFS-1308 - make configure tracks be cool about no selected items when the user indicates they might want to configure them. fix some recording styling button issues --- ruby/lib/jam_ruby/models/music_session.rb | 2 +- .../jam_ruby/models/music_session_spec.rb | 1 - web/app/assets/javascripts/configureTrack.js | 1666 +++++++++-------- web/app/assets/javascripts/ftue.js | 106 +- web/app/assets/javascripts/landing/signup.js | 3 +- .../stylesheets/web/audioWidgets.css.scss | 4 + 6 files changed, 928 insertions(+), 854 deletions(-) diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 77c8b00b2..7a3dd2e60 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -197,7 +197,7 @@ module JamRuby locidispid = connection.locidispid query = MusicSession - .select("music_sessions.*, max(coalesce(scores.score, 99)) as max_score") + .select("music_sessions.*, max(coalesce(scores.score, 99)) as max_score") .joins( %Q{ INNER JOIN diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb index a583ddbe1..4d64f12a8 100644 --- a/ruby/spec/jam_ruby/models/music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/music_session_spec.rb @@ -339,7 +339,6 @@ describe MusicSession do music_sessions.length.should == 2 music_sessions[0].id.should == later_session.id music_sessions[1].id.should == earlier_session.id - end end diff --git a/web/app/assets/javascripts/configureTrack.js b/web/app/assets/javascripts/configureTrack.js index 765cda6c0..d3bfb0eb2 100644 --- a/web/app/assets/javascripts/configureTrack.js +++ b/web/app/assets/javascripts/configureTrack.js @@ -1,835 +1,841 @@ -(function(context,$) { +(function (context, $) { - "use strict"; + "use strict"; - context.JK = context.JK || {}; - context.JK.ConfigureTrackDialog = function(app, myTracks, sessionId, sessionModel) { - var logger = context.JK.logger; - var myTrackCount; + context.JK = context.JK || {}; + context.JK.ConfigureTrackDialog = function (app, myTracks, sessionId, sessionModel) { + var logger = context.JK.logger; + var myTrackCount; - var ASSIGNMENT = { - CHAT: -2, - OUTPUT: -1, - UNASSIGNED: 0, - TRACK1: 1, - TRACK2: 2 - }; - - var VOICE_CHAT = { - NO_CHAT: "0", - CHAT: "1" - }; - - var instrument_array = []; - - // dialog variables - var inputUnassignedList = []; - var track1AudioInputChannels = []; - var track2AudioInputChannels = []; - - var outputUnassignedList = []; - var outputAssignedList = []; - - var chatUnassignedList = []; - var chatAssignedList = []; - - var chatOtherUnassignedList = []; - var chatOtherAssignedList = []; - - var devices = []; - var originalDeviceId; - var originalVoiceChat; - - var configure_audio_instructions = { - "Win32": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + - "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + - "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + - "Gear button to test that device.", - - "MacOSX": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + - "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + - "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + - "Gear button to test that device.", - - "Unix": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + - "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + - "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + - "Gear button to test that device." - }; - - var configure_voice_instructions = "If you are using a microphone to capture your instrumental or vocal audio, you can simply use that mic " + - "for both music and chat. Otherwise, choose a device to use for voice chat, and use arrow buttons to " + - "select an input on that device."; - - function events() { - - // Music Audio Tab - var $tabConfigureAudio = $('#tab-configure-audio'); - $tabConfigureAudio.unbind("click"); - $tabConfigureAudio.click(function() { - // validate voice chat settings - if (validateVoiceChatSettings(true)) { - showMusicAudioPanel(false); - } - }); - - // Voice Chat Tab - var $tabConfigureVoice = $('#tab-configure-voice'); - $tabConfigureVoice.unbind("click"); - $tabConfigureVoice.click(function() { - // validate audio settings - if (validateAudioSettings(true)) { - showVoiceChatPanel(false); - } - }); - - // Track 1 Add - var $imgTrack1Add = $('#img-track1-input-add'); - $imgTrack1Add.unbind("click"); - $imgTrack1Add.click(function() { - var $unusedMusicInputs = $('#audio-inputs-unused > option:selected'); - _handleTrackInputAdd($unusedMusicInputs, '#track1-input'); - }); - - // Track 2 Add - var $imgTrack2Add = $('#img-track2-input-add'); - $imgTrack2Add.unbind("click"); - $imgTrack2Add.click(function() { - var $unusedMusicInputs = $('#audio-inputs-unused > option:selected'); - _handleTrackInputAdd($unusedMusicInputs, '#track2-input'); - }); - - // Track 1 Remove - var $imgTrack1Remove = $('#img-track1-input-remove'); - $imgTrack1Remove.unbind("click"); - $imgTrack1Remove.click(function() { - _handleTrackInputRemove('#track1-input'); - }); - - // Track 2 Remove - var $imgTrack2Remove = $('#img-track2-input-remove'); - $imgTrack2Remove.unbind("click"); - $imgTrack2Remove.click(function() { - _handleTrackInputRemove('#track2-input'); - }); - - // Audio Output Add - var $imgAudioOutputAdd = $('#img-audio-output-add'); - $imgAudioOutputAdd.unbind("click"); - $imgAudioOutputAdd.click(function() { - var $unusedAudioOutputs = $('#audio-output-unused > option:selected'); - $unusedAudioOutputs.remove().appendTo('#audio-output-selection'); - }); - - // Audio Output Remove - var $imgAudioOutputRemove = $('#img-audio-output-remove'); - $imgAudioOutputRemove.unbind("click"); - $imgAudioOutputRemove.click(function() { - var $usedAudioOutputs = $('#audio-output-selection > option:selected'); - $usedAudioOutputs.remove().appendTo('#audio-output-unused'); - }); - - // Voice Chat Add - var $imgVoiceAdd = $('#img-voice-input-add'); - $imgVoiceAdd.unbind("click"); - $imgVoiceAdd.click(function() { - var $unusedVoiceInputs = $('#voice-inputs-unused > option:selected'); - _handleVoiceInputAdd($unusedVoiceInputs); - }); - - // Voice Chat Remove - var $imgVoiceRemove = $('#img-voice-input-remove'); - $imgVoiceRemove.unbind("click"); - $imgVoiceRemove.click(function() { - var $usedVoiceInputs = $("#voice-inputs-selection > option:selected"); - _handleVoiceInputRemove($usedVoiceInputs); - }); - - $('#audio-drivers').unbind("change"); - $('#audio-drivers').change(function() { - audioDriverChanged(); - }); - - $('#voice-chat-type').unbind("change"); - $('#voice-chat-type').change(function() { - voiceChatChanged(); - }); - - $('#btn-driver-settings').unbind("click"); - $('#btn-driver-settings').click(function() { - context.jamClient.TrackOpenControlPanel(); - }); - - $('#btn-cancel-new-audio').unbind("click"); - $('#btn-cancel-new-audio').click(context.JK.showOverlay); - - $('#btn-error-ok').click(context.JK.showOverlay); - - $('#btn-save-settings').unbind("click"); - $('#btn-save-settings').click(saveSettings); - - $('#btn-cancel-settings').unbind("click"); - $('#btn-cancel-settings').click(cancelSettings); - } - - function _handleTrackInputAdd($selectedMusicInputs, selector) { - $selectedMusicInputs.each(function() { - var deviceId = this.value; - var description = this.text; - $(this).remove().appendTo(selector); - - // if this input exists in the Voice Chat unused box, remove it - var $voiceChatUnused = $('#voice-inputs-unused > option[value="' + deviceId + '"]'); - if ($voiceChatUnused.length > 0) { - logger.debug("Removing " + deviceId + " from Voice Chat Unused"); - $voiceChatUnused.remove(); - } - }); - - _syncVoiceChatType(); - } - - function _handleTrackInputRemove(trackSelector) { - trackSelector = trackSelector + ' > option:selected'; - $(trackSelector).each(function() { - var $removedInput = $(this).remove(); - var $cloneAudio = $removedInput.clone(true, true); - var $cloneChat = $removedInput.clone(true, true); - - $cloneAudio.appendTo('#audio-inputs-unused'); - - // add it to the unused Voice Chat box - if ($('#voice-chat-type').val() == VOICE_CHAT.CHAT) { - $cloneChat.appendTo('#voice-inputs-unused'); - } - }); - - _syncVoiceChatType(); - } - - function _syncVoiceChatType() { - var $option1 = $('#voice-chat-type > option[value="1"]'); - var voiceChatType = $('#voice-chat-type').val(); - - // remove option 1 from voice chat type dropdown if no music (based on what's unused on the Music Audio tab) or chat inputs are available - if ($('#audio-inputs-unused > option').size() === 0 && chatOtherUnassignedList.length === 0 && chatOtherAssignedList.length === 0) { - $option1.remove(); - } - else { - // make sure it's not already in list before adding back - if ($option1.length === 0) { - logger.debug("Adding Option 1 back to Voice Chat dropdown."); - $('#voice-chat-type').append(''); - } - } - } - - function _handleVoiceInputAdd($selectedVoiceInputs) { - $selectedVoiceInputs.each(function() { - var id = this.value; - - // if this input is in the unused track input box, remove it - var $unusedMusic = $('#audio-inputs-unused > option[value="' + id + '"]'); - if ($unusedMusic.length > 0) { - $unusedMusic.remove(); - } - $(this).remove().appendTo('#voice-inputs-selection'); - }); - } - - function _handleVoiceInputRemove($selectedVoiceInputs) { - $selectedVoiceInputs.each(function() { - var $removedInput = $(this).remove(); - var $cloneAudio = $removedInput.clone(true, true); - var $cloneChat = $removedInput.clone(true, true); - - $cloneChat.appendTo('#voice-inputs-unused'); - - // add it to the unused Music Input box if the selected input is not type "chat" - if (!isChatInput(this.value)) { - $cloneAudio.appendTo('#audio-inputs-unused'); - } - }); - } - - function isChatInput(id) { - // copy the arrays - var chatOtherUnassignedListCopy = chatOtherUnassignedList; - var chatOtherAssignedListCopy = chatOtherAssignedList; - - // is this input in the unassigned list? - chatOtherUnassignedListCopy = $.grep(chatOtherUnassignedListCopy, function(n,i){ - return n.chat && n.id === id; - }); - - // is this input in the assigned list? - chatOtherAssignedListCopy = $.grep(chatOtherAssignedListCopy, function(n,i){ - return n.chat && n.id === id; - }); - - logger.debug("chatOtherUnassignedListCopy=" + JSON.stringify(chatOtherUnassignedListCopy)); - logger.debug("chatOtherAssignedListCopy=" + JSON.stringify(chatOtherAssignedListCopy)); - - return chatOtherUnassignedListCopy.length > 0 || chatOtherAssignedListCopy.length > 0; - } - - function audioDriverChanged() { - - context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); - - logger.debug("Called TrackSetMusicDevice with " + $('#audio-drivers').val()); - - context.jamClient.TrackLoadAssignments(); - initDialogData(); - - // refresh dialog - showVoiceChatPanel(true); - showMusicAudioPanel(true); - } - - function voiceChatChanged() { - var voiceChatVal = $('#voice-chat-type').val(); - - logger.debug("voiceChatVal=" + voiceChatVal); - - if (voiceChatVal == VOICE_CHAT.NO_CHAT) { - logger.debug("VOICE_CHAT.NO_CHAT"); - _addSelectedVoiceInputsToMusicInputs(); - - $('#voice-inputs-unused').empty(); - $('#voice-inputs-selection').empty(); - } - else if (voiceChatVal == VOICE_CHAT.CHAT) { - logger.debug("VOICE_CHAT.CHAT"); - - $('#voice-inputs-unused').empty(); - $('#voice-inputs-selection').empty(); - - // add the chat inputs (unassigned and assigned) to the unused box to force the user to select again - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherUnassignedList, "id", "name", -1); - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherAssignedList, "id", "name", -1); - - // add each unused music input if it doesn't already exist - $('#audio-inputs-unused > option').each(function() { - if ($('#voice-inputs-unused > option[value="' + this.value + '"]').length === 0) { - logger.debug("Appending " + this.value + " to the unused voice input box."); - $('#voice-inputs-unused').append(''); - } - }); - } - } - - function _addSelectedVoiceInputsToMusicInputs() { - $('#voice-inputs-selection > option').each(function() { - // if this input is not already in the available music inputs box and the selected input is not chat input, add - // it to the unused music inputs box - if ($('#audio-inputs-unused > option[value="' + this.value + '"]').length === 0 && !isChatInput(this.value)) { - logger.debug("Appending " + this.value + " to the unused audio input box."); - $('#audio-inputs-unused').append(''); - } - }); - } - - function configureDriverSettingsButton() { - if (context.jamClient.TrackHasControlPanel()) { - $('#btn-driver-settings').show(); - } - else { - $('#btn-driver-settings').hide(); - } - } - - function showMusicAudioPanel(refreshLists) { - _setInstructions('audio'); - _activateTab('audio'); - - if (refreshLists) { - $('#audio-drivers').empty(); - - // determine correct music device to preselect - var deviceId = context.jamClient.TrackGetMusicDeviceID(); - logger.debug("deviceId = " + deviceId); - - // load Audio Driver dropdown - devices = context.jamClient.TrackGetDevices(); - logger.debug("Called TrackGetDevices with response " + JSON.stringify(devices)); - var keys = Object.keys(devices); - - for (var i=0; i < keys.length; i++) { - var template = $('#template-option').html(); - var isSelected = ""; - if (keys[i] === deviceId) { - isSelected = "selected"; - } - var html = context.JK.fillTemplate(template, { - value: keys[i], - label: devices[keys[i]], - selected: isSelected - }); - - $('#audio-drivers').append(html); - } - - context.JK.dropdown($('#audio-drivers')); - - if (deviceId === '') { - context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); - } - - configureDriverSettingsButton(); - - $('#audio-inputs-unused').empty(); - $('#track1-input').empty(); - $('#track1-instrument').empty(); - $('#track2-input').empty(); - $('#track2-instrument').empty(); - $('#audio-output-unused').empty(); - $('#audio-output-selection').empty(); - - _initMusicTabData(); - - // load Unused Inputs - context.JK.loadOptions($('#template-option').html(), $('#audio-inputs-unused'), inputUnassignedList, "id", "name", -1); - - // load Track 1 Input(s) - context.JK.loadOptions($('#template-option').html(), $('#track1-input'), track1AudioInputChannels, "id", "name", -1); - - // load Track 1 Instrument - var current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK1); - - // if no instrument is stored on the backend, the user is opening this dialog for the first time after FTUE; - // initialize to the user's first instrument - if (current_instrument === 0) { - if (context.JK.userMe.instruments && context.JK.userMe.instruments.length > 0) { - var instrument_desc = context.JK.userMe.instruments[0].description; - current_instrument = context.JK.server_to_client_instrument_map[instrument_desc].client_id; - } - } - - context.JK.loadOptions($('#template-option').html(), $('#track1-instrument'), instrument_array, "id", "description", current_instrument); - - // load Track 2 Input(s) - context.JK.loadOptions($('#template-option').html(), $('#track2-input'), track2AudioInputChannels, "id", "name", -1); - - // load Track 2 Instrument - current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK2); - context.JK.loadOptions($('#template-option').html(), $('#track2-instrument'), instrument_array, "id", "description", current_instrument); - - // load Unused Outputs - context.JK.loadOptions($('#template-option').html(), $('#audio-output-unused'), outputUnassignedList, "id", "name", -1); - - // load Session Audio Output - context.JK.loadOptions($('#template-option').html(), $('#audio-output-selection'), outputAssignedList, "id", "name", -1); - } - } - - function showVoiceChatPanel(refreshLists) { - _setInstructions('voice'); - _activateTab('voice'); - - if (refreshLists) { - $('#voice-inputs-unused').empty(); - $('#voice-inputs-selection').empty(); - - _initVoiceChatTabData(); - - var chatOption = $('#voice-chat-type').val(); - - if (chatOption == VOICE_CHAT.CHAT) { - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatUnassignedList, "id", "name", -1); - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), chatAssignedList, "id", "name", -1); - - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherUnassignedList, "id", "name", -1); - context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), chatOtherAssignedList, "id", "name", -1); - } - - // disable inputs - else if (chatOption == VOICE_CHAT.NO_CHAT) { - } - } - } - - function _activateTab(type) { - if (type === 'voice') { - $('div[tab-id="music-audio"]').hide(); - $('div[tab-id="voice-chat"]').show(); - - $('#tab-configure-audio').removeClass('selected'); - $('#tab-configure-voice').addClass('selected'); - } - else { - $('div[tab-id="music-audio"]').show(); - $('div[tab-id="voice-chat"]').hide(); - - $('#tab-configure-audio').addClass('selected'); - $('#tab-configure-voice').removeClass('selected'); - } - } - - function initDialogData() { - _initMusicTabData(); - _initVoiceChatTabData(); - } - - function _initMusicTabData() { - inputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false); - //logger.debug("inputUnassignedList=" + JSON.stringify(inputUnassignedList)); - - track1AudioInputChannels = _loadList(ASSIGNMENT.TRACK1, true, false); - //logger.debug("track1AudioInputChannels=" + JSON.stringify(track1AudioInputChannels)); - - track2AudioInputChannels = _loadList(ASSIGNMENT.TRACK2, true, false); - //logger.debug("track2AudioInputChannels=" + JSON.stringify(track2AudioInputChannels)); - - outputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, false, false); - outputAssignedList = _loadList(ASSIGNMENT.OUTPUT, false, false); - } - - function _initVoiceChatTabData() { - chatUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false); - //logger.debug("chatUnassignedList=" + JSON.stringify(chatUnassignedList)); - - chatAssignedList = _loadList(ASSIGNMENT.CHAT, true, false); - //logger.debug("chatAssignedList=" + JSON.stringify(chatAssignedList)); - - chatOtherUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, true); - //logger.debug("chatOtherUnassignedList=" + JSON.stringify(chatOtherUnassignedList)); - - chatOtherAssignedList = _loadList(ASSIGNMENT.CHAT, true, true); - //logger.debug("chatOtherAssignedList=" + JSON.stringify(chatOtherAssignedList)); - } - - // TODO: copied in addTrack.js - refactor to common place - function _loadList(assignment, input, chat) { - var list = []; - - // get data needed for listboxes - var channels = context.jamClient.TrackGetChannels(); - - var musicDevices = context.jamClient.TrackGetMusicDeviceNames(input); - - // SEE loadList function in TrackAssignGui.cpp of client code - $.each(channels, function(index, val) { - - if (input !== val.input) { - return; - } - - var currAssignment = context.jamClient.TrackGetAssignment(val.id, val.input); - if (assignment !== currAssignment) { - return; - } - - // logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + currAssignment + - // ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat); - - var os = context.jamClient.GetOSAsString(); - if (os === context.JK.OS.WIN32) { - if (chat && ($.inArray(val.device_id, musicDevices) > -1 || context.jamClient.TrackIsMusicDeviceType(val.device_type))) { - return; - } - } - else { - if (chat && ($.inArray(val.device_id, musicDevices) > -1 || !context.jamClient.TrackIsMusicDeviceType(val.device_type))) { - return; - } - } - - if (!chat && $.inArray(val.device_id, musicDevices) === -1) { - return; - } - - if ((chat && !val.chat) || (!chat && val.chat)) { - return; - } - - list.push(val); - }); - - return list; - } - - function saveSettings() { - if (!context.JK.verifyNotRecordingForTrackChange(app)) { - return; - } - - if (!validateAudioSettings(false)) { - return; - } - - if (!validateVoiceChatSettings(false)) { - return; - } - - saveAudioSettings(); - saveVoiceChatSettings(); - - context.jamClient.TrackSaveAssignments(); - - originalDeviceId = $('#audio-drivers').val(); - app.layout.closeDialog('configure-audio'); - } - - function saveAudioSettings() { - - context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); - - // UNASSIGNED INPUTS - $('#audio-inputs-unused > option').each(function() { - logger.debug("Marking " + this.value + " as unassigned input."); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED); - }); - - // TRACK 1 INPUTS - $('#track1-input > option').each(function() { - logger.debug("Saving track 1 input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1); - }); - - // TRACK 1 INSTRUMENT - var instrumentVal = $('#track1-instrument').val(); - var instrumentText = $('#track1-instrument > option:selected').text().toLowerCase(); - - logger.debug("Saving track 1 instrument = " + instrumentVal); - context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal); - - - // TRACK 2 INPUTS - var track2Selected = false; - $('#track2-input > option').each(function() { - track2Selected = true; - logger.debug("Saving track 2 input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2); - }); - - if (track2Selected) { - // TRACK 2 INSTRUMENT - instrumentVal = $('#track2-instrument').val(); - instrumentText = $('#track2-instrument > option:selected').text().toLowerCase(); - - logger.debug("Saving track 2 instrument = " + instrumentVal); - context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal); - } - else { - // track 2 was removed - if (myTrackCount === 2) { - logger.debug("Deleting track " + myTracks[1].trackId); - context.jamClient.TrackSetCount(1); - //sessionModel.deleteTrack(sessionId, myTracks[1].trackId); - } - } - - // UNASSIGNED OUTPUTS - $('#audio-output-unused > option').each(function() { - logger.debug("Marking " + this.value + " as unassigned output."); - context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.UNASSIGNED); - }); - - // OUTPUT - $('#audio-output-selection > option').each(function() { - logger.debug("Saving session audio output = " + this.value); - context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT); - }); - } - - function saveVoiceChatSettings() { - var voiceChatType = $('#voice-chat-type').val(); - originalVoiceChat = voiceChatType; - - logger.debug("Calling TrackSetChatEnable with value = " + voiceChatType); - context.jamClient.TrackSetChatEnable(voiceChatType == VOICE_CHAT.CHAT ? true : false); - - if (voiceChatType == VOICE_CHAT.CHAT) { - // UNASSIGNED VOICE CHAT - $('#voice-inputs-unused > option').each(function() { - logger.debug("Marking " + this.value + " as unassigned voice input."); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED); - }); - - // VOICE CHAT INPUT - $("#voice-inputs-selection > option").each(function() { - logger.debug("Saving chat input = " + this.value); - context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT); - }); - } - // make sure any previously assigned chat devices are marked as unassigned - else if (voiceChatType == VOICE_CHAT.NO_CHAT) { - // chat devices that were assigned - $.each(chatOtherAssignedList, function(index, val) { - logger.debug("Marking " + val.id + " as unassigned voice input."); - context.jamClient.TrackSetAssignment(val.id, true, ASSIGNMENT.UNASSIGNED); - }); - } - } - - function cancelSettings() { - logger.debug("Cancel settings"); - - // reset to original device ID - context.jamClient.TrackSetMusicDevice(originalDeviceId); - - $('#voice-chat-type').val(originalVoiceChat); - - app.layout.closeDialog('configure-audio'); - } - - function validateAudioSettings(allowEmptyInput) { - var isValid = true; - var noTrackErrMsg = 'You can assign no more than 2 input ports to each of your tracks. Please update your settings to correct this.'; - var noInstrumentErrMsg = 'You must specify what instrument is being played for each track. Please update your settings to correct this.'; - var outputErrMsg = 'You must assign two output ports for stereo session audio to hear music. Please update your settings to correct this.'; - - var errMsg; - - // if there are no inputs remaining then allow the user to switch to the Voice Chat tab - // to remove some - if (allowEmptyInput && $('#audio-inputs-unused > option').size() === 0) { - return isValid; - } - else { - // verify Track 1 Input and Instrument exist - if ($('#track1-input > option').size() === 0 || $('#track1-input > option').size() > 2) { - errMsg = noTrackErrMsg; - isValid = false; - } - - if (isValid) { - if ($('#track1-instrument > option:selected').length === 0) { - errMsg = noInstrumentErrMsg; - isValid = false; - } - } - - logger.debug("validateAudioSettings:myTrackCount=" + myTrackCount); - - // if Track 2 exists, verify Input and Instrument exist - if (isValid) { - var track2Count = $('#track2-input > option').size(); - if (track2Count > 2) { - errMsg = noTrackErrMsg; - isValid = false; - } - - // only validate instrument if second track is selected - if (isValid && track2Count > 0 && $('#track2-instrument > option:selected').length === 0) { - errMsg = noInstrumentErrMsg; - isValid = false; - } - } - - // verify Session Audio Output exists - if (isValid && $('#audio-output-selection > option').size() !== 2) { - errMsg = outputErrMsg; - isValid = false; - } - - if (!isValid) { - context.JK.showErrorDialog(app, errMsg, "invalid settings"); - } - } - - return isValid; - } - - function validateVoiceChatSettings(allowEmptyInput) { - var isValid = true; - var noTrackErrMsg = 'You must select a voice input.'; - var limitExceededErrMsg = 'You cannot select more than 1 voice chat input.'; - var errMsg; - - if (allowEmptyInput && $('#voice-inputs-unused > option').size() === 0) { - return isValid; - } - else { - var chatType = $('#voice-chat-type').val(); - if (chatType == VOICE_CHAT.CHAT) { - var $voiceInputSelection = $('#voice-inputs-selection > option'); - var count = $voiceInputSelection.size(); - if (count === 0) { - errMsg = noTrackErrMsg; - isValid = false; - } - else if (count > 1) { - errMsg = limitExceededErrMsg; - isValid = false; - } - } - else if (chatType == VOICE_CHAT.NO_CHAT) { - // NO VALIDATION NEEDED - } - - if (!isValid) { - context.JK.showErrorDialog(app, errMsg, "invalid settings"); - } - } - - return isValid; - } - - function _setInstructions(type) { - var $instructions = $('#instructions', 'div[layout-id="configure-audio"]'); - if (type === 'audio') { - var os = context.jamClient.GetOSAsString(); - $instructions.html(configure_audio_instructions[os]); - } - else if (type === 'voice') { - $instructions.html(configure_voice_instructions); - } - } - - function _init() { - // load instrument array for populating listboxes, using client_id in instrument_map as ID - instrument_array = context.JK.listInstruments(); - - originalVoiceChat = context.jamClient.TrackGetChatEnable() ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT; - - $('#voice-chat-type').val(originalVoiceChat); - - originalDeviceId = context.jamClient.TrackGetMusicDeviceID(); - - context.jamClient.TrackLoadAssignments(); - initDialogData(); - - var $option1 = $('#voice-chat-type > option[value="1"]'); - - // remove option 1 from voice chat if none are available and not already assigned - if (inputUnassignedList.length === 0 && chatAssignedList.length === 0 && chatOtherAssignedList.length === 0 && chatOtherUnassignedList.length === 0) { - $option1.remove(); - } - // add it if it doesn't exist - else { - if ($option1.length === 0) { - logger.debug("Adding Option 1 back to Voice Chat dropdown."); - $('#voice-chat-type').append(''); - } - } - } - - function initialize () { - var dialogBindings = { - 'beforeShow' : function() { - return context.JK.verifyNotRecordingForTrackChange(app); - } - }; - app.bindDialog('configure-audio', dialogBindings); - - events(); - } - - // should be called before opening - function refresh() { - _init(); - myTrackCount = myTracks.length; - } - - this.initialize = initialize; - this.refresh = refresh; - - this.showMusicAudioPanel = showMusicAudioPanel; - this.showVoiceChatPanel = showVoiceChatPanel; - - return this; + var ASSIGNMENT = { + CHAT: -2, + OUTPUT: -1, + UNASSIGNED: 0, + TRACK1: 1, + TRACK2: 2 }; - })(window,jQuery); + var VOICE_CHAT = { + NO_CHAT: "0", + CHAT: "1" + }; + + var instrument_array = []; + + // dialog variables + var inputUnassignedList = []; + var track1AudioInputChannels = []; + var track2AudioInputChannels = []; + + var outputUnassignedList = []; + var outputAssignedList = []; + + var chatUnassignedList = []; + var chatAssignedList = []; + + var chatOtherUnassignedList = []; + var chatOtherAssignedList = []; + + var devices = []; + var originalDeviceId; + var originalVoiceChat; + + var configure_audio_instructions = { + "Win32": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + + "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + + "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + + "Gear button to test that device.", + + "MacOSX": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + + "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + + "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + + "Gear button to test that device.", + + "Unix": "Choose the audio device you would like to use for this session. If needed, use arrow buttons to assign audio inputs " + + "to your tracks, to indicate what instrument you are playing on each track, and to assign audio outputs for listening. " + + "If you want to use a new audio device you have not tested/certified for latency using JamKazam, click the Add New Audio " + + "Gear button to test that device." + }; + + var configure_voice_instructions = "If you are using a microphone to capture your instrumental or vocal audio, you can simply use that mic " + + "for both music and chat. Otherwise, choose a device to use for voice chat, and use arrow buttons to " + + "select an input on that device."; + + function events() { + + // Music Audio Tab + var $tabConfigureAudio = $('#tab-configure-audio'); + $tabConfigureAudio.unbind("click"); + $tabConfigureAudio.click(function () { + // validate voice chat settings + if (validateVoiceChatSettings(true)) { + showMusicAudioPanel(false); + } + }); + + // Voice Chat Tab + var $tabConfigureVoice = $('#tab-configure-voice'); + $tabConfigureVoice.unbind("click"); + $tabConfigureVoice.click(function () { + // validate audio settings + if (validateAudioSettings(true)) { + showVoiceChatPanel(false); + } + }); + + // Track 1 Add + var $imgTrack1Add = $('#img-track1-input-add'); + $imgTrack1Add.unbind("click"); + $imgTrack1Add.click(function () { + var $unusedMusicInputs = $('#audio-inputs-unused > option:selected'); + _handleTrackInputAdd($unusedMusicInputs, '#track1-input'); + }); + + // Track 2 Add + var $imgTrack2Add = $('#img-track2-input-add'); + $imgTrack2Add.unbind("click"); + $imgTrack2Add.click(function () { + var $unusedMusicInputs = $('#audio-inputs-unused > option:selected'); + _handleTrackInputAdd($unusedMusicInputs, '#track2-input'); + }); + + // Track 1 Remove + var $imgTrack1Remove = $('#img-track1-input-remove'); + $imgTrack1Remove.unbind("click"); + $imgTrack1Remove.click(function () { + _handleTrackInputRemove('#track1-input'); + }); + + // Track 2 Remove + var $imgTrack2Remove = $('#img-track2-input-remove'); + $imgTrack2Remove.unbind("click"); + $imgTrack2Remove.click(function () { + _handleTrackInputRemove('#track2-input'); + }); + + // Audio Output Add + var $imgAudioOutputAdd = $('#img-audio-output-add'); + $imgAudioOutputAdd.unbind("click"); + $imgAudioOutputAdd.click(function () { + var $unusedAudioOutputs = $('#audio-output-unused > option:selected'); + $unusedAudioOutputs.remove().appendTo('#audio-output-selection'); + }); + + // Audio Output Remove + var $imgAudioOutputRemove = $('#img-audio-output-remove'); + $imgAudioOutputRemove.unbind("click"); + $imgAudioOutputRemove.click(function () { + var $usedAudioOutputs = $('#audio-output-selection > option:selected'); + $usedAudioOutputs.remove().appendTo('#audio-output-unused'); + }); + + // Voice Chat Add + var $imgVoiceAdd = $('#img-voice-input-add'); + $imgVoiceAdd.unbind("click"); + $imgVoiceAdd.click(function () { + var $unusedVoiceInputs = $('#voice-inputs-unused > option:selected'); + _handleVoiceInputAdd($unusedVoiceInputs); + }); + + // Voice Chat Remove + var $imgVoiceRemove = $('#img-voice-input-remove'); + $imgVoiceRemove.unbind("click"); + $imgVoiceRemove.click(function () { + var $usedVoiceInputs = $("#voice-inputs-selection > option:selected"); + _handleVoiceInputRemove($usedVoiceInputs); + }); + + $('#audio-drivers').unbind("change"); + $('#audio-drivers').change(function () { + audioDriverChanged(); + }); + + $('#voice-chat-type').unbind("change"); + $('#voice-chat-type').change(function () { + voiceChatChanged(); + }); + + $('#btn-driver-settings').unbind("click"); + $('#btn-driver-settings').click(function () { + context.jamClient.TrackOpenControlPanel(); + }); + + $('#btn-cancel-new-audio').unbind("click"); + $('#btn-cancel-new-audio').click(context.JK.showOverlay); + + $('#btn-error-ok').click(context.JK.showOverlay); + + $('#btn-save-settings').unbind("click"); + $('#btn-save-settings').click(saveSettings); + + $('#btn-cancel-settings').unbind("click"); + $('#btn-cancel-settings').click(cancelSettings); + } + + function _handleTrackInputAdd($selectedMusicInputs, selector) { + $selectedMusicInputs.each(function () { + var deviceId = this.value; + var description = this.text; + $(this).remove().appendTo(selector); + + // if this input exists in the Voice Chat unused box, remove it + var $voiceChatUnused = $('#voice-inputs-unused > option[value="' + deviceId + '"]'); + if ($voiceChatUnused.length > 0) { + logger.debug("Removing " + deviceId + " from Voice Chat Unused"); + $voiceChatUnused.remove(); + } + }); + + _syncVoiceChatType(); + } + + function _handleTrackInputRemove(trackSelector) { + trackSelector = trackSelector + ' > option:selected'; + $(trackSelector).each(function () { + var $removedInput = $(this).remove(); + var $cloneAudio = $removedInput.clone(true, true); + var $cloneChat = $removedInput.clone(true, true); + + $cloneAudio.appendTo('#audio-inputs-unused'); + + // add it to the unused Voice Chat box + if ($('#voice-chat-type').val() == VOICE_CHAT.CHAT) { + $cloneChat.appendTo('#voice-inputs-unused'); + } + }); + + _syncVoiceChatType(); + } + + function _syncVoiceChatType() { + var $option1 = $('#voice-chat-type > option[value="1"]'); + + // remove option 1 from voice chat type dropdown if no music (based on what's unused on the Music Audio tab) or chat inputs are available + if ($('#audio-inputs-unused > option').size() === 0 && chatOtherUnassignedList.length === 0 && chatOtherAssignedList.length === 0) { + $option1.remove(); + } + else { + // make sure it's not already in list before adding back + if ($option1.length === 0) { + logger.debug("Adding Option 1 back to Voice Chat dropdown."); + $('#voice-chat-type').append(''); + } + } + } + + function _handleVoiceInputAdd($selectedVoiceInputs) { + $selectedVoiceInputs.each(function () { + var id = this.value; + + // if this input is in the unused track input box, remove it + var $unusedMusic = $('#audio-inputs-unused > option[value="' + id + '"]'); + if ($unusedMusic.length > 0) { + $unusedMusic.remove(); + } + $(this).remove().appendTo('#voice-inputs-selection'); + }); + } + + function _handleVoiceInputRemove($selectedVoiceInputs) { + $selectedVoiceInputs.each(function () { + var $removedInput = $(this).remove(); + var $cloneAudio = $removedInput.clone(true, true); + var $cloneChat = $removedInput.clone(true, true); + + $cloneChat.appendTo('#voice-inputs-unused'); + + // add it to the unused Music Input box if the selected input is not type "chat" + if (!isChatInput(this.value)) { + $cloneAudio.appendTo('#audio-inputs-unused'); + } + }); + } + + function isChatInput(id) { + // copy the arrays + var chatOtherUnassignedListCopy = chatOtherUnassignedList; + var chatOtherAssignedListCopy = chatOtherAssignedList; + + // is this input in the unassigned list? + chatOtherUnassignedListCopy = $.grep(chatOtherUnassignedListCopy, function (n, i) { + return n.chat && n.id === id; + }); + + // is this input in the assigned list? + chatOtherAssignedListCopy = $.grep(chatOtherAssignedListCopy, function (n, i) { + return n.chat && n.id === id; + }); + + logger.debug("chatOtherUnassignedListCopy=" + JSON.stringify(chatOtherUnassignedListCopy)); + logger.debug("chatOtherAssignedListCopy=" + JSON.stringify(chatOtherAssignedListCopy)); + + return chatOtherUnassignedListCopy.length > 0 || chatOtherAssignedListCopy.length > 0; + } + + function audioDriverChanged() { + + context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); + + logger.debug("Called TrackSetMusicDevice with " + $('#audio-drivers').val()); + + context.jamClient.TrackLoadAssignments(); + initDialogData(); + + // refresh dialog + showVoiceChatPanel(true); + showMusicAudioPanel(true); + } + + function voiceChatChanged() { + var voiceChatVal = $('#voice-chat-type').val(); + + logger.debug("voiceChatVal=" + voiceChatVal); + + if (voiceChatVal == VOICE_CHAT.NO_CHAT) { + logger.debug("VOICE_CHAT.NO_CHAT"); + _addSelectedVoiceInputsToMusicInputs(); + + $('#voice-inputs-unused').empty(); + $('#voice-inputs-selection').empty(); + } + else if (voiceChatVal == VOICE_CHAT.CHAT) { + logger.debug("VOICE_CHAT.CHAT"); + + $('#voice-inputs-unused').empty(); + $('#voice-inputs-selection').empty(); + + // add the chat inputs (unassigned and assigned) to the unused box to force the user to select again + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherUnassignedList, "id", "name", -1); + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherAssignedList, "id", "name", -1); + + // add each unused music input if it doesn't already exist + $('#audio-inputs-unused > option').each(function () { + if ($('#voice-inputs-unused > option[value="' + this.value + '"]').length === 0) { + logger.debug("Appending " + this.value + " to the unused voice input box."); + $('#voice-inputs-unused').append(''); + } + }); + } + } + + function _addSelectedVoiceInputsToMusicInputs() { + $('#voice-inputs-selection > option').each(function () { + // if this input is not already in the available music inputs box and the selected input is not chat input, add + // it to the unused music inputs box + if ($('#audio-inputs-unused > option[value="' + this.value + '"]').length === 0 && !isChatInput(this.value)) { + logger.debug("Appending " + this.value + " to the unused audio input box."); + $('#audio-inputs-unused').append(''); + } + }); + } + + function configureDriverSettingsButton() { + if (context.jamClient.TrackHasControlPanel()) { + $('#btn-driver-settings').show(); + } + else { + $('#btn-driver-settings').hide(); + } + } + + function showMusicAudioPanel(refreshLists) { + _setInstructions('audio'); + _activateTab('audio'); + + if (refreshLists) { + $('#audio-drivers').empty(); + + // determine correct music device to preselect + var deviceId = context.jamClient.TrackGetMusicDeviceID(); + logger.debug("deviceId = " + deviceId); + + // load Audio Driver dropdown + devices = context.jamClient.TrackGetDevices(); + logger.debug("Called TrackGetDevices with response " + JSON.stringify(devices)); + var keys = Object.keys(devices); + + for (var i = 0; i < keys.length; i++) { + var template = $('#template-option').html(); + var isSelected = ""; + if (keys[i] === deviceId) { + isSelected = "selected"; + } + var html = context.JK.fillTemplate(template, { + value: keys[i], + label: devices[keys[i]], + selected: isSelected + }); + + $('#audio-drivers').append(html); + } + + context.JK.dropdown($('#audio-drivers')); + + if (deviceId === '') { + context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); + } + + configureDriverSettingsButton(); + + $('#audio-inputs-unused').empty(); + $('#track1-input').empty(); + $('#track1-instrument').empty(); + $('#track2-input').empty(); + $('#track2-instrument').empty(); + $('#audio-output-unused').empty(); + $('#audio-output-selection').empty(); + + _initMusicTabData(); + + // load Unused Inputs + context.JK.loadOptions($('#template-option').html(), $('#audio-inputs-unused'), inputUnassignedList, "id", "name", -1); + + // load Track 1 Input(s) + context.JK.loadOptions($('#template-option').html(), $('#track1-input'), track1AudioInputChannels, "id", "name", -1); + + // load Track 1 Instrument + var current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK1); + + // if no instrument is stored on the backend, the user is opening this dialog for the first time after FTUE; + // initialize to the user's first instrument + if (current_instrument === 0) { + if (context.JK.userMe.instruments && context.JK.userMe.instruments.length > 0) { + var instrument_desc = context.JK.userMe.instruments[0].description; + current_instrument = context.JK.server_to_client_instrument_map[instrument_desc].client_id; + } + } + + context.JK.loadOptions($('#template-option').html(), $('#track1-instrument'), instrument_array, "id", "description", current_instrument); + + // load Track 2 Input(s) + context.JK.loadOptions($('#template-option').html(), $('#track2-input'), track2AudioInputChannels, "id", "name", -1); + + // load Track 2 Instrument + current_instrument = context.jamClient.TrackGetInstrument(ASSIGNMENT.TRACK2); + context.JK.loadOptions($('#template-option').html(), $('#track2-instrument'), instrument_array, "id", "description", current_instrument); + + // load Unused Outputs + context.JK.loadOptions($('#template-option').html(), $('#audio-output-unused'), outputUnassignedList, "id", "name", -1); + + // load Session Audio Output + context.JK.loadOptions($('#template-option').html(), $('#audio-output-selection'), outputAssignedList, "id", "name", -1); + } + } + + function showVoiceChatPanel(refreshLists) { + _setInstructions('voice'); + _activateTab('voice'); + + if (refreshLists) { + $('#voice-inputs-unused').empty(); + $('#voice-inputs-selection').empty(); + + _initVoiceChatTabData(); + + var chatOption = $('#voice-chat-type').val(); + + if (chatOption == VOICE_CHAT.CHAT) { + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatUnassignedList, "id", "name", -1); + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), chatAssignedList, "id", "name", -1); + + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-unused'), chatOtherUnassignedList, "id", "name", -1); + context.JK.loadOptions($('#template-option').html(), $('#voice-inputs-selection'), chatOtherAssignedList, "id", "name", -1); + } + + // disable inputs + else if (chatOption == VOICE_CHAT.NO_CHAT) { + } + } + } + + function _activateTab(type) { + if (type === 'voice') { + $('div[tab-id="music-audio"]').hide(); + $('div[tab-id="voice-chat"]').show(); + + $('#tab-configure-audio').removeClass('selected'); + $('#tab-configure-voice').addClass('selected'); + } + else { + $('div[tab-id="music-audio"]').show(); + $('div[tab-id="voice-chat"]').hide(); + + $('#tab-configure-audio').addClass('selected'); + $('#tab-configure-voice').removeClass('selected'); + } + } + + function initDialogData() { + _initMusicTabData(); + _initVoiceChatTabData(); + } + + function _initMusicTabData() { + inputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false); + //logger.debug("inputUnassignedList=" + JSON.stringify(inputUnassignedList)); + + track1AudioInputChannels = _loadList(ASSIGNMENT.TRACK1, true, false); + //logger.debug("track1AudioInputChannels=" + JSON.stringify(track1AudioInputChannels)); + + track2AudioInputChannels = _loadList(ASSIGNMENT.TRACK2, true, false); + //logger.debug("track2AudioInputChannels=" + JSON.stringify(track2AudioInputChannels)); + + outputUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, false, false); + outputAssignedList = _loadList(ASSIGNMENT.OUTPUT, false, false); + } + + function _initVoiceChatTabData() { + chatUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, false); + //logger.debug("chatUnassignedList=" + JSON.stringify(chatUnassignedList)); + + chatAssignedList = _loadList(ASSIGNMENT.CHAT, true, false); + //logger.debug("chatAssignedList=" + JSON.stringify(chatAssignedList)); + + chatOtherUnassignedList = _loadList(ASSIGNMENT.UNASSIGNED, true, true); + //logger.debug("chatOtherUnassignedList=" + JSON.stringify(chatOtherUnassignedList)); + + chatOtherAssignedList = _loadList(ASSIGNMENT.CHAT, true, true); + //logger.debug("chatOtherAssignedList=" + JSON.stringify(chatOtherAssignedList)); + } + + // TODO: copied in addTrack.js - refactor to common place + function _loadList(assignment, input, chat) { + var list = []; + + // get data needed for listboxes + var channels = context.jamClient.TrackGetChannels(); + + var musicDevices = context.jamClient.TrackGetMusicDeviceNames(input); + + // SEE loadList function in TrackAssignGui.cpp of client code + $.each(channels, function (index, val) { + + if (input !== val.input) { + return; + } + + var currAssignment = context.jamClient.TrackGetAssignment(val.id, val.input); + if (assignment !== currAssignment) { + return; + } + + // logger.debug("channel id=" + val.id + ", channel input=" + val.input + ", channel assignment=" + currAssignment + + // ", channel name=" + val.name + ", channel type=" + val.device_type + ", chat=" + val.chat); + + var os = context.jamClient.GetOSAsString(); + if (os === context.JK.OS.WIN32) { + if (chat && ($.inArray(val.device_id, musicDevices) > -1 || context.jamClient.TrackIsMusicDeviceType(val.device_type))) { + return; + } + } + else { + if (chat && ($.inArray(val.device_id, musicDevices) > -1 || !context.jamClient.TrackIsMusicDeviceType(val.device_type))) { + return; + } + } + + if (!chat && $.inArray(val.device_id, musicDevices) === -1) { + return; + } + + if ((chat && !val.chat) || (!chat && val.chat)) { + return; + } + + list.push(val); + }); + + return list; + } + + function saveSettings() { + if (!context.JK.verifyNotRecordingForTrackChange(app)) { + return; + } + + if (!validateAudioSettings(false)) { + return; + } + + if (!validateVoiceChatSettings(false)) { + return; + } + + saveAudioSettings(); + saveVoiceChatSettings(); + + context.jamClient.TrackSaveAssignments(); + + originalDeviceId = $('#audio-drivers').val(); + app.layout.closeDialog('configure-audio'); + } + + function saveAudioSettings() { + + context.jamClient.TrackSetMusicDevice($('#audio-drivers').val()); + + // UNASSIGNED INPUTS + $('#audio-inputs-unused > option').each(function () { + logger.debug("Marking " + this.value + " as unassigned input."); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED); + }); + + // TRACK 1 INPUTS + $('#track1-input > option').each(function () { + logger.debug("Saving track 1 input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK1); + }); + + // TRACK 1 INSTRUMENT + var instrumentVal = $('#track1-instrument').val(); + var instrumentText = $('#track1-instrument > option:selected').text().toLowerCase(); + + logger.debug("Saving track 1 instrument = " + instrumentVal); + context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK1, instrumentVal); + + + // TRACK 2 INPUTS + var track2Selected = false; + $('#track2-input > option').each(function () { + track2Selected = true; + logger.debug("Saving track 2 input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.TRACK2); + }); + + if (track2Selected) { + // TRACK 2 INSTRUMENT + instrumentVal = $('#track2-instrument').val(); + instrumentText = $('#track2-instrument > option:selected').text().toLowerCase(); + + logger.debug("Saving track 2 instrument = " + instrumentVal); + context.jamClient.TrackSetInstrument(ASSIGNMENT.TRACK2, instrumentVal); + } + else { + // track 2 was removed + if (myTrackCount === 2) { + logger.debug("Deleting track " + myTracks[1].trackId); + context.jamClient.TrackSetCount(1); + //sessionModel.deleteTrack(sessionId, myTracks[1].trackId); + } + } + + // UNASSIGNED OUTPUTS + $('#audio-output-unused > option').each(function () { + logger.debug("Marking " + this.value + " as unassigned output."); + context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.UNASSIGNED); + }); + + // OUTPUT + $('#audio-output-selection > option').each(function () { + logger.debug("Saving session audio output = " + this.value); + context.jamClient.TrackSetAssignment(this.value, false, ASSIGNMENT.OUTPUT); + }); + } + + function saveVoiceChatSettings() { + var voiceChatType = isChatInputSpecified(); + + originalVoiceChat = voiceChatType; + + logger.debug("Calling TrackSetChatEnable with value = " + voiceChatType); + context.jamClient.TrackSetChatEnable(voiceChatType == VOICE_CHAT.CHAT ? true : false); + + if (voiceChatType == VOICE_CHAT.CHAT) { + // UNASSIGNED VOICE CHAT + $('#voice-inputs-unused > option').each(function () { + logger.debug("Marking " + this.value + " as unassigned voice input."); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.UNASSIGNED); + }); + + // VOICE CHAT INPUT + $("#voice-inputs-selection > option").each(function () { + logger.debug("Saving chat input = " + this.value); + context.jamClient.TrackSetAssignment(this.value, true, ASSIGNMENT.CHAT); + }); + } + // make sure any previously assigned chat devices are marked as unassigned + else if (voiceChatType == VOICE_CHAT.NO_CHAT) { + // chat devices that were assigned + $.each(chatOtherAssignedList, function (index, val) { + logger.debug("Marking " + val.id + " as unassigned voice input."); + context.jamClient.TrackSetAssignment(val.id, true, ASSIGNMENT.UNASSIGNED); + }); + } + } + + function cancelSettings() { + logger.debug("Cancel settings"); + + // reset to original device ID + context.jamClient.TrackSetMusicDevice(originalDeviceId); + + $('#voice-chat-type').val(originalVoiceChat); + + app.layout.closeDialog('configure-audio'); + } + + function validateAudioSettings(allowEmptyInput) { + var isValid = true; + var noTrackErrMsg = 'You can assign no more than 2 input ports to each of your tracks. Please update your settings to correct this.'; + var noInstrumentErrMsg = 'You must specify what instrument is being played for each track. Please update your settings to correct this.'; + var outputErrMsg = 'You must assign two output ports for stereo session audio to hear music. Please update your settings to correct this.'; + + var errMsg; + + // if there are no inputs remaining then allow the user to switch to the Voice Chat tab + // to remove some + if (allowEmptyInput && $('#audio-inputs-unused > option').size() === 0) { + return isValid; + } + else { + // verify Track 1 Input and Instrument exist + if ($('#track1-input > option').size() === 0 || $('#track1-input > option').size() > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + + if (isValid) { + if ($('#track1-instrument > option:selected').length === 0) { + errMsg = noInstrumentErrMsg; + isValid = false; + } + } + + logger.debug("validateAudioSettings:myTrackCount=" + myTrackCount); + + // if Track 2 exists, verify Input and Instrument exist + if (isValid) { + var track2Count = $('#track2-input > option').size(); + if (track2Count > 2) { + errMsg = noTrackErrMsg; + isValid = false; + } + + // only validate instrument if second track is selected + if (isValid && track2Count > 0 && $('#track2-instrument > option:selected').length === 0) { + errMsg = noInstrumentErrMsg; + isValid = false; + } + } + + // verify Session Audio Output exists + if (isValid && $('#audio-output-selection > option').size() !== 2) { + errMsg = outputErrMsg; + isValid = false; + } + + if (!isValid) { + context.JK.showErrorDialog(app, errMsg, "invalid settings"); + } + } + + return isValid; + } + + function validateVoiceChatSettings(allowEmptyInput) { + var isValid = true; + var noTrackErrMsg = 'You must select a voice chat input.'; + var limitExceededErrMsg = 'You cannot select more than 1 voice chat input.'; + var errMsg; + + if (allowEmptyInput && $('#voice-inputs-unused > option').size() === 0) { + return isValid; + } + else { + var chatType = $('#voice-chat-type').val(); + if (chatType == VOICE_CHAT.CHAT) { + var $voiceInputSelection = $('#voice-inputs-selection > option'); + var count = $voiceInputSelection.size(); + if (count === 0) { + // this is OK; the user may have said thy want a chat with the #voice-chat-type dropdown, + // but if they didn't select anything, then... they actually don't + //errMsg = noTrackErrMsg; + isValid = true; + } + else if (count > 1) { + errMsg = limitExceededErrMsg; + isValid = false; + } + } + else if (chatType == VOICE_CHAT.NO_CHAT) { + // NO VALIDATION NEEDED + } + + if (!isValid) { + context.JK.showErrorDialog(app, errMsg, "invalid settings"); + } + } + + return isValid; + } + + function _setInstructions(type) { + var $instructions = $('#instructions', 'div[layout-id="configure-audio"]'); + if (type === 'audio') { + var os = context.jamClient.GetOSAsString(); + $instructions.html(configure_audio_instructions[os]); + } + else if (type === 'voice') { + $instructions.html(configure_voice_instructions); + } + } + + function isChatInputSpecified() { + return $('#voice-inputs-selection option').size() > 0 ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT; + } + + function _init() { + // load instrument array for populating listboxes, using client_id in instrument_map as ID + instrument_array = context.JK.listInstruments(); + + originalVoiceChat = context.jamClient.TrackGetChatEnable() ? VOICE_CHAT.CHAT : VOICE_CHAT.NO_CHAT; + + $('#voice-chat-type').val(originalVoiceChat); + + originalDeviceId = context.jamClient.TrackGetMusicDeviceID(); + + context.jamClient.TrackLoadAssignments(); + initDialogData(); + + var $option1 = $('#voice-chat-type > option[value="1"]'); + + // remove option 1 from voice chat if none are available and not already assigned + if (inputUnassignedList.length === 0 && chatAssignedList.length === 0 && chatOtherAssignedList.length === 0 && chatOtherUnassignedList.length === 0) { + $option1.remove(); + } + // add it if it doesn't exist + else { + if ($option1.length === 0) { + logger.debug("Adding Option 1 back to Voice Chat dropdown."); + $('#voice-chat-type').append(''); + } + } + } + + function initialize() { + var dialogBindings = { + 'beforeShow': function () { + return context.JK.verifyNotRecordingForTrackChange(app); + } + }; + app.bindDialog('configure-audio', dialogBindings); + + events(); + } + + // should be called before opening + function refresh() { + _init(); + myTrackCount = myTracks.length; + } + + this.initialize = initialize; + this.refresh = refresh; + + this.showMusicAudioPanel = showMusicAudioPanel; + this.showVoiceChatPanel = showVoiceChatPanel; + + return this; + }; + +})(window, jQuery); diff --git a/web/app/assets/javascripts/ftue.js b/web/app/assets/javascripts/ftue.js index 82788e9fd..e0d3f5c48 100644 --- a/web/app/assets/javascripts/ftue.js +++ b/web/app/assets/javascripts/ftue.js @@ -57,7 +57,7 @@ // Unsubscribe from FTUE VU callbacks. jamClient.FTUERegisterVUCallbacks('', '', ''); - if(!successfulFtue && app.cancelFtue) { + if (!successfulFtue && app.cancelFtue) { app.cancelFtue(); app.afterFtue = null; app.cancelFtue = null; @@ -98,7 +98,7 @@ } // renders volumes based on what the backend says - function renderVolumes() { + function renderVolumes() { $.each(context._.keys(faderReadMap), function (index, faderId) { // faderChange takes a value from 0-100 var $fader = $('[fader-id="' + faderId + '"]'); @@ -127,9 +127,9 @@ } function checkValidStateForTesting() { - var reqMissing = !musicInAndOutSet() || currentAudioDriverId == null || currentAudioDriverId == ''; + var reqMissing = !musicInAndOutSet() || currentAudioDriverId == null || currentAudioDriverId == ''; - if(reqMissing ) { + if (reqMissing) { renderDisableTest(); } else { @@ -465,8 +465,7 @@ ]; var optionsHtml = ''; var deviceOptionFunc = function (deviceKey, index, list) { - optionsHtml += ''; + optionsHtml += ''; }; for (var i = 0; i < funcs.length; i++) { optionsHtml = ''; @@ -499,18 +498,24 @@ */ function loadAudioDrivers() { var drivers = jamClient.FTUEGetDevices(false); + var voiceDrivers = jamClient.FTUEGetChatInputs(); var driverOptionFunc = function (driverKey, index, list) { - optionsHtml += ''; + if(!drivers[driverKey]) { + logger.debug("skipping unknown device:", driverKey) + } + else { + optionsHtml += ''; + } }; var optionsHtml = ''; 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' ]; + + // handle standard devices var sortedDeviceKeys = context._.keys(drivers).sort(); context._.each(sortedDeviceKeys, driverOptionFunc); $.each(selectors, function (index, selector) { @@ -519,6 +524,19 @@ $select.html(optionsHtml); context.JK.dropdown($select); }); + + selectors = ['[layout-wizard-step="0"] .settings-2-voice select']; + var sortedVoiceDeviceKeys = context._.keys(voiceDrivers).sort(); + + // handle voice inputs + context._.each(sortedVoiceDeviceKeys, driverOptionFunc); + $.each(selectors, function (index, selector) { + var $select = $(selector); + $select.empty(); + $select.html(optionsHtml); + context.JK.dropdown($select); + }); + } /** Once a configuration is decided upon, we set the user's default instrument based on data from their profile */ @@ -574,10 +592,11 @@ // used in a .change event in a select to allow the select to reliably close // needed because ftue testing blocks the UI function releaseDropdown(proc) { - setTimeout(function() { + setTimeout(function () { proc() }, 1) } + // 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. @@ -585,7 +604,7 @@ // { latency: 11.1875, latencyknown: true, latencyvar: 1} function newFtueAudioDeviceChanged(evt) { - releaseDropdown(function() { + releaseDropdown(function () { renderStartNewFtueLatencyTesting(); var $select = $(evt.currentTarget); @@ -667,7 +686,7 @@ } function newFtueSave(persist) { - console.log("newFtueSave persist(" +persist+ ")") + console.log("newFtueSave persist(" + persist + ")") newFtueUpdateLatencyView('loading'); logger.debug("Calling FTUESave(" + persist + ")"); jamClient.FTUESave(persist); @@ -690,6 +709,34 @@ logger.warn("unable to get value from framesize input: %o", $input.val()); return false; } + + // we need to help WDM users start with good starting input/output values. + if(isWDM()) { + var defaultInput = 1; + var defaultOutput = 1; + if(val == 2.5) { + defaultInput = 1; + defaultOutput = 1; + } + else if(val == 5) { + defaultInput = 3; + defaultOutput = 2; + } + else if(val == 10) { + defaultInput = 6; + defaultOutput = 5; + } + + $('#ftue-2-asio-input-latency').val(defaultInput.toString()); + $('#ftue-2-asio-output-latency').val(defaultOutput.toString()); + + logger.debug("Defaulting WDM input/output"); + logger.debug("Calling FTUESetInputLatency(" + defaultInput + ")"); + jamClient.FTUESetInputLatency(defaultInput); + logger.debug("Calling FTUESetOutputLatency(" + defaultOutput + ")"); + jamClient.FTUESetOutputLatency(defaultOutput); + } + logger.debug("Calling FTUESetFrameSize(" + val + ")"); jamClient.FTUESetFrameSize(val); return true; @@ -718,38 +765,51 @@ } function newFtueSetAsioFrameSize(evt) { - releaseDropdown(function() { + releaseDropdown(function () { renderStartNewFtueLatencyTesting(); - if(!newFtueAsioFrameSizeToBackend($(evt.currentTarget))) { + + if (!newFtueAsioFrameSizeToBackend($(evt.currentTarget))) { renderStopNewFtueLatencyTesting(); return; } - if (batchModify) { pendingFtueSave = true; } else { newFtueSave(false); } + if (batchModify) { + pendingFtueSave = true; + } else { + newFtueSave(false); + } }); } function newFtueSetAsioInputLatency(evt) { - releaseDropdown(function() { + releaseDropdown(function () { renderStartNewFtueLatencyTesting(); - if(!newFtueAsioInputLatencyToBackend($(evt.currentTarget))) { + if (!newFtueAsioInputLatencyToBackend($(evt.currentTarget))) { renderStopNewFtueLatencyTesting(); return; } - if (batchModify) { pendingFtueSave = true; } else { newFtueSave(false); } + if (batchModify) { + pendingFtueSave = true; + } else { + newFtueSave(false); + } }); } function newFtueSetAsioOutputLatency(evt) { - releaseDropdown(function() { + releaseDropdown(function () { renderStartNewFtueLatencyTesting(); - if(!newFtueAsioOutputLatencyToBackend($(evt.currentTarget))) { + if (!newFtueAsioOutputLatencyToBackend($(evt.currentTarget))) { renderStopNewFtueLatencyTesting(); return; } - if (batchModify) { pendingFtueSave = true; } else { newFtueSave(false); } + if (batchModify) { + pendingFtueSave = true; + } else { + newFtueSave(false); + } }); } @@ -769,6 +829,10 @@ } } + function isWDM() { + return jamClient.GetOSAsString() === "Win32" && !jamClient.FTUEHasControlPanel(); + } + // Based on OS and Audio Hardware, set Frame/Buffer settings appropriately // and show/hide the ASIO button. function newFtueOsSpecificSettings() { diff --git a/web/app/assets/javascripts/landing/signup.js b/web/app/assets/javascripts/landing/signup.js index a5f5a0f50..6e5a56651 100644 --- a/web/app/assets/javascripts/landing/signup.js +++ b/web/app/assets/javascripts/landing/signup.js @@ -56,7 +56,8 @@ $(data.regions).each(function(index, item) { var option = $(''); - option.text(item).val(item); + option.text(item); + option.val(item); region_select.append(option) }) diff --git a/web/app/assets/stylesheets/web/audioWidgets.css.scss b/web/app/assets/stylesheets/web/audioWidgets.css.scss index 091b8b9b4..a4d2e2971 100644 --- a/web/app/assets/stylesheets/web/audioWidgets.css.scss +++ b/web/app/assets/stylesheets/web/audioWidgets.css.scss @@ -185,6 +185,10 @@ line-height:19px; } + .recording-controls { + padding:8px 5px 8px 25px !important; + } + .details { color:#ED3618; }