diff --git a/ruby/lib/jam_ruby/jam_track_importer.rb b/ruby/lib/jam_ruby/jam_track_importer.rb
index a92aca61b..0cdf0160f 100644
--- a/ruby/lib/jam_ruby/jam_track_importer.rb
+++ b/ruby/lib/jam_ruby/jam_track_importer.rb
@@ -1352,7 +1352,7 @@ module JamRuby
stripped_time = total_time # default to the case where we just start the preview at the beginning
burp_gaps.each do |gap|
- command_strip_lead_silence = "sox \"#{ogg_44100}\" \"#{out_wav}\" silence 1 #{gap} 1%"
+ command_strip_lead_silence = "sox \"#{ogg_44100}\" \"#{out_wav}\" silence 1 #{gap} 1%"
@@log.debug("stripping silence: " + command_strip_lead_silence)
diff --git a/web/app/assets/javascripts/dialog/configureTrackDialog.js b/web/app/assets/javascripts/dialog/configureTrackDialog.js
index 3b4f478c5..421cb1d3c 100644
--- a/web/app/assets/javascripts/dialog/configureTrackDialog.js
+++ b/web/app/assets/javascripts/dialog/configureTrackDialog.js
@@ -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 window.ConfigureTracksActions.trySave();
+ return true;
}
function showVoiceChatPanel() {
@@ -133,7 +133,7 @@
//});
$btnUpdateTrackSettings.click(function() {
- if(window.ConfigureTracksActions.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() {
diff --git a/web/app/assets/javascripts/globals.js b/web/app/assets/javascripts/globals.js
index c085e548b..86e8972a0 100644
--- a/web/app/assets/javascripts/globals.js
+++ b/web/app/assets/javascripts/globals.js
@@ -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 = {
diff --git a/web/app/assets/javascripts/jquery.manageVsts.js b/web/app/assets/javascripts/jquery.manageVsts.js
new file mode 100644
index 000000000..a14cec2e1
--- /dev/null
+++ b/web/app/assets/javascripts/jquery.manageVsts.js
@@ -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);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/jquery.trackEffects.js b/web/app/assets/javascripts/jquery.trackEffects.js
new file mode 100644
index 000000000..b0a15c74e
--- /dev/null
+++ b/web/app/assets/javascripts/jquery.trackEffects.js
@@ -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);
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components.js b/web/app/assets/javascripts/react-components.js
index a0d400953..75472bb42 100644
--- a/web/app/assets/javascripts/react-components.js
+++ b/web/app/assets/javascripts/react-components.js
@@ -3,12 +3,12 @@
//= require_directory ./react-components/helpers
//= require_directory ./react-components/actions
//= require ./react-components/stores/AppStore
-//= require ./react-components/stores/ConfigureTracksStore
//= require ./react-components/stores/BrowserMediaStore
//= require ./react-components/stores/RecordingStore
//= require ./react-components/stores/VideoStore
//= require ./react-components/stores/SessionStore
//= 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
diff --git a/web/app/assets/javascripts/react-components/ConfigureAudioTrack.js.jsx.coffee b/web/app/assets/javascripts/react-components/ConfigureAudioTrack.js.jsx.coffee
new file mode 100644
index 000000000..e69de29bb
diff --git a/web/app/assets/javascripts/react-components/ConfigureLiveTracksDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/ConfigureLiveTracksDialog.js.jsx.coffee
index 308305446..6fda3639c 100644
--- a/web/app/assets/javascripts/react-components/ConfigureLiveTracksDialog.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/ConfigureLiveTracksDialog.js.jsx.coffee
@@ -2,17 +2,17 @@ context = window
ConfigureTracksStore = @ConfigureTracksStore
@ConfigureLiveTracksDialog = React.createClass({
- mixins: [Reflux.listenTo(@ConfigureTracksStore,"onConfigureTracksChanged")]
+ mixins: [Reflux.listenTo(@ConfigureTracksStore,"onConfigureTracksChanged"), Reflux.listenTo(@AppStore, "onAppInit")]
onConfigureTracksChanged:(configureTracks) ->
@setState({configureTracks: configureTracks})
+ onAppInit: (@app) ->
+
getInitialState: () ->
- {configureTracks: null}
+ {configureTracks: null, midiInterface: null}
- render: () ->
-
- action = 'ADD TRACK'
+ renderAudio: () ->
inputOneOptions = []
inputTwoOptions = []
@@ -21,73 +21,366 @@ ConfigureTracksStore = @ConfigureTracksStore
inputOneOptions.push(defaultSelectionOne)
inputTwoOptions.push(defaultSelectionTwo)
+ inputOneValue = ''
+ inputTwoValue = ''
+ selectedInstrument = ''
+ selectedVst = 'NONE'
+
instruments = []
+ instruments.push(`Select the instrument for this track `)
for displayName, value of context.JK.server_to_client_instrument_map
instruments.push(`{displayName} `)
- if @state.configureTracks?
- for input in @state.configureTracks.musicPorts.inputs
- item = `{input.name} `
- inputOneOptions.push(item)
- inputTwoOptions.push(item)
-
-
- if @state.configureTracks.editingTrack?
- action = 'EDIT TRACK'
-
vsts = []
- vsts.push(`No VST/AU plugin selected `)
- `
-
-
Track Type
-
Audio
-
MIDI
-
+ instrumentDisabled = true
+ vstDisabled = true
+
+ if @state.configureTracks?
+
+ 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 = `
{input.name} `
+ inputOneOptions.push(item)
+ inputTwoOptions.push(item)
+
+
+ for plugin in @state.configureTracks.vstPluginList.vsts
+ if plugin.isInstrument == false && plugin.category == 'Effect'
+ vsts.push(`
{plugin.name} by {plugin.manuf} `)
+ else if plugin.category == 'NONE'
+ vsts.push(`
No VST/AU plugin selected `)
+
+ if @state.configureTracks.editingTrack.vst?
+ vstAssignedThisTrack = true
+ selectedVst = @state.configureTracks.editingTrack.vst.file
+
+ vstSettingBtnClasses = classNames({'button-orange': vstAssignedThisTrack, 'button-grey': !vstAssignedThisTrack})
+ `
Audio Input Ports
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.
-
+
{inputOneOptions}
-
+
{inputTwoOptions}
Instrument
-
+
{instruments}
-
-
`
- cancel: (e) ->
- e.preventDefault()
+ renderMidi: () ->
+ midiInterfaces = []
+ midiInterfaces.push(`
Select a MIDI interface `)
+ midiInstruments = []
- update: (e) ->
+ instruments = []
+ instruments.push(`
Select the instrument for this track `)
+ for displayName, value of context.JK.server_to_client_instrument_map
+ instruments.push(`
{displayName} `)
+
+ selectedMidiInterface = ''
+ selectedInstrument = ''
+ 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(`
{midiDevice.deviceName} `)
+
+ for plugin in @state.configureTracks.vstPluginList.vsts
+ if plugin.isInstrument == true
+ midiInstruments.push(`
{plugin.name} by {plugin.manuf} `)
+ else if plugin.category == 'NONE'
+ midiInstruments.push(`
Select a VST or AU instrument `)
+
+ `
+
+
+
Instrument
+
+ {instruments}
+
+
+
+
`
+
+ 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 = `
CANCEL `
+
+ `
+
+
+
{header}
+
+
+
+
Track Type
+
Audio
+
MIDI
+
+
+ {activeElement}
+
+
+
+
`
+
+ 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?
+ vstSelected = {file: vstSelected}
+
+ ConfigureTracksActions.associateVSTWithTrack(vstSelected)
+
+ if @state.configureTracks?.trackType == 'midi'
+ if @state.midiInterface?
+ ConfigureTracksActions.associateMIDIWithTrack(@state.midiInterface)
+
+
+ @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())
- context.JK.checkbox($root.find('input[type="radio"]'))
+ $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')
+
+ 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) ->
+ $root = $(@getDOMNode())
+ $select = $root.find('select.midi-select')
+ midiInterface = $select.val()
+
+ if midiInterface == ''
+ midiInterface = null
+
+ ConfigureTracksActions.associateMIDIWithTrack(midiInterface)
+
+ @setState({midiInterface: midiInterface})
})
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/ConfigureOutputsDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/ConfigureOutputsDialog.js.jsx.coffee
new file mode 100644
index 000000000..41affdad2
--- /dev/null
+++ b/web/app/assets/javascripts/react-components/ConfigureOutputsDialog.js.jsx.coffee
@@ -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(`
Select an output port for session audio `)
+
+ if @state.configureTracks?
+ for output in @state.configureTracks.musicPorts.outputs
+ outputs.push(`
{output.name} `)
+
+ `
+
+
+
session audio outputs
+
+
+
Select two audio output ports that will be used to deliver the stereo audio of your sessions to your headphones or monitor.
+
+ {outputs}
+
+
+ {outputs}
+
+
+
+
`
+
+ 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)
+ }
+)
diff --git a/web/app/assets/javascripts/react-components/ConfigureTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/ConfigureTracks.js.jsx.coffee
index e6256f4f3..16d89786a 100644
--- a/web/app/assets/javascripts/react-components/ConfigureTracks.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/ConfigureTracks.js.jsx.coffee
@@ -19,8 +19,6 @@ gearUtils = context.JK.GearUtils
render: () ->
- console.log("@state.configureTracks", @state.configureTracks)
-
liveTracks = []
outputs = []
@@ -40,10 +38,16 @@ gearUtils = context.JK.GearUtils
else
instrument = `
`
+ trackTypeLabel = 'AUDIO'
+
+ vstName = 'None'
+ if inputsForTrack.vst
+ vstName = "#{inputsForTrack.vst.name} by #{inputsForTrack.vst.manuf}"
+
liveTracks.push(
`
-
{candidate.assignment}: {inputs}
-
None
+
{candidate.assignment}: {trackTypeLabel} {inputs}
+
{vstName}
{instrument}
+
`
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()
- context.JK.app.layout.showDialog('configure-live-tracks-dialog')
+ ConfigureTracksActions.showAddNewTrack()
openOutputTrackDialog: (e) ->
e.preventDefault()
- context.JK.app.layout.app.showDialog('configure-output-tracks-dialog')
+ ConfigureTracksActions.showEditOutputs()
})
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee
index e36502a3c..37f8c0a00 100644
--- a/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee
@@ -1,6 +1,7 @@
context = window
MixerActions = @MixerActions
+ConfigureTracksActions = @ConfigureTracksActions
@SessionMyTrack = React.createClass({
@@ -42,7 +43,9 @@ MixerActions = @MixerActions
WebkitTransform: "rotate(#{pan}deg)"
}
- #
+ if @props.associatedVst?
+ @equalizerSet = true
+ vst = `
`
`
@@ -55,11 +58,10 @@ MixerActions = @MixerActions
`
@@ -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)
+
})
diff --git a/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee
index 97323d6f8..017255665 100644
--- a/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/SessionMyTracks.js.jsx.coffee
@@ -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()
diff --git a/web/app/assets/javascripts/react-components/actions/ConfigureTracksActions.js.coffee b/web/app/assets/javascripts/react-components/actions/ConfigureTracksActions.js.coffee
index b4448c579..4a2890385 100644
--- a/web/app/assets/javascripts/react-components/actions/ConfigureTracksActions.js.coffee
+++ b/web/app/assets/javascripts/react-components/actions/ConfigureTracksActions.js.coffee
@@ -3,6 +3,20 @@ context = window
@ConfigureTracksActions = Reflux.createActions({
reset: {}
trySave: {}
+ midiScan: {}
vstScan: {}
vstScanComplete: {}
+ clearVsts: {}
+ cancelEdit: {}
+ deleteTrack: {}
+ updateOutputs: {}
+ showAddNewTrack: {}
+ showEditTrack: {}
+ showEditOutputs: {}
+ showVstSettings: {}
+ associateInputsWithTrack: {}
+ associateInstrumentWithTrack: {}
+ associateVSTWithTrack: {}
+ associateMIDIWithTrack: {}
+ desiredTrackType: {}
})
diff --git a/web/app/assets/javascripts/react-components/mixins/SessionMyTracksMixin.js.coffee b/web/app/assets/javascripts/react-components/mixins/SessionMyTracksMixin.js.coffee
index 9d808485c..858bb8ad7 100644
--- a/web/app/assets/javascripts/react-components/mixins/SessionMyTracksMixin.js.coffee
+++ b/web/app/assets/javascripts/react-components/mixins/SessionMyTracksMixin.js.coffee
@@ -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,21 @@ 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?
+ for vst in @configureTracks.vstTrackAssignments.vsts
+ if vst.track == mixerData.mixer.track - 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)
+
+
}
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee b/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee
index dbcb830dd..eea6c8bd1 100644
--- a/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee
@@ -24,21 +24,39 @@ bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDev
{
listenables: ConfigureTracksActions
- musicPorts: {inputs:[], outputs:[]}
+ musicPorts: {inputs: [], outputs: []}
trackNumber: null
editingTrack: null
+ vstPluginList: {vsts: []}
+ vstTrackAssignments: {vsts: []}
+ attachedMidiDevices: {midiDevices: []}
+ midiTrackAssignments: {tracks: []}
+ 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: () ->
logger.debug("ConfigureTracksStore:reset", this)
@trackNumber = null
@editingTrack = null
@loadChannels()
- @onVstScan()
- @onMidiScan()
+ @loadTrackInstruments()
+ @performVstScan()
+ @performMidiScan()
+ @changed()
onTrySave: () ->
@@ -48,29 +66,88 @@ bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDev
trySave: () ->
onVstScan: () ->
+ @performVstScan(true)
+
+ performVstScan: (sendChanged) ->
@hasVst = context.jamClient.hasVstHost()
logger.debug("hasVst", @hasVst)
if @hasVst
logger.debug("vstScan starting")
- result = context.jamClient.VSTScan()
+ result = context.jamClient.VSTScan("window.ConfigureTracksStore.onVstScanComplete")
logger.debug("vstScan completed", result)
- @vstPluginList = context.jamClient.VSTListVsts()
- @vstTrackAssignments = context.jamClient.VSTListTrackAssignments()
+ onClearVsts: () ->
+ context.jamClient.VSTClearAll()
- console.log("@vstPluginList", @vstPluginList)
- console.log("@vstTrackAssignments", @vstTrackAssignments)
+ setTimeout((() =>
+ @listVsts()
+
+ @changed()
+ ), 250)
+
+ onVstScanComplete: () ->
+ @listVsts()
+ @changed()
+
+
+ listVsts: () ->
+
+ @vstPluginList = context.jamClient.VSTListVsts()
+ @vstTrackAssignments = context.jamClient.VSTListTrackAssignments()
+
+ console.log("@vstTrackAssignments", @vstTrackAssignments)
onMidiScan: () ->
- @attachedMidiDevices = context.jamClient.listAttachedMidiDevices();
+ @performMidiScan()
+ @changed()
- console.log("@attachedMidiDevices", @attachedMidiDevices)
+ performMidiScan: () ->
+ context.jamClient.VST_ScanForMidiDevices();
+ @attachedMidiDevices = context.jamClient.VST_GetMidiDeviceList();
- onShowVstSettings: () ->
- context.jamClient.showHideVstGui(true, @trackNumber) if @trackNumber?
+ # trackNumber is 0-based, and optional
+ onShowVstSettings: (trackNumber) ->
+ if !trackNumber?
+ trackNumber = @trackNumber - 1 if @trackNumber?
+
+ logger.debug("show VST GUI", trackNumber)
+
+ context.jamClient.VSTShowHideGui(true, trackNumber) if trackNumber?
changed: () ->
- @item = {musicPorts: @musicPorts, trackAssignments: @trackAssignments, trackNumber: @trackNumber, editingTrack: @editingTrack}
+ @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
+
+ if @editingTrack.vst?
+ logger.debug("current track has a VST assigned:" + @editingTrack.vst.file)
+
+ @item = {
+ musicPorts: @musicPorts,
+ trackAssignments: @trackAssignments,
+ trackNumber: @trackNumber,
+ editingTrack: @editingTrack,
+ vstPluginList: @vstPluginList,
+ vstTrackAssignments: @vstTrackAssignments,
+ attachedMidiDevices: @attachedMidiDevices,
+ nextTrackNumber: @nextTrackNumber,
+ newTrack: @newTrack,
+ midiTrackAssignments: @midiTrackAssignments,
+ trackType: @trackType
+ }
@trigger(@item)
@@ -80,7 +157,9 @@ bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDev
@musicPorts = context.jamClient.FTUEGetChannels()
# let's populate this bad boy
- @trackAssignments = {inputs: {unassigned:[], assigned:[], chat:[]}, outputs: {unassigned:[], assigned: []}}
+ @trackAssignments = {inputs: {unassigned: [], assigned: [], chat: []}, outputs: {unassigned: [], assigned: []}}
+
+ nextTrackNumber = 0
for input in @musicPorts.inputs
if input.assignment == ASSIGNMENT.UNASSIGNED
@@ -88,6 +167,8 @@ bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDev
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
@@ -105,29 +186,196 @@ bool VST_EnableMidiForTrack(const QString& trackId, bool enableMidi, int midiDev
else
@trackAssignments.outputs.unassigned.push(output)
- @loadTrackInstruments(forceInputsToUnassign)
+ @nextTrackNumber = nextTrackNumber + 1
- @changed()
loadTrackInstruments: (forceInputsToUnassign) ->
for inputsForTrack in @trackAssignments.inputs.assigned
- clientInstrument = context.jamClient.TrackGetInstrument(inputsForTrack[0].assignment)
+ clientInstrument = context.jamClient.TrackGetInstrument(inputsForTrack.assignment)
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 vst?
+ logger.debug("associating track:#{@trackNumber} 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.
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}")
- @editingTrack = null
+ @newTrack = true
for inputsForTrack in @trackAssignments.inputs.assigned
- if inputsForTrack.assignment == trackNumber
- @editingTrack = inputsForTrack
+ 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
+ # ensure that we always have an instrument set (50 = electric guitar
+ context.jamClient.TrackSetInstrument(@trackNumber, 50)
+
@changed()
@app.layout.showDialog('configure-live-tracks-dialog')
+
+ onDesiredTrackType: (trackType) ->
+ @trackType = trackType
+
+ @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) ->
+
+ 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)
+
}
)
\ No newline at end of file
diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
index b0bbb0ac7..08e291141 100644
--- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
+++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee
@@ -10,6 +10,7 @@ SessionActions = @SessionActions
RecordingActions = @RecordingActions
NotificationActions = @NotificationActions
VideoActions = @VideoActions
+ConfigureTracksActions = @ConfigureTracksActions
@SessionStore = Reflux.createStore(
{
@@ -731,6 +732,8 @@ VideoActions = @VideoActions
$(document).trigger(EVENTS.SESSION_STARTED, {session: {id: @currentSessionId}}) if document
@handleAutoOpenJamTrack()
+
+ ConfigureTracksActions.reset()
)
.fail((xhr) =>
@updateCurrentSession(null)
diff --git a/web/app/assets/javascripts/wizard/gear/step_configure_tracks.js b/web/app/assets/javascripts/wizard/gear/step_configure_tracks.js
index 81c330620..e40b81609 100644
--- a/web/app/assets/javascripts/wizard/gear/step_configure_tracks.js
+++ b/web/app/assets/javascripts/wizard/gear/step_configure_tracks.js
@@ -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(forceInputsToUnassigned, wizard.getChosenInputs());
+ //configureTracksHelper.reset(forceInputsToUnassigned, wizard.getChosenInputs())
}
function initialize(_$step, _wizard) {
diff --git a/web/app/assets/stylesheets/client/client.css b/web/app/assets/stylesheets/client/client.css
index 277f98cdb..1c0385193 100644
--- a/web/app/assets/stylesheets/client/client.css
+++ b/web/app/assets/stylesheets/client/client.css
@@ -53,6 +53,8 @@
*= require dialogs/dialog
*= require ./iconInstrumentSelect
*= require ./muteSelect
+ *= require ./manageVsts
+ *= require ./vstEffects
*= require ./metronomePlaybackModeSelect
*= require ./terms
*= require ./createSession
diff --git a/web/app/assets/stylesheets/client/manageVsts.css.scss b/web/app/assets/stylesheets/client/manageVsts.css.scss
new file mode 100644
index 000000000..a7063e390
--- /dev/null
+++ b/web/app/assets/stylesheets/client/manageVsts.css.scss
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/react-components/ConfigureTracks.css.scss b/web/app/assets/stylesheets/client/react-components/ConfigureTracks.css.scss
index f76f8276d..72d90891a 100644
--- a/web/app/assets/stylesheets/client/react-components/ConfigureTracks.css.scss
+++ b/web/app/assets/stylesheets/client/react-components/ConfigureTracks.css.scss
@@ -10,7 +10,7 @@
height:220px;
.live-tracks {
- height:150px;
+ height:165px;
overflow:auto;
a {
margin-left:3px;
@@ -19,6 +19,12 @@
.live-input {
display:inline-block;
+ &:before {
+ content: '('
+ }
+ &:after {
+ content: ')'
+ }
}
.live-track {
margin-bottom:20px;
@@ -36,12 +42,44 @@
@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 {
@@ -88,6 +126,12 @@
.output {
display:inline-block;
margin-bottom:0 !important;
+ &:before {
+ content: '('
+ }
+ &:after {
+ content: ')'
+ }
}
}
h3 {
@@ -117,8 +161,8 @@
}
.live-track-actions {
display:block;
- padding-left:30px;
- margin-top:10px;
+ padding-left: 17px;
+ margin-top: 5px;
a {
font-size:12px;
}
diff --git a/web/app/assets/stylesheets/client/vstEffects.css.scss b/web/app/assets/stylesheets/client/vstEffects.css.scss
new file mode 100644
index 000000000..945e49b10
--- /dev/null
+++ b/web/app/assets/stylesheets/client/vstEffects.css.scss
@@ -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;;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
index 5e6084efc..d7bbb1f80 100644
--- a/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
+++ b/web/app/assets/stylesheets/client/wizard/gearWizard.css.scss
@@ -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"] {
diff --git a/web/app/assets/stylesheets/dialogs/configureLiveTracksDialog.css.scss b/web/app/assets/stylesheets/dialogs/configureLiveTracksDialog.css.scss
index b87510eab..684cd70b3 100644
--- a/web/app/assets/stylesheets/dialogs/configureLiveTracksDialog.css.scss
+++ b/web/app/assets/stylesheets/dialogs/configureLiveTracksDialog.css.scss
@@ -13,6 +13,9 @@
margin-bottom:10px;
}
+ .manage-audio-plugins {
+ font-size:12px;
+ }
.actions {
clear:both;
text-align:center;
@@ -20,7 +23,6 @@
.track-type {
width:100%;
@include border_box_sizing;
- margin-bottom:20px;
padding:10px;
.track-type-option {
@@ -37,7 +39,7 @@
}
}
.audio-input-ports {
- width:50%;
+ width:60%;
@include border_box_sizing;
float:left;
margin-bottom:40px;
@@ -53,18 +55,99 @@
line-height:125%;
}
}
- .instrument-selection {
- width:50%;
- @include border_box_sizing;
- float:left;
- margin-bottom:40px;
- padding:10px;
+
+ .audio {
+ .instrument-selection {
+ width:40%;
+ @include border_box_sizing;
+ float:left;
+ margin-bottom:26px;
+ padding:10px;
+ select {
+ width:90%;
+ }
+ }
}
- .audio-effects {
- width:50%;
+
+ .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;
+ }
+ }
+ .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 {
+ }
}
}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/dialogs/configureOutputsDialog.css.scss b/web/app/assets/stylesheets/dialogs/configureOutputsDialog.css.scss
new file mode 100644
index 000000000..b0e9e28a4
--- /dev/null
+++ b/web/app/assets/stylesheets/dialogs/configureOutputsDialog.css.scss
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss b/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss
index 46b1bd830..aa776ede7 100644
--- a/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss
+++ b/web/app/assets/stylesheets/dialogs/configureTracksDialog.css.scss
@@ -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;
+
}
}
\ No newline at end of file
diff --git a/web/app/views/clients/_manageVsts.html.slim b/web/app/views/clients/_manageVsts.html.slim
new file mode 100644
index 000000000..d78dcc704
--- /dev/null
+++ b/web/app/views/clients/_manageVsts.html.slim
@@ -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
\ No newline at end of file
diff --git a/web/app/views/clients/_vstEffects.html.slim b/web/app/views/clients/_vstEffects.html.slim
new file mode 100644
index 000000000..4085f9ecc
--- /dev/null
+++ b/web/app/views/clients/_vstEffects.html.slim
@@ -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 . . .
\ No newline at end of file
diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb
index 962e21298..16f30f3a1 100644
--- a/web/app/views/clients/index.html.erb
+++ b/web/app/views/clients/index.html.erb
@@ -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" %>
diff --git a/web/app/views/clients/wizard/gear/_gear_wizard.html.haml b/web/app/views/clients/wizard/gear/_gear_wizard.html.haml
index c2c1d9b50..4f8f9ab87 100644
--- a/web/app/views/clients/wizard/gear/_gear_wizard.html.haml
+++ b/web/app/views/clients/wizard/gear/_gear_wizard.html.haml
@@ -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
diff --git a/web/app/views/dialogs/_configureLiveTracksDialog.html.slim b/web/app/views/dialogs/_configureLiveTracksDialog.html.slim
index eace5771b..2c488ddaa 100644
--- a/web/app/views/dialogs/_configureLiveTracksDialog.html.slim
+++ b/web/app/views/dialogs/_configureLiveTracksDialog.html.slim
@@ -1,6 +1,2 @@
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='configure-live-tracks-dialog' id='configure-live-tracks-dialog'
- .content-head
- = image_tag "content/icon_add.png", {:height => 19, :width => 19, :class => 'content-icon'}
- h1 add live track
- .dialog-inner
- = react_component 'ConfigureLiveTracksDialog', {}
+ = react_component 'ConfigureLiveTracksDialog', {}
diff --git a/web/app/views/dialogs/_configureOutputsDialog.html.slim b/web/app/views/dialogs/_configureOutputsDialog.html.slim
new file mode 100644
index 000000000..bb6f10e7c
--- /dev/null
+++ b/web/app/views/dialogs/_configureOutputsDialog.html.slim
@@ -0,0 +1,2 @@
+.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='configure-outputs-dialog' id='configure-outputs-dialog'
+ = react_component 'ConfigureOutputsDialog', {}
diff --git a/web/app/views/dialogs/_configure_tracks_dialog.html.haml b/web/app/views/dialogs/_configure_tracks_dialog.html.haml
index cb65af8eb..42d6d1d2e 100644
--- a/web/app/views/dialogs/_configure_tracks_dialog.html.haml
+++ b/web/app/views/dialogs/_configure_tracks_dialog.html.haml
@@ -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
@@ -48,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
+
diff --git a/web/app/views/dialogs/_dialogs.html.haml b/web/app/views/dialogs/_dialogs.html.haml
index 761559fdf..2c45d7df2 100644
--- a/web/app/views/dialogs/_dialogs.html.haml
+++ b/web/app/views/dialogs/_dialogs.html.haml
@@ -44,4 +44,5 @@
= render 'dialogs/recordingSelectorDialog'
= render 'dialogs/soundCloudPlayerDialog'
= render 'dialogs/deleteVideoConfirmDialog'
-= render 'dialogs/configureLiveTracksDialog'
\ No newline at end of file
+= render 'dialogs/configureLiveTracksDialog'
+= render 'dialogs/configureOutputsDialog'
\ No newline at end of file