422 lines
15 KiB
JavaScript
422 lines
15 KiB
JavaScript
(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); |