* VRFS-1754 - new configure tracks dialog
This commit is contained in:
parent
60c72f29dd
commit
653b03bea1
|
|
@ -4,9 +4,12 @@
|
|||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.AccountAudioProfile = function (app) {
|
||||
var self = this;
|
||||
|
||||
var EVENTS = context.JK.EVENTS;
|
||||
var gearUtils = context.JK.GearUtils;
|
||||
var logger = context.JK.logger;
|
||||
var rest = context.JK.Rest();
|
||||
var self = this;
|
||||
var userId;
|
||||
|
||||
function beforeShow(data) {
|
||||
|
|
@ -35,28 +38,26 @@
|
|||
}
|
||||
|
||||
function populateAccountAudio() {
|
||||
var all = context.jamClient.FTUEGetAllAudioConfigurations();
|
||||
var good = context.jamClient.FTUEGetGoodAudioConfigurations();
|
||||
var current = context.jamClient.FTUEGetMusicProfileName();
|
||||
var profiles = gearUtils.getProfiles();
|
||||
|
||||
var profiles = [];
|
||||
context._.each(all, function(item) {
|
||||
profiles.push({id: item, good: false, class:'bad', current: current == item, active_text: current == item ? '(active)' : ''})
|
||||
context._.each(profiles, function(profile) {
|
||||
profile.active_text = profile.current ? '(active)' : '';
|
||||
});
|
||||
|
||||
if(good) {
|
||||
for(var i = 0; i < good.length; i++) {
|
||||
for(var j = 0; j < profiles.length; j++) {
|
||||
if(good[i] == profiles[j].id) {
|
||||
profiles[j].good = true;
|
||||
profiles[j].class = 'good';
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If you are in the FTUE, and you close the client and/or it crashes
|
||||
// then you will have 'FTUE' (incomplete) profiles. This is the only time
|
||||
// the user might see them, so we clean them before they get to see it
|
||||
var cleansedProfiles = [];
|
||||
context._.each(profiles, function(profile) {
|
||||
if(profile.id.indexOf('FTUE') == 0) {
|
||||
context.jamClient.TrackDeleteProfile(profile.id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
cleansedProfiles.push(profile)
|
||||
}
|
||||
});
|
||||
|
||||
var template = context._.template($('#template-account-audio').html(), {is_admin: context.JK.currentUserAdmin, profiles: profiles}, {variable: 'data'});
|
||||
var template = context._.template($('#template-account-audio').html(), {is_admin: context.JK.currentUserAdmin, profiles: cleansedProfiles}, {variable: 'data'});
|
||||
|
||||
appendAudio(template);
|
||||
}
|
||||
|
|
@ -86,11 +87,34 @@
|
|||
logger.error("unable to activate audio configuration: " + audioProfileId);
|
||||
context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + audioProfileId);
|
||||
}
|
||||
else {
|
||||
// redraw after activation of profile
|
||||
populateAccountAudio();
|
||||
}
|
||||
}
|
||||
|
||||
app.layout.showDialog('loopback-wizard');
|
||||
}
|
||||
|
||||
function handleConfigureAudioProfile(audioProfileId) {
|
||||
|
||||
if(audioProfileId != context.jamClient.FTUEGetMusicProfileName()) {
|
||||
var result = context.jamClient.FTUELoadAudioConfiguration(audioProfileId);
|
||||
|
||||
if(!result) {
|
||||
logger.error("unable to activate audio configuration: " + audioProfileId);
|
||||
context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + audioProfileId);
|
||||
}
|
||||
else {
|
||||
// redraw after activation of profile
|
||||
populateAccountAudio();
|
||||
}
|
||||
}
|
||||
|
||||
app.layout.showDialog('configure-tracks')
|
||||
.one(EVENTS.DIALOG_CLOSED, populateAccountAudio)
|
||||
}
|
||||
|
||||
function handleActivateAudioProfile(audioProfileId) {
|
||||
logger.debug("activating audio profile: " + audioProfileId);
|
||||
|
||||
|
|
@ -171,6 +195,20 @@
|
|||
return false;
|
||||
});
|
||||
|
||||
$root.on('click', 'a[data-purpose=configure-audio-profile]', function (evt) {
|
||||
evt.stopPropagation();
|
||||
var $btn = $(this);
|
||||
var status = $btn.closest('tr').attr('data-status');
|
||||
if(status == "good") {
|
||||
handleConfigureAudioProfile($btn.attr('data-id'));
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert("Unable to configure this profile. Please verify that the devices associated are connected.");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$root.on('click', 'a[data-purpose=add-profile]', function (evt) {
|
||||
evt.stopPropagation();
|
||||
handleStartAudioQualification();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
sessionScreen.setPromptLeave(false);
|
||||
|
||||
app.layout.closeDialog('configure-audio');
|
||||
app.layout.closeDialog('configure-tracks');
|
||||
|
||||
context.location = "/client#/home";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,24 @@
|
|||
var logger = context.JK.logger;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var gearUtils = context.JK.GearUtils;
|
||||
|
||||
var $dialog = null;
|
||||
var $instructions = null;
|
||||
var $musicAudioTab = null;
|
||||
var $musicAudioTabSelector = null;
|
||||
var $voiceChatTab = null;
|
||||
var $voiceChatTabSelector = null;
|
||||
var $certifiedAudioProfile = null;
|
||||
var $btnCancel = null;
|
||||
var $btnAddNewGear = null;
|
||||
var $btnUpdateTrackSettings = null;
|
||||
|
||||
var configureTracksHelper = null;
|
||||
var voiceChatHelper = null;
|
||||
var profiles = null;
|
||||
var currentProfile = null;
|
||||
|
||||
var $dialog = null;
|
||||
var $instructions = null;
|
||||
var $musicAudioTab = null;
|
||||
var $musicAudioTabSelector = null;
|
||||
var $voiceChatTab = null;
|
||||
var $voiceChatTabSelector = null;
|
||||
|
||||
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 " +
|
||||
|
|
@ -38,6 +49,8 @@
|
|||
|
||||
function setInstructions(type) {
|
||||
if (type === 'audio') {
|
||||
$instructions.html('Choose your audio device. Drag and drop to assign input ports to tracks, and specify the instrument for each track. Drag and drop to assign a pair of output ports for session stereo audio monitoring.')
|
||||
return;
|
||||
var os = context.jamClient.GetOSAsString();
|
||||
$instructions.html(configure_audio_instructions[os]);
|
||||
}
|
||||
|
|
@ -67,17 +80,16 @@
|
|||
}
|
||||
|
||||
function validateVoiceChatSettings() {
|
||||
return true;
|
||||
return voiceChatHelper.trySave();
|
||||
}
|
||||
|
||||
function showMusicAudioPanel() {
|
||||
setInstructions('audio');
|
||||
activateTab('audio');
|
||||
|
||||
}
|
||||
|
||||
function validateAudioSettings() {
|
||||
return true;
|
||||
return configureTracksHelper.trySave();
|
||||
}
|
||||
|
||||
function showVoiceChatPanel() {
|
||||
|
|
@ -88,21 +100,92 @@
|
|||
function events() {
|
||||
$musicAudioTabSelector.click(function () {
|
||||
// validate voice chat settings
|
||||
if (validateVoiceChatSettings(true)) {
|
||||
showMusicAudioPanel(false);
|
||||
if (validateVoiceChatSettings()) {
|
||||
configureTracksHelper.reset();
|
||||
voiceChatHelper.reset();
|
||||
showMusicAudioPanel();
|
||||
}
|
||||
});
|
||||
|
||||
$voiceChatTabSelector.click(function () {
|
||||
// validate audio settings
|
||||
if (validateAudioSettings(true)) {
|
||||
showVoiceChatPanel(false);
|
||||
if (validateAudioSettings()) {
|
||||
configureTracksHelper.reset();
|
||||
voiceChatHelper.reset();
|
||||
showVoiceChatPanel();
|
||||
}
|
||||
});
|
||||
|
||||
$btnCancel.click(function() {
|
||||
app.layout.closeDialog('configure-tracks')
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$btnAddNewGear.click(function() {
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$btnUpdateTrackSettings.click(function() {
|
||||
if(configureTracksHelper.trySave() && voiceChatHelper.trySave()) {
|
||||
app.layout.closeDialog('configure-tracks');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$certifiedAudioProfile.change(deviceChanged);
|
||||
}
|
||||
|
||||
function renderCertifiedGearDropdown() {
|
||||
|
||||
var optionsHtml = '';
|
||||
context._.each(profiles, function (profile) {
|
||||
if(profile.good) {
|
||||
optionsHtml += '<option title="' + profile.id + '" value="' + profile.id + '"' + (profile.current ? 'selected="selected"' : '') + '>' + profile.id + '</option>';
|
||||
}
|
||||
});
|
||||
$certifiedAudioProfile.html(optionsHtml);
|
||||
|
||||
context.JK.dropdown($certifiedAudioProfile);
|
||||
}
|
||||
|
||||
function deviceChanged() {
|
||||
var profile = $certifiedAudioProfile.val();
|
||||
|
||||
if(currentProfile == profile) {
|
||||
return; // just bail early, because the easydropdown fires change events even when you select the same value
|
||||
}
|
||||
logger.debug("activating audio profile: " + profile);
|
||||
|
||||
var result = context.jamClient.FTUELoadAudioConfiguration(profile);
|
||||
|
||||
if(!result) {
|
||||
logger.error("unable to activate audio configuration: " + profile);
|
||||
context.JK.alertSupportedNeeded("Unable to activate audio configuration for profile named: " + profile);
|
||||
renderCertifiedGearDropdown(); // force the dropdown to be reflective of the actually active profile
|
||||
}
|
||||
else {
|
||||
configureTracksHelper.reset();
|
||||
}
|
||||
|
||||
}
|
||||
function beforeShow() {
|
||||
profiles = gearUtils.getProfiles();
|
||||
renderCertifiedGearDropdown();
|
||||
showMusicAudioPanel();
|
||||
|
||||
currentProfile = context.jamClient.FTUEGetMusicProfileName();
|
||||
|
||||
if(currentProfile != $certifiedAudioProfile.val()) {
|
||||
logger.error("the currently active profile (" + currentProfile + ") is not the same as the Certified Audio Gear dropdown (" + $certifiedAudioProfile.val() + ")");
|
||||
context.JK.alertSupportedNeeded("Unable to determine the current profile.");
|
||||
}
|
||||
|
||||
configureTracksHelper.reset();
|
||||
voiceChatHelper.reset();
|
||||
|
||||
}
|
||||
|
||||
function afterHide() {
|
||||
|
|
@ -124,6 +207,17 @@
|
|||
$musicAudioTabSelector = $dialog.find('.tab-configure-audio');
|
||||
$voiceChatTab = $dialog.find('div[tab-id="voice-chat"]');
|
||||
$voiceChatTabSelector = $dialog.find('.tab-configure-voice');
|
||||
$certifiedAudioProfile = $dialog.find('.certified-audio-profile');
|
||||
$btnCancel = $dialog.find('.btn-cancel');
|
||||
$btnAddNewGear = $dialog.find('.btn-add-new-audio-gear');
|
||||
$btnUpdateTrackSettings = $dialog.find('.btn-update-settings');
|
||||
|
||||
configureTracksHelper = new JK.ConfigureTracksHelper(app);
|
||||
configureTracksHelper.initialize($dialog);
|
||||
|
||||
voiceChatHelper = new JK.VoiceChatHelper(app);
|
||||
voiceChatHelper.initialize($dialog, false);
|
||||
|
||||
events();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,422 @@
|
|||
(function (context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.ConfigureTracksHelper = function (app) {
|
||||
var logger = context.JK.logger;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var MAX_TRACKS = context.JK.MAX_TRACKS;
|
||||
var MAX_OUTPUTS = context.JK.MAX_OUTPUTS;
|
||||
var gearUtils = context.JK.GearUtils;
|
||||
|
||||
var $parent = null;
|
||||
var $templateAssignablePort = null;
|
||||
var $templateTrackTarget = null;
|
||||
var $templateOutputTarget = null;
|
||||
var $unassignedInputsHolder = null;
|
||||
var $unassignedOutputsHolder = null;
|
||||
var $tracksHolder = null;
|
||||
var $outputChannelHolder = null;
|
||||
var $instrumentsHolder = null;
|
||||
|
||||
function loadChannels() {
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
|
||||
$unassignedInputsHolder.empty();
|
||||
$unassignedOutputsHolder.empty();
|
||||
$tracksHolder.find('.ftue-input').remove();
|
||||
$outputChannelHolder.find('.ftue-input').remove();
|
||||
|
||||
var inputChannels = musicPorts.inputs;
|
||||
var outputChannels = musicPorts.outputs;
|
||||
|
||||
context._.each(inputChannels, function (inputChannel) {
|
||||
var $channel = $(context._.template($templateAssignablePort.html(), inputChannel, { variable: 'data' }));
|
||||
|
||||
if(inputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
unassignInputChannel($channel);
|
||||
}
|
||||
else if(inputChannel.assignment == ASSIGNMENT.CHAT) {
|
||||
// well, we can't show it as unused... if there were a place to show chat inputs, we would put it there.
|
||||
// but we don't have it, so just skip
|
||||
logger.debug("skipping channel ", inputChannel)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// 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($channel, $track.find('.track-target'));
|
||||
}
|
||||
|
||||
$channel.draggable({
|
||||
helper: 'clone',
|
||||
start: function() {
|
||||
var $channel = $(this);
|
||||
var $track = $channel.closest('.track-target');
|
||||
var isUnassigned = $track.length == 0;
|
||||
if(isUnassigned) {
|
||||
$tracksHolder.find('.track-target').addClass('possible-target');
|
||||
}
|
||||
else {
|
||||
$tracksHolder.find('.track-target').addClass('possible-target');
|
||||
$unassignedInputsHolder.addClass('possible-target');
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
$tracksHolder.find('.track-target').removeClass('possible-target');
|
||||
$unassignedInputsHolder.removeClass('possible-target')
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
var outputAssignment = 0;
|
||||
context._.each(outputChannels, function (outputChannel, index) {
|
||||
var $channel = $(context._.template($templateAssignablePort.html(), outputChannel, { variable: 'data' }));
|
||||
|
||||
if(outputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
unassignOutputChannel($channel);
|
||||
}
|
||||
else {
|
||||
var $output = $outputChannelHolder.find('.output[data-num="' + index + '"]')
|
||||
|
||||
if($output.length == 0) {
|
||||
context.JK.alertSupportedNeeded('Unable to find an output for channel with assignment ' + outputChannel.assignment);
|
||||
return false;
|
||||
}
|
||||
addChannelToOutput($channel, $output.find('.output-target'));
|
||||
}
|
||||
|
||||
$channel.draggable({
|
||||
helper: 'clone',
|
||||
start: function() {
|
||||
var $channel = $(this);
|
||||
var $output = $channel.closest('.output-target');
|
||||
var isUnassigned = $output.length == 0;
|
||||
if(isUnassigned) {
|
||||
$outputChannelHolder.find('.output-target').addClass('possible-target');
|
||||
}
|
||||
else {
|
||||
$outputChannelHolder.find('.output-target').addClass('possible-target');
|
||||
$unassignedOutputsHolder.addClass('possible-target');
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
$outputChannelHolder.find('.output-target').removeClass('possible-target');
|
||||
$unassignedOutputsHolder.removeClass('possible-target')
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// iterates through the dom and returns a pure data structure for track associations and output channels
|
||||
function getCurrentState() {
|
||||
|
||||
var state = {};
|
||||
state.tracks = [];
|
||||
state.unassignedChannels = [];
|
||||
state.outputs = [];
|
||||
var $unassignedInputChannels = $unassignedInputsHolder.find('.ftue-input');
|
||||
var $unassignedOutputChannels = $unassignedOutputsHolder.find('.ftue-input');
|
||||
var $tracks = $tracksHolder.find('.track-target');
|
||||
var $outputs = $outputChannelHolder.find('.output-target');
|
||||
|
||||
context._.each($unassignedInputChannels, function($unassignedInput) {
|
||||
$unassignedInput = $($unassignedInput);
|
||||
var channelId = $unassignedInput.attr('data-input-id');
|
||||
state.unassignedChannels.push(channelId);
|
||||
})
|
||||
|
||||
context._.each($unassignedOutputChannels, function($unassignedOutput) {
|
||||
$unassignedOutput = $($unassignedOutput);
|
||||
var channelId = $unassignedOutput.attr('data-input-id');
|
||||
state.unassignedChannels.push(channelId);
|
||||
})
|
||||
|
||||
context._.each($tracks, function($track, index) {
|
||||
$track = $($track);
|
||||
var $assignedChannels = $track.find('.ftue-input');
|
||||
|
||||
var track = {index: index, channels:[]};
|
||||
context._.each($assignedChannels, function($assignedChannel) {
|
||||
$assignedChannel = $($assignedChannel);
|
||||
track.channels.push($assignedChannel.attr('data-input-id'))
|
||||
});
|
||||
|
||||
// sparse array
|
||||
if(track.channels.length > 0) {
|
||||
state.tracks.push(track);
|
||||
}
|
||||
var $instrument = $instrumentsHolder.find('[data-num="' + index + '"]').find('.icon-instrument-select');
|
||||
track.instrument_id = $instrument.data('instrument_id');
|
||||
})
|
||||
|
||||
context._.each($outputs, function($output, index) {
|
||||
$output = $($output);
|
||||
var $assignedChannel = $output.find('.ftue-input');
|
||||
|
||||
// this is overkill since there should only be 1 or 0 .ftue-inputs in a given .output
|
||||
var outputSlot = {index: index, channels:[]};
|
||||
context._.each($assignedChannel, function($assignedChannel) {
|
||||
$assignedChannel = $($assignedChannel);
|
||||
outputSlot.channels.push($assignedChannel.attr('data-input-id'))
|
||||
});
|
||||
|
||||
// sparse array
|
||||
if(outputSlot.channels.length > 0) {
|
||||
state.outputs.push(outputSlot);
|
||||
}
|
||||
})
|
||||
return state;
|
||||
}
|
||||
|
||||
function validate(tracks) {
|
||||
// there must be at least one assigned channel
|
||||
if(tracks.tracks.length == 0) {
|
||||
logger.debug("ConfigureTracks validation error: must have assigned at least one input port to a track.");
|
||||
context.JK.Banner.showAlert('Must have assigned at least one input port to a track.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// there must be some instruments
|
||||
context._.each(tracks.tracks, function(track) {
|
||||
if(!track.instrument_id) {
|
||||
logger.debug("ConfigureTracks validation error: all tracks with ports assigned must specify an instrument.");
|
||||
context.JK.Banner.showAlert('All tracks with ports assigned must specify an instrument.');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// there must be exactly 2 output channels assigned
|
||||
if(tracks.outputs.length != 2 || (tracks.outputs[0].channels.length != 1 && track.outputs[1].channels.length != 1)) {
|
||||
logger.debug("ConfigureTracks validation error: must have assigned exactly two output ports");
|
||||
context.JK.Banner.showAlert('Must have assigned exactly 2 output ports.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function save(state) {
|
||||
|
||||
context._.each(state.unassignedChannels, function(unassignedChannelId) {
|
||||
context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
|
||||
});
|
||||
|
||||
// save input/tracks
|
||||
context._.each(state.tracks, function(track, index) {
|
||||
|
||||
var trackNumber = index + 1;
|
||||
|
||||
context._.each(track.channels, function(channelId) {
|
||||
context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
|
||||
|
||||
});
|
||||
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", trackNumber, track.instrument_id);
|
||||
context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
|
||||
});
|
||||
|
||||
// save outputs
|
||||
context._.each(state.outputs, function(output, index) {
|
||||
context._.each(output.channels, function(channelId) {
|
||||
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
|
||||
});
|
||||
});
|
||||
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTrackInstruments() {
|
||||
var $trackInstruments = $instrumentsHolder.find('.track-instrument');
|
||||
|
||||
context._.each($trackInstruments, function(trackInstrument) {
|
||||
var $trackInstrument = $(trackInstrument);
|
||||
|
||||
var trackIndex = parseInt($trackInstrument.attr('data-num')) + 1;
|
||||
|
||||
var clientInstrument = context.jamClient.TrackGetInstrument(trackIndex);
|
||||
|
||||
var instrument = context.JK.client_to_server_instrument_map[clientInstrument];
|
||||
|
||||
$trackInstrument.instrumentSelectorSet(instrument ? instrument.server_id : instrument);
|
||||
});
|
||||
}
|
||||
|
||||
function trySave() {
|
||||
var state = getCurrentState();
|
||||
|
||||
if(!validate(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var saved = save(state);
|
||||
|
||||
if(saved) {
|
||||
context.JK.GA.trackConfigureTracksCompletion(context.JK.detectOS());
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
loadChannels();
|
||||
loadTrackInstruments();
|
||||
}
|
||||
|
||||
function unassignOutputChannel($channel) {
|
||||
var $originallyAssignedTrack = $channel.closest('.output-target');
|
||||
$unassignedOutputsHolder.append($channel);
|
||||
$originallyAssignedTrack.attr('output-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
}
|
||||
|
||||
function unassignInputChannel($channel) {
|
||||
var $originallyAssignedTrack = $channel.closest('.track-target');
|
||||
$unassignedInputsHolder.append($channel);
|
||||
$originallyAssignedTrack.attr('track-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
|
||||
}
|
||||
|
||||
function addChannelToTrack($channel, $track) {
|
||||
var $originallyAssignedTrack = $channel.closest('.track-target');
|
||||
$track.append($channel);
|
||||
$track.attr('track-count', $track.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
$originallyAssignedTrack.attr('track-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length)
|
||||
}
|
||||
|
||||
function addChannelToOutput($channel, $slot) {
|
||||
var $originallyAssignedTrack = $channel.closest('.output-target');
|
||||
$slot.append($channel);
|
||||
$slot.attr('output-count', $slot.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
$originallyAssignedTrack.attr('output-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length)
|
||||
}
|
||||
|
||||
|
||||
function initializeUnassignedOutputDroppable() {
|
||||
$unassignedOutputsHolder.droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $channel = ui.draggable;
|
||||
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
unassignOutputChannel($channel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initializeUnassignedInputDroppable() {
|
||||
$unassignedInputsHolder.droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $channel = ui.draggable;
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
unassignInputChannel($channel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initializeOutputDroppables() {
|
||||
var i;
|
||||
for(i = 0; i < MAX_OUTPUTS; i++) {
|
||||
var $target = $(context._.template($templateOutputTarget.html(), {num: i }, { variable: 'data' }));
|
||||
$outputChannelHolder.append($target);
|
||||
$target.find('.output-target').droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $slot = $(this);
|
||||
if($slot.attr('output-count') == 1) {
|
||||
return false; // max of 1 output per slot
|
||||
}
|
||||
var $channel = ui.draggable;
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
addChannelToOutput($channel, $slot);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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.find('.track-target').droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $track = $(this);
|
||||
if($track.attr('track-count') == 2) {
|
||||
return false; // max of 2 inputs per track
|
||||
}
|
||||
|
||||
var $channel = ui.draggable;
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
addChannelToTrack($channel, $track);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initializeInstrumentDropdown() {
|
||||
var i;
|
||||
for(i = 0; i < MAX_TRACKS; i++) {
|
||||
var $root = $('<div class="track-instrument"></div>');
|
||||
$root.instrumentSelector().attr('data-num', i);
|
||||
$instrumentsHolder.append($root);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initialize(_$parent) {
|
||||
$parent = _$parent;
|
||||
|
||||
$templateAssignablePort = $('#template-assignable-port');
|
||||
$templateTrackTarget = $('#template-track-target');
|
||||
$templateOutputTarget = $('#template-output-target');
|
||||
$unassignedInputsHolder = $parent.find('.unassigned-input-channels')
|
||||
$unassignedOutputsHolder = $parent.find('.unassigned-output-channels');
|
||||
$tracksHolder = $parent.find('.tracks');
|
||||
$instrumentsHolder = $parent.find('.instruments');
|
||||
$outputChannelHolder = $parent.find('.output-channels');
|
||||
|
||||
|
||||
initializeUnassignedInputDroppable();
|
||||
initializeTrackDroppables();
|
||||
initializeInstrumentDropdown();
|
||||
|
||||
initializeUnassignedOutputDroppable();
|
||||
initializeOutputDroppables();
|
||||
}
|
||||
|
||||
this.initialize = initialize;
|
||||
this.trySave = trySave;
|
||||
this.reset = reset;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -235,21 +235,25 @@
|
|||
}
|
||||
|
||||
function FTUEGetGoodConfigurationList() {
|
||||
return ['a'];
|
||||
return ['default'];
|
||||
}
|
||||
|
||||
function FTUEGetAllAudioConfigurations() {
|
||||
return ['a'];
|
||||
return ['default'];
|
||||
}
|
||||
|
||||
function FTUEGetGoodAudioConfigurations() {
|
||||
return ['a'];
|
||||
return ['default'];
|
||||
}
|
||||
|
||||
function FTUEGetConfigurationDevice() {
|
||||
return 'Good Device';
|
||||
}
|
||||
|
||||
function FTUELoadAudioConfiguration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function FTUEIsMusicDeviceWDM() {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -850,6 +854,7 @@
|
|||
this.FTUEGetGoodAudioConfigurations = FTUEGetGoodAudioConfigurations;
|
||||
this.FTUEGetConfigurationDevice = FTUEGetConfigurationDevice;
|
||||
this.FTUEIsMusicDeviceWDM = FTUEIsMusicDeviceWDM;
|
||||
this.FTUELoadAudioConfiguration = FTUELoadAudioConfiguration;
|
||||
|
||||
// Session
|
||||
this.SessionAddTrack = SessionAddTrack;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,12 @@
|
|||
CHAT: "1"
|
||||
};
|
||||
|
||||
context.JK.EVENTS = {
|
||||
DIALOG_CLOSED : 'dialog_closed'
|
||||
}
|
||||
|
||||
context.JK.MAX_TRACKS = 6;
|
||||
context.JK.MAX_OUTPUTS = 2;
|
||||
|
||||
// TODO: store these client_id values in instruments table, or store
|
||||
// server_id as the client_id to prevent maintenance nightmares. As it's
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
// privates
|
||||
var logger = context.JK.logger;
|
||||
|
||||
var EVENTS = context.JK.EVENTS;
|
||||
var NOT_HANDLED = "not handled";
|
||||
|
||||
var me = null; // Reference to this instance for context sanity.
|
||||
|
|
@ -433,8 +434,9 @@
|
|||
var $overlay = $('.dialog-overlay');
|
||||
unstackDialogs($overlay);
|
||||
$dialog.hide();
|
||||
$dialog.triggerHandler(EVENTS.DIALOG_CLOSED, {name: dialog, dialogCount: openDialogs.length});
|
||||
$(context).triggerHandler(EVENTS.DIALOG_CLOSED, {name: dialog, dialogCount: openDialogs.length})
|
||||
dialogEvent(dialog, 'afterHide');
|
||||
$(me).triggerHandler('dialog_closed', {dialogCount: openDialogs.length})
|
||||
}
|
||||
|
||||
function screenEvent(screen, evtName, data) {
|
||||
|
|
@ -538,6 +540,11 @@
|
|||
*/
|
||||
layout();
|
||||
|
||||
// add an attribute to any dialogs, which let's it know it's current screen (useful for contextual styling)
|
||||
context._.each(openDialogs, function(dialog) {
|
||||
addScreenContextToDialog($(dialog));
|
||||
})
|
||||
|
||||
screenEvent(previousScreen, 'afterHide', data);
|
||||
screenEvent(currentScreen, 'afterShow', data);
|
||||
|
||||
|
|
@ -631,6 +638,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
function addScreenContextToDialog($dialog) {
|
||||
$dialog.attr('current-screen', currentScreen); // useful for contextual styling of dialogs
|
||||
}
|
||||
|
||||
function showDialog(dialog, options) {
|
||||
if (dialogEvent(dialog, 'beforeShow', options) === false) {
|
||||
return;
|
||||
|
|
@ -649,8 +660,10 @@
|
|||
centerDialog(dialog);
|
||||
var $dialog = $('[layout-id="' + dialog + '"]');
|
||||
stackDialogs($dialog, $overlay);
|
||||
addScreenContextToDialog($dialog)
|
||||
$dialog.show();
|
||||
dialogEvent(dialog, 'afterShow', options);
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
function centerDialog(dialog) {
|
||||
|
|
@ -903,7 +916,7 @@
|
|||
}
|
||||
|
||||
this.showDialog = function (dialog, options) {
|
||||
showDialog(dialog, options);
|
||||
return showDialog(dialog, options);
|
||||
};
|
||||
|
||||
this.dialogObscuredNotification = function(payload) {
|
||||
|
|
@ -926,6 +939,9 @@
|
|||
return activeElementEvent(evtName, data);
|
||||
}
|
||||
|
||||
this.getCurrentScreen = function() {
|
||||
return currentScreen; // will be a string of the layout-id of the active screen
|
||||
}
|
||||
this.close = function (evt) {
|
||||
close(evt);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.NotificationPanel = function(app) {
|
||||
var EVENTS = context.JK.EVENTS;
|
||||
var logger = context.JK.logger;
|
||||
var friends = [];
|
||||
var rest = context.JK.Rest();
|
||||
|
|
@ -138,7 +139,7 @@
|
|||
}
|
||||
|
||||
function events() {
|
||||
$(app.layout).on('dialog_closed', function(e, data) {if(data.dialogCount == 0) userCameBack(); });
|
||||
$(context).on(EVENTS.DIALOG_CLOSED, function(e, data) {if(data.dialogCount == 0) userCameBack(); });
|
||||
$(window).focus(userCameBack);
|
||||
$(window).blur(windowBlurred);
|
||||
app.user()
|
||||
|
|
|
|||
|
|
@ -142,6 +142,15 @@
|
|||
$element.data("prodTimer", null);
|
||||
$element.btOff();
|
||||
}, options['duration']));
|
||||
|
||||
$element.on('remove', function() {
|
||||
var timer = $element.data('prodTimer')
|
||||
if(timer) {
|
||||
clearTimeout(timer);
|
||||
$element.data("prodTimer", null);
|
||||
$element.btOff();
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Associates a bubble on hover (by default) with the specified $element, using jquery.bt.js (BeautyTips)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,222 @@
|
|||
(function (context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
context.JK.VoiceChatHelper = function (app) {
|
||||
var logger = context.JK.logger;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var MAX_TRACKS = context.JK.MAX_TRACKS;
|
||||
var MAX_OUTPUTS = context.JK.MAX_OUTPUTS;
|
||||
var gearUtils = context.JK.GearUtils;
|
||||
|
||||
var $parent = null;
|
||||
|
||||
var $reuseAudioInputRadio = null;
|
||||
var $useChatInputRadio = null;
|
||||
var $chatInputs = null;
|
||||
var $templateChatInput = null;
|
||||
var $selectedChatInput = null;// should only be used if isChatEnabled = true
|
||||
var saveImmediate = null; // if true, then every action by the user results in a save to the backend immediately, false means you have to call trySave to persist
|
||||
|
||||
function defaultReuse() {
|
||||
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
||||
$useChatInputRadio.removeAttr('checked');
|
||||
}
|
||||
|
||||
function isChatEnabled() {
|
||||
|
||||
return $useChatInputRadio.is(':checked');
|
||||
}
|
||||
|
||||
function reset() {
|
||||
|
||||
$selectedChatInput = null;
|
||||
|
||||
if(context.jamClient.TrackGetChatEnable()) {
|
||||
enableChat(false);
|
||||
}
|
||||
else {
|
||||
disableChat(false);
|
||||
}
|
||||
|
||||
$chatInputs.empty();
|
||||
|
||||
var chatInputs = gearUtils.getChatInputs();
|
||||
|
||||
context._.each(chatInputs, function(chatInput) {
|
||||
if(chatInput.assignment > 0) {
|
||||
return;
|
||||
}
|
||||
var chatChannelName = chatInput.name;
|
||||
var chatChannelId = chatInput.id;
|
||||
var isCurrentlyChat = chatInput.assignment == ASSIGNMENT.CHAT;
|
||||
var $chat = $(context._.template($templateChatInput.html(), {id: chatChannelId, name: chatChannelName}, { variable: 'data' }));
|
||||
var $chatInput = $chat.find('input');
|
||||
if(isCurrentlyChat) {
|
||||
$selectedChatInput = $chatInput;
|
||||
$selectedChatInput.attr('checked', 'checked');
|
||||
}
|
||||
$chat.hide(); // we'll show it once it's styled with iCheck
|
||||
$chatInputs.append($chat);
|
||||
});
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
context.JK.checkbox($radioButtons).on('ifChecked', function(e) {
|
||||
var $input = $(e.currentTarget);
|
||||
$selectedChatInput = $input; // for use in handleNext
|
||||
if(saveImmediate) {
|
||||
var channelId = $input.attr('data-channel-id');
|
||||
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.CHAT);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(!isChatEnabled()) {
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
$chatInputs.find('.chat-input').show().on('click', function() {
|
||||
if(!isChatEnabled()) {
|
||||
context.JK.prodBubble($parent.find('.use-chat-input h3'), 'chat-not-enabled', {}, { positions:['left']});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function disableChat(applyToBackend) {
|
||||
if(saveImmediate && applyToBackend) {
|
||||
logger.debug("voiceChatHelper: disabling chat to backend");
|
||||
context.jamClient.TrackSetChatEnable(false);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
||||
$useChatInputRadio.removeAttr('checked');
|
||||
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to disable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.debug("voiceChatHelper: disabling chat UI only");
|
||||
$reuseAudioInputRadio.iCheck('check').attr('checked', 'checked');
|
||||
$useChatInputRadio.removeAttr('checked');
|
||||
}
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
function enableChat(applyToBackend) {
|
||||
if(saveImmediate && applyToBackend) {
|
||||
logger.debug("voiceChatHelper: enabling chat to backend");
|
||||
context.jamClient.TrackSetChatEnable(true);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
$useChatInputRadio.iCheck('check').attr('checked', 'checked');
|
||||
$reuseAudioInputRadio.removeAttr('checked');
|
||||
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to enable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.debug("voiceChatHelper: enabling chat UI only");
|
||||
$useChatInputRadio.iCheck('check').attr('checked', 'checked');
|
||||
$reuseAudioInputRadio.removeAttr('checked');
|
||||
}
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('enable');
|
||||
}
|
||||
|
||||
function handleChatEnabledToggle() {
|
||||
context.JK.checkbox($reuseAudioInputRadio);
|
||||
context.JK.checkbox($useChatInputRadio);
|
||||
|
||||
// plugin sets to relative on the element; have to do this as an override
|
||||
$reuseAudioInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
$useChatInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
|
||||
$reuseAudioInputRadio.on('ifChecked', function() { disableChat(true) });
|
||||
$useChatInputRadio.on('ifChecked', function() { enableChat(true) });
|
||||
}
|
||||
|
||||
// gets the state of the UI
|
||||
function getCurrentState() {
|
||||
var state = {
|
||||
enabled:null,
|
||||
chat_channel:null
|
||||
};
|
||||
|
||||
state.enabled = $useChatInputRadio.is(':checked');
|
||||
state.chat_channel = $selectedChatInput && $selectedChatInput.attr('data-channel-id');
|
||||
logger.debug("desired chat state: enabled=" + state.enabled + ", chat_channel=" + state.chat_channel)
|
||||
return state;
|
||||
}
|
||||
|
||||
function trySave() {
|
||||
|
||||
var state = getCurrentState();
|
||||
|
||||
if(state.enabled && state.chat_channel) {
|
||||
logger.debug("enabling chat. chat_channel=" + state.chat_channel);
|
||||
context.jamClient.TrackSetChatEnable(true);
|
||||
context.jamClient.FTUESetChatInput(state.chat_channel);
|
||||
//context.jamClient.TrackSetAssignment(state.chat_channel, true, ASSIGNMENT.CHAT);
|
||||
}
|
||||
else {
|
||||
logger.debug("disabling chat.");
|
||||
context.jamClient.TrackSetChatEnable(false);
|
||||
if(state.chat_channel) {
|
||||
context.jamClient.TrackSetAssignment(state.chat_channel, true, ASSIGNMENT.UNASSIGNED);
|
||||
}
|
||||
}
|
||||
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save chat assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(_$step, _saveImmediate) {
|
||||
$parent = _$step;
|
||||
saveImmediate = _saveImmediate;
|
||||
|
||||
$reuseAudioInputRadio = $parent.find('.reuse-audio-input input');
|
||||
$useChatInputRadio = $parent.find('.use-chat-input input');
|
||||
$chatInputs = $parent.find('.chat-inputs');
|
||||
$templateChatInput = $('#template-chat-input');
|
||||
|
||||
handleChatEnabledToggle();
|
||||
}
|
||||
|
||||
this.reset = reset;
|
||||
this.trySave = trySave;
|
||||
this.initialize = initialize;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -10,175 +10,13 @@
|
|||
var MAX_TRACKS = context.JK.MAX_TRACKS;
|
||||
|
||||
var logger = context.JK.logger;
|
||||
var configureTracksHelper = new context.JK.ConfigureTracksHelper(app);
|
||||
|
||||
var $step = null;
|
||||
var $templateAssignablePort = null;
|
||||
var $templateTrackTarget = null;
|
||||
var $unassignedChannelsHolder = null;
|
||||
var $tracksHolder = null;
|
||||
var $instrumentsHolder = null;
|
||||
|
||||
|
||||
function loadChannels() {
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
|
||||
$unassignedChannelsHolder.empty();
|
||||
$tracksHolder.find('.ftue-input').remove();
|
||||
|
||||
var inputChannels = musicPorts.inputs;
|
||||
|
||||
context._.each(inputChannels, function (inputChannel) {
|
||||
if(inputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
var $channel = $(context._.template($templateAssignablePort.html(), inputChannel, { variable: 'data' }));
|
||||
unassignChannel($channel);
|
||||
}
|
||||
else {
|
||||
var $channel = $(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($channel, $track.find('.track-target'));
|
||||
}
|
||||
|
||||
$channel.draggable({
|
||||
helper: 'clone',
|
||||
start: function() {
|
||||
var $channel = $(this);
|
||||
var $track = $channel.closest('.track-target');
|
||||
var isUnassigned = $track.length == 0;
|
||||
if(isUnassigned) {
|
||||
$tracksHolder.find('.track-target').addClass('possible-target');
|
||||
}
|
||||
else {
|
||||
$tracksHolder.find('.track-target').addClass('possible-target');
|
||||
$unassignedChannelsHolder.addClass('possible-target');
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
$tracksHolder.find('.track-target').removeClass('possible-target');
|
||||
$unassignedChannelsHolder.removeClass('possible-target')
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// iterates through the dom and returns a pure data structure for track associations
|
||||
function trackAssociations() {
|
||||
|
||||
var tracks = {};
|
||||
tracks.tracks = [];
|
||||
tracks.unassignedChannels = [];
|
||||
var $unassignedChannels = $unassignedChannelsHolder.find('.ftue-input');
|
||||
var $tracks = $tracksHolder.find('.track-target');
|
||||
|
||||
context._.each($unassignedChannels, function($unassignedTrack) {
|
||||
$unassignedTrack = $($unassignedTrack);
|
||||
var channelId = $unassignedTrack.attr('data-input-id');
|
||||
tracks.unassignedChannels.push(channelId);
|
||||
})
|
||||
|
||||
context._.each($tracks, function($track, index) {
|
||||
$track = $($track);
|
||||
var $assignedChannels = $track.find('.ftue-input');
|
||||
|
||||
var track = {index: index, channels:[]};
|
||||
context._.each($assignedChannels, function($assignedChannel) {
|
||||
$assignedChannel = $($assignedChannel);
|
||||
track.channels.push($assignedChannel.attr('data-input-id'))
|
||||
});
|
||||
|
||||
// sparse array
|
||||
if(track.channels.length > 0) {
|
||||
tracks.tracks.push(track);
|
||||
}
|
||||
var $instrument = $instrumentsHolder.find('[data-num="' + index + '"]').find('.icon-instrument-select');
|
||||
track.instrument_id = $instrument.data('instrument_id');
|
||||
})
|
||||
return tracks;
|
||||
}
|
||||
|
||||
function validate(tracks) {
|
||||
// there must be at least one assigned channel
|
||||
|
||||
if(tracks.tracks.length == 0) {
|
||||
logger.debug("ConfigureTracks validation error: must have assigned at least one input port to a track.");
|
||||
context.JK.Banner.showAlert('Must have assigned at least one input port to a track.');
|
||||
return false;
|
||||
}
|
||||
|
||||
context._.each(tracks.tracks, function(track) {
|
||||
if(!track.instrument_id) {
|
||||
logger.debug("ConfigureTracks validation error: all tracks with ports assigned must specify an instrument.");
|
||||
context.JK.Banner.showAlert('All tracks with ports assigned must specify an instrument.');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function save(tracks) {
|
||||
|
||||
context._.each(tracks.unassignedChannels, function(unassignedChannelId) {
|
||||
context.jamClient.TrackSetAssignment(unassignedChannelId, true, ASSIGNMENT.UNASSIGNED);
|
||||
});
|
||||
|
||||
context._.each(tracks.tracks, function(track, index) {
|
||||
|
||||
var trackNumber = index + 1;
|
||||
|
||||
context._.each(track.channels, function(channelId) {
|
||||
context.jamClient.TrackSetAssignment(channelId, true, trackNumber);
|
||||
|
||||
});
|
||||
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", trackNumber, track.instrument_id);
|
||||
context.jamClient.TrackSetInstrument(trackNumber, context.JK.instrument_id_to_instrument[track.instrument_id].client_id);
|
||||
});
|
||||
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTrackInstruments() {
|
||||
var $trackInstruments = $instrumentsHolder.find('.track-instrument');
|
||||
|
||||
context._.each($trackInstruments, function(trackInstrument) {
|
||||
var $trackInstrument = $(trackInstrument);
|
||||
|
||||
var trackIndex = parseInt($trackInstrument.attr('data-num')) + 1;
|
||||
|
||||
var clientInstrument = context.jamClient.TrackGetInstrument(trackIndex);
|
||||
|
||||
var instrument = context.JK.client_to_server_instrument_map[clientInstrument];
|
||||
|
||||
$trackInstrument.instrumentSelectorSet(instrument ? instrument.server_id : instrument);
|
||||
});
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
var tracks = trackAssociations();
|
||||
|
||||
if(!validate(tracks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var saved = save(tracks);
|
||||
var saved = configureTracksHelper.trySave();
|
||||
|
||||
if(saved) {
|
||||
context.JK.GA.trackConfigureTracksCompletion(context.JK.detectOS());
|
||||
|
|
@ -188,77 +26,13 @@
|
|||
}
|
||||
|
||||
function beforeShow() {
|
||||
loadChannels();
|
||||
loadTrackInstruments();
|
||||
}
|
||||
|
||||
function unassignChannel($channel) {
|
||||
var $originallyAssignedTrack = $channel.closest('.track-target');
|
||||
$unassignedChannelsHolder.append($channel);
|
||||
$originallyAssignedTrack.attr('track-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
|
||||
}
|
||||
function addChannelToTrack($channel, $track) {
|
||||
var $originallyAssignedTrack = $channel.closest('.track-target');
|
||||
$track.append($channel);
|
||||
$track.attr('track-count', $track.find('.ftue-input:not(.ui-draggable-dragging)').length);
|
||||
$originallyAssignedTrack.attr('track-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length)
|
||||
}
|
||||
|
||||
function initializeUnassignedDroppable() {
|
||||
$unassignedChannelsHolder.droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $channel = ui.draggable;
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
unassignChannel($channel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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.find('.track-target').droppable(
|
||||
{
|
||||
activeClass: 'drag-in-progress',
|
||||
hoverClass: 'drag-hovering',
|
||||
drop: function( event, ui ) {
|
||||
var $track = $(this);
|
||||
var $channel = ui.draggable;
|
||||
//$channel.css('left', '0').css('top', '0');
|
||||
addChannelToTrack($channel, $track);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initializeInstrumentDropdown() {
|
||||
var i;
|
||||
for(i = 0; i < MAX_TRACKS; i++) {
|
||||
var $root = $('<div class="track-instrument"></div>');
|
||||
$root.instrumentSelector().attr('data-num', i);
|
||||
$instrumentsHolder.append($root);
|
||||
}
|
||||
configureTracksHelper.reset();
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
$templateAssignablePort = $('#template-assignable-port');
|
||||
$templateTrackTarget = $('#template-track-target');
|
||||
$unassignedChannelsHolder = $step.find('.unassigned-channels');
|
||||
$tracksHolder = $step.find('.tracks');
|
||||
$instrumentsHolder = $step.find('.instruments');
|
||||
|
||||
|
||||
initializeUnassignedDroppable();
|
||||
initializeTrackDroppables();
|
||||
initializeInstrumentDropdown();
|
||||
configureTracksHelper.initialize($step);
|
||||
}
|
||||
|
||||
this.handleNext = handleNext;
|
||||
|
|
|
|||
|
|
@ -17,144 +17,24 @@
|
|||
var $templateChatInput = null;
|
||||
var $selectedChatInput = null;// should only be used if isChatEnabled = true
|
||||
|
||||
var voiceChatHelper = new context.JK.VoiceChatHelper(app);
|
||||
|
||||
function newSession() {
|
||||
$reuseAudioInputRadio.attr('checked', 'checked').iCheck('check');
|
||||
}
|
||||
|
||||
function isChannelAvailableForChat(chatChannelId, musicPorts) {
|
||||
var result = true;
|
||||
context._.each(musicPorts.input, function(inputChannel) {
|
||||
// if the channel is currently assigned to a track, it not unassigned
|
||||
if(inputChannel.id == chatChannelId && (inputChannel.assignment > 0)) {
|
||||
result = false;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isChatEnabled() {
|
||||
return $useChatInputRadio.is(':checked');
|
||||
voiceChatHelper.reset();
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
|
||||
if(isChatEnabled()) {
|
||||
enableChat();
|
||||
}
|
||||
else {
|
||||
disableChat();
|
||||
}
|
||||
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
var chatInputs = context.jamClient.FTUEGetChatInputs();
|
||||
|
||||
$chatInputs.empty();
|
||||
|
||||
context._.each(chatInputs, function(chatChannelName, chatChannelId) {
|
||||
if(isChannelAvailableForChat(chatChannelId, musicPorts)) {
|
||||
var $chat = $(context._.template($templateChatInput.html(), {id: chatChannelId, name: chatChannelName}, { variable: 'data' }));
|
||||
$chat.hide(); // we'll show it once it's styled with iCheck
|
||||
$chatInputs.append($chat);
|
||||
}
|
||||
});
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
context.JK.checkbox($radioButtons).on('ifChecked', function(e) {
|
||||
var $input = $(e.currentTarget);
|
||||
$selectedChatInput = $input; // for use in handleNext
|
||||
var channelId = $input.attr('data-channel-id');
|
||||
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.CHAT);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(!isChatEnabled()) {
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
$chatInputs.find('.chat-input').show().on('click', function() {
|
||||
if(!isChatEnabled()) {
|
||||
context.JK.prodBubble($step.find('.use-chat-input h3'), 'chat-not-enabled', {}, { positions:['left']});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function disableChat() {
|
||||
logger.debug("FTUE: disabling chat");
|
||||
context.jamClient.TrackSetChatEnable(false);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to disable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('disable');
|
||||
}
|
||||
|
||||
function enableChat() {
|
||||
logger.debug("FTUE: enabling chat");
|
||||
context.jamClient.TrackSetChatEnable(true);
|
||||
var result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0) {
|
||||
// success
|
||||
}
|
||||
else {
|
||||
context.JK.Banner.showAlert('Unable to enable chat. ' + result);
|
||||
return false;
|
||||
}
|
||||
|
||||
var $radioButtons = $chatInputs.find('input[name="chat-device"]');
|
||||
$radioButtons.iCheck('enable');
|
||||
}
|
||||
|
||||
function handleChatEnabledToggle() {
|
||||
context.JK.checkbox($reuseAudioInputRadio);
|
||||
context.JK.checkbox($useChatInputRadio);
|
||||
|
||||
// plugin sets to relative on the element; have to do this as an override
|
||||
$reuseAudioInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
$useChatInputRadio.closest('.iradio_minimal').css('position', 'absolute');
|
||||
|
||||
$reuseAudioInputRadio.on('ifChecked', disableChat);
|
||||
$useChatInputRadio.on('ifChecked', enableChat)
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
var selectedDeviceInfo = gearUtils.selectedDeviceInfo(context.jamClient.FTUEGetInputMusicDevice(), context.jamClient.FTUEGetOutputMusicDevice());
|
||||
|
||||
var chatName = null;
|
||||
if(isChatEnabled()) {
|
||||
chatName = $selectedChatInput.attr('data-channel-name');
|
||||
}
|
||||
context.jamClient.FTUESetMusicProfileName(gearUtils.createProfileName(selectedDeviceInfo, chatName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function initialize(_$step) {
|
||||
$step = _$step;
|
||||
|
||||
$reuseAudioInputRadio = $step.find('.reuse-audio-input input');
|
||||
$useChatInputRadio = $step.find('.use-chat-input input');
|
||||
$chatInputs = $step.find('.chat-inputs');
|
||||
$templateChatInput = $('#template-chat-input');
|
||||
voiceChatHelper.initialize($step, true);
|
||||
|
||||
handleChatEnabledToggle();
|
||||
}
|
||||
|
||||
this.handleNext = handleNext;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
context.JK = context.JK || {};
|
||||
context.JK.StepSelectGear = function (app, dialog) {
|
||||
|
||||
var EVENTS = context.JK.DIALOG_CLOSED;
|
||||
var ASSIGNMENT = context.JK.ASSIGNMENT;
|
||||
var VOICE_CHAT = context.JK.VOICE_CHAT;
|
||||
var AUDIO_DEVICE_BEHAVIOR = context.JK.AUDIO_DEVICE_BEHAVIOR;
|
||||
|
|
@ -298,7 +299,7 @@
|
|||
function initializeLoopback() {
|
||||
$launchLoopbackBtn.unbind('click').click(function() {
|
||||
|
||||
$(dialog.getLoopbackWizard()).one('dialog_closed', function() {
|
||||
$(dialog.getLoopbackWizard().getDialog()).one(EVENTS.DIALOG_CLOSED, function() {
|
||||
loopbackShowing = false;
|
||||
|
||||
if(dialog.getLoopbackWizard().getGearTest().isGoodFtue()) {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
// * Linux
|
||||
function determineDeviceType(deviceId, displayName) {
|
||||
if (operatingSystem == "MacOSX") {
|
||||
if (displayName.toLowerCase().trim() == "built-in") {
|
||||
if (displayName.toLowerCase().trim().indexOf("built-in") == 0) {
|
||||
return "MacOSX_builtin";
|
||||
}
|
||||
else {
|
||||
|
|
@ -157,6 +157,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all profiles, but marks profiles good: true/false.
|
||||
* Also, current:true/false indicates which profile is active. (at most 1 profile will be marked current)
|
||||
* This is to provide a unified view of FTUEGetAllAudioConfigurations & FTUEGetGoodAudioConfigurations
|
||||
* @returns an array of profiles, where each profile is: {id: profile-name, good: boolean, class: 'bad' | 'good', current: boolean }
|
||||
*/
|
||||
gearUtils.getProfiles = function() {
|
||||
var all = context.jamClient.FTUEGetAllAudioConfigurations();
|
||||
var good = context.jamClient.FTUEGetGoodAudioConfigurations();
|
||||
var current = context.jamClient.FTUEGetMusicProfileName();
|
||||
|
||||
var profiles = [];
|
||||
context._.each(all, function(item) {
|
||||
profiles.push({id: item, good: false, class:'bad', current: current == item})
|
||||
});
|
||||
|
||||
if(good) {
|
||||
for(var i = 0; i < good.length; i++) {
|
||||
for(var j = 0; j < profiles.length; j++) {
|
||||
if(good[i] == profiles[j].id) {
|
||||
profiles[j].good = true;
|
||||
profiles[j].class = 'good';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
gearUtils.postDiagnostic = function(operatingSystem, deviceInformation, selectedDeviceInfo, gearTest, frameBuffers, isAutomated) {
|
||||
rest.createDiagnostic({
|
||||
type: 'GEAR_SELECTION',
|
||||
|
|
@ -169,4 +199,40 @@
|
|||
});
|
||||
}
|
||||
|
||||
// complete list of possibly chatInputs, whether currently assigned as the chat channel or not
|
||||
// each item should be {id: channelId, name: channelName, assignment: channel assignment}
|
||||
|
||||
gearUtils.getChatInputs = function(){
|
||||
|
||||
var musicPorts = jamClient.FTUEGetChannels();
|
||||
var chatsOnOtherDevices = context.jamClient.FTUEGetChatInputs(false);
|
||||
|
||||
var chatInputs = [];
|
||||
context._.each(musicPorts.inputs, function(input) {
|
||||
chatInputs.push({id: input.id, name: input.name, assignment:input.assignment});
|
||||
});
|
||||
|
||||
context._.each(chatsOnOtherDevices, function(chatChannelName, chatChannelId) {
|
||||
var chatInput = {id: chatChannelId, name: chatChannelName, assignment: null};
|
||||
var assignment = context.jamClient.TrackGetAssignment(chatChannelId, true);
|
||||
chatInput.assignment = assignment;
|
||||
chatInputs.push(chatInput);
|
||||
})
|
||||
|
||||
return chatInputs;
|
||||
}
|
||||
|
||||
gearUtils.isChannelAvailableForChat = function(chatChannelId, musicPorts) {
|
||||
var result = true;
|
||||
context._.each(musicPorts.inputs, function(inputChannel) {
|
||||
// if the channel is currently assigned to a track, it not unassigned
|
||||
if(inputChannel.id == chatChannelId && (inputChannel.assignment > 0)) {
|
||||
result = false;
|
||||
return false; // break
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
context.JK = context.JK || {};
|
||||
context.JK.LoopbackWizard = function (app) {
|
||||
|
||||
var EVENTS = context.JK.DIALOG_CLOSED;
|
||||
var logger = context.JK.logger;
|
||||
|
||||
var $dialog = null;
|
||||
|
|
@ -32,7 +33,6 @@
|
|||
|
||||
function closeDialog() {
|
||||
wizard.onCloseDialog();
|
||||
$self.triggerHandler('dialog_closed');
|
||||
app.layout.closeDialog('loopback-wizard');
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +71,9 @@
|
|||
$(wizard).on('wizard_close', onClosed);
|
||||
}
|
||||
|
||||
function getDialog() {
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
|
|
@ -93,6 +96,7 @@
|
|||
this.setBackState = setBackState;
|
||||
this.initialize = initialize;
|
||||
this.getGearTest = getGearTest;
|
||||
this.getDialog = getDialog;
|
||||
|
||||
return this;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
*= require ./search
|
||||
*= require ./ftue
|
||||
*= require ./jamServer
|
||||
*= require ./dragDropTracks
|
||||
*= require ./voiceChatHelper
|
||||
*= require ./wizard/gearResults
|
||||
*= require ./wizard/framebuffers
|
||||
*= require ./wizard/wizard
|
||||
|
|
|
|||
|
|
@ -1,5 +1,121 @@
|
|||
@import "client/common.css.scss";
|
||||
@charset "UTF-8";
|
||||
|
||||
#configure-tracks-dialog {
|
||||
min-height: 500px;
|
||||
max-height: 500px;
|
||||
min-height: 700px;
|
||||
max-height: 700px;
|
||||
width:800px;
|
||||
|
||||
&[current-screen="account/audio"] {
|
||||
.btn-add-new-audio-gear {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-header {
|
||||
color:white;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
.certified-audio-profile-section {
|
||||
|
||||
height:53px;
|
||||
|
||||
.easydropdown {
|
||||
width:120px;
|
||||
}
|
||||
|
||||
.easydropdown-wrapper {
|
||||
width:120px;
|
||||
}
|
||||
|
||||
.dropdown-container {
|
||||
min-width:138px;
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
position:relative;
|
||||
float:left;
|
||||
vertical-align:top;
|
||||
@include border_box_sizing;
|
||||
padding: 20px 20px 0 0;
|
||||
}
|
||||
|
||||
.sub-column {
|
||||
position:relative;
|
||||
float:left;
|
||||
vertical-align:top;
|
||||
@include border_box_sizing;
|
||||
}
|
||||
|
||||
.tab[tab-id="music-audio"] {
|
||||
.column {
|
||||
&:nth-of-type(1) {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-column {
|
||||
&:nth-of-type(1) {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab[tab-id="voice-chat"] {
|
||||
.column {
|
||||
&:nth-of-type(1) {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unused-audio-inputs-section {
|
||||
margin-top:20px;
|
||||
height:270px;
|
||||
}
|
||||
|
||||
.unused-audio-outputs-section {
|
||||
margin-top:20px;
|
||||
height:80px;
|
||||
}
|
||||
|
||||
.input-tracks-section {
|
||||
height:363px;
|
||||
}
|
||||
|
||||
.output-channels-section {
|
||||
height:80px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
bottom: 25px;
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
left:25px;
|
||||
}
|
||||
|
||||
.btn-add-new-audio-gear {
|
||||
float:left;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
float:right;
|
||||
}
|
||||
|
||||
.btn-update-settings {
|
||||
float:right;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
@import "client/common.css.scss";
|
||||
@charset "UTF-8";
|
||||
|
||||
.dialog.gear-wizard, #configure-tracks-dialog {
|
||||
|
||||
.icon-instrument-select {
|
||||
padding: 3px 0; // to combine 24 of .current-instrument + 3x on either side
|
||||
margin: 0 0 15px 25px; // 15 margin-bottom to match tracks on the left
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.unassigned-output-channels {
|
||||
min-height: 80px;
|
||||
overflow-y: auto;
|
||||
//padding-right:18px; // to keep draggables off of scrollbar. maybe necessary
|
||||
|
||||
&.drag-in-progress {
|
||||
overflow-y: visible;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
&.possible-target {
|
||||
border: solid 1px white;
|
||||
|
||||
&.drag-hovering {
|
||||
border: solid 1px #ED3618;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unassigned-input-channels {
|
||||
min-height: 240px;
|
||||
overflow-y: auto;
|
||||
//padding-right:18px; // to keep draggables off of scrollbar. maybe necessary
|
||||
|
||||
&.drag-in-progress {
|
||||
overflow-y: visible;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
&.possible-target {
|
||||
border: solid 1px white;
|
||||
|
||||
&.drag-hovering {
|
||||
border: solid 1px #ED3618;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
position: absolute;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
}
|
||||
.track, .output {
|
||||
margin-bottom: 15px;
|
||||
.track-target, .output-target {
|
||||
&.possible-target {
|
||||
border-color: white;
|
||||
}
|
||||
&.drag-hovering {
|
||||
border-color: #ED3618;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do not show tracks with 2 channels as a possible target
|
||||
.track .track-target.possible-target[track-count="2"] {
|
||||
border-color:#999;
|
||||
}
|
||||
|
||||
// do now show output slots with 1 channel as a possible target
|
||||
.output .output-target.possible-target[output-count="1"] {
|
||||
border-color:#999;
|
||||
}
|
||||
|
||||
.ftue-input {
|
||||
font-size: 12px;
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-bottom: 15px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
direction: rtl;
|
||||
&.ui-draggable-dragging {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
&:hover {
|
||||
color:white;
|
||||
overflow:visible;
|
||||
background-color:#333;
|
||||
width: auto !important;
|
||||
direction:ltr;
|
||||
position:absolute;
|
||||
line-height:19.5px;
|
||||
}*/
|
||||
}
|
||||
|
||||
.track-target, .output-target {
|
||||
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-left: 15px;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
|
||||
&.drag-in-progress {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ftue-input {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
&.ui-draggable-dragging {
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&[track-count="0"], &[output-count="0"] {
|
||||
.placeholder {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
&[track-count="2"] {
|
||||
.ftue-input {
|
||||
width: 49%;
|
||||
display: inline-block;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
float: left;
|
||||
/**&:after {
|
||||
float:right;
|
||||
content: ',';
|
||||
padding-right:3px;
|
||||
}*/
|
||||
}
|
||||
&:nth-of-type(2) {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,4 +4,11 @@
|
|||
position: absolute;
|
||||
right: 25px;
|
||||
}
|
||||
|
||||
|
||||
.network-test {
|
||||
.network-test-results {
|
||||
height:268px ! important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
.dialog.configure-tracks, .dialog.gear-wizard {
|
||||
|
||||
.voicechat-option {
|
||||
|
||||
position: relative;
|
||||
|
||||
div {
|
||||
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-left: 30px;
|
||||
margin-top: 14px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p {
|
||||
padding-left: 30px;
|
||||
margin-top: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.iradio_minimal {
|
||||
margin-top: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.ftue-box {
|
||||
background-color: #222222;
|
||||
font-size: 13px;
|
||||
padding: 8px;
|
||||
&.chat-inputs {
|
||||
height: 230px !important;
|
||||
overflow: auto;
|
||||
|
||||
p {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
white-space: nowrap;
|
||||
|
||||
.iradio_minimal {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
@import "client/common.css.scss";
|
||||
|
||||
@charset "UTF-8";
|
||||
|
||||
.dialog.gear-wizard, .dialog.network-test {
|
||||
|
|
@ -193,132 +192,8 @@
|
|||
margin-top: 45px;
|
||||
}
|
||||
|
||||
.icon-instrument-select {
|
||||
padding: 3px 0; // to combine 24 of .current-instrument + 3x on either side
|
||||
margin: 0 0 15px 25px; // 15 margin-bottom to match tracks on the left
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.unassigned-channels {
|
||||
min-height: 240px;
|
||||
overflow-y: auto;
|
||||
//padding-right:18px; // to keep draggables off of scrollbar. maybe necessary
|
||||
|
||||
&.drag-in-progress {
|
||||
overflow-y: visible;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
&.possible-target {
|
||||
border: solid 1px white;
|
||||
|
||||
&.drag-hovering {
|
||||
border: solid 1px #ED3618;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.num {
|
||||
position: absolute;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
}
|
||||
.track {
|
||||
margin-bottom: 15px;
|
||||
.track-target {
|
||||
&.possible-target {
|
||||
border-color: white;
|
||||
}
|
||||
&.drag-hovering {
|
||||
border-color: #ED3618;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ftue-input {
|
||||
font-size: 12px;
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-bottom: 15px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
direction: rtl;
|
||||
&.ui-draggable-dragging {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
&:hover {
|
||||
color:white;
|
||||
overflow:visible;
|
||||
background-color:#333;
|
||||
width: auto !important;
|
||||
direction:ltr;
|
||||
position:absolute;
|
||||
line-height:19.5px;
|
||||
}*/
|
||||
}
|
||||
|
||||
.track-target {
|
||||
|
||||
cursor: move;
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
margin-left: 15px;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
|
||||
&.drag-in-progress {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ftue-input {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
&.ui-draggable-dragging {
|
||||
padding: 4px;
|
||||
border: solid 1px #999;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&[track-count="0"] {
|
||||
.placeholder {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
&[track-count="2"] {
|
||||
.ftue-input {
|
||||
width: 49%;
|
||||
display: inline-block;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
float: left;
|
||||
/**&:after {
|
||||
float:right;
|
||||
content: ',';
|
||||
padding-right:3px;
|
||||
}*/
|
||||
}
|
||||
&:nth-of-type(2) {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.output-channels, .unassigned-output-channels {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,67 +208,9 @@
|
|||
}
|
||||
|
||||
.watch-video {
|
||||
margin-top: 97px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.voicechat-option {
|
||||
|
||||
position: relative;
|
||||
|
||||
div {
|
||||
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-left: 30px;
|
||||
margin-top: 14px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p {
|
||||
padding-left: 30px;
|
||||
margin-top: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.iradio_minimal {
|
||||
margin-top: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.ftue-box {
|
||||
&.chat-inputs {
|
||||
height: 230px !important;
|
||||
overflow: auto;
|
||||
|
||||
p {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
white-space: nowrap;
|
||||
|
||||
.iradio_minimal {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.watch-video {
|
||||
margin-top: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wizard-step[layout-wizard-step="4"] {
|
||||
|
|
@ -442,11 +259,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.network-test {
|
||||
.network-test-results {
|
||||
height:268px ! important;
|
||||
}
|
||||
}
|
||||
.wizard-step[layout-wizard-step="5"], .network-test {
|
||||
|
||||
.wizard-step-content .wizard-step-column {
|
||||
|
|
@ -557,7 +369,7 @@
|
|||
}
|
||||
|
||||
.network-test-results {
|
||||
height: 248px;
|
||||
height: 248px !important;
|
||||
@include border_box_sizing;
|
||||
&.testing {
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
{% if(data.is_admin) { %}
|
||||
<a href="#" data-id="{{profile.id}}" data-purpose="loopback-audio-profile" class="button-orange">LOOPBACK (admin only)</a>
|
||||
{% } %}
|
||||
<a href="#" data-id="{{profile.id}}" data-purpose="configure-audio-profile" class="button-orange">CONFIGURE</a>
|
||||
<a href="#" data-id="{{profile.id}}" data-purpose="delete-audio-profile" class="button-orange">DELETE</a></td>
|
||||
</tr>
|
||||
{% } %}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.dialog{ layout: 'dialog', 'layout-id' => 'configure-tracks', id: 'configure-tracks-dialog'}
|
||||
.dialog.configure-tracks{ layout: 'dialog', 'layout-id' => 'configure-tracks', id: 'configure-tracks-dialog'}
|
||||
.content-head
|
||||
= image_tag "content/icon_add.png", {:width => 19, :height => 19, :class => 'content-icon' }
|
||||
%h1 configure tracks
|
||||
|
|
@ -9,14 +9,63 @@
|
|||
|
||||
.instructions
|
||||
%span
|
||||
Choose your audio device. Drag and drop to assign input ports to tracks, and specify the instrument
|
||||
for each track. Drag and drop to assign a pair of output ports for session stereo audio monitoring.
|
||||
|
||||
.clearall
|
||||
|
||||
.tab{'tab-id' => 'music-audio'}
|
||||
|
||||
.column
|
||||
.certified-audio-profile-section
|
||||
.sub-header Certified Audio Profile
|
||||
%select.certified-audio-profile
|
||||
.clearall
|
||||
|
||||
.unused-audio-inputs-section.no-selection-range
|
||||
.sub-header Unused Input Ports
|
||||
.unassigned-input-channels
|
||||
|
||||
.unused-audio-outputs-section.no-selection-range
|
||||
.sub-header Unused Output Ports
|
||||
.unassigned-output-channels
|
||||
|
||||
.column
|
||||
.input-tracks-section
|
||||
.sub-column
|
||||
.sub-header Track Input Port(s)
|
||||
.input-tracks.tracks.no-selection-range
|
||||
.sub-column
|
||||
.sub-header Instrument
|
||||
.instruments.no-selection-range
|
||||
|
||||
.output-channels-section
|
||||
.sub-header Audio Output Port
|
||||
.output-channels.no-selection-range
|
||||
.clearall
|
||||
|
||||
|
||||
|
||||
.tab{'tab-id' => 'voice-chat'}
|
||||
|
||||
.column
|
||||
%form.select-voice-chat-option.section
|
||||
.sub-header Select Voice Chat Option
|
||||
.voicechat-option.reuse-audio-input
|
||||
%input{type:"radio", name: "voicechat", checked:"checked"}
|
||||
%h3 Use Music Microphone
|
||||
%p I am already using a microphone to capture my vocal or instrumental music, so I can talk with other musicians using that microphone
|
||||
.voicechat-option.use-chat-input
|
||||
%input{type:"radio", name: "voicechat"}
|
||||
%h3 Use Chat Microphone
|
||||
%p I am not using a microphone for acoustic instruments or vocals, so use the input selected to the right for voice chat during my sessions
|
||||
.column
|
||||
.select-voice-chat
|
||||
.sub-header Voice Chat Input
|
||||
.ftue-box.chat-inputs
|
||||
.clearall
|
||||
|
||||
.buttons
|
||||
%a.btn-add-new-audio-gear.button-grey{'layout-link' => 'add-new-audio-gear'} ADD NEW AUDIO GEAR
|
||||
%a.button-orange.btn-update-settings{href:'#'} UPDATE SETTINGS
|
||||
%a.button-grey.btn-cancel{href:'#'} CANCEL
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
<!-- my tracks -->
|
||||
<div class="session-mytracks">
|
||||
<h2>my tracks</h2>
|
||||
<div id="track-settings" class="session-add" style="display:block;" layout-link="configure-audio">
|
||||
<div id="track-settings" class="session-add" style="display:block;" layout-link="configure-tracks">
|
||||
<%= image_tag "content/icon_settings_lg.png", {:width => 18, :height => 18} %> Settings
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -74,15 +74,17 @@
|
|||
%li Select the instrument for each track.
|
||||
.center
|
||||
%a.button-orange.watch-video{href:'#'} WATCH VIDEO
|
||||
.wizard-step-column.no-selection-range
|
||||
.wizard-step-column
|
||||
%h2 Unassigned Ports
|
||||
.unassigned-channels
|
||||
.wizard-step-column.no-selection-range
|
||||
.unassigned-input-channels.no-selection-range
|
||||
.wizard-step-column
|
||||
%h2 Track Input Port(s)
|
||||
.tracks
|
||||
.wizard-step-column.no-selection-range
|
||||
.tracks.no-selection-range
|
||||
.wizard-step-column
|
||||
%h2 Instrument
|
||||
.instruments
|
||||
.instruments.no-selection-range
|
||||
.output-channels
|
||||
.unassigned-output-channels
|
||||
|
||||
.wizard-step{ 'layout-wizard-step' => "3", 'dialog-title' => "Configure Voice Chat", 'dialog-purpose' => "ConfigureVoiceChat" }
|
||||
.ftuesteps
|
||||
|
|
@ -98,14 +100,15 @@
|
|||
%a.button-orange.watch-video{href:'#'} WATCH VIDEO
|
||||
.wizard-step-column
|
||||
%h2 Select Voice Chat Option
|
||||
.voicechat-option.reuse-audio-input
|
||||
%input{type:"radio", name: "voicechat", checked:"checked"}
|
||||
%h3 Use Music Microphone
|
||||
%p I am already using a microphone to capture my vocal or instrumental music, so I can talk with other musicians using that microphone
|
||||
.voicechat-option.use-chat-input
|
||||
%input{type:"radio", name: "voicechat"}
|
||||
%h3 Use Chat Microphone
|
||||
%p I am not using a microphone for acoustic instruments or vocals, so use the input selected to the right for voice chat during my sessions
|
||||
%form
|
||||
.voicechat-option.reuse-audio-input
|
||||
%input{type:"radio", name: "voicechat", checked:"checked"}
|
||||
%h3 Use Music Microphone
|
||||
%p I am already using a microphone to capture my vocal or instrumental music, so I can talk with other musicians using that microphone
|
||||
.voicechat-option.use-chat-input
|
||||
%input{type:"radio", name: "voicechat"}
|
||||
%h3 Use Chat Microphone
|
||||
%p I am not using a microphone for acoustic instruments or vocals, so use the input selected to the right for voice chat during my sessions
|
||||
.wizard-step-column
|
||||
%h2 Voice Chat Input
|
||||
.ftue-box.chat-inputs
|
||||
|
|
@ -220,8 +223,16 @@
|
|||
.track-target{'data-num' => '{{data.num}}', 'track-count' => 0}
|
||||
%span.placeholder None
|
||||
|
||||
|
||||
%script{type: 'text/template', id: 'template-output-target'}
|
||||
.output{'data-num' => '{{data.num}}'}
|
||||
.num {{data.num + 1}}:
|
||||
.output-target{'data-num' => '{{data.num}}', 'output-count' => 0}
|
||||
%span.placeholder None
|
||||
|
||||
|
||||
%script{type: 'text/template', id: 'template-chat-input'}
|
||||
.chat-input
|
||||
%input{type:"radio", name: "chat-device", 'data-channel-id' => '{{data.id}}', 'data-channel-name' => '{{data.name}}'}
|
||||
%p
|
||||
= '{{data.name}}'
|
||||
%span {{data.name}}
|
||||
Loading…
Reference in New Issue