This commit is contained in:
Seth Call 2015-11-09 15:33:04 -06:00
parent 022fd60b3c
commit 1da8c73721
33 changed files with 1282 additions and 124 deletions

View File

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

View File

@ -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() {

View File

@ -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 = {

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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(`<option value="">Select the instrument for this track</option>`)
for displayName, value of context.JK.server_to_client_instrument_map
instruments.push(`<option value={value.server_id}>{displayName}</option>`)
if @state.configureTracks?
for input in @state.configureTracks.musicPorts.inputs
item = `<option value={input.id}>{input.name}</option>`
inputOneOptions.push(item)
inputTwoOptions.push(item)
if @state.configureTracks.editingTrack?
action = 'EDIT TRACK'
vsts = []
vsts.push(`<option value="">No VST/AU plugin selected</option>`)
`<div>
<div className="track-type">
<h3>Track Type</h3>
<div className="track-type-option"><input type="radio" value="audio" name="track-type" defaultValue="checked" /><label>Audio</label></div>
<div className="track-type-option"><input type="radio" value="midi" name="track-type"/><label>MIDI</label></div>
</div>
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 = `<option value={input.id}>{input.name}</option>`
inputOneOptions.push(item)
inputTwoOptions.push(item)
for plugin in @state.configureTracks.vstPluginList.vsts
if plugin.isInstrument == false && plugin.category == 'Effect'
vsts.push(`<option value={plugin.file}>{plugin.name} by {plugin.manuf}</option>`)
else if plugin.category == 'NONE'
vsts.push(`<option value={plugin.file}>No VST/AU plugin selected</option>`)
if @state.configureTracks.editingTrack.vst?
vstAssignedThisTrack = true
selectedVst = @state.configureTracks.editingTrack.vst.file
vstSettingBtnClasses = classNames({'button-orange': vstAssignedThisTrack, 'button-grey': !vstAssignedThisTrack})
`<div className="audio">
<div className="audio-input-ports">
<h3>Audio Input Ports</h3>
<p>Select one or two inputs ports to assign to this track. Note that if you assign a single input port, the app will automatically duplicate this port into a stereo track.</p>
<select name="input-one">
<select className="input-one" name="input-one" onChange={this.inputChanged} value={inputOneValue}>
{inputOneOptions}
</select>
<select name="input-two">
<select className="input-two" name="input-two" onChange={this.inputChanged} value={inputTwoValue}>
{inputTwoOptions}
</select>
</div>
<div className="instrument-selection">
<h3>Instrument</h3>
<select name="instrument">
<select className="instrument-pick" name="instrument" onChange={this.instrumentSelected} value={selectedInstrument} disabled={instrumentDisabled}>
{instruments}
</select>
</div>
<div className="audio-effects">
<h3>Audio Effects (optional)</h3>
<select name="">
<select className="vsts" name="vsts" onChange={this.vstsChanged} value={selectedVst} disabled={vstDisabled}>
{vsts}
</select>
<a>manage audio plugins</a>
<a onClick={this.vstSettings} className="button-orange">SETTING . . .</a>
</div>
<div className="actions">
<a onClick={this.cancel} className="button-grey">CANCEL</a>
<a onClick={this.update} className="button-orange">{action}</a>
<a className="manage-audio-plugins" onClick={this.manageAudioPlugins}>manage audio plugins <div className="down-arrow"></div></a>
<div className="settings-holder">
<a onClick={this.vstSettings} className={vstSettingBtnClasses}>SETTINGS . . .</a>
</div>
</div>
</div>`
cancel: (e) ->
e.preventDefault()
renderMidi: () ->
midiInterfaces = []
midiInterfaces.push(`<option value="">Select a MIDI interface</option>`)
midiInstruments = []
update: (e) ->
instruments = []
instruments.push(`<option value="">Select the instrument for this track</option>`)
for displayName, value of context.JK.server_to_client_instrument_map
instruments.push(`<option value={value.server_id}>{displayName}</option>`)
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(`<option value={midiDevice.deviceIndex}>{midiDevice.deviceName}</option>`)
for plugin in @state.configureTracks.vstPluginList.vsts
if plugin.isInstrument == true
midiInstruments.push(`<option value={plugin.file}>{plugin.name} by {plugin.manuf}</option>`)
else if plugin.category == 'NONE'
midiInstruments.push(`<option value={plugin.file}>Select a VST or AU instrument</option>`)
`<div className="midi">
<div className="midi-interface">
<h3>MIDI Interface</h3>
<select className="midi-select" name="midi-select" onChange={this.midiInterfaceChanged} value={selectedMidiInterface}>
{midiInterfaces}
</select>
<a className="scan-midi" onClick={this.scanMidi}>scan for connected MIDI interfaces</a>
</div>
<div className="instrument-selection">
<h3>Instrument</h3>
<select className="instrument-pick" name="instrument" onChange={this.instrumentSelected} value={selectedInstrument} disabled={instrumentDisabled}>
{instruments}
</select>
</div>
<div className="midi-instrument">
<h3>MIDI Instrument (VST or AU Plugin)</h3>
<select className="vsts" name="midi-instrument" onChange={this.vstsChanged} value={selectedMidiInstrument} disabled={midiInstrumentDisabled}>
{midiInstruments}
</select>
<a className="manage-audio-plugins" onClick={this.manageAudioPlugins}>manage audio plugins <div className="down-arrow"></div></a>
<div className="settings-holder">
<a onClick={this.vstSettings} className={vstSettingBtnClasses}>SETTING . . .</a>
</div>
</div>
</div>`
render: () ->
action = 'ADD TRACK'
header = 'add track'
isAudio = !@state.configureTracks? || @state.configureTracks.trackType == 'audio'
isMidi = !isAudio
if isAudio
activeElement = @renderAudio()
else
activeElement = @renderMidi()
if !@state.configureTracks?.newTrack
action = 'CLOSE'
header = 'update track'
else
cancelBtn = `<a onClick={this.onCancel} className="button-grey">CANCEL</a>`
`<div>
<div className="content-head">
<img className="content-icon" src="/assets/content/icon_add.png" height={19} width={19}/>
<h1>{header}</h1>
</div>
<div className="dialog-inner">
<div className="track-type">
<h3>Track Type</h3>
<div className="track-type-option"><input type="radio" value="audio" name="track-type" checked={isAudio} /><label>Audio</label></div>
<div className="track-type-option"><input type="radio" value="midi" name="track-type" checked={isMidi} /><label>MIDI</label></div>
</div>
{activeElement}
<div className="actions">
{cancelBtn}
<a onClick={this.doClose} className="button-orange">{action}</a>
</div>
</div>
</div>`
inputChanged: (e) ->
$root = $(@getDOMNode())
$select1 = $root.find('.input-one')
$select2 = $root.find('.input-two')
audioInput1 = $select1.val()
audioInput2 = $select2.val()
if audioInput1 == ''
audioInput1 = null
if audioInput2 == ''
audioInput2 = null
if audioInput1? && audioInput1 == audioInput2
e.preventDefault()
# TODO: tell user they can't do this
return
ConfigureTracksActions.associateInputsWithTrack(audioInput1, audioInput2)
vstsChanged: (e) ->
$root = $(@getDOMNode())
$select = $root.find('select.vsts')
vstSelected = $select.val()
if vstSelected?
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})
})

View File

@ -0,0 +1,87 @@
context = window
ConfigureTracksStore = @ConfigureTracksStore
@ConfigureOutputsDialog = React.createClass({
mixins: [Reflux.listenTo(@ConfigureTracksStore, "onConfigureTracksChanged"), Reflux.listenTo(@AppStore, "onAppInit")]
onConfigureTracksChanged: (configureTracks) ->
@setState({configureTracks: configureTracks})
onAppInit: (@app) ->
getInitialState: () ->
{configureTracks: null}
render: () ->
outputs = []
outputs.push(`<option value="">Select an output port for session audio</option>`)
if @state.configureTracks?
for output in @state.configureTracks.musicPorts.outputs
outputs.push(`<option value={output.id}>{output.name}</option>`)
`<div>
<div className="content-head">
<img className="content-icon" src="/assets/shared/icon_session.png" height={24} width={24}/>
<h1>session audio outputs</h1>
</div>
<div className="dialog-inner">
<p>Select two audio output ports that will be used to deliver the stereo audio of your sessions to your headphones or monitor.</p>
<select className="output-1" >
{outputs}
</select>
<select className="output-2" >
{outputs}
</select>
<div className="actions">
<a onClick={this.onCancel} className="button-grey">CANCEL</a>
<a onClick={this.onClose} className="button-orange">UPDATE PORTS</a>
</div>
</div>
</div>`
componentDidUpdate: () ->
$root = $(@getDOMNode())
$output1 = $root.find('.output-1')
$output2 = $root.find('.output-2')
if @state.configureTracks? && @state.configureTracks.trackAssignments.outputs.assigned.length == 2
output1 = @state.configureTracks.trackAssignments.outputs.assigned[0].id
output2 = @state.configureTracks.trackAssignments.outputs.assigned[1].id
$output1.val(output1)
$output2.val(output2)
onClose: (e) ->
e.preventDefault()
$root = $(@getDOMNode())
$output1 = $root.find('.output-1')
$output2 = $root.find('.output-2')
output1 = $output1.val()
output2 = $output2.val()
if output1 == null || output1 == ''
context.JK.Banner.showAlert("Both output ports must have a selection.")
return
if output2 == null || output2 == ''
context.JK.Banner.showAlert("Both output ports must have a selection.")
return
if output1? && output1 != '' && output1 == output2
context.JK.Banner.showAlert("Both output ports can not be the same.")
return
ConfigureTracksActions.updateOutputs(output1, output2)
@app.layout.closeDialog('configure-outputs-dialog', false)
onCancel: (e) ->
@app.layout.closeDialog('configure-outputs-dialog', true)
}
)

View File

@ -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 = `<span><img src={context.JK.getInstrumentIconMap24()[inputsForTrack.instrument_id].asset} /></span>`
trackTypeLabel = 'AUDIO'
vstName = 'None'
if inputsForTrack.vst
vstName = "#{inputsForTrack.vst.name} by #{inputsForTrack.vst.manuf}"
liveTracks.push(
`<div key={candidate.assignment} className="live-track">
<div className="input-track-info"><span className="assignment">{candidate.assignment}:</span>{inputs}</div>
<div className="plugin-info">None</div>
<div className={classNames({'input-track-info': true, one: inputsForTrack.length == 1, two: inputsForTrack.length == 2})}><span className="assignment">{candidate.assignment}:</span><span className="track-type-label">{trackTypeLabel}</span>{inputs}</div>
<div className="plugin-info">{vstName}</div>
<div className="plugin-instrument">{instrument}</div>
<div className="live-track-actions">
<a className="update-live-track" onClick={this.onUpdateLiveTrack.bind(this, inputsForTrack)}>update</a>
@ -68,7 +72,9 @@ gearUtils = context.JK.GearUtils
<div className="live-tracks">
{liveTracks}
</div>
<a onClick={this.openLiveTrackDialog} className="button-orange">ADD A LIVE TRACK . . . </a>
<div className="add-track-action">
<a onClick={this.openLiveTrackDialog} className="button-orange">ADD TRACK . . . </a>
</div>
</div>
<div className="outputs-view">
<div>
@ -79,21 +85,36 @@ gearUtils = context.JK.GearUtils
<a onClick={this.openOutputTrackDialog} className="button-orange">UPDATE OUTPUTS . . . </a>
</div>
</div>
<div className="clearall"></div>
</div>`
onUpdateLiveTrack:(liveTrack, e) ->
e.preventDefault()
ConfigureTracksActions.showEditTrack(liveTrack.assignment)
onDeleteLiveTrack:(liveTrack, e) ->
e.preventDefault()
if liveTrack.assignment == 1
# can't delete the last assignment
context.JK.Banner.showAlert('You can not delete the 1st audio track.')
else
context.JK.Banner.showYesNo({
title: "Confirm Deletion",
html: "Are you sure you want to delete this live track?",
yes: =>
ConfigureTracksActions.deleteTrack(liveTrack.assignment)
})
openLiveTrackDialog: (e) ->
e.preventDefault()
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()
})

View File

@ -1,6 +1,7 @@
context = window
MixerActions = @MixerActions
ConfigureTracksActions = @ConfigureTracksActions
@SessionMyTrack = React.createClass({
@ -42,7 +43,9 @@ MixerActions = @MixerActions
WebkitTransform: "rotate(#{pan}deg)"
}
# <div className="track-icon-equalizer" />
if @props.associatedVst?
@equalizerSet = true
vst = `<div className="track-icon-equalizer" />`
`<div className={trackClasses}>
<div className="disabled-track-overlay" />
@ -55,11 +58,10 @@ MixerActions = @MixerActions
<div className="track-buttons">
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
<div className="track-icon-pan" style={panStyle}/>
{vst}
</div>
<br className="clearall"/>
</div>
<br className="clearall"/>
</div>
</div>`
@ -96,6 +98,8 @@ MixerActions = @MixerActions
context.JK.helpBubble($root.find('.disabled-track-overlay'), 'missing-my-tracks', {}, {positions:['top'], offsetParent: $root.closest('.top-parent')})
@initializeVstEffects()
componentWillUpdate: (nextProps, nextState) ->
$root = $(this.getDOMNode())
$mute = $root.find('.track-icon-mute')
@ -116,4 +120,32 @@ MixerActions = @MixerActions
$mute.on("mouseleave", false)
$pan.on("mouseentere", false)
$pan.on("mouseleave", false)
componentDidUpdate:() ->
@initializeVstEffects()
initializeVstEffects: () ->
$root = $(this.getDOMNode())
$equalizer = $root.find('.track-icon-equalizer')
if $equalizer.length > 0 && !$equalizer.data('initialized')
logger.debug("initializing trackEffects", $equalizer)
$equalizer.trackEffects({postShow: @prepVstEffects}).on(context.JK.EVENTS.VST_EFFECT_SELECTED, @vstOperation).data('initialized', true).click(() =>
logger.debug("clicked!")
$equalizer.btOn()
)
prepVstEffects: ($container) ->
$container.find('.vst-name').text(@props.associatedVst?.name)
vstOperation: (e, data) ->
logger.debug("track effect selection: " + data.vstOperation)
if !@props.associatedVst?
logger.warn("no associated VST")
return
if data.vstOperation == 'open-vst'
ConfigureTracksActions.showVstSettings(@props.associatedVst.track)
else
ConfigureTracksActions.showEditTrack(@props.associatedVst.track + 1)
})

View File

@ -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()

View File

@ -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: {}
})

View File

@ -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)
}

View File

@ -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.<br/><br/>You can free some up by editing an AUDIO track.')
return
@openLiveTrackDialog(@nextTrackNumber)
onShowEditTrack: (trackNumber) ->
@openLiveTrackDialog(trackNumber)
openLiveTrackDialog: (trackNumber) ->
@trackNumber = trackNumber
logger.debug("opening live track dialog for track #{trackNumber}")
@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)
}
)

View File

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

View File

@ -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) {

View File

@ -53,6 +53,8 @@
*= require dialogs/dialog
*= require ./iconInstrumentSelect
*= require ./muteSelect
*= require ./manageVsts
*= require ./vstEffects
*= require ./metronomePlaybackModeSelect
*= require ./terms
*= require ./createSession

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;;
}
}
}
}

View File

@ -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"] {

View File

@ -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 {
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

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

View File

@ -0,0 +1,9 @@
script type='text/template' id='template-vst-effects'
ul
li data-manage-vst-option="open-vst"
a href='#'
| Open&nbsp;
span.vst-name
li data-manage-vst-option="update-track"
a href='#' Update Track . . .

View File

@ -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" %>

View File

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

View File

@ -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', {}

View File

@ -0,0 +1,2 @@
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='configure-outputs-dialog' id='configure-outputs-dialog'
= react_component 'ConfigureOutputsDialog', {}

View File

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

View File

@ -44,4 +44,5 @@
= render 'dialogs/recordingSelectorDialog'
= render 'dialogs/soundCloudPlayerDialog'
= render 'dialogs/deleteVideoConfirmDialog'
= render 'dialogs/configureLiveTracksDialog'
= render 'dialogs/configureLiveTracksDialog'
= render 'dialogs/configureOutputsDialog'