From 1da8c7372160452bcd7b289adb4e9eda03ccbf55 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Mon, 9 Nov 2015 15:33:04 -0600 Subject: [PATCH] * wip --- ruby/lib/jam_ruby/jam_track_importer.rb | 2 +- .../dialog/configureTrackDialog.js | 8 +- web/app/assets/javascripts/globals.js | 4 +- .../assets/javascripts/jquery.manageVsts.js | 71 ++++ .../assets/javascripts/jquery.trackEffects.js | 75 ++++ .../assets/javascripts/react-components.js | 2 +- .../ConfigureAudioTrack.js.jsx.coffee | 0 .../ConfigureLiveTracksDialog.js.jsx.coffee | 367 ++++++++++++++++-- .../ConfigureOutputsDialog.js.jsx.coffee | 87 +++++ .../ConfigureTracks.js.jsx.coffee | 35 +- .../SessionMyTrack.js.jsx.coffee | 38 +- .../SessionMyTracks.js.jsx.coffee | 2 +- .../actions/ConfigureTracksActions.js.coffee | 14 + .../mixins/SessionMyTracksMixin.js.coffee | 28 +- .../stores/ConfigureTracksStore.js.coffee | 288 +++++++++++++- .../stores/SessionStore.js.coffee | 3 + .../wizard/gear/step_configure_tracks.js | 9 +- web/app/assets/stylesheets/client/client.css | 2 + .../stylesheets/client/manageVsts.css.scss | 23 ++ .../react-components/ConfigureTracks.css.scss | 50 ++- .../stylesheets/client/vstEffects.css.scss | 39 ++ .../client/wizard/gearWizard.css.scss | 59 ++- .../configureLiveTracksDialog.css.scss | 103 ++++- .../dialogs/configureOutputsDialog.css.scss | 36 ++ .../dialogs/configureTracksDialog.css.scss | 16 +- web/app/views/clients/_manageVsts.html.slim | 7 + web/app/views/clients/_vstEffects.html.slim | 9 + web/app/views/clients/index.html.erb | 2 + .../wizard/gear/_gear_wizard.html.haml | 11 +- .../_configureLiveTracksDialog.html.slim | 6 +- .../dialogs/_configureOutputsDialog.html.slim | 2 + .../_configure_tracks_dialog.html.haml | 5 +- web/app/views/dialogs/_dialogs.html.haml | 3 +- 33 files changed, 1282 insertions(+), 124 deletions(-) create mode 100644 web/app/assets/javascripts/jquery.manageVsts.js create mode 100644 web/app/assets/javascripts/jquery.trackEffects.js create mode 100644 web/app/assets/javascripts/react-components/ConfigureAudioTrack.js.jsx.coffee create mode 100644 web/app/assets/javascripts/react-components/ConfigureOutputsDialog.js.jsx.coffee create mode 100644 web/app/assets/stylesheets/client/manageVsts.css.scss create mode 100644 web/app/assets/stylesheets/client/vstEffects.css.scss create mode 100644 web/app/assets/stylesheets/dialogs/configureOutputsDialog.css.scss create mode 100644 web/app/views/clients/_manageVsts.html.slim create mode 100644 web/app/views/clients/_vstEffects.html.slim create mode 100644 web/app/views/dialogs/_configureOutputsDialog.html.slim 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(``) for displayName, value of context.JK.server_to_client_instrument_map instruments.push(``) - if @state.configureTracks? - for input in @state.configureTracks.musicPorts.inputs - item = `` - inputOneOptions.push(item) - inputTwoOptions.push(item) - - - if @state.configureTracks.editingTrack? - action = 'EDIT TRACK' - vsts = [] - vsts.push(``) - `
-
-

Track Type

-
-
-
+ 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 = `` + inputOneOptions.push(item) + inputTwoOptions.push(item) + + + for plugin in @state.configureTracks.vstPluginList.vsts + if plugin.isInstrument == false && plugin.category == 'Effect' + vsts.push(``) + else if plugin.category == 'NONE' + vsts.push(``) + + 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}

Audio Effects (optional)

- {vsts} - manage audio plugins - SETTING . . . -
- -
- CANCEL - {action} + manage audio plugins
+
+ SETTINGS . . . +
` - cancel: (e) -> - e.preventDefault() + renderMidi: () -> + midiInterfaces = [] + midiInterfaces.push(``) + midiInstruments = [] - update: (e) -> + instruments = [] + instruments.push(``) + for displayName, value of context.JK.server_to_client_instrument_map + instruments.push(``) + + 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(``) + + for plugin in @state.configureTracks.vstPluginList.vsts + if plugin.isInstrument == true + midiInstruments.push(``) + else if plugin.category == 'NONE' + midiInstruments.push(``) + + `
+
+

MIDI Interface

+ + scan for connected MIDI interfaces +
+
+

Instrument

+ +
+
+

MIDI Instrument (VST or AU Plugin)

+ + manage audio plugins
+
+ SETTING . . . +
+
+
` + + 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

+
+
+
+ + {activeElement} + +
+ {cancelBtn} + {action} +
+
+
` + + 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(``) + + if @state.configureTracks? + for output in @state.configureTracks.musicPorts.outputs + outputs.push(``) + + `
+
+ +

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.

+ + +
+ CANCEL + UPDATE PORTS +
+
+
` + + 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}
update @@ -68,7 +72,9 @@ gearUtils = context.JK.GearUtils
{liveTracks}
- ADD A LIVE TRACK . . . +
+ ADD TRACK . . . +
@@ -79,21 +85,36 @@ gearUtils = context.JK.GearUtils UPDATE OUTPUTS . . .
+
` 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
+ {vst}

- -
` @@ -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