* merged
This commit is contained in:
commit
b07aedc9cc
|
|
@ -138,7 +138,8 @@
|
|||
context.VideoActions.videoWindowClosed()
|
||||
}
|
||||
else if (type === ALERT_NAMES.VST_CHANGED) {
|
||||
context.ConfigureTracksActions.onVstChanged()
|
||||
console.log("VST CHANGED!")
|
||||
context.ConfigureTracksActions.vstChanged()
|
||||
}
|
||||
else if((!context.JK.CurrentSessionModel || !context.JK.CurrentSessionModel.inSession()) &&
|
||||
(ALERT_NAMES.INPUT_IO_RATE == type || ALERT_NAMES.INPUT_IO_JTR == type || ALERT_NAMES.OUTPUT_IO_RATE == type || ALERT_NAMES.OUTPUT_IO_JTR== type)) {
|
||||
|
|
|
|||
|
|
@ -22,136 +22,7 @@
|
|||
var $instrumentsHolder = null;
|
||||
var isDragging = false;
|
||||
|
||||
function removeHoverer($hoverChannel) {
|
||||
var $channel = $hoverChannel.data('original')
|
||||
$channel.data('cloned', null);
|
||||
$hoverChannel.remove();
|
||||
}
|
||||
|
||||
function hoverIn($channel) {
|
||||
if(isDragging) return;
|
||||
|
||||
var $container = $channel.closest('.target');
|
||||
var inTarget = $container.length > 0;
|
||||
if(!inTarget) {
|
||||
$container = $channel.closest('.channels-holder')
|
||||
}
|
||||
|
||||
var $inputs = $container.find('.ftue-input');
|
||||
|
||||
var index = $inputs.index($channel);
|
||||
// $channel.css('padding', '0 5px');
|
||||
if(inTarget) {
|
||||
$channel.data('container', $container)
|
||||
$channel.addClass('hovering');
|
||||
$channel.css('color', 'white')
|
||||
$channel.css('background-color', '#333');
|
||||
$channel.css('border', '#333');
|
||||
$channel.css('border-radius', '2px');
|
||||
$channel.css('min-width', '49%');
|
||||
$channel.css('width', 'auto');
|
||||
$channel.css('position', 'absolute');
|
||||
$container.css('overflow', 'visible');
|
||||
}
|
||||
else {
|
||||
var $offsetParent = $channel.offsetParent();
|
||||
var parentOffset = $offsetParent.offset();
|
||||
|
||||
var hoverChannel = $(context._.template($templateAssignablePort.html(), {id: 'bogus', name: $channel.text(), direction: 'bogus'}, { variable: 'data' }));
|
||||
hoverChannel
|
||||
.css('position', 'absolute')
|
||||
.css('color', 'white')
|
||||
.css('left', $channel.position().left)
|
||||
.css('top', $channel.position().top)
|
||||
.css('background-color', '#333')
|
||||
.css('min-width', $channel.width())
|
||||
.css('min-height', $channel.height())
|
||||
.css('z-index', 10000)
|
||||
.css('background-position', '4px 6px')
|
||||
.css('padding-left', '14px')
|
||||
.data('original', $channel);
|
||||
|
||||
$channel.data('cloned', hoverChannel);
|
||||
hoverChannel
|
||||
.hover(function(e) {
|
||||
var hoverCheckTimeout = hoverChannel.data('hoverCheckTimeout');
|
||||
if(hoverCheckTimeout) {
|
||||
clearTimeout(hoverCheckTimeout);
|
||||
hoverChannel.data('hoverCheckTimeout', null);
|
||||
}
|
||||
}, function() { removeHoverer($(this)); })
|
||||
.mousedown(function(e) {
|
||||
// because we have obscured the element the user wants to drag,
|
||||
// we proxy a mousedown on the hover-element to the covered .ftue-input ($channel).
|
||||
// this causes jquery.drag to get going even though the user clicked a different element
|
||||
$channel.trigger(e)
|
||||
})
|
||||
hoverChannel.data('hoverCheckTimeout', setTimeout(function() {
|
||||
// check if element has already been left
|
||||
hoverChannel.data('hoverCheckTimeout', null);
|
||||
removeHoverer(hoverChannel);
|
||||
}, 500));
|
||||
hoverChannel.prependTo($offsetParent);
|
||||
}
|
||||
|
||||
$channel.css('z-index', 10000)
|
||||
if(inTarget && $inputs.length == 2) {
|
||||
|
||||
if(index == 0) {
|
||||
$channel.css('right', '50%')
|
||||
}
|
||||
else {
|
||||
$channel.css('left', '51%')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function hoverOut($channel) {
|
||||
|
||||
var $cloned = $channel.data('cloned');
|
||||
if($cloned) {
|
||||
return; // let the cloned handle the rest of hover out logic when it's hovered-out
|
||||
}
|
||||
|
||||
$channel
|
||||
.removeClass('hovering')
|
||||
.css('color', '')
|
||||
.css('font-weight', '')
|
||||
.css('position', '')
|
||||
.css('width', '')
|
||||
.css('background-color', '')
|
||||
.css('padding', '')
|
||||
.css('padding-left', '')
|
||||
.css('background-position', '')
|
||||
.css('border', '')
|
||||
.css('border-radius', '')
|
||||
.css('right', '')
|
||||
.css('left', '')
|
||||
.css('min-width', '')
|
||||
.css('z-index', '')
|
||||
.css('margin-left', '')
|
||||
.css('max-width', 'auto');
|
||||
|
||||
//var $container = $channel.closest('.target');
|
||||
var $container = $channel.data('container');
|
||||
if($container) {
|
||||
$container.css('overflow', '')
|
||||
}
|
||||
}
|
||||
|
||||
function fixClone($clone) {
|
||||
$clone
|
||||
.css('color', '')
|
||||
.css('font-weight', '')
|
||||
.css('width', 'auto')
|
||||
.css('background-color', '')
|
||||
.css('padding', '')
|
||||
.css('border', '')
|
||||
.css('border-radius', '')
|
||||
.css('right', '')
|
||||
.css('min-width', '')
|
||||
}
|
||||
|
||||
// inputChannelFilter is an optional argument that is used by the Gear Wizard.
|
||||
// basically, if an input channel isn't in there, it's not going to be displayed
|
||||
|
|
@ -176,11 +47,6 @@
|
|||
|
||||
var $channel = $(context._.template($templateAssignablePort.html(), $.extend({}, inputChannel, {direction:'in'}), { variable: 'data' }));
|
||||
|
||||
$channel.hover(
|
||||
function() { hoverIn ($(this)) },
|
||||
function() { hoverOut($(this)) }
|
||||
);
|
||||
|
||||
if(forceInputsToUnassign || inputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
unassignInputChannel($channel);
|
||||
}
|
||||
|
|
@ -205,10 +71,7 @@
|
|||
context._.each(outputChannels, function (outputChannel, index) {
|
||||
var $channel = $(context._.template($templateAssignablePort.html(), $.extend({}, outputChannel, {direction:'out'}), { variable: 'data' }));
|
||||
|
||||
$channel.hover(
|
||||
function() { hoverIn ($(this)) },
|
||||
function() { hoverOut($(this)) }
|
||||
);
|
||||
|
||||
|
||||
if(outputChannel.assignment == ASSIGNMENT.UNASSIGNED) {
|
||||
unassignOutputChannel($channel);
|
||||
|
|
@ -223,29 +86,6 @@
|
|||
}
|
||||
addChannelToOutput($channel, $output.find('.output-target'));
|
||||
}
|
||||
|
||||
$channel.draggable({
|
||||
helper: 'clone',
|
||||
start: function(e,ui) {
|
||||
isDragging = true;
|
||||
var $channel = $(this);
|
||||
fixClone(ui.helper);
|
||||
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() {
|
||||
isDragging = false;
|
||||
$outputChannelHolder.find('.output-target').removeClass('possible-target');
|
||||
$unassignedOutputsHolder.removeClass('possible-target')
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -439,112 +279,9 @@
|
|||
$originallyAssignedTrack.attr('output-count', $originallyAssignedTrack.find('.ftue-input:not(.ui-draggable-dragging)').length)
|
||||
}
|
||||
|
||||
|
||||
function initializeUnassignedOutputDroppable() {
|
||||
$unassignedOutputsHolder.droppable(
|
||||
{
|
||||
accept: '.ftue-input[data-direction="out"]',
|
||||
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(
|
||||
{
|
||||
accept: '.ftue-input[data-direction="in"]',
|
||||
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(
|
||||
{
|
||||
accept: '.ftue-input[data-direction="out"]',
|
||||
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(
|
||||
{
|
||||
accept: '.ftue-input[data-direction="in"]',
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
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.')
|
||||
$instructions.html("Click the 'ADD LIVE TRACK' button to add more tracks. You may set up a live track for each instrumental and/or vocal part to perform in sessions. You must also set up exactly two Session Audio Output ports to deliver the stereo audio in your sessions.")
|
||||
return;
|
||||
var os = context.jamClient.GetOSAsString();
|
||||
$instructions.html(configure_audio_instructions[os]);
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
}
|
||||
|
||||
function validateAudioSettings() {
|
||||
return configureTracksHelper.trySave();
|
||||
return true;
|
||||
}
|
||||
|
||||
function showVoiceChatPanel() {
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
$musicAudioTabSelector.click(function () {
|
||||
// validate voice chat settings
|
||||
if (validateVoiceChatSettings()) {
|
||||
configureTracksHelper.reset();
|
||||
window.ConfigureTracksActions.reset(false);
|
||||
voiceChatHelper.reset();
|
||||
showMusicAudioPanel();
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
// validate audio settings
|
||||
if (validateAudioSettings()) {
|
||||
logger.debug("initializing voice chat helper")
|
||||
configureTracksHelper.reset();
|
||||
window.ConfigureTracksActions.reset(false);
|
||||
voiceChatHelper.reset();
|
||||
showVoiceChatPanel();
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@
|
|||
//});
|
||||
|
||||
$btnUpdateTrackSettings.click(function() {
|
||||
if(configureTracksHelper.trySave() && voiceChatHelper.trySave()) {
|
||||
if(voiceChatHelper.trySave()) {
|
||||
app.layout.closeDialog('configure-tracks');
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
});
|
||||
$certifiedAudioProfile.html(optionsHtml);
|
||||
|
||||
context.JK.dropdown($certifiedAudioProfile);
|
||||
//context.JK.dropdown($certifiedAudioProfile);
|
||||
}
|
||||
|
||||
function deviceChanged() {
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
|
||||
currentProfile = profile;
|
||||
|
||||
configureTracksHelper.reset();
|
||||
window.ConfigureTracksActions.reset(false);
|
||||
}
|
||||
|
||||
function beforeShow() {
|
||||
|
|
@ -207,13 +207,16 @@
|
|||
return;
|
||||
}
|
||||
|
||||
configureTracksHelper.reset();
|
||||
window.ConfigureTracksActions.reset(false);
|
||||
voiceChatHelper.reset();
|
||||
voiceChatHelper.beforeShow();
|
||||
}
|
||||
|
||||
function afterShow() {
|
||||
sessionUtils.SessionPageEnter();
|
||||
|
||||
//context.ConfigureTracksActions.vstScan();
|
||||
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
|
|
@ -247,8 +250,8 @@
|
|||
$btnAddNewGear = $dialog.find('.btn-add-new-audio-gear');
|
||||
$btnUpdateTrackSettings = $dialog.find('.btn-update-settings');
|
||||
|
||||
configureTracksHelper = new context.JK.ConfigureTracksHelper(app);
|
||||
configureTracksHelper.initialize($dialog);
|
||||
//configureTracksHelper = new context.JK.ConfigureTracksHelper(app);
|
||||
//configureTracksHelper.initialize($dialog);
|
||||
|
||||
voiceChatHelper = new context.JK.VoiceChatHelper(app);
|
||||
voiceChatHelper.initialize($dialog, 'configure_track_dialog', true, {vuType: "vertical", lightCount: 10, lightWidth: 3, lightHeight: 17}, 191);
|
||||
|
|
|
|||
|
|
@ -1052,6 +1052,16 @@
|
|||
function GetAutoStart() { return true; }
|
||||
function SaveSettings() {}
|
||||
|
||||
|
||||
function VSTScan(callback) {setTimeout(eval(callback+ "()"), 1000)}
|
||||
function hasVstHost() { return false;}
|
||||
function getPluginList() { return {vsts:[]} }
|
||||
|
||||
function clearPluginList() {}
|
||||
function listTrackAssignments() {
|
||||
return {}
|
||||
}
|
||||
|
||||
// Javascript Bridge seems to camel-case
|
||||
// Set the instance functions:
|
||||
this.AbortRecording = AbortRecording;
|
||||
|
|
@ -1315,6 +1325,11 @@
|
|||
this.StopNetworkTest = StopNetworkTest;
|
||||
this.log = log;
|
||||
this.getOperatingMode = getOperatingMode;
|
||||
this.VSTScan = VSTScan;
|
||||
this.hasVstHost = hasVstHost;
|
||||
this.getPluginList = getPluginList;
|
||||
this.clearPluginList = clearPluginList;
|
||||
this.listTrackAssignments = listTrackAssignments;
|
||||
this.clientID = "devtester";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@
|
|||
METRONOME_PLAYBACK_MODE_SELECTED: 'metronome_playback_mode_selected',
|
||||
CHECKOUT_SIGNED_IN: 'checkout_signed_in',
|
||||
CHECKOUT_SKIP_SIGN_IN: 'checkout_skip_sign_in',
|
||||
PREVIEW_PLAYED: 'preview_played'
|
||||
PREVIEW_PLAYED: 'preview_played',
|
||||
VST_OPERATION_SELECTED: 'vst_operation_selected',
|
||||
VST_EFFECT_SELECTED: 'vst_effect_selected'
|
||||
};
|
||||
|
||||
context.JK.PLAYBACK_MONITOR_MODE = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
|
||||
|
||||
// creates an iconic/graphical instrument selector. useful when there is minimal real-estate
|
||||
|
||||
$.fn.manageVsts = function(options) {
|
||||
|
||||
return this.each(function(index) {
|
||||
|
||||
function close() {
|
||||
$parent.btOff();
|
||||
$parent.focus();
|
||||
}
|
||||
|
||||
var $parent = $(this);
|
||||
|
||||
function onManageVstSelected() {
|
||||
var $li = $(this);
|
||||
var vstOperation = $li.attr('data-manage-vst-option');
|
||||
|
||||
close();
|
||||
$parent.triggerHandler(context.JK.EVENTS.VST_OPERATION_SELECTED, {vstOperation: vstOperation});
|
||||
return false;
|
||||
};
|
||||
|
||||
// if the user goes into the bubble, remove
|
||||
function waitForBubbleHover($bubble) {
|
||||
$bubble.hoverIntent({
|
||||
over: function() {
|
||||
if(timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
},
|
||||
out: function() {
|
||||
$parent.btOff();
|
||||
}});
|
||||
}
|
||||
|
||||
var timeout = null;
|
||||
|
||||
context.JK.hoverBubble($parent, $('#template-manage-vsts').html(), {
|
||||
trigger:'none',
|
||||
cssClass: 'manage-vsts-popup',
|
||||
spikeGirth:0,
|
||||
spikeLength:0,
|
||||
width:190,
|
||||
closeWhenOthersOpen: true,
|
||||
offsetParent: $parent.closest('.dialog'),
|
||||
positions:['bottom'],
|
||||
preShow: function() {
|
||||
},
|
||||
postShow:function(container) {
|
||||
$(container).find('li').click(onManageVstSelected)
|
||||
if(timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
waitForBubbleHover($(container))
|
||||
timeout = setTimeout(function() {$parent.btOff()}, 3000)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
|
||||
|
||||
// creates an iconic/graphical instrument selector. useful when there is minimal real-estate
|
||||
|
||||
$.fn.trackEffects = function(options) {
|
||||
|
||||
return this.each(function(index) {
|
||||
|
||||
function close() {
|
||||
$parent.btOff();
|
||||
$parent.focus();
|
||||
}
|
||||
|
||||
var $parent = $(this);
|
||||
|
||||
function onOptionSelected() {
|
||||
var $li = $(this);
|
||||
var vstOperation = $li.attr('data-manage-vst-option');
|
||||
|
||||
close();
|
||||
$parent.triggerHandler(context.JK.EVENTS.VST_EFFECT_SELECTED, {vstOperation: vstOperation});
|
||||
return false;
|
||||
};
|
||||
|
||||
// if the user goes into the bubble, remove
|
||||
function waitForBubbleHover($bubble) {
|
||||
$bubble.hoverIntent({
|
||||
over: function() {
|
||||
if(timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
},
|
||||
out: function() {
|
||||
$parent.btOff();
|
||||
}});
|
||||
}
|
||||
|
||||
var timeout = null;
|
||||
|
||||
context.JK.hoverBubble($parent, $('#template-vst-effects').html(), {
|
||||
trigger:'none',
|
||||
cssClass: 'vst-effects-popup',
|
||||
spikeGirth:0,
|
||||
spikeLength:0,
|
||||
width:220,
|
||||
closeWhenOthersOpen: true,
|
||||
offsetParent: $parent.closest('.screen'),
|
||||
positions:['bottom'],
|
||||
preShow: function() {
|
||||
|
||||
},
|
||||
postShow:function(container) {
|
||||
if (options && options['postShow']) {
|
||||
options['postShow']($(container))
|
||||
}
|
||||
$(container).find('li').click(onOptionSelected)
|
||||
if(timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
waitForBubbleHover($(container))
|
||||
timeout = setTimeout(function() {$parent.btOff()}, 3000)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
})(window, jQuery);
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
//= require ./react-components/stores/SessionStore
|
||||
//= require ./react-components/stores/SessionStatsStore
|
||||
//= require ./react-components/stores/MixerStore
|
||||
//= require ./react-components/stores/ConfigureTracksStore
|
||||
//= require ./react-components/stores/JamTrackStore
|
||||
//= require ./react-components/stores/SessionNotificationStore
|
||||
//= require ./react-components/stores/MediaPlaybackStore
|
||||
|
|
|
|||
|
|
@ -0,0 +1,419 @@
|
|||
context = window
|
||||
ConfigureTracksStore = @ConfigureTracksStore
|
||||
@ConfigureLiveTracksDialog = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@ConfigureTracksStore,"onConfigureTracksChanged"), Reflux.listenTo(@AppStore, "onAppInit")]
|
||||
|
||||
onConfigureTracksChanged:(configureTracks) ->
|
||||
@setState({configureTracks: configureTracks})
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
getInitialState: () ->
|
||||
{configureTracks: null, midiInterface: null}
|
||||
|
||||
renderAudio: () ->
|
||||
inputOneOptions = []
|
||||
inputTwoOptions = []
|
||||
|
||||
defaultSelectionOne = `<option value="">Select an input port for this track (required)</option>`
|
||||
defaultSelectionTwo = `<option value="">Select an input port for this track (optional)</option>`
|
||||
|
||||
inputOneOptions.push(defaultSelectionOne)
|
||||
inputTwoOptions.push(defaultSelectionTwo)
|
||||
inputOneValue = ''
|
||||
inputTwoValue = ''
|
||||
selectedInstrument = ''
|
||||
selectedVst = 'NONE'
|
||||
|
||||
|
||||
instruments = []
|
||||
instruments.push(`<option value="">Select the instrument for this track</option>`)
|
||||
for displayName, value of context.JK.server_to_client_instrument_map
|
||||
instruments.push(`<option value={value.server_id}>{displayName}</option>`)
|
||||
|
||||
vsts = []
|
||||
|
||||
instrumentDisabled = true
|
||||
vstDisabled = true
|
||||
|
||||
|
||||
if @state.configureTracks?
|
||||
|
||||
if @state.configureTracks.scanningVsts
|
||||
scan =
|
||||
`<div className="vstScan">
|
||||
<div className="spinner-small"></div><span>Scanning your system<br/>for VST & AU plug-ins...</span>
|
||||
</div>`
|
||||
|
||||
selectedInstrument = @state.configureTracks.editingTrack.instrument_id if @state.configureTracks.editingTrack.instrument_id?
|
||||
|
||||
if @state.configureTracks.editingTrack.length == 1
|
||||
input = @state.configureTracks.editingTrack[0]
|
||||
if input.number == 0
|
||||
inputOneValue = input.id
|
||||
else
|
||||
inputTwoValue = input.id
|
||||
|
||||
if @state.configureTracks.editingTrack.length > 1
|
||||
inputOneValue = @state.configureTracks.editingTrack[0].id
|
||||
inputTwoValue = @state.configureTracks.editingTrack[1].id
|
||||
|
||||
instrumentDisabled = @state.configureTracks.editingTrack.length == 0
|
||||
vstDisabled = @state.configureTracks.editingTrack.length == 0
|
||||
|
||||
for input in @state.configureTracks.musicPorts.inputs
|
||||
|
||||
include = false
|
||||
# we need to see that this input is unassigned, or one of the two selected
|
||||
for unassignedInputs in @state.configureTracks.trackAssignments.inputs.unassigned
|
||||
if unassignedInputs.id == input.id
|
||||
include = true
|
||||
break
|
||||
|
||||
if !include
|
||||
# not see if it's the currently edited track
|
||||
for currentInput in @state.configureTracks.editingTrack
|
||||
if currentInput.id == input.id
|
||||
include = true
|
||||
|
||||
if include
|
||||
item = `<option value={input.id}>{input.name}</option>`
|
||||
inputOneOptions.push(item)
|
||||
inputTwoOptions.push(item)
|
||||
|
||||
|
||||
for plugin in @state.configureTracks.vstPluginList.vsts
|
||||
if plugin.isInstrument == false && plugin.category == 'Effect'
|
||||
vsts.push(`<option value={plugin.file}>{plugin.name} by {plugin.manuf}</option>`)
|
||||
else if plugin.category == 'NONE'
|
||||
vsts.push(`<option value={plugin.file}>No VST/AU plugin selected</option>`)
|
||||
|
||||
if @state.configureTracks.editingTrack.vst?
|
||||
vstAssignedThisTrack = true
|
||||
selectedVst = @state.configureTracks.editingTrack.vst.file
|
||||
|
||||
vstSettingBtnClasses = classNames({'button-orange': vstAssignedThisTrack, 'button-grey': !vstAssignedThisTrack})
|
||||
`<div className="audio">
|
||||
<div className="audio-input-ports">
|
||||
<h3>Audio Input Ports</h3>
|
||||
<p>Select one or two inputs ports to assign to this track. Note that if you assign a single input port, the app will automatically duplicate this port into a stereo track.</p>
|
||||
<select className="input-one" name="input-one" onChange={this.inputChanged} value={inputOneValue}>
|
||||
{inputOneOptions}
|
||||
</select>
|
||||
<select className="input-two" name="input-two" onChange={this.inputChanged} value={inputTwoValue}>
|
||||
{inputTwoOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div className="instrument-selection">
|
||||
<h3>Instrument</h3>
|
||||
<select className="instrument-pick" name="instrument" onChange={this.instrumentSelected} value={selectedInstrument} disabled={instrumentDisabled}>
|
||||
{instruments}
|
||||
</select>
|
||||
</div>
|
||||
<div className="audio-effects">
|
||||
<h3>Audio Effects (optional)</h3>
|
||||
<select className="vsts" name="vsts" onChange={this.vstsChanged} value={selectedVst} disabled={vstDisabled}>
|
||||
{vsts}
|
||||
</select>
|
||||
<a className="manage-audio-plugins" onClick={this.manageAudioPlugins}>manage audio plugins <div className="down-arrow"></div></a>
|
||||
<div className="settings-holder">
|
||||
<a onClick={this.vstSettings} className={vstSettingBtnClasses}>SETTINGS . . .</a>
|
||||
</div>
|
||||
{scan}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
renderMidi: () ->
|
||||
midiInterfaces = []
|
||||
midiInterfaces.push(`<option value="">Select a MIDI interface</option>`)
|
||||
midiInstruments = []
|
||||
|
||||
instruments = []
|
||||
for displayName, value of context.JK.server_to_client_instrument_map
|
||||
instruments.push(`<option value={value.server_id}>{displayName}</option>`)
|
||||
|
||||
selectedMidiInterface = ''
|
||||
selectedInstrument = context.JK.client_to_server_instrument_map[50].server_id # default to electric guitar
|
||||
selectedMidiInstrument = ''
|
||||
|
||||
instrumentDisabled = true
|
||||
midiInstrumentDisabled = true
|
||||
vstAssignedThisTrack = false
|
||||
|
||||
if @state.configureTracks?
|
||||
|
||||
logger.debug("current midi device: " + @state.configureTracks.editingTrack.midiDeviceIndex)
|
||||
selectedMidiInterface = @state.configureTracks.editingTrack.midiDeviceIndex
|
||||
|
||||
selectedInstrument = @state.configureTracks.editingTrack.instrument_id if @state.configureTracks.editingTrack.instrument_id?
|
||||
instrumentDisabled = !@state.midiInterface? || !selectedMidiInterface?
|
||||
midiInstrumentDisabled = !@state.midiInterface? || !selectedMidiInterface?
|
||||
midiInstrumentDisabled = false
|
||||
instrumentDisabled = false
|
||||
|
||||
if @state.configureTracks.editingTrack.vst?
|
||||
vstAssignedThisTrack = true
|
||||
selectedMidiInstrument = @state.configureTracks.editingTrack.vst.file
|
||||
vstSettingBtnClasses = classNames({'button-orange': vstAssignedThisTrack, 'button-grey': !vstAssignedThisTrack})
|
||||
|
||||
for midiDevice in @state.configureTracks.attachedMidiDevices.midiDevices
|
||||
midiInterfaces.push(`<option value={midiDevice.deviceIndex}>{midiDevice.deviceName}</option>`)
|
||||
|
||||
for plugin in @state.configureTracks.vstPluginList.vsts
|
||||
if plugin.isInstrument == true
|
||||
midiInstruments.push(`<option value={plugin.file}>{plugin.name} by {plugin.manuf}</option>`)
|
||||
else if plugin.category == 'NONE'
|
||||
midiInstruments.push(`<option value={plugin.file}>Select a VST or AU instrument</option>`)
|
||||
|
||||
`<div className="midi">
|
||||
<div className="midi-interface">
|
||||
<h3>MIDI Interface</h3>
|
||||
<select className="midi-select" name="midi-select" onChange={this.midiInterfaceChanged} value={selectedMidiInterface}>
|
||||
{midiInterfaces}
|
||||
</select>
|
||||
<a className="scan-midi" onClick={this.scanMidi}>scan for connected MIDI interfaces</a>
|
||||
</div>
|
||||
<div className="instrument-selection">
|
||||
<h3>Instrument</h3>
|
||||
<select className="instrument-pick" name="instrument" onChange={this.instrumentSelected} value={selectedInstrument} disabled={instrumentDisabled}>
|
||||
{instruments}
|
||||
</select>
|
||||
</div>
|
||||
<div className="midi-instrument">
|
||||
<h3>MIDI Instrument (VST or AU Plugin)</h3>
|
||||
<select className="vsts" name="midi-instrument" onChange={this.vstsChanged} value={selectedMidiInstrument} disabled={midiInstrumentDisabled}>
|
||||
{midiInstruments}
|
||||
</select>
|
||||
<a className="manage-audio-plugins" onClick={this.manageAudioPlugins}>manage audio plugins <div className="down-arrow"></div></a>
|
||||
<div className="settings-holder">
|
||||
<a onClick={this.vstSettings} className={vstSettingBtnClasses}>SETTING . . .</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
render: () ->
|
||||
|
||||
action = 'ADD TRACK'
|
||||
header = 'add track'
|
||||
|
||||
isAudio = !@state.configureTracks? || @state.configureTracks.trackType == 'audio'
|
||||
isMidi = !isAudio
|
||||
|
||||
if isAudio
|
||||
activeElement = @renderAudio()
|
||||
else
|
||||
activeElement = @renderMidi()
|
||||
|
||||
if !@state.configureTracks?.newTrack
|
||||
action = 'CLOSE'
|
||||
header = 'update track'
|
||||
else
|
||||
cancelBtn = `<a onClick={this.onCancel} className="button-grey">CANCEL</a>`
|
||||
|
||||
`<div>
|
||||
<div className="content-head">
|
||||
<img className="content-icon" src="/assets/content/icon_add.png" height={19} width={19}/>
|
||||
<h1>{header}</h1>
|
||||
</div>
|
||||
<div className="dialog-inner">
|
||||
<div className="track-type">
|
||||
<h3>Track Type</h3>
|
||||
<div className="track-type-option"><input type="radio" value="audio" name="track-type" checked={isAudio} /><label>Audio</label></div>
|
||||
<div className="track-type-option"><input type="radio" value="midi" name="track-type" checked={isMidi} /><label>MIDI</label></div>
|
||||
</div>
|
||||
|
||||
{activeElement}
|
||||
|
||||
<div className="actions">
|
||||
{cancelBtn}
|
||||
<a onClick={this.doClose} className="button-orange">{action}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
inputChanged: (e) ->
|
||||
$root = $(@getDOMNode())
|
||||
$select1 = $root.find('.input-one')
|
||||
$select2 = $root.find('.input-two')
|
||||
|
||||
audioInput1 = $select1.val()
|
||||
audioInput2 = $select2.val()
|
||||
|
||||
if audioInput1 == ''
|
||||
audioInput1 = null
|
||||
|
||||
if audioInput2 == ''
|
||||
audioInput2 = null
|
||||
|
||||
if audioInput1? && audioInput1 == audioInput2
|
||||
e.preventDefault()
|
||||
# TODO: tell user they can't do this
|
||||
return
|
||||
|
||||
ConfigureTracksActions.associateInputsWithTrack(audioInput1, audioInput2)
|
||||
|
||||
vstsChanged: (e) ->
|
||||
$root = $(@getDOMNode())
|
||||
$select = $root.find('select.vsts')
|
||||
vstSelected = $select.val()
|
||||
if vstSelected != 'NONE'
|
||||
vstSelected = {file: vstSelected}
|
||||
|
||||
if @state.configureTracks?.trackType == 'midi'
|
||||
@updateMidiAssociations()
|
||||
else
|
||||
ConfigureTracksActions.associateVSTWithTrack(vstSelected)
|
||||
|
||||
|
||||
@setState({midiInterface: null})
|
||||
|
||||
instrumentSelected: (e) ->
|
||||
$root = $(@getDOMNode())
|
||||
$select = $root.find('.instrument-pick')
|
||||
|
||||
instrumentId = $select.val()
|
||||
ConfigureTracksActions.associateInstrumentWithTrack(instrumentId)
|
||||
|
||||
|
||||
doClose: (e) ->
|
||||
e.preventDefault()
|
||||
# check that instrument is selected
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$instrument = $root.find('.instrument-pick')
|
||||
|
||||
instrumentId = $instrument.val()
|
||||
|
||||
$select1 = $root.find('.input-one')
|
||||
$select2 = $root.find('.input-two')
|
||||
|
||||
audioInput1 = $select1.val()
|
||||
audioInput2 = $select2.val()
|
||||
|
||||
if audioInput1 == ''
|
||||
audioInput1 = null
|
||||
|
||||
if audioInput2 == ''
|
||||
audioInput2 = null
|
||||
|
||||
if audioInput1 == null && audioInput2 == null
|
||||
context.JK.Banner.showAlert("At least one input must be specified.")
|
||||
return
|
||||
|
||||
if instrumentId == null || instrumentId == ''
|
||||
context.JK.Banner.showAlert("Please select an instrument.")
|
||||
return
|
||||
|
||||
@app.layout.closeDialog('configure-live-tracks-dialog', false)
|
||||
|
||||
onCancel: (e) ->
|
||||
|
||||
ConfigureTracksActions.cancelEdit()
|
||||
|
||||
@app.layout.closeDialog('configure-live-tracks-dialog', true)
|
||||
|
||||
vstSettings: (e) ->
|
||||
e.preventDefault()
|
||||
ConfigureTracksActions.showVstSettings()
|
||||
|
||||
|
||||
componentDidMount: () ->
|
||||
$root = $(@getDOMNode())
|
||||
$radio = context.JK.checkbox($root.find('input[type="radio"]'))
|
||||
$radio.on("ifChanged", @trackTypeChanged);
|
||||
|
||||
componentWillUpdate: () ->
|
||||
@ignoreICheck = true
|
||||
$root = $(@getDOMNode())
|
||||
$radio = $root.find('input[type="radio"]')
|
||||
#$radio.iCheck('enable')
|
||||
$radio.iCheck('enable')
|
||||
|
||||
componentDidUpdate: () ->
|
||||
$root = $(@getDOMNode())
|
||||
$radio = $root.find('input[type="radio"]')
|
||||
$radio = context.JK.checkbox($root.find('input[type="radio"]'))
|
||||
$radio.on("ifChanged", @trackTypeChanged);
|
||||
if @state.configureTracks.editingTrack.assignment == 1
|
||||
$radio.iCheck('disable')
|
||||
else
|
||||
$radio.iCheck('enable')
|
||||
|
||||
@ignoreICheck = false
|
||||
|
||||
$manageAudioPlugins = $root.find('.manage-audio-plugins')
|
||||
|
||||
unless $manageAudioPlugins.data('initialized')
|
||||
$manageAudioPlugins.manageVsts().on(context.JK.EVENTS.VST_OPERATION_SELECTED, @vstOperation).data('initialized', true)
|
||||
|
||||
trackTypeChanged: (event) ->
|
||||
|
||||
if @ignoreICheck
|
||||
logger.debug("ignoring track type changed")
|
||||
return
|
||||
|
||||
$checkedType = $(event.target);
|
||||
value = $checkedType.val()
|
||||
logger.debug("trackTypeChanged: " + value, $checkedType)
|
||||
ConfigureTracksActions.desiredTrackType(value)
|
||||
#@setState({trackType: value})
|
||||
|
||||
vstOperation: (e, data) ->
|
||||
|
||||
if data.vstOperation == 'scan'
|
||||
ConfigureTracksActions.vstScan()
|
||||
else if data.vstOperation == 'clear'
|
||||
ConfigureTracksActions.clearVsts()
|
||||
|
||||
manageAudioPlugins: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$manageAudioPlugins = $root.find('.manage-audio-plugins')
|
||||
$manageAudioPlugins.btOn()
|
||||
|
||||
scanMidi: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
ConfigureTracksActions.midiScan()
|
||||
|
||||
|
||||
midiInterfaceChanged: (e) ->
|
||||
|
||||
@updateMidiAssociations()
|
||||
|
||||
updateMidiAssociations: (e) ->
|
||||
$root = $(@getDOMNode())
|
||||
$select = $root.find('select.midi-select')
|
||||
midiInterface = $select.val()
|
||||
|
||||
$select = $root.find('select.vsts')
|
||||
vstSelected = $select.val()
|
||||
|
||||
logger.debug("updateMidiAssocations", vstSelected, midiInterface)
|
||||
if vstSelected != 'NONE'
|
||||
vstSelected = {file: vstSelected}
|
||||
else
|
||||
vstSelected = null
|
||||
|
||||
if midiInterface == ''
|
||||
midiInterface = null
|
||||
|
||||
midi = @state.midiInterface || midiInterface
|
||||
|
||||
if vstSelected? && midi?
|
||||
logger.debug("updating midi:#{midi} & vst: #{vstSelected.file}")
|
||||
|
||||
ConfigureTracksActions.associateVSTWithTrack(vstSelected)
|
||||
setTimeout((() =>
|
||||
ConfigureTracksActions.associateMIDIWithTrack(midi)
|
||||
), 250)
|
||||
|
||||
else if midi?
|
||||
logger.debug("updating midi:#{midiInterface}")
|
||||
ConfigureTracksActions.associateMIDIWithTrack(midiInterface)
|
||||
|
||||
@setState({midiInterface: midiInterface})
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
context = window
|
||||
ConfigureTracksStore = @ConfigureTracksStore
|
||||
@ConfigureOutputsDialog = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@ConfigureTracksStore, "onConfigureTracksChanged"), Reflux.listenTo(@AppStore, "onAppInit")]
|
||||
|
||||
onConfigureTracksChanged: (configureTracks) ->
|
||||
@setState({configureTracks: configureTracks})
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
getInitialState: () ->
|
||||
{configureTracks: null}
|
||||
|
||||
render: () ->
|
||||
|
||||
outputs = []
|
||||
outputs.push(`<option value="">Select an output port for session audio</option>`)
|
||||
|
||||
if @state.configureTracks?
|
||||
for output in @state.configureTracks.musicPorts.outputs
|
||||
outputs.push(`<option value={output.id}>{output.name}</option>`)
|
||||
|
||||
`<div>
|
||||
<div className="content-head">
|
||||
<img className="content-icon" src="/assets/shared/icon_session.png" height={24} width={24}/>
|
||||
<h1>session audio outputs</h1>
|
||||
</div>
|
||||
<div className="dialog-inner">
|
||||
<p>Select two audio output ports that will be used to deliver the stereo audio of your sessions to your headphones or monitor.</p>
|
||||
<select className="output-1" >
|
||||
{outputs}
|
||||
</select>
|
||||
<select className="output-2" >
|
||||
{outputs}
|
||||
</select>
|
||||
<div className="actions">
|
||||
<a onClick={this.onCancel} className="button-grey">CANCEL</a>
|
||||
<a onClick={this.onClose} className="button-orange">UPDATE PORTS</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
componentDidUpdate: () ->
|
||||
$root = $(@getDOMNode())
|
||||
$output1 = $root.find('.output-1')
|
||||
$output2 = $root.find('.output-2')
|
||||
|
||||
if @state.configureTracks? && @state.configureTracks.trackAssignments.outputs.assigned.length == 2
|
||||
|
||||
output1 = @state.configureTracks.trackAssignments.outputs.assigned[0].id
|
||||
output2 = @state.configureTracks.trackAssignments.outputs.assigned[1].id
|
||||
|
||||
$output1.val(output1)
|
||||
$output2.val(output2)
|
||||
|
||||
onClose: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
$root = $(@getDOMNode())
|
||||
$output1 = $root.find('.output-1')
|
||||
$output2 = $root.find('.output-2')
|
||||
|
||||
output1 = $output1.val()
|
||||
output2 = $output2.val()
|
||||
|
||||
if output1 == null || output1 == ''
|
||||
context.JK.Banner.showAlert("Both output ports must have a selection.")
|
||||
return
|
||||
|
||||
if output2 == null || output2 == ''
|
||||
context.JK.Banner.showAlert("Both output ports must have a selection.")
|
||||
return
|
||||
|
||||
if output1? && output1 != '' && output1 == output2
|
||||
context.JK.Banner.showAlert("Both output ports can not be the same.")
|
||||
return
|
||||
|
||||
ConfigureTracksActions.updateOutputs(output1, output2)
|
||||
|
||||
@app.layout.closeDialog('configure-outputs-dialog', false)
|
||||
|
||||
onCancel: (e) ->
|
||||
|
||||
@app.layout.closeDialog('configure-outputs-dialog', true)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup
|
||||
ASSIGNMENT = context.JK.ASSIGNMENT
|
||||
VOICE_CHAT = context.JK.VOICE_CHAT
|
||||
MAX_TRACKS = context.JK.MAX_TRACKS
|
||||
MAX_OUTPUTS = context.JK.MAX_OUTPUTS
|
||||
gearUtils = context.JK.GearUtils
|
||||
|
||||
@ConfigureTracks = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@ConfigureTracksStore,"onConfigureTracksChanged")]
|
||||
|
||||
getInitialState: () ->
|
||||
{configureTracks: null}
|
||||
|
||||
onConfigureTracksChanged: (configureTracks) ->
|
||||
@setState({configureTracks: configureTracks})
|
||||
|
||||
render: () ->
|
||||
|
||||
liveTracks = []
|
||||
outputs = []
|
||||
|
||||
trackAssignments = @state.configureTracks?.trackAssignments
|
||||
|
||||
if trackAssignments
|
||||
|
||||
for inputsForTrack in trackAssignments.inputs.assigned
|
||||
candidate = inputsForTrack[0]
|
||||
|
||||
inputs = []
|
||||
for input in inputsForTrack
|
||||
inputs.push(`<div className="live-input">{input.name}</div>`)
|
||||
|
||||
if !inputsForTrack.instrument_id?
|
||||
instrument = `<span className="none">?</span>`
|
||||
else
|
||||
instrument = `<span><img src={context.JK.getInstrumentIconMap24()[inputsForTrack.instrument_id].asset} /></span>`
|
||||
|
||||
trackTypeLabel = 'AUDIO'
|
||||
|
||||
vstName = 'None'
|
||||
if inputsForTrack.vst? && inputsForTrack.vst != 'NONE'
|
||||
vstName = "#{inputsForTrack.vst.name} by #{inputsForTrack.vst.manuf}"
|
||||
|
||||
liveTracks.push(
|
||||
`<div key={candidate.assignment} className="live-track">
|
||||
<div className={classNames({'input-track-info': true, one: inputsForTrack.length == 1, two: inputsForTrack.length == 2})}><span className="assignment">{candidate.assignment}:</span><span className="track-type-label">{trackTypeLabel}</span>{inputs}</div>
|
||||
<div className="plugin-info">{vstName}</div>
|
||||
<div className="plugin-instrument">{instrument}</div>
|
||||
<div className="live-track-actions">
|
||||
<a className="update-live-track" onClick={this.onUpdateLiveTrack.bind(this, inputsForTrack)}>update</a>
|
||||
<a className="delete-live-track" onClick={this.onDeleteLiveTrack.bind(this, inputsForTrack)}>delete</a>
|
||||
</div>
|
||||
</div>`)
|
||||
|
||||
for output, i in trackAssignments.outputs.assigned
|
||||
outputs.push(
|
||||
`<div key={output.id} className="output-track">
|
||||
<div className="output-track-info"><span className="assignment">{i + 1}:</span><div className="output">{output.name}</div></div>
|
||||
</div>`)
|
||||
|
||||
`<div className="ConfigureTracks">
|
||||
<select className="certified-audio-profile" style={{display:'none'}}></select>
|
||||
<div className="inputs-view">
|
||||
<div>
|
||||
<h3 className="session-audio-inputs-header">Session Audio Inputs (Live Performance Tracks)</h3>
|
||||
<h3 className="plugin-header">Plugin</h3>
|
||||
<h3 className="instrument-header">Instrument</h3>
|
||||
</div>
|
||||
<div className="live-tracks">
|
||||
{liveTracks}
|
||||
</div>
|
||||
<div className="add-track-action">
|
||||
<a onClick={this.openLiveTrackDialog} className="button-orange">ADD TRACK . . . </a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="outputs-view">
|
||||
<div>
|
||||
<h3 className="session-audio-outputs-header">Session Audio Outputs (Requires 2 Ports)</h3>
|
||||
<div className="output-tracks">
|
||||
{outputs}
|
||||
</div>
|
||||
<a onClick={this.openOutputTrackDialog} className="button-orange">UPDATE OUTPUTS . . . </a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="clearall"></div>
|
||||
</div>`
|
||||
|
||||
onUpdateLiveTrack:(liveTrack, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
ConfigureTracksActions.showEditTrack(liveTrack.assignment)
|
||||
|
||||
onDeleteLiveTrack:(liveTrack, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
if liveTrack.assignment == 1
|
||||
# can't delete the last assignment
|
||||
context.JK.Banner.showAlert('You can not delete the 1st audio track.')
|
||||
else
|
||||
context.JK.Banner.showYesNo({
|
||||
title: "Confirm Deletion",
|
||||
html: "Are you sure you want to delete this live track?",
|
||||
yes: =>
|
||||
ConfigureTracksActions.deleteTrack(liveTrack.assignment)
|
||||
})
|
||||
|
||||
|
||||
openLiveTrackDialog: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
ConfigureTracksActions.showAddNewTrack()
|
||||
|
||||
openOutputTrackDialog: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
ConfigureTracksActions.showEditOutputs()
|
||||
})
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
context = window
|
||||
|
||||
MixerActions = @MixerActions
|
||||
ConfigureTracksActions = @ConfigureTracksActions
|
||||
|
||||
@SessionMyTrack = React.createClass({
|
||||
|
||||
|
|
@ -42,7 +43,9 @@ MixerActions = @MixerActions
|
|||
WebkitTransform: "rotate(#{pan}deg)"
|
||||
}
|
||||
|
||||
# <div className="track-icon-equalizer" />
|
||||
if @props.associatedVst?
|
||||
@equalizerSet = true
|
||||
vst = `<div className="track-icon-equalizer" />`
|
||||
|
||||
`<div className={trackClasses}>
|
||||
<div className="disabled-track-overlay" />
|
||||
|
|
@ -55,11 +58,10 @@ MixerActions = @MixerActions
|
|||
<div className="track-buttons">
|
||||
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
|
||||
<div className="track-icon-pan" style={panStyle}/>
|
||||
{vst}
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
|
||||
|
||||
<br className="clearall"/>
|
||||
</div>
|
||||
</div>`
|
||||
|
|
@ -96,6 +98,8 @@ MixerActions = @MixerActions
|
|||
|
||||
context.JK.helpBubble($root.find('.disabled-track-overlay'), 'missing-my-tracks', {}, {positions:['top'], offsetParent: $root.closest('.top-parent')})
|
||||
|
||||
@initializeVstEffects()
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) ->
|
||||
$root = $(this.getDOMNode())
|
||||
$mute = $root.find('.track-icon-mute')
|
||||
|
|
@ -116,4 +120,32 @@ MixerActions = @MixerActions
|
|||
$mute.on("mouseleave", false)
|
||||
$pan.on("mouseentere", false)
|
||||
$pan.on("mouseleave", false)
|
||||
|
||||
componentDidUpdate:() ->
|
||||
@initializeVstEffects()
|
||||
|
||||
initializeVstEffects: () ->
|
||||
$root = $(this.getDOMNode())
|
||||
$equalizer = $root.find('.track-icon-equalizer')
|
||||
if $equalizer.length > 0 && !$equalizer.data('initialized')
|
||||
logger.debug("initializing trackEffects", $equalizer)
|
||||
$equalizer.trackEffects({postShow: @prepVstEffects}).on(context.JK.EVENTS.VST_EFFECT_SELECTED, @vstOperation).data('initialized', true).click(() =>
|
||||
logger.debug("clicked!")
|
||||
$equalizer.btOn()
|
||||
)
|
||||
prepVstEffects: ($container) ->
|
||||
$container.find('.vst-name').text(@props.associatedVst?.name)
|
||||
|
||||
vstOperation: (e, data) ->
|
||||
logger.debug("track effect selection: " + data.vstOperation)
|
||||
|
||||
if !@props.associatedVst?
|
||||
logger.warn("no associated VST")
|
||||
return
|
||||
|
||||
if data.vstOperation == 'open-vst'
|
||||
ConfigureTracksActions.showVstSettings(@props.associatedVst.track)
|
||||
else
|
||||
ConfigureTracksActions.showEditTrack(@props.associatedVst.track + 1)
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
|
|||
|
||||
@SessionMyTracks = React.createClass({
|
||||
|
||||
mixins: [@SessionMyTracksMixin, Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit")]
|
||||
mixins: [@SessionMyTracksMixin, Reflux.listenTo(@SessionMyTracksStore,"onInputsChanged"), Reflux.listenTo(@AppStore,"onAppInit"), Reflux.listenTo(@ConfigureTracksStore, "onConfigureTracksChanged")]
|
||||
|
||||
goToFtue: (e) ->
|
||||
e.preventDefault()
|
||||
|
|
|
|||
|
|
@ -19,4 +19,5 @@ context = window
|
|||
associateVSTWithTrack: {}
|
||||
associateMIDIWithTrack: {}
|
||||
desiredTrackType: {}
|
||||
vstChanged: {}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,9 +4,21 @@ context = window
|
|||
|
||||
onInputsChanged: (sessionMixers) ->
|
||||
|
||||
@sessionMixers = sessionMixers
|
||||
|
||||
session = sessionMixers.session
|
||||
mixers = sessionMixers.mixers
|
||||
@recompute()
|
||||
|
||||
onConfigureTracksChanged: (configureTracks) ->
|
||||
|
||||
@configureTracks = configureTracks
|
||||
|
||||
@recompute()
|
||||
|
||||
recompute: () ->
|
||||
return if !@sessionMixers?
|
||||
|
||||
session = @sessionMixers.session
|
||||
mixers = @sessionMixers.mixers
|
||||
|
||||
tracks = []
|
||||
|
||||
|
|
@ -38,11 +50,30 @@ context = window
|
|||
instrumentIcon = context.JK.getInstrumentIcon45(track.instrument_id);
|
||||
|
||||
trackName = "#{name}: #{track.instrument}"
|
||||
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, hasMixer:hasMixer, name: name, trackName: trackName, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id})
|
||||
|
||||
associatedVst = null
|
||||
# find any VST info
|
||||
if hasMixer && @configureTracks?
|
||||
|
||||
# bug in the backend; track is wrong for personal mixers (always 1), but correct for master mix
|
||||
trackAssignment = -1
|
||||
if @props.mode == context.JK.MIX_MODES.MASTER
|
||||
trackAssignment = mixerData.mixer.track
|
||||
else
|
||||
trackAssignment = mixerData.oppositeMixer?.track
|
||||
|
||||
console.log("checking associations", @configureTracks.vstTrackAssignments.vsts, mixerData.mixer)
|
||||
for vst in @configureTracks.vstTrackAssignments.vsts
|
||||
if vst.track == trackAssignment - 1 && vst.name != 'NONE'
|
||||
logger.debug("found VST on track", vst, track)
|
||||
associatedVst = vst
|
||||
break
|
||||
|
||||
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, hasMixer:hasMixer, name: name, trackName: trackName, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id, associatedVst: associatedVst})
|
||||
else
|
||||
logger.warn("SessionMyTracks: unable to find participant")
|
||||
|
||||
this.setState(tracks: tracks, session:session, chat: chat)
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,439 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
ASSIGNMENT = context.JK.ASSIGNMENT
|
||||
VOICE_CHAT = context.JK.VOICE_CHAT
|
||||
MAX_TRACKS = context.JK.MAX_TRACKS
|
||||
MAX_OUTPUTS = context.JK.MAX_OUTPUTS
|
||||
gearUtils = context.JK.GearUtils
|
||||
|
||||
###
|
||||
|
||||
QVariantMap scanForPlugins();
|
||||
QVariantMap VSTListVsts();
|
||||
void VSTClearAll();
|
||||
QVariantMap VSTSetTrackAssignment(const QVariantMap vst, const QString& trackId);
|
||||
QVariantMap VSTListTrackAssignments();
|
||||
void VSTShowHideGui(bool show,const QString& trackId);
|
||||
void VST_ScanForMidiDevices();
|
||||
QVariantMap VST_GetMidiDeviceList();
|
||||
bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDeviceIndex);
|
||||
###
|
||||
|
||||
@ConfigureTracksStore = Reflux.createStore(
|
||||
{
|
||||
listenables: ConfigureTracksActions
|
||||
|
||||
musicPorts: {inputs: [], outputs: []}
|
||||
trackNumber: null
|
||||
editingTrack: null
|
||||
vstPluginList: {vsts: []}
|
||||
vstTrackAssignments: {vsts: []}
|
||||
attachedMidiDevices: {midiDevices: []}
|
||||
midiTrackAssignments: {tracks: []}
|
||||
scanningVsts: false
|
||||
trackType: 'audio'
|
||||
|
||||
init: () ->
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
this.listenTo(context.MixerStore, this.onMixersChanged)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
editingTrackValid: () ->
|
||||
true
|
||||
|
||||
onMixersChanged: (mixers) ->
|
||||
@loadChannels()
|
||||
@loadTrackInstruments()
|
||||
@changed()
|
||||
|
||||
onReset: (force) ->
|
||||
logger.debug("ConfigureTracksStore:reset", this)
|
||||
@trackNumber = null
|
||||
@editingTrack = null
|
||||
@loadChannels()
|
||||
@loadTrackInstruments()
|
||||
|
||||
if force || context.jamClient.hasVstAssignment()
|
||||
@performVstScan()
|
||||
@performMidiScan()
|
||||
@changed()
|
||||
|
||||
|
||||
onTrySave: () ->
|
||||
logger.debug("ConfigureTracksStore:trySave")
|
||||
@trySave()
|
||||
|
||||
trySave: () ->
|
||||
|
||||
onVstScan: () ->
|
||||
@performVstScan(true)
|
||||
|
||||
@changed()
|
||||
|
||||
performVstScan: (sendChanged) ->
|
||||
@hasVst = gon.global.vst_enabled & context.jamClient.hasVstHost()
|
||||
logger.debug("hasVst", @hasVst)
|
||||
if @hasVst
|
||||
logger.debug("vstScan starting")
|
||||
@scanningVsts = true
|
||||
result = context.jamClient.VSTScan("window.ConfigureTracksStore.onVstScanComplete")
|
||||
|
||||
onClearVsts: () ->
|
||||
context.jamClient.VSTClearAll()
|
||||
|
||||
setTimeout((() =>
|
||||
@listVsts()
|
||||
|
||||
@changed()
|
||||
), 250)
|
||||
|
||||
onVstScanComplete: () ->
|
||||
# XXX must wait a long time to get track assignments after scan/
|
||||
console.log("vst scan complete")
|
||||
@scanningVsts = false
|
||||
setTimeout((() =>
|
||||
@listVsts()
|
||||
@changed()
|
||||
), 100 )
|
||||
|
||||
onVstChanged: () ->
|
||||
setTimeout()
|
||||
logger.debug("vst changed")
|
||||
|
||||
setTimeout((() =>
|
||||
@listVsts()
|
||||
@changed()
|
||||
), 0)
|
||||
|
||||
listVsts: () ->
|
||||
|
||||
@vstPluginList = context.jamClient.VSTListVsts()
|
||||
@vstTrackAssignments = context.jamClient.VSTListTrackAssignments()
|
||||
|
||||
console.log("@vstTrackAssignments", @vstTrackAssignments)
|
||||
|
||||
onMidiScan: () ->
|
||||
@performMidiScan()
|
||||
@changed()
|
||||
|
||||
performMidiScan: () ->
|
||||
|
||||
if !@hasVst
|
||||
logger.debug("performMidiScan skipped due to no VST")
|
||||
return
|
||||
context.jamClient.VST_ScanForMidiDevices();
|
||||
@attachedMidiDevices = context.jamClient.VST_GetMidiDeviceList();
|
||||
|
||||
# trackNumber is 0-based, and optional
|
||||
onShowVstSettings: (trackNumber) ->
|
||||
if !@hasVst
|
||||
logger.debug("onShowVstSettings skipped due to no VST")
|
||||
return
|
||||
|
||||
if !trackNumber?
|
||||
trackNumber = @trackNumber - 1 if @trackNumber?
|
||||
|
||||
logger.debug("show VST GUI", trackNumber)
|
||||
|
||||
context.jamClient.VSTShowHideGui(true, trackNumber) if trackNumber?
|
||||
|
||||
changed: () ->
|
||||
@editingTrack = []
|
||||
@editingTrack.assignment = @trackNumber
|
||||
|
||||
if @trackNumber?
|
||||
|
||||
for inputsForTrack in @trackAssignments.inputs.assigned
|
||||
if inputsForTrack.assignment == @trackNumber
|
||||
@editingTrack = inputsForTrack
|
||||
break
|
||||
|
||||
|
||||
# slap on vst, if any, from list of vst assignments
|
||||
for vst in @vstTrackAssignments.vsts
|
||||
if vst.track == @editingTrack.assignment - 1
|
||||
@editingTrack.vst = vst
|
||||
@editingTrack.midiDeviceIndex = vst.midiDeviceIndex
|
||||
break
|
||||
|
||||
for inputsForTrack in @trackAssignments.inputs.assigned
|
||||
if vst.track == inputsForTrack.assignment - 1
|
||||
inputsForTrack.vst = vst
|
||||
|
||||
if @editingTrack.vst?
|
||||
logger.debug("current track has a VST assigned:" + @editingTrack.vst.file)
|
||||
|
||||
logger.debug("trackAssignments:", @trackAssignments)
|
||||
logger.debug("editingTrack:", @editingTrack)
|
||||
|
||||
@item = {
|
||||
musicPorts: @musicPorts,
|
||||
trackAssignments: @trackAssignments,
|
||||
trackNumber: @trackNumber,
|
||||
editingTrack: @editingTrack,
|
||||
vstPluginList: @vstPluginList,
|
||||
vstTrackAssignments: @vstTrackAssignments,
|
||||
attachedMidiDevices: @attachedMidiDevices,
|
||||
nextTrackNumber: @nextTrackNumber,
|
||||
newTrack: @newTrack,
|
||||
midiTrackAssignments: @midiTrackAssignments,
|
||||
scanningVsts: @scanningVsts,
|
||||
trackType: @trackType
|
||||
}
|
||||
|
||||
@trigger(@item)
|
||||
|
||||
loadChannels: (forceInputsToUnassign, inputChannelFilter) ->
|
||||
# inputChannelFilter is an optional argument that is used by the Gear Wizard.
|
||||
# basically, if an input channel isn't in there, it's not going to be displayed
|
||||
@musicPorts = context.jamClient.FTUEGetChannels()
|
||||
|
||||
# let's populate this bad boy
|
||||
@trackAssignments = {inputs: {unassigned: [], assigned: [], chat: []}, outputs: {unassigned: [], assigned: []}}
|
||||
|
||||
nextTrackNumber = 0
|
||||
|
||||
for input in @musicPorts.inputs
|
||||
if input.assignment == ASSIGNMENT.UNASSIGNED
|
||||
@trackAssignments.inputs.unassigned.push(input)
|
||||
else if input.assignment == ASSIGNMENT.CHAT
|
||||
@trackAssignments.inputs.chat.push(input)
|
||||
else
|
||||
nextTrackNumber = input.assignment if input.assignment > nextTrackNumber
|
||||
|
||||
# make sure this assignment isn't already preset (you can have multiple inputs per 'track slot')
|
||||
found = false
|
||||
for assigned in @trackAssignments.inputs.assigned
|
||||
if assigned.assignment == input.assignment
|
||||
assigned.push(input)
|
||||
found = true
|
||||
|
||||
if !found
|
||||
initial = [input]
|
||||
initial.assignment = input.assignment # store the assignment on the array itself, so we don't have to check inside the array for an input's assignment (which will all be the same)
|
||||
@trackAssignments.inputs.assigned.push(initial)
|
||||
for output in @musicPorts.outputs
|
||||
if output.assignment == ASSIGNMENT.OUTPUT
|
||||
@trackAssignments.outputs.assigned.push(output)
|
||||
else
|
||||
@trackAssignments.outputs.unassigned.push(output)
|
||||
|
||||
@nextTrackNumber = nextTrackNumber + 1
|
||||
|
||||
|
||||
loadTrackInstruments: (forceInputsToUnassign) ->
|
||||
for inputsForTrack in @trackAssignments.inputs.assigned
|
||||
|
||||
clientInstrument = context.jamClient.TrackGetInstrument(inputsForTrack.assignment)
|
||||
|
||||
if clientInstrument == 0
|
||||
logger.debug("defaulting track instrument for assignment #{@trackNumber}")
|
||||
# ensure that we always have an instrument set (50 = electric guitar
|
||||
context.jamClient.TrackSetInstrument(inputsForTrack.assignment, 50)
|
||||
clientInstrument = 50
|
||||
|
||||
instrument = context.JK.client_to_server_instrument_map[clientInstrument];
|
||||
|
||||
inputsForTrack.instrument_id = instrument?.server_id
|
||||
|
||||
|
||||
onAssociateInputsWithTrack: (inputId1, inputId2) ->
|
||||
return unless @trackNumber?
|
||||
|
||||
for inputs in @editingTrack
|
||||
context.jamClient.TrackSetAssignment(inputs.id, true, ASSIGNMENT.UNASSIGNED)
|
||||
|
||||
if inputId1?
|
||||
logger.debug("setting input1 #{inputId1} to #{@trackNumber}")
|
||||
context.jamClient.TrackSetAssignment(inputId1, true, @trackNumber)
|
||||
|
||||
if inputId2?
|
||||
logger.debug("setting input2 #{inputId2} to #{@trackNumber}")
|
||||
context.jamClient.TrackSetAssignment(inputId2, true, @trackNumber)
|
||||
|
||||
result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
|
||||
onAssociateInstrumentWithTrack: (instrumentId) ->
|
||||
return unless @trackNumber?
|
||||
|
||||
logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", @trackNumber, instrumentId)
|
||||
|
||||
if instrumentId != null && instrumentId != ''
|
||||
context.jamClient.TrackSetInstrument(@trackNumber, context.JK.instrument_id_to_instrument[instrumentId].client_id)
|
||||
else
|
||||
context.jamClient.TrackSetInstrument(@trackNumber, 0)
|
||||
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
|
||||
|
||||
result = context.jamClient.TrackSaveAssignments()
|
||||
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
|
||||
onAssociateVSTWithTrack: (vst) ->
|
||||
|
||||
if !@hasVst
|
||||
logger.debug("onAssociateVSTWithTrack skipped due to no VST")
|
||||
return
|
||||
|
||||
if vst?
|
||||
logger.debug("associating track:#{@trackNumber - 1} with VST:#{vst.file}")
|
||||
|
||||
found = null
|
||||
for knownVst in @vstPluginList.vsts
|
||||
if knownVst.file == vst.file
|
||||
found = knownVst
|
||||
break
|
||||
if found?
|
||||
context.jamClient.VSTSetTrackAssignment(found, @trackNumber - 1)
|
||||
else
|
||||
logger.error("unable to locate vst for #{vst}")
|
||||
else
|
||||
logger.debug("unassociated track:#{@trackNumber} with VST")
|
||||
# no way to unset VST assignment yet
|
||||
|
||||
setTimeout((() => (
|
||||
@listVsts()
|
||||
|
||||
@changed()
|
||||
)), 250)
|
||||
|
||||
onCancelEdit: () ->
|
||||
if @newTrack
|
||||
for input in @editingTrack
|
||||
context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED)
|
||||
result = context.jamClient.TrackSaveAssignments()
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
else
|
||||
logger.error("unable to process cancel for an existing track")
|
||||
|
||||
onDeleteTrack: (assignment) ->
|
||||
track = null
|
||||
for inputsForTrack in @trackAssignments.inputs.assigned
|
||||
if inputsForTrack.assignment == assignment
|
||||
track = inputsForTrack
|
||||
break
|
||||
|
||||
if track?
|
||||
for input in inputsForTrack
|
||||
context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED)
|
||||
result = context.jamClient.TrackSaveAssignments()
|
||||
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
else
|
||||
logger.error("unable to find track to delete")
|
||||
|
||||
onShowAddNewTrack: () ->
|
||||
|
||||
# check if we have what we need... namely, free ports
|
||||
|
||||
if @trackAssignments.inputs.unassigned.length == 0
|
||||
context.JK.Banner.showAlert('You have no more unassigned input ports.<br/><br/>You can free some up by editing an AUDIO track.')
|
||||
return
|
||||
|
||||
@openLiveTrackDialog(@nextTrackNumber)
|
||||
|
||||
onShowEditTrack: (trackNumber) ->
|
||||
@openLiveTrackDialog(trackNumber)
|
||||
|
||||
openLiveTrackDialog: (trackNumber) ->
|
||||
@trackNumber = trackNumber
|
||||
logger.debug("opening live track dialog for track #{trackNumber}")
|
||||
|
||||
@newTrack = true
|
||||
for inputsForTrack in @trackAssignments.inputs.assigned
|
||||
logger.debug("inputsForTrack.assignment @trackNumber", inputsForTrack.assignment, @trackNumber )
|
||||
if inputsForTrack.assignment == @trackNumber
|
||||
@newTrack = false
|
||||
break
|
||||
|
||||
if @newTrack
|
||||
@trackType = 'audio'
|
||||
else
|
||||
if @trackNumber == 1
|
||||
@trackType = 'audio'
|
||||
else
|
||||
@trackType = 'audio'
|
||||
for trackAssignment in @vstTrackAssignments.vsts
|
||||
if trackAssignment.track == @trackNumber - 1
|
||||
if trackAssignment.midiDeviceIndex > -1
|
||||
logger.debug("editing midi track")
|
||||
@trackType = 'midi'
|
||||
break
|
||||
|
||||
if @newTrack
|
||||
|
||||
assignment = context.jamClient.TrackGetInstrument(@trackNumber)
|
||||
|
||||
if assignment == 0
|
||||
logger.debug("defaulting track instrument for assignment #{@trackNumber}")
|
||||
# ensure that we always have an instrument set (50 = electric guitar
|
||||
context.jamClient.TrackSetInstrument(@trackNumber, 50)
|
||||
|
||||
@performVstScan()
|
||||
@performMidiScan()
|
||||
|
||||
@changed()
|
||||
|
||||
@app.layout.showDialog('configure-live-tracks-dialog')
|
||||
|
||||
onDesiredTrackType: (trackType) ->
|
||||
@trackType = trackType
|
||||
|
||||
if @trackType == 'midi'
|
||||
@trackNumber = 100
|
||||
@changed()
|
||||
|
||||
onUpdateOutputs: (outputId1, outputId2) ->
|
||||
|
||||
context.jamClient.TrackSetAssignment(outputId1, true, ASSIGNMENT.OUTPUT);
|
||||
context.jamClient.TrackSetAssignment(outputId2, true, ASSIGNMENT.OUTPUT);
|
||||
|
||||
result = context.jamClient.TrackSaveAssignments();
|
||||
|
||||
if(!result || result.length == 0)
|
||||
|
||||
else
|
||||
context.JK.Banner.showAlert('Unable to save assignments. ' + result);
|
||||
|
||||
onShowEditOutputs: () ->
|
||||
@app.layout.showDialog('configure-outputs-dialog')
|
||||
|
||||
onAssociateMIDIWithTrack: (midiInterface) ->
|
||||
|
||||
@trackNumber = 100
|
||||
|
||||
if !midiInterface? || midiInterface == ''
|
||||
logger.debug("disabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}")
|
||||
context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, false, 0)
|
||||
else
|
||||
logger.debug("enabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}")
|
||||
context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, true, midiInterface)
|
||||
|
||||
setTimeout((() => (
|
||||
@listVsts()
|
||||
|
||||
@changed()
|
||||
)), 250)
|
||||
|
||||
}
|
||||
)
|
||||
|
|
@ -10,6 +10,7 @@ SessionActions = @SessionActions
|
|||
RecordingActions = @RecordingActions
|
||||
NotificationActions = @NotificationActions
|
||||
VideoActions = @VideoActions
|
||||
ConfigureTracksActions = @ConfigureTracksActions
|
||||
|
||||
@SessionStore = Reflux.createStore(
|
||||
{
|
||||
|
|
@ -733,6 +734,7 @@ VideoActions = @VideoActions
|
|||
@handleAutoOpenJamTrack()
|
||||
|
||||
@watchBackendStats()
|
||||
ConfigureTracksActions.reset(false)
|
||||
)
|
||||
.fail((xhr) =>
|
||||
@updateCurrentSession(null)
|
||||
|
|
|
|||
|
|
@ -733,6 +733,10 @@
|
|||
return date.toLocaleTimeString();
|
||||
}
|
||||
|
||||
context.JK.iconMapBase = function() {
|
||||
return icon_map_base
|
||||
}
|
||||
|
||||
context.JK.formatUtcTime = function(date, change) {
|
||||
if (change) {
|
||||
date.setMinutes(Math.ceil(date.getMinutes() / 30) * 30);
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@
|
|||
}
|
||||
|
||||
function handleNext() {
|
||||
var saved = configureTracksHelper.trySave();
|
||||
/** var saved = configureTracksHelper.trySave();
|
||||
|
||||
if(saved) {
|
||||
context.JK.GA.trackConfigureTracksCompletion(context.JK.detectOS());
|
||||
successfullyAssignedOnce = true;
|
||||
}
|
||||
|
||||
return saved;
|
||||
*/
|
||||
return context.ConfigureTracksStore.editingTrackValid()
|
||||
}
|
||||
|
||||
function newSession() {
|
||||
|
|
@ -38,7 +38,8 @@
|
|||
function beforeShow() {
|
||||
var forceInputsToUnassigned = !successfullyAssignedOnce;
|
||||
|
||||
configureTracksHelper.reset(forceInputsToUnassigned, wizard.getChosenInputs())
|
||||
window.ConfigureTracksActions.reset(false);
|
||||
//configureTracksHelper.reset(forceInputsToUnassigned, wizard.getChosenInputs())
|
||||
}
|
||||
|
||||
function initialize(_$step, _wizard) {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
*= require dialogs/dialog
|
||||
*= require ./iconInstrumentSelect
|
||||
*= require ./muteSelect
|
||||
*= require ./manageVsts
|
||||
*= require ./vstEffects
|
||||
*= require ./metronomePlaybackModeSelect
|
||||
*= require ./terms
|
||||
*= require ./createSession
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
@import "client/common";
|
||||
|
||||
.manage-vsts-popup {
|
||||
.bt-content {
|
||||
height:38px;
|
||||
width:190px;
|
||||
background-color:#333;
|
||||
overflow:auto;
|
||||
border:1px solid #ED3618;
|
||||
text-align:left;
|
||||
font-family: 'Raleway', Arial, Helvetica, sans-serif;
|
||||
ul {
|
||||
@include vertical-align-column;
|
||||
height:100%;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
li {
|
||||
font-size:12px;
|
||||
margin-left:0 !important;
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
@import "client/common";
|
||||
|
||||
.ConfigureTracks {
|
||||
|
||||
.inputs-view {
|
||||
border-width:1px 0;
|
||||
border-color:$ColorText;
|
||||
border-style:solid;
|
||||
padding:20px 0;
|
||||
height:220px;
|
||||
|
||||
.live-tracks {
|
||||
height:165px;
|
||||
overflow:auto;
|
||||
a {
|
||||
margin-left:3px;
|
||||
}
|
||||
}
|
||||
|
||||
.live-input {
|
||||
display:inline-block;
|
||||
&:before {
|
||||
content: '('
|
||||
}
|
||||
&:after {
|
||||
content: ')'
|
||||
}
|
||||
}
|
||||
.live-track {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
a.delete-live-track {
|
||||
margin-left:20px;
|
||||
}
|
||||
.assignment {
|
||||
display:inline-block;
|
||||
width:20px;
|
||||
}
|
||||
|
||||
.input-track-info {
|
||||
@include border_box_sizing;
|
||||
width:60%;
|
||||
display:inline-block;
|
||||
|
||||
&.one {
|
||||
.live-input {
|
||||
width:50%;
|
||||
@include border_box_sizing;
|
||||
}
|
||||
}
|
||||
|
||||
&.two {
|
||||
.live-input {
|
||||
max-width:40%;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@include border_box_sizing;
|
||||
&:nth-of-type(1) {
|
||||
padding-right:5px;
|
||||
}
|
||||
&:nth-of-type(2) {
|
||||
padding-left:5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.track-type-label {
|
||||
display:inline-block;
|
||||
white-space:nowrap;
|
||||
padding-right:7px;
|
||||
}
|
||||
|
||||
.plugin-info {
|
||||
@include border_box_sizing;
|
||||
width:30%;
|
||||
display:inline-block;
|
||||
white-space:nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.plugin-instrument {
|
||||
@include border_box_sizing;
|
||||
width:10%;
|
||||
display:inline-block;
|
||||
text-align:center;
|
||||
|
||||
img {
|
||||
vertical-align:middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.outputs-view {
|
||||
border-width:0 0 1px;
|
||||
border-color:$ColorText;
|
||||
border-style:solid;
|
||||
padding:20px 0;
|
||||
|
||||
.assignment {
|
||||
display:inline-block;
|
||||
width:20px;
|
||||
}
|
||||
|
||||
|
||||
.output-tracks {
|
||||
height:73px;
|
||||
overflow:auto;
|
||||
a {
|
||||
margin-left:3px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.output-track {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.output-track-info {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.output {
|
||||
display:inline-block;
|
||||
margin-bottom:0 !important;
|
||||
&:before {
|
||||
content: '('
|
||||
}
|
||||
&:after {
|
||||
content: ')'
|
||||
}
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
display:inline-block;
|
||||
font-size:14px;
|
||||
margin:0 0 20px;
|
||||
@include border_box_sizing;
|
||||
&.session-audio-inputs-header {
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
width:60%;
|
||||
}
|
||||
|
||||
&.session-audio-outputs-header {
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
width:60%;
|
||||
}
|
||||
|
||||
&.plugin-header {
|
||||
width:30%;
|
||||
}
|
||||
&.instrument-header {
|
||||
width:10%;
|
||||
text-align:center;
|
||||
}
|
||||
}
|
||||
.live-track-actions {
|
||||
display:block;
|
||||
padding-left: 17px;
|
||||
margin-top: 5px;
|
||||
a {
|
||||
font-size:12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
@import "client/common";
|
||||
|
||||
.vst-effects-popup {
|
||||
margin-top: 3px;
|
||||
margin-left: 120px;
|
||||
|
||||
.bt-content {
|
||||
width:220px;
|
||||
background-color:#333;
|
||||
overflow:auto;
|
||||
border:1px solid #ED3618;
|
||||
text-align:left;
|
||||
font-family: 'Raleway', Arial, Helvetica, sans-serif;
|
||||
ul {
|
||||
@include vertical-align-column;
|
||||
height:100%;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
li {
|
||||
font-size:12px;
|
||||
margin-left:0 !important;
|
||||
list-style-type: none;
|
||||
margin-bottom:0 !important;
|
||||
|
||||
padding:7px 0 10px 0;
|
||||
|
||||
.vst-name {
|
||||
text-overflow:ellipsis;
|
||||
overflow:hidden;
|
||||
}
|
||||
&:nth-of-type(1) {
|
||||
|
||||
border-width:0 0 1px 0 !important;
|
||||
border-style:solid !important;;
|
||||
border-color:#ED3618 !important;;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
width: 25%;
|
||||
|
||||
&:nth-of-type(2) {
|
||||
width: 21%;
|
||||
width: 71%;
|
||||
}
|
||||
|
||||
&:nth-of-type(3) {
|
||||
|
|
@ -217,9 +217,64 @@
|
|||
margin-top: 45px;
|
||||
}
|
||||
|
||||
.output-channels, .unassigned-output-channels {
|
||||
.outputs-view {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.inputs-view {
|
||||
padding:0;
|
||||
border-width:0;
|
||||
|
||||
h3.session-audio-inputs-header {
|
||||
font-weight:normal;
|
||||
width:70%;
|
||||
font-size:14px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
h3.plugin-header {
|
||||
width:20%;
|
||||
font-size:14px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
h3.instrument-header {
|
||||
width:10%;
|
||||
font-size:14px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
.input-track-info {
|
||||
width:70%;
|
||||
}
|
||||
|
||||
.plugin-info {
|
||||
width:20%;
|
||||
}
|
||||
|
||||
.plugin-instrument {
|
||||
width:10%;
|
||||
}
|
||||
|
||||
.live-tracks {
|
||||
height:198px;
|
||||
}
|
||||
.live-input {
|
||||
display:block;
|
||||
max-width:90%;
|
||||
&:before {
|
||||
content: ''
|
||||
}
|
||||
&:after {
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
.input-track-info .live-input {
|
||||
padding-left:19px;
|
||||
padding-right:0;
|
||||
}
|
||||
.add-track-action { text-align:center;}
|
||||
}
|
||||
}
|
||||
|
||||
.wizard-step[layout-wizard-step="3"] {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
@import "client/common";
|
||||
|
||||
#configure-live-tracks-dialog {
|
||||
width: 800px;
|
||||
|
||||
.dialog-inner {
|
||||
width:auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.manage-audio-plugins {
|
||||
font-size:12px;
|
||||
}
|
||||
.actions {
|
||||
clear:both;
|
||||
text-align:center;
|
||||
}
|
||||
.track-type {
|
||||
width:100%;
|
||||
@include border_box_sizing;
|
||||
padding:10px;
|
||||
|
||||
.track-type-option {
|
||||
margin-bottom:10px;
|
||||
}
|
||||
label {
|
||||
vertical-align:middle;
|
||||
display:inline-block;
|
||||
margin-left:10px;
|
||||
}
|
||||
.iradio_minimal {
|
||||
vertical-align:middle;
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
.audio-input-ports {
|
||||
width:60%;
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:40px;
|
||||
padding:10px;
|
||||
|
||||
select {
|
||||
width: 90%;
|
||||
@include border_box_sizing;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
p {
|
||||
margin-bottom:10px;
|
||||
line-height:125%;
|
||||
}
|
||||
}
|
||||
|
||||
.audio {
|
||||
.instrument-selection {
|
||||
width:40%;
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:26px;
|
||||
padding:10px;
|
||||
select {
|
||||
width:90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.midi-interface {
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:20px;
|
||||
padding:10px;
|
||||
position:relative;
|
||||
width:50%;
|
||||
|
||||
select {
|
||||
width:80%;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
a {
|
||||
font-size:12px;
|
||||
}
|
||||
}
|
||||
.midi {
|
||||
.instrument-selection {
|
||||
width:50%;
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:26px;
|
||||
padding:10px;
|
||||
select {
|
||||
width:80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.midi-instrument {
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:20px;
|
||||
padding:10px;
|
||||
position:relative;
|
||||
width:50%;
|
||||
clear:both;
|
||||
|
||||
select {
|
||||
width:80%;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.down-arrow {
|
||||
cursor:pointer;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid #fc0;
|
||||
position: relative;
|
||||
top: -8px;
|
||||
right: -125px;
|
||||
}
|
||||
|
||||
.settings-holder {
|
||||
float: right;
|
||||
margin-right: 65px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
.audio-effects {
|
||||
width:40%;
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
margin-bottom:20px;
|
||||
padding:10px;
|
||||
position:relative;
|
||||
|
||||
select {
|
||||
width:90%;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
a.manage-audio-plugins {
|
||||
position:relative;
|
||||
}
|
||||
.down-arrow {
|
||||
cursor:pointer;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 8px solid #fc0;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: -20px;
|
||||
}
|
||||
.settings-holder {
|
||||
right:10%;
|
||||
text-align:right;
|
||||
position:absolute;
|
||||
margin-top: -27px;
|
||||
@include border_box_sizing;
|
||||
padding: 10px 0 10px 10px;
|
||||
}
|
||||
a.button-orange {
|
||||
}
|
||||
}
|
||||
|
||||
.vstScan {
|
||||
|
||||
margin-top:20px;
|
||||
|
||||
.spinner-small {
|
||||
float:left;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size:12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
@import "client/common";
|
||||
|
||||
#configure-outputs-dialog {
|
||||
width: 425px;
|
||||
|
||||
.dialog-inner {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
clear: both;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom:10px;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
|
||||
&.output-1 {
|
||||
margin-bottom:15px;
|
||||
}
|
||||
&.output-2 {
|
||||
margin-bottom:50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
#configure-tracks-dialog {
|
||||
min-height: 700px;
|
||||
max-height: 700px;
|
||||
width:800px;
|
||||
|
||||
&[current-screen="account/audio"] {
|
||||
|
|
@ -120,21 +118,21 @@
|
|||
}
|
||||
|
||||
.buttons {
|
||||
bottom: 25px;
|
||||
position: absolute;
|
||||
right: 25px;
|
||||
left:25px;
|
||||
position:static;
|
||||
margin-top:20px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.btn-add-new-audio-gear {
|
||||
float:left;
|
||||
position:absolute;
|
||||
left:20px;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
float:right;
|
||||
|
||||
}
|
||||
|
||||
.btn-update-settings {
|
||||
float:right;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
script type='text/template' id='template-manage-vsts'
|
||||
ul
|
||||
li data-manage-vst-option="scan"
|
||||
a href='#' scan for new or updated plugins
|
||||
|
||||
li data-manage-vst-option="clear"
|
||||
a href='#' clear plug-in list
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
script type='text/template' id='template-vst-effects'
|
||||
ul
|
||||
li data-manage-vst-option="open-vst"
|
||||
a href='#'
|
||||
| Open
|
||||
span.vst-name
|
||||
|
||||
li data-manage-vst-option="update-track"
|
||||
a href='#' Update Track . . .
|
||||
|
|
@ -20,6 +20,8 @@
|
|||
<%= render "jamServer" %>
|
||||
<%= render "iconInstrumentSelect" %>
|
||||
<%= render "muteSelect" %>
|
||||
<%= render "manageVsts" %>
|
||||
<%= render "vstEffects" %>
|
||||
<%= render "metronome_playback_mode" %>
|
||||
<%= render "clients/wizard/buttons" %>
|
||||
<%= render "clients/wizard/gear/gear_wizard" %>
|
||||
|
|
|
|||
|
|
@ -81,16 +81,7 @@
|
|||
.center
|
||||
%a.button-orange.watch-video{href:'https://www.youtube.com/watch?v=SjMeMZpKNR4', rel:'external'} WATCH VIDEO
|
||||
.wizard-step-column
|
||||
%h2 Unassigned Ports
|
||||
.unassigned-input-channels.channels-holder
|
||||
.wizard-step-column
|
||||
%h2 Track Input Port(s)
|
||||
.tracks
|
||||
.wizard-step-column
|
||||
%h2 Instrument
|
||||
.instruments
|
||||
.output-channels
|
||||
.unassigned-output-channels.channels-holder
|
||||
= react_component 'ConfigureTracks', {}
|
||||
|
||||
.wizard-step{ 'layout-wizard-step' => "3", 'dialog-title' => "Configure Voice Chat", 'dialog-purpose' => "ConfigureVoiceChat" }
|
||||
.ftuesteps
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='configure-live-tracks-dialog' id='configure-live-tracks-dialog'
|
||||
= react_component 'ConfigureLiveTracksDialog', {}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='configure-outputs-dialog' id='configure-outputs-dialog'
|
||||
= react_component 'ConfigureOutputsDialog', {}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
%h1 configure tracks
|
||||
.dialog-inner
|
||||
.dialog-tabs
|
||||
%a.selected.tab-configure-audio Music Audio
|
||||
%a.selected.tab-configure-audio Inputs & Outputs
|
||||
%a.tab-configure-voice Voice Chat
|
||||
|
||||
.instructions
|
||||
|
|
@ -16,32 +16,8 @@
|
|||
|
||||
.tab.no-selection-range{'tab-id' => 'music-audio'}
|
||||
|
||||
.column
|
||||
.certified-audio-profile-section
|
||||
.sub-header Certified Audio Profile
|
||||
%select.certified-audio-profile
|
||||
.clearall
|
||||
= react_component 'ConfigureTracks', {}
|
||||
|
||||
.unused-audio-inputs-section
|
||||
.sub-header Unused Input Ports
|
||||
.unassigned-input-channels.channels-holder
|
||||
|
||||
.unused-audio-outputs-section
|
||||
.sub-header Unused Output Ports
|
||||
.unassigned-output-channels.channels-holder
|
||||
|
||||
.column
|
||||
.input-tracks-section
|
||||
.sub-column
|
||||
.sub-header Track Input Port(s)
|
||||
.input-tracks.tracks
|
||||
.sub-column
|
||||
.sub-header Instrument
|
||||
.instruments
|
||||
|
||||
.output-channels-section
|
||||
.sub-header Audio Output Port
|
||||
.output-channels
|
||||
.clearall
|
||||
|
||||
|
||||
|
|
@ -72,5 +48,6 @@
|
|||
|
||||
.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
|
||||
%a.button-orange.btn-update-settings{href:'#'} SAVE SETTINGS
|
||||
|
||||
|
|
|
|||
|
|
@ -44,3 +44,5 @@
|
|||
= render 'dialogs/recordingSelectorDialog'
|
||||
= render 'dialogs/soundCloudPlayerDialog'
|
||||
= render 'dialogs/deleteVideoConfirmDialog'
|
||||
= render 'dialogs/configureLiveTracksDialog'
|
||||
= render 'dialogs/configureOutputsDialog'
|
||||
|
|
@ -395,5 +395,7 @@ if defined?(Bundler)
|
|||
output_jitter: {warn: 0.5, poor: 1},
|
||||
}
|
||||
}
|
||||
config.vst_enabled = true
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -102,4 +102,6 @@ SampleApp::Application.configure do
|
|||
config.react.variant = :development
|
||||
|
||||
config.time_shift_style = :sox # or sbsms
|
||||
|
||||
config.vst_enabled = true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -22,4 +22,5 @@ Gon.global.jamtrack_landing_bubbles_enabled = Rails.application.config.jamtrack_
|
|||
Gon.global.jamtrack_browser_bubbles_enabled = Rails.application.config.jamtrack_browser_bubbles_enabled
|
||||
Gon.global.bugsnag_key = Rails.application.config.bugsnag_key
|
||||
Gon.global.bugsnag_notify_release_stages = Rails.application.config.bugsnag_notify_release_stages
|
||||
Gon.global.vst_enabled = Rails.application.config.vst_enabled
|
||||
Gon.global.env = Rails.env
|
||||
|
|
|
|||
|
|
@ -95,6 +95,11 @@ namespace :jam_tracks do
|
|||
JamTrackImporter.synchronize_all(skip_audio_upload: false)
|
||||
end
|
||||
|
||||
task sync_tim_tracks: :environment do |task, args|
|
||||
JamTrackImporter.storage_format = 'TimTracks'
|
||||
JamTrackImporter.synchronize_all(skip_audio_upload:false)
|
||||
end
|
||||
|
||||
task tency_dups: :environment do |task, args|
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue